From c3e224b60d07cfcb06ce495c41ed374cebfed13d Mon Sep 17 00:00:00 2001 From: Casper Meijn Date: Wed, 7 Aug 2024 15:28:36 +0200 Subject: [PATCH] feat(prost-build): Add protoc executable path to Config Set the path to `protoc` executable to be used by `prost-build` Use the provided path to find `protoc`. This can either be a file name which is searched for in the `PATH` or an aboslute path to use a specific executable. --- prost-build/README.md | 11 ----------- prost-build/src/config.rs | 32 ++++++++++++++++++++++++++++---- prost-build/src/lib.rs | 21 +++++++++++++-------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/prost-build/README.md b/prost-build/README.md index 4646dbc8d..e16957c8e 100644 --- a/prost-build/README.md +++ b/prost-build/README.md @@ -7,17 +7,6 @@ a Cargo build. See the crate [documentation](https://docs.rs/prost-build/) for examples of how to integrate `prost-build` into a Cargo project. -## `protoc` - -`prost-build` uses `protoc` to parse the proto files. There are two ways to make `protoc` -available for `prost-build`: - -* Include `protoc` in your `PATH`. This can be done by following the [`protoc` install instructions]. -* Pass the `PROTOC=` environment variable with the path to - `protoc`. - -[`protoc` install instructions]: https://github.com/protocolbuffers/protobuf#protocol-compiler-installation - ## License `prost-build` is distributed under the terms of the Apache License (Version 2.0). diff --git a/prost-build/src/config.rs b/prost-build/src/config.rs index 50d26a24d..5087cd418 100644 --- a/prost-build/src/config.rs +++ b/prost-build/src/config.rs @@ -44,6 +44,7 @@ pub struct Config { pub(crate) enable_type_names: bool, pub(crate) type_name_domains: PathMap, pub(crate) protoc_args: Vec, + pub(crate) protoc_executable: PathBuf, pub(crate) disable_comments: PathMap<()>, pub(crate) skip_debug: PathMap<()>, pub(crate) skip_protoc_run: bool, @@ -703,6 +704,30 @@ impl Config { self } + /// Set the path to `protoc` executable to be used by `prost-build` + /// + /// Use the provided path to find `protoc`. This can either be a file name which is + /// searched for in the `PATH` or an aboslute path to use a specific executable. + /// + /// # Example `build.rs` + /// + /// ```rust,no_run + /// # use std::io::Result; + /// fn main() -> Result<()> { + /// let mut prost_build = prost_build::Config::new(); + /// prost_build.protoc_executable("protoc-27.1"); + /// prost_build.compile_protos(&["src/frontend.proto", "src/backend.proto"], &["src"])?; + /// Ok(()) + /// } + /// ``` + pub fn protoc_executable(&mut self, executable: S) -> &mut Self + where + S: Into, + { + self.protoc_executable = executable.into(); + self + } + /// Configures the optional module filename for easy inclusion of all generated Rust files /// /// If set, generates a file (inside the `OUT_DIR` or `out_dir()` as appropriate) which contains @@ -878,9 +903,7 @@ impl Config { }; if !self.skip_protoc_run { - let protoc = protoc_from_env(); - - let mut cmd = Command::new(protoc.clone()); + let mut cmd = Command::new(&self.protoc_executable); cmd.arg("--include_imports") .arg("--include_source_info") .arg("-o") @@ -920,7 +943,7 @@ impl Config { )), Err(err) => return Err(Error::new( err.kind(), - format!("failed to invoke protoc (hint: https://docs.rs/prost-build/#sourcing-protoc): (path: {:?}): {}", &protoc, err), + format!("failed to invoke protoc (hint: https://docs.rs/prost-build/#sourcing-protoc): (path: {:?}): {}", &self.protoc_executable, err), )), Ok(output) => output, }; @@ -1145,6 +1168,7 @@ impl default::Default for Config { enable_type_names: false, type_name_domains: PathMap::default(), protoc_args: Vec::new(), + protoc_executable: protoc_from_env(), disable_comments: PathMap::default(), skip_debug: PathMap::default(), skip_protoc_run: false, diff --git a/prost-build/src/lib.rs b/prost-build/src/lib.rs index 46a2454ad..1e74d0c96 100644 --- a/prost-build/src/lib.rs +++ b/prost-build/src/lib.rs @@ -101,7 +101,14 @@ //! ## Sourcing `protoc` //! //! `prost-build` depends on the Protocol Buffers compiler, `protoc`, to parse `.proto` files into -//! a representation that can be transformed into Rust. If set, `prost-build` uses the `PROTOC` +//! a representation that can be transformed into Rust. +//! +//! The easiest way for `prost-build` to find `protoc` is to install it in your `PATH`. +//! This can be done by following the [`protoc` install instructions]. `prost-build` will search +//! the current path for `protoc` or `protoc.exe`. +//! +//! When `protoc` is installed in a different location, set `PROTOC` to the path of the executable. +//! If set, `prost-build` uses the `PROTOC` //! for locating `protoc`. For example, on a macOS system where Protobuf is installed //! with Homebrew, set the environment variables to: //! @@ -109,16 +116,14 @@ //! PROTOC=/usr/local/bin/protoc //! ``` //! -//! and in a typical Linux installation: -//! -//! ```bash -//! PROTOC=/usr/bin/protoc -//! ``` +//! Alternatively, the path to `protoc` execuatable can be explicitly set +//! via [`Config::protoc_executable()`]. //! -//! If no `PROTOC` environment variable is set then `prost-build` will search the -//! current path for `protoc` or `protoc.exe`. If `prost-build` can not find `protoc` +//! If `prost-build` can not find `protoc` //! via these methods the `compile_protos` method will fail. //! +//! [`protoc` install instructions]: https://github.com/protocolbuffers/protobuf#protocol-compiler-installation +//! //! ### Compiling `protoc` from source //! //! To compile `protoc` from source you can use the `protobuf-src` crate and