The pkg-config dependency is harmless because that small crate just calls pkg-config and parses its output. There's an issue though that its error type is String so one can't expect to discriminate failure modes. I've just been considering making a PR to add a proper error type to pkg-config.
As to pkg-config alternatives it seems to me that the only "idiomatic" alternative is building the dependency from source if pkg-config fails for whatever reason. Page Moved
The actual libgit2 build script does something slightly different and unexpected however:
if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
if pkg_config::find_library("libgit2").is_ok() {
return
}
}
openssl-sys can't get away with building from source so it allows setting the search paths in env variables and calls pkg-config if none of them are set:
let lib_dir = env::var("OPENSSL_LIB_DIR").ok();
let include_dir = env::var("OPENSSL_INCLUDE_DIR").ok();
if lib_dir.is_none() && include_dir.is_none() {
// rustc doesn't seem to work with pkg-config's output in mingw64
if !target.contains("windows") {
if let Ok(info) = pkg_config::find_library("openssl") {
// avoid empty include paths as they are not supported by GCC
if info.include_paths.len() > 0 {
let paths = env::join_paths(info.include_paths).unwrap();
println!("cargo:include={}", paths.to_str().unwrap());
}
return;
}
}
if let Some(mingw_paths) = get_mingw_in_path() {
for path in mingw_paths {
println!("cargo:rustc-link-search=native={}", path);
}
}
}
I've personally found pkg-config to be pretty unreliable on Windows, so I would recommend just avoiding it altogether. In my opinion the "most robust" build scripts do something like:
Try to use the system version of the package, if available. This may involve probing, using pkg-config, etc. This may be disabled by default (e.g. in libgit2's case) or come with an option to always disable (as with the pkg-config crate itself).
Failing that, either provide an error with information about how to install the crate, or compile a locally bundled version of the source code. For example this is how libcurl-sys and libgit2-sys work.
For MSVC you'll almost always need a branch in logic to compile for either Unix or MSVC, although if you're using CMake then there's a cmake crate to in theory handle that all for you.
Hope that helps! I will agree that writing robust build scripts is kinda hard but it's unfortunately just a hard problem!
A year later this still looks like it's the current state of affairs. There's a room for improvement.
I'm inadvertently screwing Windows users by relying on pkg-config. It seems pkg-config doesn't have any fallback at all for msvc targets, and I don't know how to provide one. It'd be nice if pkg-config (or another crate like it) had a cross-platform fallback built-in.
Existing alternatives are ad-hoc. Some support env vars, some bundle the code. There's a lot of duplication, little unification. Sadly, some of it is inherent to the problem due to platforms' quirks, and messiness and fragility of include paths and linker flags.
There's no standard for sharing information between build scripts OK, there is, thanks @sfackler
If your crate depends on libz-sys, the include directory is provided to your crate's build script via the DEP_Z_INCLUDE environment variable: Page Moved