9a544c60b0
Remove the old LBI bootstrap/system-state path and make Depot stage and install packages against standard FHS paths instead of rewriting payloads into the custom /system layout. This drops the bootstrap command surface, system-state storage, /system path normalization, and bootstrap chroot helper while moving rootfs state defaults back under /var and aliases under /usr/bin. Preserve hardlink topology throughout the package lifecycle. Add shared fs_copy helpers for symlink/hardlink-aware tree copies, use them for source preparation, binary packages, Rust installs, and lib32 staging, and keep hardlinks intact during stripping, atomic installation, and package archive creation. Replace the external fakeroot wrapper with an internal user-namespace based install command wrapper. Install phases now run as UID/GID 0 inside a private namespace while mapping ownership back to the invoking user on the host. Split the package spec parser into loading, model, config, and tests modules without changing the public PackageSpec surface. Keep strict unknown-key handling, manual source validation, config/appends support, lib32 overrides, and generated output helpers in the new layout. Tighten build and dependency behavior: - emit explicit shared-library selectors when static builds are disabled - apply configure_arch entries for the effective target/lib32 architecture - add CMake sysroot defaults for non-live DEPOT_ROOTFS builds - resolve Rust source_subdir before build hooks and binary installation - satisfy dependencies and local sibling plans through package real_name aliases - accept bare git:// source URLs as HEAD checkouts Update tests around FHS path expectations, namespace fakeroot installs, hardlink-preserving copies/archives/installs/stripping, real_name dependency resolution, configure_arch expansion, CMake sysroot defaults, Rust source subdirs, and git:// URL parsing. Bump suppaftp to 8.0.4 and lzma-rust2 to 0.16.4. Bump Depot to 0.50.0
2384 lines
53 KiB
Rust
2384 lines
53 KiB
Rust
use super::*;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
#[test]
|
|
fn parse_single_source_table() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo-$version.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo-$version"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.package.name, "foo");
|
|
assert_eq!(spec.sources().len(), 1);
|
|
assert_eq!(
|
|
spec.expand_vars(&spec.sources()[0].url),
|
|
"https://example.com/foo-1.0.tar.gz"
|
|
);
|
|
assert!(spec.sources()[0].patches.is_empty());
|
|
assert!(spec.sources()[0].post_extract.is_empty());
|
|
assert!(spec.sources()[0].cherry_pick.is_empty());
|
|
assert_eq!(spec.spec_dir, tmp.path());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_source_array() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[source]]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[[source]]
|
|
url = "https://example.com/bar.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "bar"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.sources().len(), 2);
|
|
assert_eq!(spec.sources()[0].extract_dir, "foo");
|
|
assert_eq!(spec.sources()[1].extract_dir, "bar");
|
|
}
|
|
|
|
#[test]
|
|
fn parse_source_without_sha256_defaults_to_skip() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.sources()[0].sha256, "skip");
|
|
}
|
|
|
|
#[test]
|
|
fn parse_git_source_with_cherry_pick() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.git#main"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
cherry_pick = ["deadbeef", "cafebabe"]
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.sources()[0].cherry_pick,
|
|
vec!["deadbeef".to_string(), "cafebabe".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_package_dependencies_overrides() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "llvm"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/llvm.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "llvm"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[dependencies]
|
|
runtime = ["base"]
|
|
groups = ["toolchain"]
|
|
|
|
[package_dependencies.clang]
|
|
runtime = ["llvm-libs", "llvm-libgcc"]
|
|
groups = ["compiler"]
|
|
|
|
[package_dependencies.llvm-libs]
|
|
runtime = ["llvm-libgcc", "zstd"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm").runtime,
|
|
vec!["base".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm").groups,
|
|
vec!["toolchain".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("clang").runtime,
|
|
vec!["llvm-libs".to_string(), "llvm-libgcc".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("clang").groups,
|
|
vec!["compiler".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm-libs").runtime,
|
|
vec!["llvm-libgcc".to_string(), "zstd".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm-libs").groups,
|
|
Vec::<String>::new()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_lib32_dependencies_override() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "llvm"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/llvm.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "llvm"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[dependencies]
|
|
runtime = ["base"]
|
|
groups = ["toolchain"]
|
|
|
|
[dependencies.lib32]
|
|
build = ["gcc-multilib"]
|
|
runtime = ["lib32-zlib"]
|
|
test = ["bats"]
|
|
groups = ["lib32-toolchain"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm").runtime,
|
|
vec!["base".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("llvm").groups,
|
|
vec!["toolchain".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("lib32-llvm").build,
|
|
vec!["gcc-multilib".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("lib32-llvm").runtime,
|
|
vec!["lib32-zlib".to_string(), "llvm".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("lib32-llvm").test,
|
|
vec!["bats".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.dependencies_for_output("lib32-llvm").groups,
|
|
vec!["lib32-toolchain".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_package_alternatives_overrides() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "llvm"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/llvm.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "llvm"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[alternatives]
|
|
provides = ["toolchain"]
|
|
conflicts = ["gcc"]
|
|
|
|
[package_alternatives.clang]
|
|
provides = ["cc", "c++", "gcc"]
|
|
conflicts = ["clang-legacy"]
|
|
|
|
[package_alternatives.llvm]
|
|
provides = ["binutils"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.alternatives_for_output("llvm").provides,
|
|
vec!["binutils".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("llvm").conflicts,
|
|
Vec::<String>::new()
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("clang").provides,
|
|
vec!["cc".to_string(), "c++".to_string(), "gcc".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("clang").conflicts,
|
|
vec!["clang-legacy".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("other").provides,
|
|
vec!["toolchain".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("other").conflicts,
|
|
vec!["gcc".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_lib32_alternatives_override() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "llvm"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/llvm.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "llvm"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[alternatives]
|
|
provides = ["toolchain"]
|
|
replaces = ["clang"]
|
|
|
|
[alternatives.lib32]
|
|
provides = ["lib32-toolchain"]
|
|
conflicts = ["lib32-gcc"]
|
|
replaces = ["lib32-clang"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.alternatives_for_output("llvm").replaces,
|
|
vec!["clang".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("lib32-llvm").provides,
|
|
vec!["lib32-toolchain".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("lib32-llvm").conflicts,
|
|
vec!["lib32-gcc".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.alternatives_for_output("lib32-llvm").replaces,
|
|
vec!["lib32-clang".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn lib32_output_does_not_fallback_to_primary_alternatives() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "llvm"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
build_32 = true
|
|
|
|
[alternatives]
|
|
provides = ["toolchain"]
|
|
conflicts = ["gcc"]
|
|
replaces = ["clang"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
let lib32 = spec.alternatives_for_output("lib32-llvm");
|
|
|
|
assert!(lib32.provides.is_empty());
|
|
assert!(lib32.conflicts.is_empty());
|
|
assert!(lib32.replaces.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_python_build_type() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "python"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(matches!(spec.build.build_type, BuildType::Python));
|
|
}
|
|
|
|
#[test]
|
|
fn parse_perl_build_type() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "perl"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(matches!(spec.build.build_type, BuildType::Perl));
|
|
}
|
|
|
|
#[test]
|
|
fn parse_python_config_settings_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "python"
|
|
|
|
[build.flags]
|
|
config-setting = ["editable_mode=compat", "setup-args=--plat-name=x86_64"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.config_settings,
|
|
vec![
|
|
"editable_mode=compat".to_string(),
|
|
"setup-args=--plat-name=x86_64".to_string()
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_multiple_licenses() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = ["MIT", "Apache-2.0"]
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.package.license,
|
|
vec!["MIT".to_string(), "Apache-2.0".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_rejects_empty_sources() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
// `source = []` is not accepted (must have at least one entry)
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
source = []
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
assert!(PackageSpec::from_file(&path).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_allows_metapackage_without_sources() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo-meta"
|
|
version = "1.0"
|
|
description = "metapackage"
|
|
homepage = "https://example.com"
|
|
license = "MIT"
|
|
|
|
[build]
|
|
type = "meta"
|
|
|
|
[dependencies]
|
|
runtime = ["foo", "bar"]
|
|
groups = ["base"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.source.is_empty());
|
|
assert!(spec.manual_sources.is_empty());
|
|
assert!(spec.is_metapackage());
|
|
assert_eq!(spec.dependencies.runtime, vec!["foo", "bar"]);
|
|
assert_eq!(spec.dependencies.groups, vec!["base"]);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_manual_source_with_url() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[manual_sources]]
|
|
url = "https://example.com/manual.patch"
|
|
sha256 = "skip"
|
|
dest = "patches/manual.patch"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.manual_sources.len(), 1);
|
|
assert_eq!(
|
|
spec.manual_sources[0].url.as_deref(),
|
|
Some("https://example.com/manual.patch")
|
|
);
|
|
assert_eq!(spec.manual_sources[0].file, None);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_manual_source_rejects_missing_file_and_url() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[manual_sources]]
|
|
sha256 = "skip"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let err = PackageSpec::from_file(&path).expect_err("spec should be rejected");
|
|
assert!(
|
|
err.to_string()
|
|
.contains("must specify one of 'file', 'files', 'url', or 'urls'")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_manual_source_rejects_file_and_url_together() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[manual_sources]]
|
|
file = "manual.patch"
|
|
url = "https://example.com/manual.patch"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let err = PackageSpec::from_file(&path).expect_err("spec should be rejected");
|
|
assert!(
|
|
err.to_string()
|
|
.contains("cannot mix local ('file'/'files') and remote ('url'/'urls') entries")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_manual_source_with_files_array() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[manual_sources]]
|
|
files = ["other", "system-auth"]
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.manual_sources.len(), 1);
|
|
assert_eq!(spec.manual_sources[0].files, vec!["other", "system-auth"]);
|
|
assert!(spec.manual_sources[0].urls.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_apply_config() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
let mut config = crate::config::Config::for_rootfs(Path::new("/tmp/nonexistent"));
|
|
|
|
// Mock some overrides and appends
|
|
config.build_overrides = toml::from_str(
|
|
r#"
|
|
[flags]
|
|
cc = "my-cc"
|
|
cxx = "my-cxx"
|
|
ar = "my-ar"
|
|
ranlib = "my-ranlib"
|
|
strip = "my-strip"
|
|
ld = "ld.lld"
|
|
nm = "my-nm"
|
|
objcopy = "my-objcopy"
|
|
objdump = "my-objdump"
|
|
readelf = "my-readelf"
|
|
CPP = "clang-cpp"
|
|
tool_dir = "/opt/toolchain/bin"
|
|
cflags = ["-O2"]
|
|
replace_cflags = ["-O2=>-O3"]
|
|
cxxflags = ["-O2", "-pipe"]
|
|
replace_cxxflags = ["-pipe=>-fPIC"]
|
|
passthrough_env = ["RUSTFLAGS"]
|
|
env_vars = ["SETUPTOOLS_SCM_PRETEND_VERSION=$version"]
|
|
bindir = "/opt/bin"
|
|
sbindir = "/opt/sbin"
|
|
libdir = "/opt/lib64"
|
|
sysconfdir = "/opt/etc"
|
|
datarootdir = "/opt/share-root"
|
|
makeflags = "-j8"
|
|
make_vars = ["V=1"]
|
|
make_dirs = ["lib"]
|
|
make_test_dirs = ["tests"]
|
|
make_install_dirs = ["lib"]
|
|
ltoflags = ["-flto=auto"]
|
|
RUSTLTOFLAGS = ["-Clinker-plugin-lto"]
|
|
replace_ltoflags = ["auto=>thin"]
|
|
rustflags = ["-C", "debuginfo=2"]
|
|
replace_rustflags = ["debuginfo=2=>opt-level=2"]
|
|
use_lto = true
|
|
no_flags = true
|
|
no_strip = true
|
|
no_delete_static = true
|
|
no_compress_man = true
|
|
skip_tests = true
|
|
keep = ["etc/locale.gen"]
|
|
configure_file = "configure.gnu"
|
|
config-setting = ["editable_mode=compat"]
|
|
post_configure = ["echo configured"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
config.appends.insert(
|
|
"build.flags.cflags".to_string(),
|
|
vec![toml::Value::String("-g".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.replace_cflags".to_string(),
|
|
vec![toml::Value::String(
|
|
"-D_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string(),
|
|
)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.cxxflags".to_string(),
|
|
vec![toml::Value::String("-stdlib=libc++".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.replace_cxxflags".to_string(),
|
|
vec![toml::Value::String(
|
|
"-stdlib=libc++=>-stdlib=libstdc++".to_string(),
|
|
)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.rustflags".to_string(),
|
|
vec![toml::Value::Array(vec![
|
|
toml::Value::String("-C".to_string()),
|
|
toml::Value::String("opt-level=3".to_string()),
|
|
])],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.replace_rustflags".to_string(),
|
|
vec![toml::Value::String("opt-level=3=>opt-level=z".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.keep".to_string(),
|
|
vec![toml::Value::Array(vec![toml::Value::String(
|
|
"etc/locale.gen".to_string(),
|
|
)])],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.ltoflags".to_string(),
|
|
vec![toml::Value::Array(vec![toml::Value::String(
|
|
"-fno-fat-lto-objects".to_string(),
|
|
)])],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.replace_ltoflags".to_string(),
|
|
vec![toml::Value::String(
|
|
"-fno-fat-lto-objects=>-flto-jobs=8".to_string(),
|
|
)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.use_lto".to_string(),
|
|
vec![toml::Value::Boolean(false)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.no_strip".to_string(),
|
|
vec![toml::Value::Boolean(false)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.no_compress_man".to_string(),
|
|
vec![toml::Value::Boolean(false)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.no_delete_static".to_string(),
|
|
vec![toml::Value::Boolean(false)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.passthrough_env".to_string(),
|
|
vec![toml::Value::String("CARGO_HOME".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.env_vars".to_string(),
|
|
vec![toml::Value::String(
|
|
"SOURCE_DATE_EPOCH=1700000000".to_string(),
|
|
)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.make_test_vars".to_string(),
|
|
vec![toml::Value::String("TESTS=smoke".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.makeflags".to_string(),
|
|
vec![toml::Value::String("--output-sync=target".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.make_dirs".to_string(),
|
|
vec![toml::Value::String("libelf".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.make_test_dirs".to_string(),
|
|
vec![toml::Value::String("fuzz".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.make_install_dirs".to_string(),
|
|
vec![toml::Value::String("tools".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.make_install_vars".to_string(),
|
|
vec![toml::Value::String("DESTDIR=/tmp/pkg".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.configure_file".to_string(),
|
|
vec![toml::Value::String("build-aux/configure".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.libexecdir".to_string(),
|
|
vec![toml::Value::String("/opt/libexec".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.datadir".to_string(),
|
|
vec![toml::Value::String("/opt/share-data".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.config-setting".to_string(),
|
|
vec![toml::Value::String(
|
|
"setup-args=--plat-name=x86_64".to_string(),
|
|
)],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.post_configure".to_string(),
|
|
vec![toml::Value::String("touch configured.stamp".to_string())],
|
|
);
|
|
config.appends.insert(
|
|
"build.flags.configure_x86_64".to_string(),
|
|
vec![toml::Value::String("--enable-x86-tuning".to_string())],
|
|
);
|
|
|
|
spec.apply_config(&config);
|
|
|
|
assert_eq!(spec.build.flags.cc, "my-cc");
|
|
assert_eq!(spec.build.flags.cxx, "my-cxx");
|
|
assert_eq!(spec.build.flags.ar, "my-ar");
|
|
assert_eq!(spec.build.flags.ranlib, "my-ranlib");
|
|
assert_eq!(spec.build.flags.strip, "my-strip");
|
|
assert_eq!(spec.build.flags.ld, "ld.lld");
|
|
assert_eq!(spec.build.flags.nm, "my-nm");
|
|
assert_eq!(spec.build.flags.objcopy, "my-objcopy");
|
|
assert_eq!(spec.build.flags.objdump, "my-objdump");
|
|
assert_eq!(spec.build.flags.readelf, "my-readelf");
|
|
assert_eq!(spec.build.flags.cpp, "clang-cpp");
|
|
assert_eq!(spec.build.flags.tool_dir, "/opt/toolchain/bin");
|
|
assert!(spec.build.flags.cflags.contains(&"-O2".to_string()));
|
|
assert!(spec.build.flags.cflags.contains(&"-g".to_string()));
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_cflags
|
|
.contains(&"-O2=>-O3".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_cflags
|
|
.contains(&"-D_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string())
|
|
);
|
|
assert!(spec.build.flags.cxxflags.contains(&"-O2".to_string()));
|
|
assert!(spec.build.flags.cxxflags.contains(&"-pipe".to_string()));
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.cxxflags
|
|
.contains(&"-stdlib=libc++".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_cxxflags
|
|
.contains(&"-pipe=>-fPIC".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_cxxflags
|
|
.contains(&"-stdlib=libc++=>-stdlib=libstdc++".to_string())
|
|
);
|
|
assert!(spec.build.flags.rustflags.contains(&"-C".to_string()));
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.rustflags
|
|
.contains(&"debuginfo=2".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.rustflags
|
|
.contains(&"opt-level=3".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_rustflags
|
|
.contains(&"debuginfo=2=>opt-level=2".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_rustflags
|
|
.contains(&"opt-level=3=>opt-level=z".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.ltoflags
|
|
.contains(&"-flto=auto".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.rustltoflags
|
|
.contains(&"-Clinker-plugin-lto".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.ltoflags
|
|
.contains(&"-fno-fat-lto-objects".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_ltoflags
|
|
.contains(&"auto=>thin".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.replace_ltoflags
|
|
.contains(&"-fno-fat-lto-objects=>-flto-jobs=8".to_string())
|
|
);
|
|
assert!(!spec.build.flags.use_lto);
|
|
assert!(spec.build.flags.no_flags);
|
|
assert!(!spec.build.flags.no_strip);
|
|
assert!(!spec.build.flags.no_delete_static);
|
|
assert!(!spec.build.flags.no_compress_man);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.keep
|
|
.contains(&"etc/locale.gen".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.passthrough_env
|
|
.contains(&"RUSTFLAGS".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.passthrough_env
|
|
.contains(&"CARGO_HOME".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.env_vars
|
|
.contains(&"SETUPTOOLS_SCM_PRETEND_VERSION=$version".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.env_vars
|
|
.contains(&"SOURCE_DATE_EPOCH=1700000000".to_string())
|
|
);
|
|
assert_eq!(spec.build.flags.bindir, "/opt/bin");
|
|
assert_eq!(spec.build.flags.sbindir, "/opt/sbin");
|
|
assert_eq!(spec.build.flags.libdir, "/opt/lib64");
|
|
assert_eq!(spec.build.flags.libexecdir, "/opt/libexec");
|
|
assert_eq!(spec.build.flags.sysconfdir, "/opt/etc");
|
|
assert_eq!(spec.build.flags.datarootdir, "/opt/share-root");
|
|
assert_eq!(spec.build.flags.datadir, "/opt/share-data");
|
|
assert_eq!(
|
|
spec.build.flags.configure_arch.get("x86_64"),
|
|
Some(&vec!["--enable-x86-tuning".to_string()])
|
|
);
|
|
assert_eq!(spec.build.flags.makeflags, "-j8 --output-sync=target");
|
|
assert!(spec.build.flags.make_vars.contains(&"V=1".to_string()));
|
|
assert!(spec.build.flags.make_dirs.contains(&"lib".to_string()));
|
|
assert!(spec.build.flags.make_dirs.contains(&"libelf".to_string()));
|
|
assert!(spec.build.flags.skip_tests);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_test_vars
|
|
.contains(&"TESTS=smoke".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_test_dirs
|
|
.contains(&"tests".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_test_dirs
|
|
.contains(&"fuzz".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_install_vars
|
|
.contains(&"DESTDIR=/tmp/pkg".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_install_dirs
|
|
.contains(&"lib".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.make_install_dirs
|
|
.contains(&"tools".to_string())
|
|
);
|
|
assert_eq!(spec.build.flags.configure_file, "build-aux/configure");
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.config_settings
|
|
.contains(&"editable_mode=compat".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.config_settings
|
|
.contains(&"setup-args=--plat-name=x86_64".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.post_configure
|
|
.contains(&"echo configured".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.post_configure
|
|
.contains(&"touch configured.stamp".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_apply_config_preserves_package_scalar_tool_and_layout_overrides() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
spec.build.flags.ld = "ld.lld".to_string();
|
|
spec.build.flags.libdir = "/package/lib".to_string();
|
|
spec.build.flags.sysconfdir = "/package/etc".to_string();
|
|
let mut config = crate::config::Config::for_rootfs(Path::new("/tmp/nonexistent"));
|
|
config.build_overrides = toml::from_str(
|
|
r#"
|
|
ld = "/config/bin/ld"
|
|
fuse_ld = "/config/bin/ld.lld"
|
|
ranlib = "/config/bin/ranlib"
|
|
libdir = "/config/lib"
|
|
sysconfdir = "/config/etc"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
spec.apply_config(&config);
|
|
|
|
assert_eq!(spec.build.flags.ld, "ld.lld");
|
|
assert_eq!(spec.build.flags.libdir, "/package/lib");
|
|
assert_eq!(spec.build.flags.sysconfdir, "/package/etc");
|
|
assert_eq!(spec.build.flags.ranlib, "/config/bin/ranlib");
|
|
assert_eq!(spec.build.flags.fuse_ld, "/config/bin/ld.lld");
|
|
}
|
|
|
|
#[test]
|
|
fn test_apply_config_preserves_package_lto_disable() {
|
|
let mut spec = mk_spec("glibc", "2.43");
|
|
spec.build.flags.use_lto = false;
|
|
let mut config = crate::config::Config::for_rootfs(Path::new("/tmp/nonexistent"));
|
|
config.build_overrides = toml::from_str(
|
|
r#"
|
|
[flags]
|
|
ltoflags = ["-flto=thin"]
|
|
use_lto = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
spec.apply_config(&config);
|
|
|
|
assert!(!spec.build.flags.use_lto);
|
|
assert_eq!(spec.build.flags.ltoflags, vec!["-flto=thin".to_string()]);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_no_flags_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
no_flags = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.no_flags);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_tool_commands_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
cc = "/tools/bin/cc"
|
|
cxx = "/tools/bin/c++"
|
|
ar = "/tools/bin/ar"
|
|
ranlib = "/tools/bin/ranlib"
|
|
strip = "/tools/bin/strip"
|
|
ld = "/tools/bin/ld"
|
|
fuse_ld = "/usr/bin/ld.lld"
|
|
nm = "/tools/bin/nm"
|
|
objcopy = "/tools/bin/objcopy"
|
|
objdump = "/tools/bin/objdump"
|
|
readelf = "/tools/bin/readelf"
|
|
cpp = "/tools/bin/cpp"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.cc, "/tools/bin/cc");
|
|
assert_eq!(spec.build.flags.cxx, "/tools/bin/c++");
|
|
assert_eq!(spec.build.flags.ar, "/tools/bin/ar");
|
|
assert_eq!(spec.build.flags.ranlib, "/tools/bin/ranlib");
|
|
assert_eq!(spec.build.flags.strip, "/tools/bin/strip");
|
|
assert_eq!(spec.build.flags.ld, "/tools/bin/ld");
|
|
assert_eq!(spec.build.flags.fuse_ld, "/usr/bin/ld.lld");
|
|
assert_eq!(spec.build.flags.nm, "/tools/bin/nm");
|
|
assert_eq!(spec.build.flags.objcopy, "/tools/bin/objcopy");
|
|
assert_eq!(spec.build.flags.objdump, "/tools/bin/objdump");
|
|
assert_eq!(spec.build.flags.readelf, "/tools/bin/readelf");
|
|
assert_eq!(spec.build.flags.cpp, "/tools/bin/cpp");
|
|
}
|
|
|
|
#[test]
|
|
fn parse_ltoflags_and_use_lto_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
ltoflags = ["-flto=auto", "-fuse-linker-plugin"]
|
|
use_lto = false
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.ltoflags,
|
|
vec!["-flto=auto".to_string(), "-fuse-linker-plugin".to_string()]
|
|
);
|
|
assert!(!spec.build.flags.use_lto);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_ltoflags_and_use_lto_aliases_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
LTOFLAGS = "-flto=auto"
|
|
"use-lto" = false
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.ltoflags, vec!["-flto=auto".to_string()]);
|
|
assert!(!spec.build.flags.use_lto);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_no_strip_no_delete_static_and_no_compress_man_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
no_strip = true
|
|
"no-delete-static" = true
|
|
no-compress-man = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.no_strip);
|
|
assert!(spec.build.flags.no_delete_static);
|
|
assert!(spec.build.flags.no_compress_man);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_no_flags_alias_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
"no-flags" = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.no_flags);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_skip_tests_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
skip_tests = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.skip_tests);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_skip_tests_alias_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
"skip-tests" = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.skip_tests);
|
|
}
|
|
|
|
#[test]
|
|
fn reject_unknown_nested_keys_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[dependencies]
|
|
runtime = ["glibc"]
|
|
skip_tests = true
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let err = PackageSpec::from_file(&path).expect_err("expected unknown nested key to fail");
|
|
assert!(
|
|
err.to_string()
|
|
.contains("unknown key: dependencies.skip_tests")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_configure_file_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
configure_file = "build-aux/configure"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.configure_file, "build-aux/configure");
|
|
}
|
|
|
|
#[test]
|
|
fn parse_install_dirs_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "cmake"
|
|
|
|
[build.flags]
|
|
bindir = "/custom/bin"
|
|
sbindir = "/custom/sbin"
|
|
libdir = "/custom/lib64"
|
|
libexecdir = "/custom/libexec"
|
|
sysconfdir = "/custom/etc"
|
|
localstatedir = "/custom/var"
|
|
sharedstatedir = "/custom/var/lib"
|
|
includedir = "/custom/include"
|
|
datarootdir = "/custom/share-root"
|
|
datadir = "/custom/share"
|
|
mandir = "/custom/share/man"
|
|
infodir = "/custom/share/info"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.bindir, "/custom/bin");
|
|
assert_eq!(spec.build.flags.sbindir, "/custom/sbin");
|
|
assert_eq!(spec.build.flags.libdir, "/custom/lib64");
|
|
assert_eq!(spec.build.flags.libexecdir, "/custom/libexec");
|
|
assert_eq!(spec.build.flags.sysconfdir, "/custom/etc");
|
|
assert_eq!(spec.build.flags.localstatedir, "/custom/var");
|
|
assert_eq!(spec.build.flags.sharedstatedir, "/custom/var/lib");
|
|
assert_eq!(spec.build.flags.includedir, "/custom/include");
|
|
assert_eq!(spec.build.flags.datarootdir, "/custom/share-root");
|
|
assert_eq!(spec.build.flags.datadir, "/custom/share");
|
|
assert_eq!(spec.build.flags.mandir, "/custom/share/man");
|
|
assert_eq!(spec.build.flags.infodir, "/custom/share/info");
|
|
}
|
|
|
|
#[test]
|
|
fn parse_lib32_build_flags_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
"build-32" = "true"
|
|
"lib32-only" = "yes"
|
|
"CFLAGS-lib32" = ["-mstackrealign"]
|
|
"CXXFLAGS-lib32" = ["-fno-rtti"]
|
|
"configure-lib32" = ["--disable-static"]
|
|
"post_configure-lib32" = ["echo configured lib32"]
|
|
"post_compile-lib32" = ["echo compiled lib32"]
|
|
"post_install-lib32" = ["echo lib32"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.build_32);
|
|
assert!(spec.build.flags.lib32_only);
|
|
assert!(spec.builds_lib32_output());
|
|
assert!(spec.builds_only_lib32_output());
|
|
assert_eq!(spec.build.flags.cflags_lib32, vec!["-mstackrealign"]);
|
|
assert_eq!(spec.build.flags.cxxflags_lib32, vec!["-fno-rtti"]);
|
|
assert_eq!(spec.build.flags.configure_lib32, vec!["--disable-static"]);
|
|
assert_eq!(
|
|
spec.build.flags.post_configure_lib32,
|
|
vec!["echo configured lib32"]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.post_compile_lib32,
|
|
vec!["echo compiled lib32"]
|
|
);
|
|
assert_eq!(spec.build.flags.post_install_lib32, vec!["echo lib32"]);
|
|
}
|
|
|
|
#[test]
|
|
fn multilib_builds_skip_automatic_tests() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
assert!(!spec.should_skip_automatic_tests());
|
|
|
|
spec.build.flags.build_32 = true;
|
|
assert!(spec.should_skip_automatic_tests());
|
|
|
|
spec.build.flags.build_32 = false;
|
|
spec.build.flags.skip_tests = true;
|
|
assert!(spec.should_skip_automatic_tests());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_post_configure_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "cmake"
|
|
|
|
[build.flags]
|
|
post_configure = ["cmake -L . > cmake-options.txt"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.post_configure,
|
|
vec!["cmake -L . > cmake-options.txt".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_keep_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
keep = ["etc/locale.gen", "etc/resolv.conf"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.keep,
|
|
vec!["etc/locale.gen".to_string(), "etc/resolv.conf".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_split_docs_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
split_docs = true
|
|
doc_dirs = ["/opt/docs", "usr/share/devhelp"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert!(spec.build.flags.split_docs);
|
|
assert_eq!(
|
|
spec.build.flags.doc_dirs,
|
|
vec!["/opt/docs".to_string(), "usr/share/devhelp".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_build_flags_appends_from_spec_file() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
replace_cflags = ["-O2=>-O3"]
|
|
replace_rustflags = ["debuginfo=2=>opt-level=2"]
|
|
cxxflags = ["-O2"]
|
|
cxxflags += [ "-Wno-gnu-statement-expression-from-macro-expansion" ]
|
|
ldflags += "-Wl,--as-needed"
|
|
replace_cflags += [ "_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2" ]
|
|
replace_rustflags += "opt-level=3=>opt-level=z"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.cxxflags,
|
|
vec![
|
|
"-O2".to_string(),
|
|
"-Wno-gnu-statement-expression-from-macro-expansion".to_string()
|
|
]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.ldflags,
|
|
vec!["-Wl,--as-needed".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.replace_cflags,
|
|
vec![
|
|
"-O2=>-O3".to_string(),
|
|
"_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string()
|
|
]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.replace_rustflags,
|
|
vec![
|
|
"debuginfo=2=>opt-level=2".to_string(),
|
|
"opt-level=3=>opt-level=z".to_string()
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_configure_arch_appends_from_spec_file() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
configure = ["--base"]
|
|
configure_x86_64 += ["--enable-sse2"]
|
|
configure_aarch64 += "--enable-neon"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.configure, vec!["--base".to_string()]);
|
|
assert_eq!(
|
|
spec.build.flags.configure_arch.get("x86_64"),
|
|
Some(&vec!["--enable-sse2".to_string()])
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.configure_arch.get("aarch64"),
|
|
Some(&vec!["--enable-neon".to_string()])
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_build_flags_appends_accepts_quoted_and_uppercase_keys() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
"cflags" += ["-fPIC"]
|
|
CXXFLAGS += ["-stdlib=libc++"]
|
|
"LDFLAGS" += "-Wl,--as-needed"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.cflags, vec!["-fPIC".to_string()]);
|
|
assert_eq!(
|
|
spec.build.flags.cxxflags,
|
|
vec!["-stdlib=libc++".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.ldflags,
|
|
vec!["-Wl,--as-needed".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn apply_config_reads_build_flag_appends_from_rootfs_build_toml() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let config_path = tmp.path().join("etc/depot.d/build.toml");
|
|
std::fs::create_dir_all(config_path.parent().unwrap()).unwrap();
|
|
std::fs::write(
|
|
&config_path,
|
|
r#"
|
|
[flags]
|
|
cflags += ["-g"]
|
|
CXXFLAGS += ["-stdlib=libc++"]
|
|
LDFLAGS += "-Wl,--as-needed"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let config = crate::config::Config::for_rootfs(tmp.path());
|
|
assert_eq!(
|
|
config.appends.get("build.flags.cflags").unwrap()[0]
|
|
.as_array()
|
|
.unwrap()[0]
|
|
.as_str(),
|
|
Some("-g")
|
|
);
|
|
assert_eq!(
|
|
config.appends.get("build.flags.cxxflags").unwrap()[0]
|
|
.as_array()
|
|
.unwrap()[0]
|
|
.as_str(),
|
|
Some("-stdlib=libc++")
|
|
);
|
|
assert_eq!(
|
|
config.appends.get("build.flags.ldflags").unwrap()[0].as_str(),
|
|
Some("-Wl,--as-needed")
|
|
);
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
spec.apply_config(&config);
|
|
|
|
assert!(spec.build.flags.cflags.contains(&"-g".to_string()));
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.cxxflags
|
|
.contains(&"-stdlib=libc++".to_string())
|
|
);
|
|
assert!(
|
|
spec.build
|
|
.flags
|
|
.ldflags
|
|
.contains(&"-Wl,--as-needed".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_passthrough_env_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "custom"
|
|
|
|
[build.flags]
|
|
passthrough_env = ["RUSTFLAGS", "CARGO_HOME"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.passthrough_env,
|
|
vec!["RUSTFLAGS".to_string(), "CARGO_HOME".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_env_vars_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "python"
|
|
|
|
[build.flags]
|
|
env_vars = ["SETUPTOOLS_SCM_PRETEND_VERSION=$version", "PYO3_CONFIG_FILE=$specdir/pyo3.toml"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.env_vars,
|
|
vec![
|
|
"SETUPTOOLS_SCM_PRETEND_VERSION=$version".to_string(),
|
|
"PYO3_CONFIG_FILE=$specdir/pyo3.toml".to_string()
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_test_dependencies_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[dependencies]
|
|
build = ["make"]
|
|
test = ["python", "bats"]
|
|
optional = ["gtk-doc"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.dependencies.test,
|
|
vec!["python".to_string(), "bats".to_string()]
|
|
);
|
|
assert_eq!(spec.dependencies.optional, vec!["gtk-doc".to_string()]);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_make_var_overrides_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
make_vars = ["V=1", "CC=clang"]
|
|
make_exec = "ninja"
|
|
make_target = "bootstrap"
|
|
make_targets = ["stage1", "stage2"]
|
|
make_dirs = ["lib", "libelf"]
|
|
make_test_vars = ["TESTS=unit"]
|
|
make_test_target = "test"
|
|
make_test_targets = ["test-unit", "test-integration"]
|
|
make_test_dirs = ["tests"]
|
|
make_install_vars = ["STRIPPROG=true"]
|
|
make_install_target = "install/strip"
|
|
make_install_targets = ["install-runtime", "install-devel"]
|
|
make_install_dirs = ["lib", "apps"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(
|
|
spec.build.flags.make_vars,
|
|
vec!["V=1".to_string(), "CC=clang".to_string()]
|
|
);
|
|
assert_eq!(spec.build.flags.make_exec, "ninja");
|
|
assert_eq!(spec.build.flags.make_target, "bootstrap");
|
|
assert_eq!(
|
|
spec.build.flags.make_targets,
|
|
vec!["stage1".to_string(), "stage2".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.make_dirs,
|
|
vec!["lib".to_string(), "libelf".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.make_test_vars,
|
|
vec!["TESTS=unit".to_string()]
|
|
);
|
|
assert_eq!(spec.build.flags.make_test_target, "test".to_string());
|
|
assert_eq!(
|
|
spec.build.flags.make_test_targets,
|
|
vec!["test-unit".to_string(), "test-integration".to_string()]
|
|
);
|
|
assert_eq!(spec.build.flags.make_test_dirs, vec!["tests".to_string()]);
|
|
assert_eq!(
|
|
spec.build.flags.make_install_vars,
|
|
vec!["STRIPPROG=true".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.make_install_target,
|
|
"install/strip".to_string()
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.make_install_targets,
|
|
vec!["install-runtime".to_string(), "install-devel".to_string()]
|
|
);
|
|
assert_eq!(
|
|
spec.build.flags.make_install_dirs,
|
|
vec!["lib".to_string(), "apps".to_string()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_makeflags_from_spec() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[source]
|
|
url = "https://example.com/foo.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo"
|
|
|
|
[build]
|
|
type = "autotools"
|
|
|
|
[build.flags]
|
|
MAKEFLAGS = ["-j12", "--output-sync=target"]
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
assert_eq!(spec.build.flags.makeflags, "-j12 --output-sync=target");
|
|
}
|
|
|
|
#[test]
|
|
fn test_chost_cbuild_overrides() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
let config = crate::config::Config {
|
|
cache_dir: "/tmp".into(),
|
|
build_dir: "/tmp".into(),
|
|
db_dir: "/tmp".into(),
|
|
build_overrides: toml::from_str(
|
|
r#"
|
|
chost = "x86_64-sfg-linux-gnu"
|
|
cbuild = "x86_64-pc-linux-gnu"
|
|
"#,
|
|
)
|
|
.unwrap(),
|
|
package_overrides: toml::Value::Table(toml::map::Map::new()),
|
|
appends: std::collections::HashMap::new(),
|
|
repo_settings: crate::config::RepoSettings::default(),
|
|
source_repos: std::collections::BTreeMap::new(),
|
|
binary_repos: std::collections::BTreeMap::new(),
|
|
mirrors: std::collections::HashMap::new(),
|
|
repo_clone_dir: PathBuf::from("/tmp"),
|
|
package_cache_dir: PathBuf::from("/tmp"),
|
|
install_test_deps: false,
|
|
};
|
|
|
|
spec.apply_config(&config);
|
|
assert_eq!(spec.build.flags.chost, "x86_64-sfg-linux-gnu");
|
|
assert_eq!(spec.build.flags.cbuild, "x86_64-pc-linux-gnu");
|
|
}
|
|
|
|
#[test]
|
|
fn test_default_and_override_carch() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
// Default should be host arch
|
|
assert_eq!(spec.build.flags.carch, std::env::consts::ARCH.to_string());
|
|
|
|
// Override via config
|
|
let mut config = crate::config::Config::for_rootfs(Path::new("/tmp/nonexistent"));
|
|
config.build_overrides = toml::from_str(
|
|
r#"[flags]
|
|
carch = "armv7"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
spec.apply_config(&config);
|
|
assert_eq!(spec.build.flags.carch, "armv7");
|
|
}
|
|
|
|
#[test]
|
|
fn test_package_filename() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
spec.package.revision = 2;
|
|
assert_eq!(
|
|
spec.package_filename("x86_64"),
|
|
"foo-1.0-2-x86_64.depot.pkg.tar.zst"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_packages_array() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let path = tmp.path().join("pkg.toml");
|
|
|
|
std::fs::write(
|
|
&path,
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0"
|
|
description = "d"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[packages]]
|
|
name = "foo-dev"
|
|
version = "1.0"
|
|
description = "development files"
|
|
homepage = "h"
|
|
license = "MIT"
|
|
|
|
[[source]]
|
|
url = "https://example.com/foo-1.0.tar.gz"
|
|
sha256 = "skip"
|
|
extract_dir = "foo-1.0"
|
|
|
|
[build]
|
|
type = "custom"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
let spec = PackageSpec::from_file(&path).unwrap();
|
|
let outputs = spec.outputs();
|
|
assert_eq!(outputs.len(), 2);
|
|
assert_eq!(outputs[0].name, "foo");
|
|
assert_eq!(outputs[1].name, "foo-dev");
|
|
}
|
|
|
|
#[test]
|
|
fn docs_output_uses_runtime_dependency_on_parent_package() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
spec.build.flags.split_docs = true;
|
|
let docs_name = PackageSpec::docs_package_name("foo");
|
|
|
|
let deps = spec.dependencies_for_output(&docs_name);
|
|
assert_eq!(deps.runtime, vec!["foo".to_string()]);
|
|
|
|
let alternatives = spec.alternatives_for_output(&docs_name);
|
|
assert!(alternatives.provides.is_empty());
|
|
assert!(alternatives.conflicts.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn docs_package_for_output_derives_name_and_description() {
|
|
let mut spec = mk_spec("foo", "1.0");
|
|
spec.build.flags.split_docs = true;
|
|
|
|
let docs = spec.docs_package_for_output(&spec.package);
|
|
assert_eq!(docs.name, "foo-docs");
|
|
assert_eq!(docs.description, "Documentation for foo");
|
|
assert_eq!(docs.version, "1.0");
|
|
}
|
|
|
|
fn mk_spec(name: &str, version: &str) -> PackageSpec {
|
|
PackageSpec {
|
|
package: PackageInfo {
|
|
name: name.into(),
|
|
real_name: None,
|
|
version: version.into(),
|
|
revision: 1,
|
|
description: "d".into(),
|
|
homepage: "h".into(),
|
|
abi_breaking: false,
|
|
license: vec!["MIT".into()],
|
|
},
|
|
packages: Vec::new(),
|
|
alternatives: Alternatives::default(),
|
|
manual_sources: Vec::new(),
|
|
source: vec![Source {
|
|
url: "h".into(),
|
|
sha256: "s".into(),
|
|
extract_dir: "e".into(),
|
|
patches: Vec::new(),
|
|
post_extract: Vec::new(),
|
|
cherry_pick: Vec::new(),
|
|
}],
|
|
build: Build {
|
|
build_type: BuildType::Custom,
|
|
flags: BuildFlags::default(),
|
|
},
|
|
dependencies: Dependencies::default(),
|
|
package_alternatives: Default::default(),
|
|
package_dependencies: Default::default(),
|
|
spec_dir: PathBuf::from("."),
|
|
}
|
|
}
|