From: Ezekiel Newren via GitGitGadget Date: Thu, 27 Nov 2025 01:10:29 GMT Subject: [PATCH 07/13] cargo: create crate link-with-c Message-ID: In-Reply-To: From: Ezekiel Newren Signed-off-by: Ezekiel Newren --- rust/link-with-c/Cargo.toml | 9 +++++ rust/link-with-c/src/lib.rs | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 rust/link-with-c/Cargo.toml create mode 100644 rust/link-with-c/src/lib.rs diff --git a/rust/link-with-c/Cargo.toml b/rust/link-with-c/Cargo.toml new file mode 100644 index 0000000000..adb38fdc9c --- /dev/null +++ b/rust/link-with-c/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "link-with-c" +version = "0.1.0" +edition = "2018" + +[lib] +crate-type = ["staticlib", "rlib"] + +[dependencies] diff --git a/rust/link-with-c/src/lib.rs b/rust/link-with-c/src/lib.rs new file mode 100644 index 0000000000..f6faaf774d --- /dev/null +++ b/rust/link-with-c/src/lib.rs @@ -0,0 +1,77 @@ +use std::collections::HashMap; +use std::path::PathBuf; + + +fn parse_bool_from_str(value: &str) -> bool { + match value { + "1" | "true" | "yes" | "on" => true, + "0" | "false" | "no" | "off" => false, + _ => false + } +} + +fn parse_bool_from_option(value: Option<&String>, default: bool) -> bool { + match value { + Some(v) => { + parse_bool_from_str(v.as_str()) + }, + None => default, + } +} + +/// To build without linking against C libraries run `USE_LINKING=false cargo build` +/// To run tests set GIT_BUILD_DIR and run `USE_LINKING=true cargo test` +pub struct BuildHelper { + crate_env: HashMap, +} + + +impl BuildHelper { + pub fn new(crate_env: HashMap) -> Self { + Self { + crate_env, + } + } + + pub fn crate_name(&self) -> String { + self.crate_env["CARGO_PKG_NAME"].clone() + } + + pub fn dir_crate(&self) -> PathBuf { + PathBuf::from(self.crate_env["CARGO_MANIFEST_DIR"].clone()) + } + + pub fn build(self) { + let use_linking = parse_bool_from_option(self.crate_env.get("USE_LINKING"), self.crate_env.get("CARGO_TARGET_DIR").is_none()); + let dir_crate = self.dir_crate(); + let dir_git = dir_crate.parent().unwrap().parent().unwrap(); + + println!("cargo:rerun-if-changed={}", dir_git.display()); + + if use_linking { + if let Some(git_build_dir) = self.crate_env.get("GIT_BUILD_DIR") { + let path_git_build_dir = PathBuf::from(git_build_dir); + let is_abs = path_git_build_dir.is_absolute(); + if !is_abs { + panic!("GIT_BUILD_DIR must be an absolute path: {}'", path_git_build_dir.display()); + } + if !path_git_build_dir.is_dir() { + panic!("'GIT_BUILD_DIR' is not a directory: {}", path_git_build_dir.display()); + } + println!("cargo:rustc-link-search=native={}", git_build_dir); + } else { + panic!("environment variable 'GIT_BUILD_DIR' is not set"); + } + + println!("cargo:rustc-link-lib=static=git"); + println!("cargo:rustc-link-lib=pcre2-8"); + if self.crate_env.get("ZLIB_NG").is_some() { + println!("cargo:rustc-link-lib=z-ng"); + } else { + println!("cargo:rustc-link-lib=z"); + } + } else { + println!("cargo:warning={} is not linking against C objects, `USE_LINKING=true cargo test`", self.crate_env["CARGO_PKG_NAME"]); + } + } +} -- gitgitgadget