Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
43 changes: 40 additions & 3 deletions cargo/build/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,49 @@ pub fn collect_protobuf_includes() -> Vec<PathBuf> {
paths::get_env_paths("PROTOBUF_INCLUDE_PATH")
}

fn is_protobuf_lib(name: &str) -> bool {
// Protobuf's CMake build prefixes these archives with `lib` on every platform,
// including Windows, where `collect_static_libs` keeps the file stem as-is.
matches!(name.strip_prefix("lib").unwrap_or(name), "protobuf" | "utf8_validity")
}

/// Returns the paths to the protobuf libraries (to be used as a search path) and a
/// list of libraries to be linked.
///
/// This is an allowlist rather than "everything in the directory", because a protobuf
/// install tree holds several archives that must not be linked together:
///
/// * `protobuf` is the library Crubit uses, and it has undefined references into
/// `utf8_validity`, so the two belong together.
/// * `utf8_range` is compiled from the same `utf8_range.c` as `utf8_validity` and
/// defines the same symbols, so linking both is a duplicate symbol error.
/// * `protobuf-lite` is a subset of `protobuf`, and would collide with it likewise.
/// * `protoc` and `upb` are not used by Crubit.
pub fn collect_protobuf_libs() -> (Vec<PathBuf>, Vec<OsString>) {
paths::collect_static_libs("PROTOBUF_LIB_STATIC_PATH", |name| {
name.strip_prefix("lib").unwrap_or(name) == "protobuf"
})
paths::collect_static_libs("PROTOBUF_LIB_STATIC_PATH", is_protobuf_lib)
}

/// Unit tests for protobuf library allowlist matching.
///
/// Note: These tests use standard `#[test]` rather than `googletest` because
/// `crubit_build` is a build helper crate built via Cargo.
#[cfg(test)]
mod tests {
use super::*;

#[test] // allow_core_test (see mod tests doc comment)
fn test_is_protobuf_lib() {
assert!(is_protobuf_lib("protobuf"));
assert!(is_protobuf_lib("libprotobuf"));
assert!(is_protobuf_lib("utf8_validity"));
assert!(is_protobuf_lib("libutf8_validity"));
assert!(!is_protobuf_lib("utf8_range"));
assert!(!is_protobuf_lib("libutf8_range"));
assert!(!is_protobuf_lib("protobuf-lite"));
assert!(!is_protobuf_lib("libprotobuf-lite"));
assert!(!is_protobuf_lib("protoc"));
assert!(!is_protobuf_lib("upb"));
}
}

/// Locates pre-generated .pb.cc C++ source files corresponding to `proto_sources`
Expand Down
4 changes: 3 additions & 1 deletion docs/cpp/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ export ABSL_INCLUDE_PATH=/path/to/absl/include/dir
export ABSL_LIB_STATIC_PATH=/path/to/absl/libs
## This path contains google/protobuf/ dir with all the includes.
export PROTOBUF_INCLUDE_PATH=/path/to/protobuf/include/dir
## This path contains libprotobuf.a
## This path contains libprotobuf.a and libutf8_validity.a. Other archives that a
## protobuf install tree holds (libutf8_range.a, libprotobuf-lite.a, libprotoc.a,
## libupb.a) are ignored; the first two would collide with the ones above.
export PROTOBUF_LIB_STATIC_PATH=/path/to/protobuf/libs

cargo build --bin rs_bindings_from_cc
Expand Down
Loading