Skip to content

Commit

Permalink
Allow overriding system root via environment
Browse files Browse the repository at this point in the history
Use the PKG_CONFIG_SYSROOT_DIR (preferred) or SYSROOT (fallback)
environment variables to override the default path used to determine
whether a library is a system library or not (/usr).

This enables cross-compilation scenarios where the system root is not a
subdirectory of /usr. Specifically, when building Rust packages in the
Chomium OS SDK, each board's sysroot is located in /build/$BOARD rather
than a subdirectory of /usr. Additionally, cros_sdk only specifies
SYSROOT (PKG_CONFIG_SYSROOT_DIR is set by the pkg-config-$BOARD cross
compilation helpers, but that isn't available in pkg-config-rs).

This has only been tested on Linux, as I don't have a macOS machine
handy, but I believe the macOS path should work as before (it does not
consider the new sysroot variables).

Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
  • Loading branch information
danielverkamp authored and sdroege committed Sep 4, 2020
1 parent 070b4e9 commit 81468be
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ use std::ffi::{OsStr, OsString};
use std::fmt;
use std::io;
use std::ops::{Bound, RangeBounds};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::process::{Command, Output};
use std::str;

Expand Down Expand Up @@ -145,7 +145,7 @@ impl fmt::Display for Error {
Install a sysroot for the target platform and configure it via
PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a
cross-compiling wrapper for pkg-config and set it via
PKG_CONFIG environment variable."
PKG_CONFIG environment variable.",
),
Error::Command {
ref command,
Expand Down Expand Up @@ -499,6 +499,17 @@ impl Library {
}
}

let system_roots = if cfg!(target_os = "macos") {
vec![PathBuf::from("/Library"), PathBuf::from("/System")]
} else {
let sysroot = config
.env_var_os("PKG_CONFIG_SYSROOT_DIR")
.or_else(|| config.env_var_os("SYSROOT"))
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from("/usr"));
vec![sysroot]
};

let words = split_flags(output);
let parts = words
.iter()
Expand Down Expand Up @@ -530,7 +541,7 @@ impl Library {
continue;
}

if statik && is_static_available(val, &dirs) {
if statik && is_static_available(val, &system_roots, &dirs) {
let meta = format!("rustc-link-lib=static={}", val);
config.print_metadata(&meta);
} else {
Expand Down Expand Up @@ -583,13 +594,8 @@ fn envify(name: &str) -> String {
}

/// System libraries should only be linked dynamically
fn is_static_available(name: &str, dirs: &[PathBuf]) -> bool {
fn is_static_available(name: &str, system_roots: &[PathBuf], dirs: &[PathBuf]) -> bool {
let libname = format!("lib{}.a", name);
let system_roots = if cfg!(target_os = "macos") {
vec![Path::new("/Library"), Path::new("/System")]
} else {
vec![Path::new("/usr")]
};

dirs.iter().any(|dir| {
!system_roots.iter().any(|sys| dir.starts_with(sys)) && dir.join(&libname).exists()
Expand Down Expand Up @@ -654,18 +660,23 @@ fn split_flags(output: &[u8]) -> Vec<String> {
#[test]
#[cfg(target_os = "macos")]
fn system_library_mac_test() {
let system_roots = vec![PathBuf::from("/Library"), PathBuf::from("/System")];

assert!(!is_static_available(
"PluginManager",
system_roots,
&[PathBuf::from("/Library/Frameworks")]
));
assert!(!is_static_available(
"python2.7",
system_roots,
&[PathBuf::from(
"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config"
)]
));
assert!(!is_static_available(
"ffi_convenience",
system_roots,
&[PathBuf::from(
"/Library/Ruby/Gems/2.0.0/gems/ffi-1.9.10/ext/ffi_c/libffi-x86_64/.libs"
)]
Expand All @@ -675,6 +686,7 @@ fn system_library_mac_test() {
if Path::new("/usr/local/lib/libpng16.a").exists() {
assert!(is_static_available(
"png16",
system_roots,
&[PathBuf::from("/usr/local/lib")]
));

Expand All @@ -691,7 +703,12 @@ fn system_library_mac_test() {
fn system_library_linux_test() {
assert!(!is_static_available(
"util",
&[PathBuf::from("/usr")],
&[PathBuf::from("/usr/lib/x86_64-linux-gnu")]
));
assert!(!is_static_available("dialog", &[PathBuf::from("/usr/lib")]));
assert!(!is_static_available(
"dialog",
&[PathBuf::from("/usr")],
&[PathBuf::from("/usr/lib")]
));
}

0 comments on commit 81468be

Please sign in to comment.