Skip to content

Commit

Permalink
temp: testing changes
Browse files Browse the repository at this point in the history
  • Loading branch information
eerii committed Dec 2, 2024
1 parent de059c9 commit ab21f07
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 83 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ version-compare = "0.2"
heck = "0.5"
cfg-expr = { version = "0.17", features = ["targets"] }
system-deps-binary = { path = "./binary", optional = true }
cc = { version = "1.2", optional = true }

[dev-dependencies]
lazy_static = "1"
itertools = "0.13"
assert_matches = "1.5"

[features]
binary = [ "dep:system-deps-binary" ]
default = [ "binary" ]
binary = [ "dep:system-deps-binary", "dep:cc" ]
gx = [ "system-deps-binary/gz" ]
xz = [ "system-deps-binary/xz" ]
zip = [ "system-deps-binary/zip" ]
1 change: 0 additions & 1 deletion binary/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
name = "system-deps-binary"
version = "0.1.0"
edition = "2021"
links = "system-deps-binary"

[build-dependencies]
system-deps-meta = { path = "../meta" }
Expand Down
2 changes: 1 addition & 1 deletion binary/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn paths() -> HashMap<String, Vec<PathBuf>> {
let mut follow_list = HashMap::new();

// Global overrides from environment
// TODO: This need to come first
// TODO: Change this so the env set global url always is first in the list of paths
if let Some(url) = env("SYSTEM_DEPS_BINARY_URL") {
let checksum = env("SYSTEM_DEPS_BINARY_CHECKSUM");
let pkg_paths = env("SYSTEM_DEPS_BINARY_PKG_PATHS");
Expand Down
2 changes: 1 addition & 1 deletion meta/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn find_by_path(mut dir: PathBuf) -> Option<PathBuf> {
/// Get the manifest from the project directory. This is **not** the directory
/// where `system-deps` is cloned, it should point to the top level `Cargo.toml`
/// file. This is needed to obtain metadata from all of dependencies, including
/// those upstream of the package being compiled.
/// those downstream of the package being compiled.
///
/// If the target directory is not a subfolder of the project it will not be
/// possible to detect it automatically. In this case, the user will be asked
Expand Down
6 changes: 5 additions & 1 deletion meta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ fn check_cfg(lit: &str) -> Option<bool> {

/// Inserts values from b into a only if they don't already exist.
/// TODO: This function could be a lot cleaner and it needs better error handling.
/// The logic for merging values needs to handle more cases so during testing this will have to be rewritten.
/// Additionally, make sure that only downstream crates can override the metadata.
fn merge(a: &mut Value, b: Value) {
match (a, b) {
(a @ &mut Value::Object(_), Value::Object(b)) => {
Expand All @@ -66,7 +68,7 @@ fn merge(a: &mut Value, b: Value) {
}

/// Recursively read dependency manifests to find metadata matching a key.
/// The matching metadata is aggregated in a list, with upstream crates having priority
/// The matching metadata is aggregated in a list, with downstream crates having priority
/// for overwriting values. It will only read from the metadata sections matching the
/// provided key.
///
Expand Down Expand Up @@ -99,6 +101,8 @@ pub fn read_metadata(key: &str) -> Values {
// Iterate through the dependency tree to visit all packages
let mut visited: HashSet<&str> = packages.iter().map(|p| p.name.as_str()).collect();
while let Some(pkg) = packages.pop_front() {
// TODO: Optional packages

for dep in &pkg.dependencies {
match dep.kind {
DependencyKind::Normal | DependencyKind::Build => {}
Expand Down
165 changes: 87 additions & 78 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,28 +203,6 @@
//! Libraries can be statically linked by defining the environment variable `SYSTEM_DEPS_$NAME_LINK=static`.
//! You can also use `SYSTEM_DEPS_LINK=static` to statically link all the libraries.
//!
//! # Programmatically add libraries
//!
//! Imagine that you have a base library that is already using system deps, and you have a set of optional plugins that you
//! want to link into the resulting binary. While it would be possible to add them all as metadata entries in the crate's Cargo.toml,
//! it doesn't scale very well and it doesn't allow to include user defined libraries.
//!
//! As an alternative, it is possible to use `Config::add_pkg_config_libraries` to specify a list of extra libraries to query from `pkg-config`.
//! This is called in the build script where the library is being built, which allows to query the environment, read the metadata and
//! configuration, and much more to decide what libraries to add.
//!
//! ```should_panic
//! fn main() {
//! let mut config = system_deps::Config::new();
//! if let Ok(list) = std::env::var("PLUGIN_LIST") {
//! config = config.add_pkg_config_libraries(list.split(","));
//! }
//! config
//! .probe()
//! .unwrap();
//! }
//! ```
//!
//! The libraries specified with this option can have any form readable by `pkg-config`, and they will inherit the main libraries'
//! binary paths if you are using them. If `pkg-config` can't find some entry, it will print a warning but the compilation won't fail.
//!
Expand Down Expand Up @@ -748,7 +726,6 @@ type FnBuildInternal =
pub struct Config {
env: EnvVariables,
build_internals: HashMap<String, Box<FnBuildInternal>>,
external_pkg_config_libs: Vec<String>,
}

impl Default for Config {
Expand All @@ -767,30 +744,9 @@ impl Config {
Self {
env,
build_internals: HashMap::new(),
external_pkg_config_libs: Vec::new(),
}
}

/// Search and link more libraries than the ones specified in the Cargo.toml.
///
/// Any library name that pkg-config accepts is valid, for example "name" or "name >= 1.0".
/// These are considered optional and will not stop the build, they will emit a warning if
/// they can't be found.
///
/// When using the `binary` feature, they will use the same `PKG_CONFIG_PATH` overrides from
/// the downloaded binaries as the parent libraries.
///
/// # Arguments
/// * `libs`: a list of libraries to link.
pub fn add_pkg_config_libraries<T: AsRef<str>>(
mut self,
libs: impl Iterator<Item = T>,
) -> Self {
self.external_pkg_config_libs
.extend(libs.map(|s| s.as_ref().into()));
self
}

/// Probe all libraries configured in the Cargo.toml
/// `[package.metadata.system-deps]` section.
///
Expand Down Expand Up @@ -836,6 +792,54 @@ impl Config {
let mut libraries = self.probe_pkg_config()?;
libraries.override_from_flags(&self.env);

// TODO: Generate shared library
// This doesn't work, multiple symbols
//#[cfg(feature = "binary")]
//if libraries.libs.contains_key("gstreamer_1_0") {
// let out_dir = env::var("OUT_DIR").unwrap();
// let mut library = Library::from_env_variables("gstreamer-full");
//
// let mut cc = cc::Build::new();
//
// cc.shared_flag(true).flag("-Wl,--whole-archive");
//
// for (_, lib) in libraries.libs.drain() {
// lib.link_paths.iter().for_each(|l| {
// cc.flag(format!("-L{}", l.to_string_lossy()));
// });
// lib.libs.iter().for_each(|l| {
// if lib.statik && l.is_static_available {
// cc.flag("-Wl,-Bstatic");
// } else {
// cc.flag("-Wl,-Bdynamic");
// }
// cc.flag(format!("-l{}", l.name));
// });
// lib.ld_args.iter().for_each(|f| {
// cc.flag(f.join(" "));
// });
//
// library.include_paths.extend(lib.include_paths);
// }
//
// let lib_path = format!("{}/libgstreamer-full.so", out_dir);
// library.libs = vec![InternalLib::new("gstreamer-full".into(), true)];
// library.link_paths = vec![PathBuf::from(out_dir)];
//
// let mut cmd = cc
// .flag("-Wl,--no-whole-archive")
// .flag("-Wl,-Bdynamic")
// .flag("-o")
// .flag(lib_path)
// .get_compiler()
// .to_command();
//
// println!("cargo:warning={:?}", cmd);
// cmd.status().unwrap();
//
// libraries.libs.insert("gstreamer-full".into(), library);
//}

Ok(libraries)
}

Expand All @@ -851,7 +855,6 @@ impl Config {

let metadata = MetaData::from_file(&path)?;
let mut libraries = Dependencies::default();
let mut combined_pkg_config_path = vec![];

for dep in metadata.deps.iter() {
if let Some(cfg) = &dep.cfg {
Expand Down Expand Up @@ -931,12 +934,12 @@ impl Config {
system_deps_binary::get_path(""),
]
.concat();
combined_pkg_config_path.extend_from_slice(&pkg_config_path);

// should the lib be statically linked?
let statik = self
.env
.has_value(&EnvVariable::new_link(Some(name)), "static")
let statik = cfg!(feature = "binary")
|| self
.env
.has_value(&EnvVariable::new_link(Some(name)), "static")
|| self.env.has_value(&EnvVariable::new_link(None), "static");

let mut library = if self.env.contains(&EnvVariable::new_no_pkg_config(name)) {
Expand Down Expand Up @@ -977,29 +980,29 @@ impl Config {
}

// Process libraries added to pkg-config using `Self::add_pkg_config_libraries`
for entry in &self.external_pkg_config_libs {
let mut config = pkg_config::Config::new();
config
.print_system_libs(false)
.cargo_metadata(false)
.statik(true);

let mut it = entry.trim().splitn(2, " ");
let name = it.next().unwrap();
if let Some(version) = it.next() {
config.range_version(metadata::parse_version(version));
}

match Library::wrap_pkg_config_dir(&combined_pkg_config_path, || config.probe(name)) {
Ok(lib) => {
let mut lib = Library::from_pkg_config(name, lib);
// TODO: Change to StaticLinking::Always
lib.statik = true;
libraries.add(name, lib)
}
Err(_) => println!("cargo:warning=Extra library `{}` is not available", entry),
};
}
//for entry in &self.external_pkg_config_libs {
// let mut config = pkg_config::Config::new();
// config
// .print_system_libs(false)
// .cargo_metadata(false)
// .statik(true);
//
// let mut it = entry.trim().splitn(2, " ");
// let name = it.next().unwrap();
// if let Some(version) = it.next() {
// config.range_version(metadata::parse_version(version));
// }
//
// match Library::wrap_pkg_config_dir(&combined_pkg_config_path, || config.probe(name)) {
// Ok(lib) => {
// let mut lib = Library::from_pkg_config(name, lib);
// // TODO: Change to StaticLinking::Always
// lib.statik = true;
// libraries.add(name, lib)
// }
// Err(_) => println!("cargo:warning=Extra library `{}` is not available", entry),
// };
//}

Ok(libraries)
}
Expand Down Expand Up @@ -1255,31 +1258,37 @@ impl Library {
}
}

fn wrap_pkg_config_dir<P, F, R>(pkg_config_dir: &[P], f: F) -> Result<R, pkg_config::Error>
/// Calls a function changing the environment so that `pkg-config` will try to
/// look first in the provided path.
pub fn wrap_pkg_config_dir<P, F, R>(pkg_config_dir: &[P], f: F) -> Result<R, pkg_config::Error>
where
P: AsRef<std::ffi::OsStr>,
F: FnOnce() -> Result<R, pkg_config::Error>,
{
// Save current PKG_CONFIG_PATH, so we can restore it
let old = env::var("PKG_CONFIG_PATH");
let old_paths = old
let prev = env::var("PKG_CONFIG_PATH").ok();
let prev_paths = prev
.as_ref()
.map(env::split_paths)
.unwrap()
.into_iter()
.flatten()
.collect::<Vec<_>>();

let paths = env::join_paths(
pkg_config_dir
.iter()
.map(|p| p.as_ref())
.chain(old_paths.iter().map(|p| p.as_os_str())),
.chain(prev_paths.iter().map(|p| p.as_os_str())),
)
.unwrap();

env::set_var("PKG_CONFIG_PATH", paths);

let res = f();

env::set_var("PKG_CONFIG_PATH", old.unwrap_or_else(|_| "".into()));
if let Some(prev) = prev {
env::set_var("PKG_CONFIG_PATH", prev);
}

res
}
Expand Down

0 comments on commit ab21f07

Please sign in to comment.