mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
470 lines
12 KiB
Rust
470 lines
12 KiB
Rust
//! Tests for multiple build scripts feature.
|
|
|
|
use crate::prelude::*;
|
|
use cargo_test_support::compare::assert_e2e;
|
|
use cargo_test_support::git;
|
|
use cargo_test_support::publish::validate_crate_contents;
|
|
use cargo_test_support::str;
|
|
use cargo_test_support::{project, Project};
|
|
use std::fs::File;
|
|
|
|
#[cargo_test]
|
|
fn build_without_feature_enabled_aborts_with_error() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
build = ["build1.rs", "build2.rs"]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("build1.rs", "fn main() {}")
|
|
.file("build2.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
|
|
|
|
Caused by:
|
|
feature `multiple-build-scripts` is required
|
|
|
|
The package requires the Cargo feature called `multiple-build-scripts`, but that feature is not stabilized in this version of Cargo ([..]).
|
|
Consider adding `cargo-features = ["multiple-build-scripts"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.
|
|
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#multiple-build-scripts for more information about the status of this feature.
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
fn basic_empty_project() -> Project {
|
|
project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
build = ["build1.rs", "build2.rs"]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("build1.rs", "fn main() {}")
|
|
.file("build2.rs", "fn main() {}")
|
|
.build()
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn empty_multiple_build_script_project() {
|
|
let p = basic_empty_project();
|
|
p.cargo("check")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.with_status(0)
|
|
.with_stderr_data(str![[r#"
|
|
[COMPILING] foo v0.1.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn multiple_build_scripts_metadata() {
|
|
let p = basic_empty_project();
|
|
p.cargo("metadata --format-version=1")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.with_status(0)
|
|
.with_stderr_data("")
|
|
.with_stdout_data(
|
|
str![[r#"
|
|
{
|
|
"metadata": null,
|
|
"packages": [
|
|
{
|
|
"authors": [],
|
|
"categories": [],
|
|
"default_run": null,
|
|
"dependencies": [],
|
|
"description": null,
|
|
"documentation": null,
|
|
"edition": "2024",
|
|
"features": {},
|
|
"homepage": null,
|
|
"id": "path+[ROOTURL]/foo#0.1.0",
|
|
"keywords": [],
|
|
"license": null,
|
|
"license_file": null,
|
|
"links": null,
|
|
"manifest_path": "[ROOT]/foo/Cargo.toml",
|
|
"metadata": null,
|
|
"name": "foo",
|
|
"publish": null,
|
|
"readme": null,
|
|
"repository": null,
|
|
"rust_version": null,
|
|
"source": null,
|
|
"targets": [
|
|
{
|
|
"crate_types": [
|
|
"bin"
|
|
],
|
|
"doc": true,
|
|
"doctest": false,
|
|
"edition": "2024",
|
|
"kind": [
|
|
"bin"
|
|
],
|
|
"name": "foo",
|
|
"src_path": "[ROOT]/foo/src/main.rs",
|
|
"test": true
|
|
},
|
|
{
|
|
"crate_types": [
|
|
"bin"
|
|
],
|
|
"doc": false,
|
|
"doctest": false,
|
|
"edition": "2024",
|
|
"kind": [
|
|
"custom-build"
|
|
],
|
|
"name": "build-script-build1",
|
|
"src_path": "[ROOT]/foo/build1.rs",
|
|
"test": false
|
|
},
|
|
{
|
|
"crate_types": [
|
|
"bin"
|
|
],
|
|
"doc": false,
|
|
"doctest": false,
|
|
"edition": "2024",
|
|
"kind": [
|
|
"custom-build"
|
|
],
|
|
"name": "build-script-build2",
|
|
"src_path": "[ROOT]/foo/build2.rs",
|
|
"test": false
|
|
}
|
|
],
|
|
"version": "0.1.0"
|
|
}
|
|
],
|
|
"resolve": {
|
|
"nodes": [
|
|
{
|
|
"dependencies": [],
|
|
"deps": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.1.0"
|
|
}
|
|
],
|
|
"root": "path+[ROOTURL]/foo#0.1.0"
|
|
},
|
|
"target_directory": "[ROOT]/foo/target",
|
|
"version": 1,
|
|
"workspace_default_members": [
|
|
"path+[ROOTURL]/foo#0.1.0"
|
|
],
|
|
"workspace_members": [
|
|
"path+[ROOTURL]/foo#0.1.0"
|
|
],
|
|
"workspace_root": "[ROOT]/foo"
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn verify_package_multiple_build_scripts() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
license = "MIT"
|
|
description = "foo"
|
|
documentation = "docs.rs/foo"
|
|
authors = []
|
|
|
|
build = ["build1.rs", "build2.rs"]
|
|
include = [ "src/main.rs", "build1.rs" ]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("build1.rs", "fn main() {}")
|
|
.file("build2.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("package")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.with_status(0)
|
|
.with_stderr_data(str![[r#"
|
|
[PACKAGING] foo v0.1.0 ([ROOT]/foo)
|
|
[WARNING] ignoring `package.build` entry `build2.rs` as it is not included in the published package
|
|
[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
|
|
[VERIFYING] foo v0.1.0 ([ROOT]/foo)
|
|
[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap();
|
|
validate_crate_contents(
|
|
f,
|
|
"foo-0.1.0.crate",
|
|
&[
|
|
"Cargo.toml",
|
|
"Cargo.toml.orig",
|
|
"src/main.rs",
|
|
"build1.rs",
|
|
"Cargo.lock",
|
|
],
|
|
[(
|
|
"Cargo.toml",
|
|
str![[r##"
|
|
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
#
|
|
# When uploading crates to the registry Cargo will automatically
|
|
# "normalize" Cargo.toml files for maximal compatibility
|
|
# with all versions of Cargo and also rewrite `path` dependencies
|
|
# to registry (e.g., crates.io) dependencies.
|
|
#
|
|
# If you are reading this file be aware that the original Cargo.toml
|
|
# will likely look very different (and much more reasonable).
|
|
# See Cargo.toml.orig for the original contents.
|
|
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
edition = "2024"
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
authors = []
|
|
build = "build1.rs"
|
|
include = [
|
|
"src/main.rs",
|
|
"build1.rs",
|
|
]
|
|
autolib = false
|
|
autobins = false
|
|
autoexamples = false
|
|
autotests = false
|
|
autobenches = false
|
|
description = "foo"
|
|
documentation = "docs.rs/foo"
|
|
readme = false
|
|
license = "MIT"
|
|
|
|
[[bin]]
|
|
name = "foo"
|
|
path = "src/main.rs"
|
|
|
|
"##]],
|
|
)],
|
|
);
|
|
}
|
|
|
|
fn add_git_vendor_config(p: &Project, git_project: &Project) {
|
|
p.change_file(
|
|
".cargo/config.toml",
|
|
&format!(
|
|
r#"
|
|
[source."git+{url}"]
|
|
git = "{url}"
|
|
replace-with = 'vendor'
|
|
|
|
[source.vendor]
|
|
directory = 'vendor'
|
|
"#,
|
|
url = git_project.url()
|
|
),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn verify_vendor_multiple_build_scripts() {
|
|
let git_project = git::new("dep", |project| {
|
|
project
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
name = "dep"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
license = "MIT"
|
|
description = "dependency of foo"
|
|
documentation = "docs.rs/dep"
|
|
authors = []
|
|
|
|
build = ["build1.rs", "build2.rs"]
|
|
include = [ "src/main.rs", "build1.rs" ]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("build1.rs", "fn main() {}")
|
|
.file("build2.rs", "fn main() {}")
|
|
});
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
|
|
[dependencies.dep]
|
|
git = '{}'
|
|
"#,
|
|
git_project.url()
|
|
),
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("vendor --respect-source-config")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.with_status(0)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] git repository `[ROOTURL]/dep`
|
|
[LOCKING] 1 package to latest [..] compatible version
|
|
Vendoring dep v0.1.0 ([ROOTURL]/dep#[..]) ([ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]) to vendor/dep
|
|
[WARNING] ignoring `package.build` entry `build2.rs` as it is not included in the published package
|
|
To use vendored sources, add this to your .cargo/config.toml for this project:
|
|
|
|
|
|
"#]])
|
|
.run();
|
|
add_git_vendor_config(&p, &git_project);
|
|
|
|
assert_e2e().eq(
|
|
p.read_file("vendor/dep/Cargo.toml"),
|
|
str![[r##"
|
|
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
#
|
|
# When uploading crates to the registry Cargo will automatically
|
|
# "normalize" Cargo.toml files for maximal compatibility
|
|
# with all versions of Cargo and also rewrite `path` dependencies
|
|
# to registry (e.g., crates.io) dependencies.
|
|
#
|
|
# If you are reading this file be aware that the original Cargo.toml
|
|
# will likely look very different (and much more reasonable).
|
|
# See Cargo.toml.orig for the original contents.
|
|
|
|
cargo-features = ["multiple-build-scripts"]
|
|
|
|
[package]
|
|
edition = "2024"
|
|
name = "dep"
|
|
version = "0.1.0"
|
|
authors = []
|
|
build = "build1.rs"
|
|
include = [
|
|
"src/main.rs",
|
|
"build1.rs",
|
|
]
|
|
autolib = false
|
|
autobins = false
|
|
autoexamples = false
|
|
autotests = false
|
|
autobenches = false
|
|
description = "dependency of foo"
|
|
documentation = "docs.rs/dep"
|
|
readme = false
|
|
license = "MIT"
|
|
|
|
[[bin]]
|
|
name = "dep"
|
|
path = "src/main.rs"
|
|
|
|
"##]],
|
|
);
|
|
|
|
p.cargo("check")
|
|
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn rerun_untracks_other_files() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
foo();
|
|
bar();
|
|
}
|
|
fn foo() {
|
|
let _path = "assets/foo.txt";
|
|
}
|
|
fn bar() {
|
|
let path = "assets/bar.txt";
|
|
println!("cargo::rerun-if-changed={path}");
|
|
}"#,
|
|
)
|
|
.file("assets/foo.txt", "foo")
|
|
.file("assets/bar.txt", "bar")
|
|
.build();
|
|
p.cargo("build").run();
|
|
|
|
// Editing foo.txt won't recompile, leading to unnoticed changes
|
|
|
|
p.change_file("assets/foo.txt", "foo updated");
|
|
p.cargo("build -v")
|
|
.with_stderr_data(str![[r#"
|
|
[FRESH] foo v0.1.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Editing bar.txt will recompile
|
|
|
|
p.change_file("assets/bar.txt", "bar updated");
|
|
p.cargo("build -v")
|
|
.with_stderr_data(str![[r#"
|
|
[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `assets/bar.txt` has changed ([TIME_DIFF_AFTER_LAST_BUILD])
|
|
[COMPILING] foo v0.1.0 ([ROOT]/foo)
|
|
[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`
|
|
[RUNNING] `rustc --crate-name foo --edition=2024 src/main.rs [..] --crate-type bin [..]
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|