Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/continuous-integration-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
matrix:
toolchain:
- stable
- 1.56.0
- 1.56.1
os:
- ubuntu-latest
- macos-latest
Expand Down Expand Up @@ -180,6 +180,6 @@ jobs:
default: true
profile: minimal
- uses: Swatinem/rust-cache@v1
- name: cargo check
run: cd test-vendored && cargo check
- name: cargo test -p test-vendored
run: cargo test -p test-vendored

13 changes: 13 additions & 0 deletions prost-build/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fn main() {
// let protoc_include = if let Some(include) = std::env::var_os("PROTOC_INCLUDE") {
// include.into()
// } else {
// std::env::current_dir().unwrap().join("third-party")
// };

// println!(
// "cargo:rustc-env=PROTOC_INCLUDE={}",
// protoc_include.display()
// );
// println!("cargo:rerun-if-env-changed=PROTOC_INCLUDE");
}
104 changes: 40 additions & 64 deletions prost-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,45 +92,35 @@
//! ## 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` and
//! `PROTOC_INCLUDE` environment variables for locating `protoc` and the Protobuf includes
//! directory. For example, on a macOS system where Protobuf is installed with Homebrew, set the
//! environment to:
//! a representation that can be transformed into Rust. 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:
//!
//! ```bash
//! PROTOC=/usr/local/bin/protoc
//! PROTOC_INCLUDE=/usr/local/include
//! ```
//!
//! and in a typical Linux installation:
//!
//! ```bash
//! PROTOC=/usr/bin/protoc
//! PROTOC_INCLUDE=/usr/include
//! ```
//!
//! If no `PROTOC` environment variable is set then `prost-build` will search the
//! current path for `protoc` or `protoc.exe`. If `protoc` is not found via these
//! two methods then `prost-build` will attempt to compile `protoc` from the bundled
//! source.
//!
//! If you would not like `prost-build` to not compile `protoc` from source ever then
//! ensure you have set `PROTOC_NO_VENDOR` environment variable as this will disable
//! compiling from source even if the `vendored` feature flag is enabled.
//!
//! If you would like to always compile from source then setting the `vendored` feature
//! flag will force `prost-build` to always build `protoc` from source.
//!
//! If `PROTOC_INCLUDE` is not found in the environment, then the Protobuf include directory
//! bundled in the prost-build crate is be used.
//! current path for `protoc` or `protoc.exe`. If `prost-buld` can not find `protoc`
//! via these methods the `compile_protos` method will fail.
//!
//! ### Compiling `protoc` from source
//!
//! Compiling `protoc` from source requires a few external dependencies. Currently,
//! `prost-build` uses `cmake` to build `protoc`. For more information check out the
//! [protobuf build instructions][protobuf-build].
//! To compile `protoc` from source you can use the `protobuf-src` crate and
//! set the correct environment variables.
//! ```no_run,ignore, rust
//! std::env::set_var("PROTOC", protobuf_src::protoc());
//!
//! [protobuf-build]: https://github.com/protocolbuffers/protobuf/blob/master/src/README.md
//! // Now compile your proto files via prost-build
//! ```
//!
//! [`protobuf-src`]: https://docs.rs/protobuf-src

mod ast;
mod code_generator;
Expand Down Expand Up @@ -257,8 +247,6 @@ pub struct Config {
disable_comments: PathMap<()>,
skip_protoc_run: bool,
include_file: Option<PathBuf>,
protoc_path: Option<PathBuf>,
protoc_include_path: Option<PathBuf>,
}

impl Config {
Expand Down Expand Up @@ -735,24 +723,6 @@ impl Config {
self
}

/// Configures the path from where to find the `protoc` binary.
pub fn protoc_path<P>(&mut self, arg: P) -> &mut Self
where
P: Into<PathBuf>,
{
self.protoc_path = Some(arg.into());
self
}

/// Configures the path from where the protobuf include files are.
pub fn protoc_include_path<P>(&mut self, arg: P) -> &mut Self
where
P: Into<PathBuf>,
{
self.protoc_include_path = Some(arg.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
Expand Down Expand Up @@ -844,17 +814,7 @@ impl Config {
};

if !self.skip_protoc_run {
let protoc = self
.protoc_path
.as_ref()
.map(PathBuf::clone)
.unwrap_or_else(protoc_from_env);

let protoc_include = self
.protoc_include_path
.as_ref()
.map(PathBuf::clone)
.unwrap_or_else(protoc_from_env);
let protoc = protoc_from_env();

let mut cmd = Command::new(protoc.clone());
cmd.arg("--include_imports")
Expand All @@ -863,12 +823,21 @@ impl Config {
.arg(&file_descriptor_set_path);

for include in includes {
cmd.arg("-I").arg(include.as_ref());
if include.as_ref().exists() {
cmd.arg("-I").arg(include.as_ref());
} else {
println!(
"ignoring {} since it does not exist.",
include.as_ref().display()
)
}
}

// Set the protoc include after the user includes in case the user wants to
// override one of the built-in .protos.
cmd.arg("-I").arg(protoc_include);
if let Some(protoc_include) = protoc_include_from_env() {
cmd.arg("-I").arg(protoc_include);
}

for arg in &self.protoc_args {
cmd.arg(arg);
Expand All @@ -878,6 +847,8 @@ impl Config {
cmd.arg(proto.as_ref());
}

println!("Running: {:?}", cmd);

let output = cmd.output().map_err(|error| {
Error::new(
error.kind(),
Expand Down Expand Up @@ -1083,8 +1054,6 @@ impl default::Default for Config {
protoc_args: Vec::new(),
disable_comments: PathMap::default(),
skip_protoc_run: false,
protoc_path: None,
protoc_include_path: None,
include_file: None,
}
}
Expand Down Expand Up @@ -1243,17 +1212,24 @@ pub fn compile_protos(protos: &[impl AsRef<Path>], includes: &[impl AsRef<Path>]

/// Returns the path to the `protoc` binary.
pub fn protoc_from_env() -> PathBuf {
let msg = "
Could not find `protoc` installation and this build crate cannot proceed without
this knowledge. If `protoc` is installed and this crate had trouble finding
it, you can set the `PROTOC` environment variable with the specific path to your
installed `protoc` binary.

For more information: https://docs.rs/prost-build/#sourcing-protoc
";

env::var_os("PROTOC")
.map(PathBuf::from)
.or_else(|| which::which("protoc").ok())
.expect("`PROTOC` environment variable not set or `protoc` not found in `PATH`.")
.expect(msg)
}

/// Returns the path to the Protobuf include directory.
pub fn protoc_include_from_env() -> PathBuf {
let protoc_include: PathBuf = env::var_os("PROTOC_INCLUDE")
.expect("`PROTOC_INCLUDE` environment variable not set")
.into();
pub fn protoc_include_from_env() -> Option<PathBuf> {
let protoc_include: PathBuf = env::var_os("PROTOC_INCLUDE")?.into();

if !protoc_include.exists() {
panic!(
Expand All @@ -1268,7 +1244,7 @@ pub fn protoc_include_from_env() -> PathBuf {
);
}

protoc_include
Some(protoc_include)
}

#[cfg(test)]
Expand Down
18 changes: 4 additions & 14 deletions prost-types/src/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub struct FieldDescriptorProto {
/// For booleans, "true" or "false".
/// For strings, contains the default text contents (not escaped in any way).
/// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
/// TODO(kenton): Base-64 encode?
#[prost(string, optional, tag="7")]
pub default_value: ::core::option::Option<::prost::alloc::string::String>,
/// If set, gives the index of a oneof in the containing type's oneof_decl
Expand Down Expand Up @@ -630,19 +631,8 @@ pub struct FieldOptions {
/// implementation must either *always* check its required fields, or *never*
/// check its required fields, regardless of whether or not the message has
/// been parsed.
///
/// As of 2021, lazy does no correctness checks on the byte stream during
/// parsing. This may lead to crashes if and when an invalid byte stream is
/// finally parsed upon access.
///
/// TODO(b/211906113): Enable validation on lazy fields.
#[prost(bool, optional, tag="5", default="false")]
pub lazy: ::core::option::Option<bool>,
/// unverified_lazy does no correctness checks on the byte stream. This should
/// only be used where lazy with verification is prohibitive for performance
/// reasons.
#[prost(bool, optional, tag="15", default="false")]
pub unverified_lazy: ::core::option::Option<bool>,
/// Is this field deprecated?
/// Depending on the target platform, this can emit Deprecated annotations
/// for accessors, or it will be completely ignored; in the very least, this
Expand Down Expand Up @@ -903,8 +893,8 @@ pub mod source_code_info {
/// location.
///
/// Each element is a field number or an index. They form a path from
/// the root FileDescriptorProto to the place where the definition occurs.
/// For example, this path:
/// the root FileDescriptorProto to the place where the definition. For
/// example, this path:
/// \[ 4, 3, 2, 7, 1 \]
/// refers to:
/// file.message_type(3) // 4, 3
Expand Down Expand Up @@ -1080,7 +1070,7 @@ pub mod generated_code_info {
/// in the type URL, for example "foo.bar.com/x/y.z" will yield type
/// name "y.z".
///
/// JSON
/// # JSON
///
/// The JSON representation of an `Any` value uses the regular
/// representation of the deserialized, embedded message, with an
Expand Down
4 changes: 2 additions & 2 deletions tests/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fn bootstrap() {
.parent()
.unwrap()
.join("tests")
.join("src")
.join("include");
let protobuf = include.join("google").join("protobuf");

Expand All @@ -27,7 +28,6 @@ fn bootstrap() {
prost_build::Config::new()
.compile_well_known_types()
.btree_map(&["."])
.protoc_include_path(include)
.out_dir(tempdir.path())
.compile_protos(
&[
Expand All @@ -45,7 +45,7 @@ fn bootstrap() {
protobuf.join("timestamp.proto"),
protobuf.join("type.proto"),
],
&[""],
&[include],
)
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ option objc_class_prefix = "GPB";
// foo = any.unpack(Foo.class);
// }
//
// Example 3: Pack and unpack a message in Python.
// Example 3: Pack and unpack a message in Python.
//
// foo = Foo(...)
// any = Any()
Expand All @@ -74,7 +74,7 @@ option objc_class_prefix = "GPB";
// any.Unpack(foo)
// ...
//
// Example 4: Pack and unpack a message in Go
// Example 4: Pack and unpack a message in Go
//
// foo := &pb.Foo{...}
// any, err := anypb.New(foo)
Expand All @@ -95,7 +95,7 @@ option objc_class_prefix = "GPB";
//
//
// JSON
//
// ====
// The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ message FieldDescriptorProto {
// For booleans, "true" or "false".
// For strings, contains the default text contents (not escaped in any way).
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
// TODO(kenton): Base-64 encode?
optional string default_value = 7;

// If set, gives the index of a oneof in the containing type's oneof_decl
Expand Down Expand Up @@ -603,19 +604,8 @@ message FieldOptions {
// implementation must either *always* check its required fields, or *never*
// check its required fields, regardless of whether or not the message has
// been parsed.
//
// As of 2021, lazy does no correctness checks on the byte stream during
// parsing. This may lead to crashes if and when an invalid byte stream is
// finally parsed upon access.
//
// TODO(b/211906113): Enable validation on lazy fields.
optional bool lazy = 5 [default = false];

// unverified_lazy does no correctness checks on the byte stream. This should
// only be used where lazy with verification is prohibitive for performance
// reasons.
optional bool unverified_lazy = 15 [default = false];

// Is this field deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for accessors, or it will be completely ignored; in the very least, this
Expand Down Expand Up @@ -813,8 +803,8 @@ message SourceCodeInfo {
// location.
//
// Each element is a field number or an index. They form a path from
// the root FileDescriptorProto to the place where the definition occurs.
// For example, this path:
// the root FileDescriptorProto to the place where the definition. For
// example, this path:
// [ 4, 3, 2, 7, 1 ]
// refers to:
// file.message_type(3) // 4, 3
Expand Down
6 changes: 5 additions & 1 deletion tests/vendored/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
[package]
name = "test-vendored"
version = "0.1.0"
edition = "2018"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
prost = { path = "../.." }
prost-types = { path = "../../prost-types" }
bytes = "1"

[build-dependencies]
prost-build = { path = "../../prost-build" }
prost-build = { path = "../../prost-build" , features = ["cleanup-markdown"]}
protobuf-src = "1.0.5+3.19.3"
Loading