Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/Cargo.lock
/target
Cargo.lock
target
37 changes: 33 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
[package]
name = "system-deps"
[workspace]
members = ["meta"]
exclude = ["target"]

[workspace.package]
version = "7.0.5"
authors = [
"Guillaume Desmottes <[email protected]>",
Expand All @@ -18,17 +21,43 @@ keywords = [
edition = "2018"
rust-version = "1.78.0"
documentation = "https://docs.rs/system-deps/"

[workspace.dependencies]
system-deps-meta = { path = "./meta" }

[package]
name = "system-deps"
version.workspace = true
authors.workspace = true
license.workspace = true
description.workspace = true
keywords.workspace = true
edition.workspace = true
documentation.workspace = true
readme = "README.md"

[dependencies]
pkg-config = "0.3.25"
system-deps-meta = { workspace = true, optional = true }
pkg-config = "0.3"
toml = { version = "0.8", default-features = false, features = ["parse"] }
version-compare = "0.2"
heck = "0.5"
# allow cfg-expr between 0.17 and 0.20 to keep MSRV lower
cfg-expr = { version = ">= 0.17, < 0.21", features = ["targets"] }

[build-dependencies]
system-deps-meta = { workspace = true, optional = true }

[dev-dependencies]
lazy_static = "1"
system-deps-meta = { workspace = true, features = ["test"] }
itertools = "0.14"
assert_matches = "1.5"
tiny_http = "0.12"

[features]
default = []
# FIXME: How can this be done when using resolver v2? Features are separated
binary = ["system-deps-meta/binary"]
gz = ["system-deps-meta/gz"]
xz = ["system-deps-meta/xz"]
zip = ["system-deps-meta/zip"]
35 changes: 35 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pub fn main() {
#[cfg(feature = "binary")]
binary::build().unwrap_or_else(|e| panic!("{}", e));
}

#[cfg(feature = "binary")]
mod binary {
use std::{fs, path::Path};

use system_deps_meta::{
binary::{merge, Paths},
error::{BinaryError, Error},
parse::read_metadata,
BUILD_MANIFEST, TARGET_DIR,
};

// Add pkg-config paths to the overrides
pub fn build() -> Result<(), Error> {
// Read metadata from the crate graph
let metadata = read_metadata(BUILD_MANIFEST, "system-deps", merge)?;

// Download the binaries and get their pkg_config paths
let paths: Paths = metadata.into_iter().collect();

// Write the binary paths to a file for later use
let dest = Path::new(TARGET_DIR).join("paths.toml");
fs::write(&dest, paths.to_string()?).map_err(BinaryError::InvalidDirectory)?;
println!(
"cargo:rustc-env=SYSTEM_DEPS_BINARY_PATHS={}",
dest.display()
);

Ok(())
}
}
28 changes: 28 additions & 0 deletions meta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "system-deps-meta"
version.workspace = true
authors.workspace = true
license.workspace = true
description.workspace = true
keywords.workspace = true
edition.workspace = true
documentation.workspace = true

[dependencies]
cargo_metadata = "0.20"
serde = "1.0"
toml = "0.8"
cfg-expr = { version = ">= 0.17, < 0.21", features = ["targets"] }
sha256 = { version = "1.6", optional = true }
attohttpc = { version = "0.29", optional = true }
flate2 = { version = "1.1", optional = true }
xz = { version = "0.1", optional = true }
tar = { version = "0.4", optional = true }
zip = { version = "2.4", optional = true }

[features]
binary = ["dep:sha256", "dep:attohttpc"]
gz = ["dep:flate2", "dep:tar"]
xz = ["dep:xz", "dep:tar"]
zip = ["dep:zip"]
test = []
81 changes: 81 additions & 0 deletions meta/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::{
env,
path::{Path, PathBuf},
};

/// Environment variable to override the top level `Cargo.toml`.
const MANIFEST_VAR: &str = "SYSTEM_DEPS_BUILD_MANIFEST";

/// Environment variable to override the directory where `system-deps`
/// will store build products such as binary outputs.
const TARGET_VAR: &str = "SYSTEM_DEPS_TARGET_DIR";

/// Try to find the project root using locate-project
fn find_with_cargo(dir: &Path) -> Option<PathBuf> {
let out = std::process::Command::new(env!("CARGO"))
.current_dir(dir)
.arg("locate-project")
.arg("--workspace")
.arg("--message-format=plain")
.output()
.ok()?
.stdout;
if out.is_empty() {
return None;
}
Some(PathBuf::from(std::str::from_utf8(&out).ok()?.trim()))
}

/// 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 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
/// to specify the `SYSTEM_DEPS_MANIFEST` variable to point to it.
///
/// See https://github.com/rust-lang/cargo/issues/3946 for updates on first
/// class support for finding the workspace root.
fn manifest() -> PathBuf {
println!("cargo:rerun-if-env-changed={}", MANIFEST_VAR);
if let Ok(root) = env::var(MANIFEST_VAR) {
return PathBuf::from(&root);
}

// When build scripts are invoked, they have one argument pointing to the
// build path of the crate in the target directory. This is different than
// the `OUT_DIR` environment variable, that can point to a target directory
// where the checkout of the dependency is.
let mut dir = PathBuf::from(
std::env::args()
.next()
.expect("There should be cargo arguments for determining the root"),
);
dir.pop();

// Try to find the project with cargo
find_with_cargo(&dir).expect(
"Error determining the cargo root manifest.\n\
Please set `SYSTEM_DEPS_MANIFEST` to the path of your project's Cargo.toml",
)
}

/// Set compile time values for the manifest and target paths, and the compile target.
/// This step needs to happen in a build script so that the paths are only calculated
/// once and every invocation of `system-deps` references the same metadata.
pub fn main() {
let manifest = manifest();
println!("cargo:rerun-if-changed={}", manifest.display());
println!("cargo:rustc-env={}={}", MANIFEST_VAR, manifest.display());

// TODO: Use an user cache dir, similar to .cargo?
let target_dir = env::var(TARGET_VAR).or(env::var("OUT_DIR")).unwrap();
println!("cargo:rerun-if-env-changed={}", TARGET_VAR);
println!("cargo:rustc-env={}={}", TARGET_VAR, target_dir);

println!(
"cargo:rustc-env=TARGET={}",
std::env::var("TARGET").unwrap()
);
}
Loading
Loading