mz_build_tools/
lib.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Provides access to tools required in build scripts.
11//!
12//! For example, many crates have a build script that depends on the Protobuf
13//! compiler, `protoc`. If we're building with Cargo we'll bootstrap `protoc`
14//! by compiling it with [`protobuf-src`], but if we're building with Bazel
15//! then we'll use the version of `protoc` included in the runfiles.
16
17use cfg_if::cfg_if;
18use std::path::PathBuf;
19
20// Note: This crate's BUILD.bazel compiles with the rustc flag `--cfg=bazel`.
21
22// Runfiles are a Bazel concept, they're a way to provide files at execution
23// time. This dependency is provided only by the Bazel build.
24#[cfg(bazel)]
25extern crate runfiles;
26
27/// Returns if we're currently building with Bazel.
28pub const fn is_bazel_build() -> bool {
29    cfg_if! {
30        if #[cfg(bazel)] {
31            true
32        } else {
33            false
34        }
35    }
36}
37
38/// Returns the path to `protoc`.
39///
40/// Looks for `protoc` in the following places:
41///
42/// * Bazel runfiles, if we're building with Bazel.
43/// * Bootstraps `protoc` via protobuf-src, if default features are enabled.
44/// * `PROTOC` environment variable, if it's set.
45/// * The system's `$PATH`, via [`which`].
46///
47/// If `protoc` can't be found then this function will panic.
48pub fn protoc() -> PathBuf {
49    cfg_if! {
50        if #[cfg(bazel)] {
51            let r = runfiles::Runfiles::create().unwrap();
52            r.rlocation("com_google_protobuf/protoc").expect("set by Bazel")
53        } else if #[cfg(feature = "protobuf-src")] {
54            protobuf_src::protoc()
55        } else {
56            // If we're not building with Bazel, nor have the `protobuf-src`
57            // feature specified, then try using the system's `protoc`.
58            match std::option_env!("PROTOC") {
59                Some(path) => PathBuf::from(path),
60                None => which::which("protoc").expect("protoc to exist on system"),
61            }
62        }
63    }
64}
65
66/// Returns the path to the protobuf includes directory.
67///
68/// Note: this is primarily used to include "well known types".
69pub fn protoc_include() -> PathBuf {
70    cfg_if! {
71        if #[cfg(bazel)] {
72            let r = runfiles::Runfiles::create().unwrap();
73            r.rlocation("com_google_protobuf/src").expect("set by Bazel")
74        } else if #[cfg(feature = "protobuf-src")] {
75            protobuf_src::include()
76        } else {
77            let path = std::option_env!("PROTOC_INCLUDE").unwrap_or_default();
78            PathBuf::from(path)
79        }
80    }
81}