summaryrefslogtreecommitdiff
path: root/build.rs
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2020-10-14 15:35:59 +0200
committerJeff Vander Stoep <jeffv@google.com>2020-10-14 15:44:30 +0200
commit3adfea8b276f06db63ae4182233560537aca2ffb (patch)
treea543e650c0d9b57239020605562e73d35f9db409 /build.rs
parente028ffbabf8620351ce637bb48a8bb539c753c38 (diff)
downloadgrpcio-sys-3adfea8b276f06db63ae4182233560537aca2ffb.tar.gz
Import grpcio-sys 0.6.0
And add metadata files using the following command: get_rust_pkg.py --add3prf -v grpcio-sys-0.6.0 -o grpcio-sys Use LICENSE file from parent grpcio crate. Add README.android as requested during security review. Test: None Change-Id: Ib5f5c2af6f51d50c536cc4b6979666d480a57041
Diffstat (limited to 'build.rs')
-rw-r--r--build.rs407
1 files changed, 407 insertions, 0 deletions
diff --git a/build.rs b/build.rs
new file mode 100644
index 00000000..b5f34eab
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,407 @@
+// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
+
+use std::env::VarError;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::path::{Path, PathBuf};
+use std::{env, fs, io};
+
+use cmake::Config as CmakeConfig;
+use pkg_config::{Config as PkgConfig, Library};
+use walkdir::WalkDir;
+
+const GRPC_VERSION: &str = "1.29.1";
+
+fn probe_library(library: &str, cargo_metadata: bool) -> Library {
+ match PkgConfig::new()
+ .atleast_version(GRPC_VERSION)
+ .cargo_metadata(cargo_metadata)
+ .probe(library)
+ {
+ Ok(lib) => lib,
+ Err(e) => panic!("can't find library {} via pkg-config: {:?}", library, e),
+ }
+}
+
+fn prepare_grpc() {
+ let mut modules = vec![
+ "grpc",
+ "grpc/third_party/cares/cares",
+ "grpc/third_party/address_sorting",
+ "grpc/third_party/abseil-cpp",
+ ];
+
+ if cfg!(feature = "secure") && !cfg!(feature = "openssl") {
+ modules.push("grpc/third_party/boringssl-with-bazel");
+ }
+
+ for module in modules {
+ if is_directory_empty(module).unwrap_or(true) {
+ panic!(
+ "Can't find module {}. You need to run `git submodule \
+ update --init --recursive` first to build the project.",
+ module
+ );
+ }
+ }
+}
+
+fn is_directory_empty<P: AsRef<Path>>(p: P) -> Result<bool, io::Error> {
+ let mut entries = fs::read_dir(p)?;
+ Ok(entries.next().is_none())
+}
+
+fn trim_start<'a>(s: &'a str, prefix: &str) -> Option<&'a str> {
+ if s.starts_with(prefix) {
+ Some(s.trim_start_matches(prefix))
+ } else {
+ None
+ }
+}
+
+fn build_grpc(cc: &mut cc::Build, library: &str) {
+ prepare_grpc();
+
+ let mut third_party = vec![
+ "cares/cares/lib",
+ "abseil-cpp/absl/strings",
+ "abseil-cpp/absl/time",
+ "abseil-cpp/absl/base",
+ "abseil-cpp/absl/types",
+ "abseil-cpp/absl/numeric",
+ ];
+
+ let dst = {
+ let mut config = CmakeConfig::new("grpc");
+
+ if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "macos") {
+ config.cxxflag("-stdlib=libc++");
+ }
+
+ // Ensure CoreFoundation be found in macos or ios
+ if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "macos")
+ || get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "ios")
+ {
+ println!("cargo:rustc-link-lib=framework=CoreFoundation");
+ }
+
+ if env::var("CARGO_CFG_TARGET_ENV").unwrap() == "musl" {
+ config.define("CMAKE_CXX_COMPILER", "g++");
+ }
+
+ // Cross-compile support for iOS
+ match env::var("TARGET").unwrap().as_str() {
+ "aarch64-apple-ios" => {
+ config
+ .define("CMAKE_OSX_SYSROOT", "iphoneos")
+ .define("CMAKE_OSX_ARCHITECTURES", "arm64");
+ }
+ "armv7-apple-ios" => {
+ config
+ .define("CMAKE_OSX_SYSROOT", "iphoneos")
+ .define("CMAKE_OSX_ARCHITECTURES", "armv7");
+ }
+ "armv7s-apple-ios" => {
+ config
+ .define("CMAKE_OSX_SYSROOT", "iphoneos")
+ .define("CMAKE_OSX_ARCHITECTURES", "armv7s");
+ }
+ "i386-apple-ios" => {
+ config
+ .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
+ .define("CMAKE_OSX_ARCHITECTURES", "i386");
+ }
+ "x86_64-apple-ios" => {
+ config
+ .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
+ .define("CMAKE_OSX_ARCHITECTURES", "x86_64");
+ }
+ _ => {}
+ };
+
+ // Allow overriding of the target passed to cmake
+ // (needed for Android crosscompile)
+ if let Ok(val) = env::var("CMAKE_TARGET_OVERRIDE") {
+ config.target(&val);
+ }
+
+ // We don't need to generate install targets.
+ config.define("gRPC_INSTALL", "false");
+ // We don't need to build csharp target.
+ config.define("gRPC_BUILD_CSHARP_EXT", "false");
+ // We don't need to build codegen target.
+ config.define("gRPC_BUILD_CODEGEN", "false");
+ // We don't need to build benchmarks.
+ config.define("gRPC_BENCHMARK_PROVIDER", "none");
+ if cfg!(feature = "openssl") {
+ config.define("gRPC_SSL_PROVIDER", "package");
+ if cfg!(feature = "openssl-vendored") {
+ config.register_dep("openssl");
+ }
+ } else if cfg!(feature = "secure") {
+ third_party.extend_from_slice(&["boringssl-with-bazel"]);
+ }
+ if cfg!(feature = "no-omit-frame-pointer") {
+ config
+ .cflag("-fno-omit-frame-pointer")
+ .cxxflag("-fno-omit-frame-pointer");
+ }
+ // Uses zlib from libz-sys.
+ setup_libz(&mut config);
+ config.build_target(library).uses_cxx11().build()
+ };
+
+ let build_dir = format!("{}/build", dst.display());
+ if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
+ let profile = match &*env::var("PROFILE").unwrap() {
+ "bench" | "release" => "Release",
+ _ => "Debug",
+ };
+ println!("cargo:rustc-link-search=native={}/{}", build_dir, profile);
+ for path in third_party {
+ println!(
+ "cargo:rustc-link-search=native={}/third_party/{}/{}",
+ build_dir, path, profile
+ );
+ }
+ } else {
+ println!("cargo:rustc-link-search=native={}", build_dir);
+ for path in third_party {
+ println!(
+ "cargo:rustc-link-search=native={}/third_party/{}",
+ build_dir, path,
+ );
+ }
+ }
+
+ // link libz
+ println!("cargo:rustc-link-lib=static=z");
+ // link cares
+ println!("cargo:rustc-link-lib=static=cares");
+ // link address_sorting
+ println!("cargo:rustc-link-lib=static=address_sorting");
+ // link absl/base
+ println!("cargo:rustc-link-lib=static=absl_base");
+ println!("cargo:rustc-link-lib=static=absl_raw_logging_internal");
+ println!("cargo:rustc-link-lib=static=absl_dynamic_annotations");
+ println!("cargo:rustc-link-lib=static=absl_throw_delegate");
+ println!("cargo:rustc-link-lib=static=absl_log_severity");
+ println!("cargo:rustc-link-lib=static=absl_spinlock_wait");
+ // link absl/strings
+ println!("cargo:rustc-link-lib=static=absl_strings");
+ println!("cargo:rustc-link-lib=static=absl_strings_internal");
+ println!("cargo:rustc-link-lib=static=absl_str_format_internal");
+ // link absl/time
+ println!("cargo:rustc-link-lib=static=absl_civil_time");
+ println!("cargo:rustc-link-lib=static=absl_time_zone");
+ println!("cargo:rustc-link-lib=static=absl_time");
+ // link absl/types
+ println!("cargo:rustc-link-lib=static=absl_bad_optional_access");
+ // link absl/numeric
+ println!("cargo:rustc-link-lib=static=absl_int128");
+ // link grpc related lib
+ println!("cargo:rustc-link-lib=static=gpr");
+ println!("cargo:rustc-link-lib=static=upb");
+ println!("cargo:rustc-link-lib=static={}", library);
+
+ if cfg!(feature = "secure") {
+ if cfg!(feature = "openssl") && !cfg!(feature = "openssl-vendored") {
+ figure_ssl_path(&build_dir);
+ } else {
+ println!("cargo:rustc-link-lib=static=ssl");
+ println!("cargo:rustc-link-lib=static=crypto");
+ }
+ }
+
+ cc.include("grpc/include");
+}
+
+fn figure_ssl_path(build_dir: &str) {
+ let path = format!("{}/CMakeCache.txt", build_dir);
+ let f = BufReader::new(std::fs::File::open(&path).unwrap());
+ let mut cnt = 0;
+ for l in f.lines() {
+ let l = l.unwrap();
+ let t = trim_start(&l, "OPENSSL_CRYPTO_LIBRARY:FILEPATH=")
+ .or_else(|| trim_start(&l, "OPENSSL_SSL_LIBRARY:FILEPATH="));
+ if let Some(s) = t {
+ let path = Path::new(s);
+ println!(
+ "cargo:rustc-link-search=native={}",
+ path.parent().unwrap().display()
+ );
+ cnt += 1;
+ }
+ }
+ if cnt != 2 {
+ panic!(
+ "CMake cache invalid, file {} contains {} ssl keys!",
+ path, cnt
+ );
+ }
+ println!("cargo:rustc-link-lib=ssl");
+ println!("cargo:rustc-link-lib=crypto");
+}
+
+fn setup_libz(config: &mut CmakeConfig) {
+ config.define("gRPC_ZLIB_PROVIDER", "package");
+ config.register_dep("Z");
+ // cmake script expect libz.a being under ${DEP_Z_ROOT}/lib, but libz-sys crate put it
+ // under ${DEP_Z_ROOT}/build. Append the path to CMAKE_PREFIX_PATH to get around it.
+ let zlib_root = env::var("DEP_Z_ROOT").unwrap();
+ let prefix_path = if let Ok(prefix_path) = env::var("CMAKE_PREFIX_PATH") {
+ format!("{};{}/build", prefix_path, zlib_root)
+ } else {
+ format!("{}/build", zlib_root)
+ };
+ // To avoid linking system library, set lib path explicitly.
+ println!("cargo:rustc-link-search=native={}/build", zlib_root);
+ println!("cargo:rustc-link-search=native={}/lib", zlib_root);
+ env::set_var("CMAKE_PREFIX_PATH", prefix_path);
+}
+
+fn get_env(name: &str) -> Option<String> {
+ println!("cargo:rerun-if-env-changed={}", name);
+ match env::var(name) {
+ Ok(s) => Some(s),
+ Err(VarError::NotPresent) => None,
+ Err(VarError::NotUnicode(s)) => {
+ panic!("unrecognize env var of {}: {:?}", name, s.to_string_lossy());
+ }
+ }
+}
+
+// Generate the bindings to grpc C-core.
+// Try to disable the generation of platform-related bindings.
+fn bindgen_grpc(mut config: bindgen::Builder, file_path: &PathBuf) {
+ // Search header files with API interface
+ let mut headers = Vec::new();
+ for result in WalkDir::new(Path::new("./grpc/include")) {
+ let dent = result.expect("Error happened when search headers");
+ if !dent.file_type().is_file() {
+ continue;
+ }
+ let mut file = fs::File::open(dent.path()).expect("couldn't open headers");
+ let mut buf = String::new();
+ file.read_to_string(&mut buf)
+ .expect("Coundn't read header content");
+ if buf.contains("GRPCAPI") || buf.contains("GPRAPI") {
+ headers.push(String::from(dent.path().to_str().unwrap()));
+ }
+ }
+
+ // To control the order of bindings
+ headers.sort();
+ for path in headers {
+ config = config.header(path);
+ }
+
+ let cfg = config
+ .header("grpc_wrap.cc")
+ .clang_arg("-xc++")
+ .clang_arg("-I./grpc/include")
+ .clang_arg("-std=c++11")
+ .rustfmt_bindings(true)
+ .impl_debug(true)
+ .whitelist_function(r"\bgrpc_.*")
+ .whitelist_function(r"\bgpr_.*")
+ .whitelist_function(r"\bgrpcwrap_.*")
+ .whitelist_var(r"\bGRPC_.*")
+ .whitelist_type(r"\bgrpc_.*")
+ .whitelist_type(r"\bgpr_.*")
+ .whitelist_type(r"\bgrpcwrap_.*")
+ .whitelist_type(r"\bcensus_context.*")
+ .whitelist_type(r"\bverify_peer_options.*")
+ .blacklist_type(r"(__)?pthread.*")
+ .blacklist_function(r"\bgpr_mu_.*")
+ .blacklist_function(r"\bgpr_cv_.*")
+ .blacklist_function(r"\bgpr_once_.*")
+ .blacklist_type(r"gpr_mu")
+ .blacklist_type(r"gpr_cv")
+ .blacklist_type(r"gpr_once")
+ .constified_enum_module(r"grpc_status_code")
+ .default_enum_style(bindgen::EnumVariation::Rust {
+ non_exhaustive: false,
+ });
+ println!("running {}", cfg.command_line_flags().join(" "));
+ cfg.generate()
+ .expect("Unable to generate grpc bindings")
+ .write_to_file(file_path)
+ .expect("Couldn't write bindings!");
+}
+
+// Determine if need to update bindings. Supported platforms do not
+// need to be updated by default unless the UPDATE_BIND is specified.
+// Other platforms use bindgen to generate the bindings every time.
+fn config_binding_path(config: bindgen::Builder) {
+ let file_path: PathBuf;
+ let target = env::var("TARGET").unwrap();
+ match target.as_str() {
+ "x86_64-unknown-linux-gnu" | "aarch64-unknown-linux-gnu" => {
+ // Cargo treats nonexistent files changed, so we only emit the rerun-if-changed
+ // directive when we expect the target-specific pre-generated binding file to be
+ // present.
+ println!("cargo:rerun-if-changed=bindings/{}-bindings.rs", &target);
+
+ file_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
+ .join("bindings")
+ .join(format!("{}-bindings.rs", &target));
+ if env::var("UPDATE_BIND").map(|s| s == "1").unwrap_or(false) {
+ bindgen_grpc(config, &file_path);
+ }
+ }
+ _ => {
+ file_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("grpc-bindings.rs");
+ bindgen_grpc(config, &file_path);
+ }
+ };
+ println!(
+ "cargo:rustc-env=BINDING_PATH={}",
+ file_path.to_str().unwrap()
+ );
+}
+
+fn main() {
+ println!("cargo:rerun-if-changed=grpc_wrap.cc");
+ println!("cargo:rerun-if-changed=grpc");
+ println!("cargo:rerun-if-env-changed=UPDATE_BIND");
+
+ // create a builder to compile grpc_wrap.cc
+ let mut cc = cc::Build::new();
+ // create a config to generate binding file
+ let mut bind_config = bindgen::Builder::default();
+
+ let library = if cfg!(feature = "secure") {
+ cc.define("GRPC_SYS_SECURE", None);
+ bind_config = bind_config.clang_arg("-DGRPC_SYS_SECURE");
+ "grpc"
+ } else {
+ "grpc_unsecure"
+ };
+
+ if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
+ // At lease vista
+ cc.define("_WIN32_WINNT", Some("0x600"));
+ bind_config = bind_config.clang_arg("-D _WIN32_WINNT=0x600");
+ }
+
+ if get_env("GRPCIO_SYS_USE_PKG_CONFIG").map_or(false, |s| s == "1") {
+ // Print cargo metadata.
+ let lib_core = probe_library(library, true);
+ for inc_path in lib_core.include_paths {
+ cc.include(inc_path);
+ }
+ } else {
+ build_grpc(&mut cc, library);
+ }
+
+ cc.cpp(true);
+ if !cfg!(target_env = "msvc") {
+ cc.flag("-std=c++11");
+ }
+ cc.file("grpc_wrap.cc");
+ cc.warnings_into_errors(true);
+ cc.compile("libgrpc_wrap.a");
+
+ config_binding_path(bind_config);
+}