Skip to content

Commit f62193f

Browse files
committed
build: LIBGIT2_NO_VENDOR to force to use system libgit2
Specify `LIBGIT2_NO_VENDOR` to force to use system libgit2. Due to the additive nature of Cargo features, if some crate in the dependency graph activates `vendored` feature, there is no way to revert it back. This env var serves as a workaround for this purpose. An alternative is having `no_vendored` feature. We still need to modify `build.rs` to make both `vendored` and `no_vendored` play nice with each other (or bail out as they are mutual-exclusive). However, there is no way to activate a Cargo feature via environment variable (see rust-lang/cargo#4829). Altering environment variables may be the only way to interact with some external build systems. It is also pretty common that people don't want to vendor anything and rather to see the build fail than vendoring. Some prior arts: * `OPENSSL_NO_VENDOR` in `openssl` crate, which serves the exact purpose of `LIBGIT2_NO_VENDOR` [^1]. * Crate `ssh2` has a similar `LIBSSH2_SYS_USE_PKG_CONFIG`, but it doesn't force to do so. It still falls back to vendored lib [^2]. * Crate `curl` has a feature `force-system-lib-on-osx` to trump all others features. It was created primarily for Rust releases [^3]. [^1]: https://github.com/sfackler/rust-openssl/blob/50787ed35bf9efa9dd3cbb1993a2564014b67489/openssl/src/lib.rs#L65 [^2]: https://github.com/alexcrichton/ssh2-rs/blob/d9a1dfac4b8c09c5437eb477606b82aa4f67b092/libssh2-sys/build.rs#L22-L33 [^3]: https://github.com/alexcrichton/curl-rust/blob/431babf1dffe205641793353d3d57fdd36fe8534/curl-sys/build.rs#L15-L20
1 parent d6d3c0b commit f62193f

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

Diff for: README.md

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ source for libgit2 is included in the libgit2-sys crate so there's no need to
2121
pre-install the libgit2 library, the libgit2-sys crate will figure that and/or
2222
build that for you.
2323

24+
You can enable the Cargo feature `vendored-libgit2` to always compile and
25+
statically link to a copy of libgit2. Sometimes the libgit2 on the system is
26+
required to be found and used even when `vendored-libgit2` is activated. In
27+
this case, you shall set the environment variable `LIBGIT2_NO_VENDOR=1`.
28+
2429
## Building git2-rs
2530

2631
```sh

Diff for: libgit2-sys/build.rs

+41-8
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,55 @@ use std::io;
44
use std::path::{Path, PathBuf};
55
use std::process::Command;
66

7+
/// Tries to use system libgit2 and emits necessary build script instructions.
8+
fn try_system_libgit2() -> Result<pkg_config::Library, pkg_config::Error> {
9+
let mut cfg = pkg_config::Config::new();
10+
match cfg.range_version("1.6.4".."1.7.0").probe("libgit2") {
11+
Ok(lib) => {
12+
for include in &lib.include_paths {
13+
println!("cargo:root={}", include.display());
14+
}
15+
Ok(lib)
16+
}
17+
Err(e) => {
18+
println!("cargo:warning=failed to probe system libgit2: {e}");
19+
Err(e)
20+
}
21+
}
22+
}
23+
724
fn main() {
825
let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
926
let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
1027
let vendored = env::var("CARGO_FEATURE_VENDORED").is_ok();
1128
let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok();
1229

30+
// Specify `LIBGIT2_NO_VENDOR` to force to use system libgit2.
31+
// Due to the additive nature of Cargo features, if some crate in the
32+
// dependency graph activates `vendored` feature, there is no way to revert
33+
// it back. This env var serves as a workaround for this purpose.
34+
println!("cargo:rerun-if-env-changed=LIBGIT2_NO_VENDOR");
35+
let forced_no_vendor = env::var_os("LIBGIT2_NO_VENDOR").map_or(false, |s| s != "0");
36+
37+
if forced_no_vendor {
38+
if try_system_libgit2().is_err() {
39+
panic!(
40+
"\
41+
The environment variable `LIBGIT2_NO_VENDOR` has been set but no compatible system libgit2 could be found.
42+
The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VENDOR=0`.
43+
",
44+
);
45+
}
46+
47+
// We've reached here, implying we're using system libgit2.
48+
return;
49+
}
50+
1351
// To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves.
1452
let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat;
15-
if try_to_use_system_libgit2 {
16-
let mut cfg = pkg_config::Config::new();
17-
if let Ok(lib) = cfg.range_version("1.6.4".."1.7.0").probe("libgit2") {
18-
for include in &lib.include_paths {
19-
println!("cargo:root={}", include.display());
20-
}
21-
return;
22-
}
53+
if try_to_use_system_libgit2 && try_system_libgit2().is_ok() {
54+
// using system libgit2 has worked
55+
return;
2356
}
2457

2558
println!("cargo:rustc-cfg=libgit2_vendored");

0 commit comments

Comments
 (0)