2016-05-26 00:06:25 +00:00
|
|
|
extern crate cargo;
|
|
|
|
extern crate cargotest;
|
|
|
|
extern crate hamcrest;
|
|
|
|
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
use std::process::Command;
|
|
|
|
use std::sync::{Once, ONCE_INIT};
|
|
|
|
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
2014-07-11 16:08:51 +00:00
|
|
|
|
|
|
|
use cargo::util::process;
|
2016-05-26 00:06:25 +00:00
|
|
|
use cargotest::{is_nightly, rustc_host};
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
use cargotest::support::{project, execs, main_file, basic_bin_manifest};
|
2016-05-26 00:06:25 +00:00
|
|
|
use hamcrest::{assert_that, existing_file};
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2014-08-11 05:04:15 +00:00
|
|
|
fn disabled() -> bool {
|
2014-12-21 18:45:39 +00:00
|
|
|
// First, disable if ./configure requested so
|
2015-02-13 04:10:07 +00:00
|
|
|
match env::var("CFG_DISABLE_CROSS_TESTS") {
|
2015-03-26 18:17:44 +00:00
|
|
|
Ok(ref s) if *s == "1" => return true,
|
2014-12-21 18:45:39 +00:00
|
|
|
_ => {}
|
2014-08-11 05:04:15 +00:00
|
|
|
}
|
2014-12-21 18:45:39 +00:00
|
|
|
|
|
|
|
// Right now the windows bots cannot cross compile due to the mingw setup,
|
|
|
|
// so we disable ourselves on all but macos/linux setups where the rustc
|
|
|
|
// install script ensures we have both architectures
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
if !(cfg!(target_os = "macos") ||
|
|
|
|
cfg!(target_os = "linux") ||
|
|
|
|
cfg!(target_env = "msvc")) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It's not particularly common to have a cross-compilation setup, so
|
|
|
|
// try to detect that before we fail a bunch of tests through no fault
|
|
|
|
// of the user.
|
2017-01-09 14:51:37 +00:00
|
|
|
static CAN_RUN_CROSS_TESTS: AtomicBool = ATOMIC_BOOL_INIT;
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
static CHECK: Once = ONCE_INIT;
|
|
|
|
|
|
|
|
let cross_target = alternate();
|
|
|
|
|
|
|
|
CHECK.call_once(|| {
|
|
|
|
let p = project("cross_test")
|
|
|
|
.file("Cargo.toml", &basic_bin_manifest("cross_test"))
|
|
|
|
.file("src/cross_test.rs", &main_file(r#""testing!""#, &[]));
|
|
|
|
|
|
|
|
let result = p.cargo_process("build")
|
|
|
|
.arg("--target").arg(&cross_target)
|
|
|
|
.exec_with_output();
|
|
|
|
|
|
|
|
if result.is_ok() {
|
2017-01-09 14:51:37 +00:00
|
|
|
CAN_RUN_CROSS_TESTS.store(true, Ordering::SeqCst);
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-01-09 14:51:37 +00:00
|
|
|
if CAN_RUN_CROSS_TESTS.load(Ordering::SeqCst) {
|
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an
appropriate cross standard library is not found. This behavior is
unhelpful, because the failures are verbose, unexpected, and there's no
obvious way to make them go away.
Instead, it would be better to check once before all the tests that an
appropriate cross-compilation setup is available. Once that check has
been done, a single test can fail with an appropriate `panic!` message
while the other tests silently pass. The `panic!` message can inform
the user about their options, either setting an appropriate environment
variable, or using rustup to install the necessary cross standard
library.
Assuming the user has rustup installed, the single failure now looks
something like:
```
thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu.
This failure can be safely ignored. If you would prefer to not see this
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1".
Alternatively, you can install the necessary libraries for cross-compilation with
rustup toolchain install stable-i686-unknown-linux-gnu
You may need to install runtime libraries for your Linux distribution as well.
', tests/cross-compile.rs:87
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Fixes #3086.
2017-01-06 19:30:38 +00:00
|
|
|
// We were able to compile a simple project, so the user has the
|
|
|
|
// necessary std:: bits installed. Therefore, tests should not
|
|
|
|
// be disabled.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can't compile a simple cross project. We want to warn the user
|
|
|
|
// by failing a single test and having the remainder of the cross tests
|
|
|
|
// pass. We don't use std::sync::Once here because panicing inside its
|
|
|
|
// call_once method would poison the Once instance, which is not what
|
|
|
|
// we want.
|
|
|
|
static HAVE_WARNED: AtomicBool = ATOMIC_BOOL_INIT;
|
|
|
|
|
|
|
|
if HAVE_WARNED.swap(true, Ordering::SeqCst) {
|
|
|
|
// We are some other test and somebody else is handling the warning.
|
|
|
|
// Just disable the current test.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We are responsible for warning the user, which we do by panicing.
|
|
|
|
let rustup_available = Command::new("rustup").output().is_ok();
|
|
|
|
|
|
|
|
let linux_help = if cfg!(target_os = "linux") {
|
|
|
|
"
|
|
|
|
|
|
|
|
You may need to install runtime libraries for your Linux distribution as well.".to_string()
|
|
|
|
} else {
|
|
|
|
"".to_string()
|
|
|
|
};
|
|
|
|
|
|
|
|
let rustup_help = if rustup_available {
|
|
|
|
format!("
|
|
|
|
|
|
|
|
Alternatively, you can install the necessary libraries for cross-compilation with
|
|
|
|
|
|
|
|
rustup target add {}{}", cross_target, linux_help)
|
|
|
|
} else {
|
|
|
|
"".to_string()
|
|
|
|
};
|
|
|
|
|
|
|
|
panic!("Cannot cross compile to {}.
|
|
|
|
|
|
|
|
This failure can be safely ignored. If you would prefer to not see this
|
|
|
|
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \"1\".{}
|
|
|
|
", cross_target, rustup_help);
|
2014-08-11 05:04:15 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 21:42:37 +00:00
|
|
|
fn alternate() -> String {
|
|
|
|
let platform = match env::consts::OS {
|
|
|
|
"linux" => "unknown-linux-gnu",
|
|
|
|
"macos" => "apple-darwin",
|
|
|
|
"windows" => "pc-windows-msvc",
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
let arch = match env::consts::ARCH {
|
|
|
|
"x86" => "x86_64",
|
|
|
|
"x86_64" => "i686",
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
format!("{}-{}", arch, platform)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn alternate_arch() -> &'static str {
|
|
|
|
match env::consts::ARCH {
|
|
|
|
"x86" => "x86_64",
|
|
|
|
"x86_64" => "x86",
|
2014-07-11 16:08:51 +00:00
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-15 00:00:39 +00:00
|
|
|
fn host() -> String {
|
|
|
|
let platform = match env::consts::OS {
|
|
|
|
"linux" => "unknown-linux-gnu",
|
|
|
|
"macos" => "apple-darwin",
|
|
|
|
"windows" => "pc-windows-msvc",
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
let arch = match env::consts::ARCH {
|
|
|
|
"x86" => "i686",
|
|
|
|
"x86_64" => "x86_64",
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
format!("{}-{}", arch, platform)
|
|
|
|
}
|
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn simple_cross() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
2015-01-19 22:27:51 +00:00
|
|
|
let p = project("foo")
|
2014-08-17 05:10:36 +00:00
|
|
|
.file("Cargo.toml", r#"
|
2015-01-19 22:27:51 +00:00
|
|
|
[package]
|
2014-08-17 05:10:36 +00:00
|
|
|
name = "foo"
|
2015-01-19 22:27:51 +00:00
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
2014-08-17 05:10:36 +00:00
|
|
|
"#)
|
2015-03-26 18:17:44 +00:00
|
|
|
.file("build.rs", &format!(r#"
|
2014-08-17 05:10:36 +00:00
|
|
|
fn main() {{
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(std::env::var("TARGET").unwrap(), "{}");
|
2014-08-17 05:10:36 +00:00
|
|
|
}}
|
2015-03-26 18:17:44 +00:00
|
|
|
"#, alternate()))
|
2015-07-22 21:42:37 +00:00
|
|
|
.file("src/main.rs", &format!(r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-07-22 21:42:37 +00:00
|
|
|
fn main() {{
|
|
|
|
assert_eq!(env::consts::ARCH, "{}");
|
|
|
|
}}
|
|
|
|
"#, alternate_arch()));
|
2014-07-11 16:08:51 +00:00
|
|
|
|
|
|
|
let target = alternate();
|
Refactor Cargo's backend, again!
This commit started out identifying a relatively simple bug in Cargo. A recent
change made it such that the resolution graph included all target-specific
dependencies, relying on the structure of the backend to filter out those which
don't need to get built. This was unfortunately not accounted for in the portion
of the backend that schedules work, mistakenly causing spurious rebuilds if
different runs of the graph pulled in new crates. For example if `cargo build`
didn't build any target-specific dependencies but then later `cargo test` did
(e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would
cause a rebuild of the entire graph.
This class of bug is certainly not the first in a long and storied history of
the backend having multiple points where dependencies are calculated and those
often don't quite agree with one another. The purpose of this rewrite is
twofold:
1. The `Stage` enum in the backend for scheduling work and ensuring that maximum
parallelism is achieved is removed entirely. There is already a function on
`Context` which expresses the dependency between targets (`dep_targets`)
which takes a much finer grain of dependencies into account as well as
already having all the logic for what-depends-on-what. This duplication has
caused numerous problems in the past, an unifying these two will truly grant
maximum parallelism while ensuring that everyone agrees on what their
dependencies are.
2. A large number of locations in the backend have grown to take a (Package,
Target, Profile, Kind) tuple, or some subset of this tuple. In general this
represents a "unit of work" and is much easier to pass around as one
variable, so a `Unit` was introduced which references all of these variables.
Almost the entire backend was altered to take a `Unit` instead of these
variables specifically, typically providing all of the contextual information
necessary for an operation.
A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure
that everyone *also* agrees on what architecture they're compiling everything
for. There have been many bugs in the past where one part of the backend
determined that a package was built for one architecture and then another part
thought it was built for another. With the inclusion of `Kind` in dependency
management this is handled in a much cleaner fashion as it's only calculated in
one location.
Some other miscellaneous changes made were:
* The `Platform` enumeration has finally been removed. This has been entirely
subsumed by `Kind`.
* The hokey logic for "build this crate once" even though it may be depended on
by both the host/target kinds has been removed. This is now handled in a much
nicer fashion where if there's no target then Kind::Target is just never used,
and multiple requests for a package are just naturally deduplicated.
* There's no longer any need to build up the "requirements" for a package in
terms of what platforms it's compiled for, this now just naturally falls out
of the dependency graph.
* If a build script is overridden then its entire tree of dependencies are not
compiled, not just the build script itself.
* The `threadpool` dependency has been replaced with one on `crossbeam`. The
method of calculating dependencies has quite a few non-static lifetimes and
the scoped threads of `crossbeam` are now used instead of a thread pool.
* Once any thread fails to execute a command work is no longer scheduled unlike
before where some extra pending work may continue to start.
* Many functions used early on, such as `compile` and `build_map` have been
massively simplified by farming out dependency management to
`Context::dep_targets`.
* There is now a new profile to represent running a build script. This is used
to inject dependencies as well as represent that a library depends on running
a build script, not just building it.
This change has currently been tested against cross-compiling Servo to Android
and passes the test suite (which has quite a few corner cases for build scripts
and such), so I'm pretty confident that this refactoring won't have at least too
many regressions!
2015-10-02 06:48:47 +00:00
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
2014-07-11 16:08:51 +00:00
|
|
|
execs().with_status(0));
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(&p.target_bin(&target, "foo"), existing_file());
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2016-01-30 08:31:42 +00:00
|
|
|
assert_that(process(&p.target_bin(&target, "foo")),
|
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2016-01-30 08:31:42 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn simple_cross_config() {
|
2016-01-30 08:31:42 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let p = project("foo")
|
|
|
|
.file(".cargo/config", &format!(r#"
|
|
|
|
[build]
|
|
|
|
target = "{}"
|
|
|
|
"#, alternate()))
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
"#)
|
|
|
|
.file("build.rs", &format!(r#"
|
|
|
|
fn main() {{
|
|
|
|
assert_eq!(std::env::var("TARGET").unwrap(), "{}");
|
|
|
|
}}
|
|
|
|
"#, alternate()))
|
|
|
|
.file("src/main.rs", &format!(r#"
|
|
|
|
use std::env;
|
|
|
|
fn main() {{
|
|
|
|
assert_eq!(env::consts::ARCH, "{}");
|
|
|
|
}}
|
|
|
|
"#, alternate_arch()));
|
|
|
|
|
|
|
|
let target = alternate();
|
|
|
|
assert_that(p.cargo_process("build").arg("-v"),
|
|
|
|
execs().with_status(0));
|
|
|
|
assert_that(&p.target_bin(&target, "foo"), existing_file());
|
|
|
|
|
2015-10-28 09:20:00 +00:00
|
|
|
assert_that(process(&p.target_bin(&target, "foo")),
|
2015-02-27 01:04:25 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn simple_deps() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
2014-07-11 16:08:51 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.bar]
|
|
|
|
path = "../bar"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", r#"
|
|
|
|
extern crate bar;
|
|
|
|
fn main() { bar::bar(); }
|
|
|
|
"#);
|
|
|
|
let p2 = project("bar")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "bar"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
"#)
|
|
|
|
.file("src/lib.rs", "pub fn bar() {}");
|
|
|
|
p2.build();
|
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target),
|
2014-07-11 16:08:51 +00:00
|
|
|
execs().with_status(0));
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(&p.target_bin(&target, "foo"), existing_file());
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2015-10-28 09:20:00 +00:00
|
|
|
assert_that(process(&p.target_bin(&target, "foo")),
|
2015-02-27 01:04:25 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn plugin_deps() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
2016-05-26 00:06:25 +00:00
|
|
|
if !is_nightly() { return }
|
2014-08-11 05:04:15 +00:00
|
|
|
|
2014-07-11 18:22:07 +00:00
|
|
|
let foo = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.bar]
|
|
|
|
path = "../bar"
|
|
|
|
|
|
|
|
[dependencies.baz]
|
|
|
|
path = "../baz"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", r#"
|
2015-01-13 16:41:04 +00:00
|
|
|
#![feature(plugin)]
|
2015-02-13 04:10:07 +00:00
|
|
|
#![plugin(bar)]
|
2014-07-11 18:22:07 +00:00
|
|
|
extern crate baz;
|
|
|
|
fn main() {
|
|
|
|
assert_eq!(bar!(), baz::baz());
|
|
|
|
}
|
|
|
|
"#);
|
|
|
|
let bar = project("bar")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "bar"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
2014-07-11 16:08:51 +00:00
|
|
|
|
2014-08-14 06:08:02 +00:00
|
|
|
[lib]
|
2014-07-11 18:22:07 +00:00
|
|
|
name = "bar"
|
|
|
|
plugin = true
|
|
|
|
"#)
|
|
|
|
.file("src/lib.rs", r#"
|
2015-03-10 19:58:18 +00:00
|
|
|
#![feature(plugin_registrar, quote, rustc_private)]
|
2014-07-11 18:22:07 +00:00
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
extern crate rustc_plugin;
|
2014-07-11 18:22:07 +00:00
|
|
|
extern crate syntax;
|
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
use rustc_plugin::Registry;
|
2016-05-15 00:14:24 +00:00
|
|
|
use syntax::tokenstream::TokenTree;
|
2014-07-11 18:22:07 +00:00
|
|
|
use syntax::codemap::Span;
|
2015-03-09 19:07:35 +00:00
|
|
|
use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
|
2014-07-11 18:22:07 +00:00
|
|
|
|
|
|
|
#[plugin_registrar]
|
|
|
|
pub fn foo(reg: &mut Registry) {
|
|
|
|
reg.register_macro("bar", expand_bar);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
2014-08-29 19:00:15 +00:00
|
|
|
-> Box<MacResult + 'static> {
|
2015-03-09 19:07:35 +00:00
|
|
|
MacEager::expr(quote_expr!(cx, 1))
|
2014-07-11 18:22:07 +00:00
|
|
|
}
|
|
|
|
"#);
|
|
|
|
let baz = project("baz")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "baz"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
"#)
|
2015-02-13 04:10:07 +00:00
|
|
|
.file("src/lib.rs", "pub fn baz() -> i32 { 1 }");
|
2014-07-11 18:22:07 +00:00
|
|
|
bar.build();
|
|
|
|
baz.build();
|
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(foo.cargo_process("build").arg("--target").arg(&target),
|
2014-07-11 18:22:07 +00:00
|
|
|
execs().with_status(0));
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(&foo.target_bin(&target, "foo"), existing_file());
|
2014-07-11 18:22:07 +00:00
|
|
|
|
2015-10-28 09:20:00 +00:00
|
|
|
assert_that(process(&foo.target_bin(&target, "foo")),
|
2015-02-27 01:04:25 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-07-11 18:22:07 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn plugin_to_the_max() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
2016-05-26 00:06:25 +00:00
|
|
|
if !is_nightly() { return }
|
2014-08-11 05:04:15 +00:00
|
|
|
|
2014-07-11 18:22:07 +00:00
|
|
|
let foo = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.bar]
|
|
|
|
path = "../bar"
|
|
|
|
|
|
|
|
[dependencies.baz]
|
|
|
|
path = "../baz"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", r#"
|
2015-01-13 16:41:04 +00:00
|
|
|
#![feature(plugin)]
|
2015-02-13 04:10:07 +00:00
|
|
|
#![plugin(bar)]
|
2014-07-11 18:22:07 +00:00
|
|
|
extern crate baz;
|
|
|
|
fn main() {
|
|
|
|
assert_eq!(bar!(), baz::baz());
|
|
|
|
}
|
|
|
|
"#);
|
|
|
|
let bar = project("bar")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "bar"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
2014-08-14 06:08:02 +00:00
|
|
|
[lib]
|
2014-07-11 18:22:07 +00:00
|
|
|
name = "bar"
|
|
|
|
plugin = true
|
|
|
|
|
|
|
|
[dependencies.baz]
|
|
|
|
path = "../baz"
|
|
|
|
"#)
|
|
|
|
.file("src/lib.rs", r#"
|
2015-03-10 19:58:18 +00:00
|
|
|
#![feature(plugin_registrar, quote, rustc_private)]
|
2014-07-11 18:22:07 +00:00
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
extern crate rustc_plugin;
|
2014-07-11 18:22:07 +00:00
|
|
|
extern crate syntax;
|
|
|
|
extern crate baz;
|
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
use rustc_plugin::Registry;
|
2016-05-15 00:14:24 +00:00
|
|
|
use syntax::tokenstream::TokenTree;
|
2014-07-11 18:22:07 +00:00
|
|
|
use syntax::codemap::Span;
|
2015-03-09 19:07:35 +00:00
|
|
|
use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
|
2014-07-11 18:22:07 +00:00
|
|
|
|
|
|
|
#[plugin_registrar]
|
|
|
|
pub fn foo(reg: &mut Registry) {
|
|
|
|
reg.register_macro("bar", expand_bar);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
2014-08-29 19:00:15 +00:00
|
|
|
-> Box<MacResult + 'static> {
|
2015-03-09 19:07:35 +00:00
|
|
|
MacEager::expr(quote_expr!(cx, baz::baz()))
|
2014-07-11 18:22:07 +00:00
|
|
|
}
|
|
|
|
"#);
|
|
|
|
let baz = project("baz")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "baz"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
"#)
|
Consider transitive fingerprints for freshness
Originally discovered through #1236, this commit fixes a bug in Cargo where
crates may not be recompiled when they need to (leading to obscure errors from
the compiler). The scenario in question looks like:
* Assume a dependency graph of `A -> B -> C` and `A -> C`
* Build all packages
* Modify C
* Rebuild, but hit Ctrl+C while B is building
* Modify A
* Rebuild again
Previously, Cargo only considered the freshness of a package to be the freshness
of the package itself (checking source files, for example). To handle transitive
recompilations, Cargo propagates a dirty bit throughout the dependency graph
automatically (instead if calculating it as such).
In the above example, however, we have a problem where as part of the last
rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just
recompiled, but `B`'s source code is untainted, so Cargo does not think that it
needs to recompile `B`. This is wrong, however, because one of `B`'s
dependencies was rebuilt, so it needs to be rebuilt.
To fix this problem, the fingerprint (a short hash) for all packages is now
transitively propagated (the fingerprint changes when an upstream package
changes). This should ensure that even when Ctrl+C is hit (or the situation
explained in #1236) that Cargo will still consider packages whose source code is
untainted as candidates for recompilation.
The implementation is somewhat tricky due to the actual fingerprint for a path
dependency not being known until *after* the crate is compiled (the fingerprint
is the mtime of the dep-info file).
Closes #1236
2015-01-29 03:37:19 +00:00
|
|
|
.file("src/lib.rs", "pub fn baz() -> i32 { 1 }");
|
2014-07-11 18:22:07 +00:00
|
|
|
bar.build();
|
|
|
|
baz.build();
|
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(foo.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
2014-07-29 02:35:08 +00:00
|
|
|
execs().with_status(0));
|
Consider transitive fingerprints for freshness
Originally discovered through #1236, this commit fixes a bug in Cargo where
crates may not be recompiled when they need to (leading to obscure errors from
the compiler). The scenario in question looks like:
* Assume a dependency graph of `A -> B -> C` and `A -> C`
* Build all packages
* Modify C
* Rebuild, but hit Ctrl+C while B is building
* Modify A
* Rebuild again
Previously, Cargo only considered the freshness of a package to be the freshness
of the package itself (checking source files, for example). To handle transitive
recompilations, Cargo propagates a dirty bit throughout the dependency graph
automatically (instead if calculating it as such).
In the above example, however, we have a problem where as part of the last
rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just
recompiled, but `B`'s source code is untainted, so Cargo does not think that it
needs to recompile `B`. This is wrong, however, because one of `B`'s
dependencies was rebuilt, so it needs to be rebuilt.
To fix this problem, the fingerprint (a short hash) for all packages is now
transitively propagated (the fingerprint changes when an upstream package
changes). This should ensure that even when Ctrl+C is hit (or the situation
explained in #1236) that Cargo will still consider packages whose source code is
untainted as candidates for recompilation.
The implementation is somewhat tricky due to the actual fingerprint for a path
dependency not being known until *after* the crate is compiled (the fingerprint
is the mtime of the dep-info file).
Closes #1236
2015-01-29 03:37:19 +00:00
|
|
|
println!("second");
|
2015-02-27 01:04:25 +00:00
|
|
|
assert_that(foo.cargo("build").arg("-v")
|
2015-07-22 21:42:37 +00:00
|
|
|
.arg("--target").arg(&target),
|
2014-07-11 18:22:07 +00:00
|
|
|
execs().with_status(0));
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(&foo.target_bin(&target, "foo"), existing_file());
|
2014-07-11 18:22:07 +00:00
|
|
|
|
2015-10-28 09:20:00 +00:00
|
|
|
assert_that(process(&foo.target_bin(&target, "foo")),
|
2015-02-27 01:04:25 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-07-14 17:57:04 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn linker_and_ar() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
2014-07-14 17:57:04 +00:00
|
|
|
let target = alternate();
|
|
|
|
let p = project("foo")
|
2015-03-26 18:17:44 +00:00
|
|
|
.file(".cargo/config", &format!(r#"
|
2014-07-14 17:57:04 +00:00
|
|
|
[target.{}]
|
|
|
|
ar = "my-ar-tool"
|
|
|
|
linker = "my-linker-tool"
|
2015-03-26 18:17:44 +00:00
|
|
|
"#, target))
|
|
|
|
.file("Cargo.toml", &basic_bin_manifest("foo"))
|
2015-07-22 21:42:37 +00:00
|
|
|
.file("src/foo.rs", &format!(r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-07-22 21:42:37 +00:00
|
|
|
fn main() {{
|
|
|
|
assert_eq!(env::consts::ARCH, "{}");
|
|
|
|
}}
|
|
|
|
"#, alternate_arch()));
|
2014-07-14 17:57:04 +00:00
|
|
|
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target)
|
2014-07-14 17:57:04 +00:00
|
|
|
.arg("-v"),
|
|
|
|
execs().with_status(101)
|
2016-05-20 16:23:50 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.5.0 ({url})
|
2017-01-03 21:22:58 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo src[/]foo.rs --crate-type bin \
|
2017-01-12 05:35:17 +00:00
|
|
|
--emit=dep-info,link -C debuginfo=2 \
|
2016-08-02 06:22:29 +00:00
|
|
|
-C metadata=[..] \
|
2016-10-04 23:16:30 +00:00
|
|
|
--out-dir {dir}[/]target[/]{target}[/]debug[/]deps \
|
2014-07-14 17:57:04 +00:00
|
|
|
--target {target} \
|
|
|
|
-C ar=my-ar-tool -C linker=my-linker-tool \
|
2016-11-28 15:27:14 +00:00
|
|
|
-L dependency={dir}[/]target[/]{target}[/]debug[/]deps \
|
|
|
|
-L dependency={dir}[/]target[/]debug[/]deps`
|
2014-07-14 17:57:04 +00:00
|
|
|
",
|
|
|
|
dir = p.root().display(),
|
2014-08-06 16:21:10 +00:00
|
|
|
url = p.url(),
|
2014-07-14 17:57:04 +00:00
|
|
|
target = target,
|
2015-03-26 18:17:44 +00:00
|
|
|
)));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-07-29 00:08:46 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn plugin_with_extra_dylib_dep() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
2016-05-26 00:06:25 +00:00
|
|
|
if !is_nightly() { return }
|
2014-08-11 05:04:15 +00:00
|
|
|
|
2014-07-29 00:08:46 +00:00
|
|
|
let foo = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.bar]
|
|
|
|
path = "../bar"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", r#"
|
2015-01-13 16:41:04 +00:00
|
|
|
#![feature(plugin)]
|
2015-02-13 04:10:07 +00:00
|
|
|
#![plugin(bar)]
|
2014-07-29 00:08:46 +00:00
|
|
|
|
|
|
|
fn main() {}
|
|
|
|
"#);
|
|
|
|
let bar = project("bar")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "bar"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
2014-08-14 06:08:02 +00:00
|
|
|
[lib]
|
2014-07-29 00:08:46 +00:00
|
|
|
name = "bar"
|
|
|
|
plugin = true
|
|
|
|
|
|
|
|
[dependencies.baz]
|
|
|
|
path = "../baz"
|
|
|
|
"#)
|
|
|
|
.file("src/lib.rs", r#"
|
2015-03-10 19:58:18 +00:00
|
|
|
#![feature(plugin_registrar, rustc_private)]
|
2014-07-29 00:08:46 +00:00
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
extern crate rustc_plugin;
|
2014-07-29 00:08:46 +00:00
|
|
|
extern crate baz;
|
|
|
|
|
2015-11-30 19:21:04 +00:00
|
|
|
use rustc_plugin::Registry;
|
2014-07-29 00:08:46 +00:00
|
|
|
|
|
|
|
#[plugin_registrar]
|
|
|
|
pub fn foo(reg: &mut Registry) {
|
|
|
|
println!("{}", baz::baz());
|
|
|
|
}
|
|
|
|
"#);
|
|
|
|
let baz = project("baz")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "baz"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
|
2014-08-14 06:08:02 +00:00
|
|
|
[lib]
|
2014-07-29 00:08:46 +00:00
|
|
|
name = "baz"
|
|
|
|
crate_type = ["dylib"]
|
|
|
|
"#)
|
2015-02-13 04:10:07 +00:00
|
|
|
.file("src/lib.rs", "pub fn baz() -> i32 { 1 }");
|
2014-07-29 00:08:46 +00:00
|
|
|
bar.build();
|
|
|
|
baz.build();
|
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(foo.cargo_process("build").arg("--target").arg(&target),
|
2014-07-29 00:08:46 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-08-11 04:12:32 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn cross_tests() {
|
2014-08-11 05:04:15 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
2014-08-11 04:12:32 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[project]
|
|
|
|
name = "foo"
|
|
|
|
authors = []
|
|
|
|
version = "0.0.0"
|
2014-08-11 05:08:57 +00:00
|
|
|
|
|
|
|
[[bin]]
|
|
|
|
name = "bar"
|
2014-08-11 04:12:32 +00:00
|
|
|
"#)
|
2015-07-22 21:42:37 +00:00
|
|
|
.file("src/main.rs", &format!(r#"
|
2014-08-11 04:12:32 +00:00
|
|
|
extern crate foo;
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-07-22 21:42:37 +00:00
|
|
|
fn main() {{
|
|
|
|
assert_eq!(env::consts::ARCH, "{}");
|
|
|
|
}}
|
|
|
|
#[test] fn test() {{ main() }}
|
|
|
|
"#, alternate_arch()))
|
|
|
|
.file("src/lib.rs", &format!(r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-07-22 21:42:37 +00:00
|
|
|
pub fn foo() {{ assert_eq!(env::consts::ARCH, "{}"); }}
|
|
|
|
#[test] fn test_foo() {{ foo() }}
|
|
|
|
"#, alternate_arch()));
|
2014-08-11 04:12:32 +00:00
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(p.cargo_process("test").arg("--target").arg(&target),
|
2014-08-11 04:12:32 +00:00
|
|
|
execs().with_status(0)
|
2016-05-19 00:51:07 +00:00
|
|
|
.with_stderr(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.0 ({foo})
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2017-04-06 14:18:07 +00:00
|
|
|
[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
|
|
|
|
[RUNNING] target[/]{triple}[/]debug[/]deps[/]bar-[..][EXE]", foo = p.url(), triple = target))
|
2016-05-19 00:51:07 +00:00
|
|
|
.with_stdout("
|
2014-08-11 04:12:32 +00:00
|
|
|
running 1 test
|
2017-04-06 14:18:07 +00:00
|
|
|
test test_foo ... ok
|
2014-08-11 04:12:32 +00:00
|
|
|
|
|
|
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
|
|
|
|
|
|
|
|
|
|
|
running 1 test
|
2017-04-06 14:18:07 +00:00
|
|
|
test test ... ok
|
2014-08-11 04:12:32 +00:00
|
|
|
|
|
|
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
|
|
|
|
2016-05-19 00:51:07 +00:00
|
|
|
"));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-08-25 14:51:13 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn no_cross_doctests() {
|
2016-03-15 00:00:39 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[project]
|
|
|
|
name = "foo"
|
|
|
|
authors = []
|
|
|
|
version = "0.0.0"
|
|
|
|
"#)
|
|
|
|
.file("src/lib.rs", r#"
|
|
|
|
//! ```
|
|
|
|
//! extern crate foo;
|
|
|
|
//! assert!(true);
|
|
|
|
//! ```
|
|
|
|
"#);
|
2017-02-15 14:16:41 +00:00
|
|
|
p.build();
|
2016-03-15 00:00:39 +00:00
|
|
|
|
|
|
|
let host_output = format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.0 ({foo})
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
|
2016-05-12 15:23:53 +00:00
|
|
|
[DOCTEST] foo
|
|
|
|
", foo = p.url());
|
2016-03-15 00:00:39 +00:00
|
|
|
|
2016-05-20 16:23:50 +00:00
|
|
|
println!("a");
|
2017-02-15 14:16:41 +00:00
|
|
|
assert_that(p.cargo("test"),
|
2016-03-15 00:00:39 +00:00
|
|
|
execs().with_status(0)
|
2016-05-20 16:23:50 +00:00
|
|
|
.with_stderr(&host_output));
|
2016-03-15 00:00:39 +00:00
|
|
|
|
2016-05-20 16:23:50 +00:00
|
|
|
println!("b");
|
2016-03-15 00:00:39 +00:00
|
|
|
let target = host();
|
2017-02-15 14:16:41 +00:00
|
|
|
assert_that(p.cargo("test").arg("--target").arg(&target),
|
2016-03-15 00:00:39 +00:00
|
|
|
execs().with_status(0)
|
2016-11-06 02:14:16 +00:00
|
|
|
.with_stderr(&format!("\
|
|
|
|
[COMPILING] foo v0.0.0 ({foo})
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
|
|
|
|
[DOCTEST] foo
|
|
|
|
", foo = p.url(), triple = target)));
|
2016-03-15 00:00:39 +00:00
|
|
|
|
2016-05-20 16:23:50 +00:00
|
|
|
println!("c");
|
2016-03-15 00:00:39 +00:00
|
|
|
let target = alternate();
|
2017-02-15 14:16:41 +00:00
|
|
|
assert_that(p.cargo("test").arg("--target").arg(&target),
|
2016-03-15 00:00:39 +00:00
|
|
|
execs().with_status(0)
|
2016-05-19 00:51:07 +00:00
|
|
|
.with_stderr(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.0 ({foo})
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
|
2016-05-20 16:23:50 +00:00
|
|
|
", foo = p.url(), triple = target)));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2016-03-15 00:00:39 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn simple_cargo_run() {
|
2014-08-25 14:51:13 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let p = project("foo")
|
2014-08-27 15:01:26 +00:00
|
|
|
.file("Cargo.toml", r#"
|
2014-08-25 14:51:13 +00:00
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
2014-08-27 15:01:26 +00:00
|
|
|
"#)
|
2015-07-22 21:42:37 +00:00
|
|
|
.file("src/main.rs", &format!(r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-07-22 21:42:37 +00:00
|
|
|
fn main() {{
|
|
|
|
assert_eq!(env::consts::ARCH, "{}");
|
|
|
|
}}
|
|
|
|
"#, alternate_arch()));
|
2014-08-25 14:51:13 +00:00
|
|
|
|
|
|
|
let target = alternate();
|
2015-07-22 21:42:37 +00:00
|
|
|
assert_that(p.cargo_process("run").arg("--target").arg(&target),
|
2014-08-25 14:51:13 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-08-28 19:46:04 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn cross_with_a_build_script() {
|
2014-11-07 17:25:25 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let target = alternate();
|
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = 'build.rs'
|
|
|
|
"#)
|
2015-03-26 18:17:44 +00:00
|
|
|
.file("build.rs", &format!(r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-03-26 18:17:44 +00:00
|
|
|
use std::path::PathBuf;
|
2014-11-07 17:25:25 +00:00
|
|
|
fn main() {{
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(env::var("TARGET").unwrap(), "{0}");
|
|
|
|
let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
|
|
|
assert_eq!(path.file_name().unwrap().to_str().unwrap(), "out");
|
2014-11-07 17:25:25 +00:00
|
|
|
path.pop();
|
2015-03-26 18:17:44 +00:00
|
|
|
assert!(path.file_name().unwrap().to_str().unwrap()
|
|
|
|
.starts_with("foo-"));
|
2014-11-07 17:25:25 +00:00
|
|
|
path.pop();
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(path.file_name().unwrap().to_str().unwrap(), "build");
|
2014-11-07 17:25:25 +00:00
|
|
|
path.pop();
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(path.file_name().unwrap().to_str().unwrap(), "debug");
|
2015-03-03 21:46:02 +00:00
|
|
|
path.pop();
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(path.file_name().unwrap().to_str().unwrap(), "{0}");
|
2014-11-07 17:25:25 +00:00
|
|
|
path.pop();
|
2015-03-26 18:17:44 +00:00
|
|
|
assert_eq!(path.file_name().unwrap().to_str().unwrap(), "target");
|
2014-11-07 17:25:25 +00:00
|
|
|
}}
|
2015-03-26 18:17:44 +00:00
|
|
|
"#, target))
|
2014-11-07 17:25:25 +00:00
|
|
|
.file("src/main.rs", "fn main() {}");
|
|
|
|
|
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
|
|
|
execs().with_status(0)
|
2016-05-14 21:44:18 +00:00
|
|
|
.with_stderr(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.0 (file://[..])
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..]`
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..]`
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-05-11 16:55:43 +00:00
|
|
|
", target = target,
|
2015-03-26 18:17:44 +00:00
|
|
|
dir = p.root().display())));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-07 17:25:25 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn build_script_needed_for_host_and_target() {
|
2014-11-07 19:09:59 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let target = alternate();
|
2016-05-26 00:06:25 +00:00
|
|
|
let host = rustc_host();
|
2014-11-07 19:09:59 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = 'build.rs'
|
|
|
|
|
|
|
|
[dependencies.d1]
|
|
|
|
path = "d1"
|
|
|
|
[build-dependencies.d2]
|
|
|
|
path = "d2"
|
|
|
|
"#)
|
|
|
|
|
|
|
|
.file("build.rs", r#"
|
|
|
|
extern crate d2;
|
|
|
|
fn main() { d2::d2(); }
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", "
|
|
|
|
extern crate d1;
|
|
|
|
fn main() { d1::d1(); }
|
|
|
|
")
|
|
|
|
.file("d1/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = 'build.rs'
|
|
|
|
"#)
|
|
|
|
.file("d1/src/lib.rs", "
|
|
|
|
pub fn d1() {}
|
|
|
|
")
|
|
|
|
.file("d1/build.rs", r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2014-11-07 19:09:59 +00:00
|
|
|
fn main() {
|
2015-02-13 04:10:07 +00:00
|
|
|
let target = env::var("TARGET").unwrap();
|
2014-11-07 19:09:59 +00:00
|
|
|
println!("cargo:rustc-flags=-L /path/to/{}", target);
|
|
|
|
}
|
|
|
|
"#)
|
|
|
|
.file("d2/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d2"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.d1]
|
|
|
|
path = "../d1"
|
|
|
|
"#)
|
|
|
|
.file("d2/src/lib.rs", "
|
|
|
|
extern crate d1;
|
|
|
|
pub fn d2() { d1::d1(); }
|
|
|
|
");
|
|
|
|
|
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
|
|
|
execs().with_status(0)
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] d1 v0.0.0 ({url}/d1)", url = p.url()))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] d1[/]build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]d1-[..]`",
|
2016-05-11 16:55:43 +00:00
|
|
|
dir = p.root().display()))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] `{dir}[/]target[/]debug[/]build[/]d1-[..][/]build-script-build`",
|
2015-10-11 18:33:55 +00:00
|
|
|
dir = p.root().display()))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains("\
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`")
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] d2 v0.0.0 ({url}/d2)", url = p.url()))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..] \
|
2016-05-11 16:55:43 +00:00
|
|
|
-L /path/to/{host}`", host = host))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.0 ({url})", url = p.url()))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..] \
|
2016-05-11 16:55:43 +00:00
|
|
|
-L /path/to/{host}`", dir = p.root().display(), host = host))
|
2016-05-18 23:41:30 +00:00
|
|
|
.with_stderr_contains(&format!("\
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..] \
|
2016-05-11 16:55:43 +00:00
|
|
|
-L /path/to/{target}`", target = target)));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-07 20:59:44 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn build_deps_for_the_right_arch() {
|
2014-11-07 20:59:44 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[dependencies.d2]
|
|
|
|
path = "d2"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", "extern crate d2; fn main() {}")
|
|
|
|
.file("d1/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
"#)
|
|
|
|
.file("d1/src/lib.rs", "
|
|
|
|
pub fn d1() {}
|
|
|
|
")
|
|
|
|
.file("d2/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d2"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[build-dependencies.d1]
|
|
|
|
path = "../d1"
|
|
|
|
"#)
|
|
|
|
.file("d2/build.rs", "extern crate d1; fn main() {}")
|
|
|
|
.file("d2/src/lib.rs", "");
|
|
|
|
|
|
|
|
let target = alternate();
|
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-12-18 00:32:20 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn build_script_only_host() {
|
2014-12-18 00:32:20 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[build-dependencies.d1]
|
|
|
|
path = "d1"
|
|
|
|
"#)
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.file("build.rs", "extern crate d1; fn main() {}")
|
|
|
|
.file("d1/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
"#)
|
|
|
|
.file("d1/src/lib.rs", "
|
|
|
|
pub fn d1() {}
|
|
|
|
")
|
|
|
|
.file("d1/build.rs", r#"
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2014-12-18 00:32:20 +00:00
|
|
|
|
|
|
|
fn main() {
|
2015-07-22 21:42:37 +00:00
|
|
|
assert!(env::var("OUT_DIR").unwrap().replace("\\", "/")
|
|
|
|
.contains("target/debug/build/d1-"),
|
2015-02-13 04:10:07 +00:00
|
|
|
"bad: {:?}", env::var("OUT_DIR"));
|
2014-12-18 00:32:20 +00:00
|
|
|
}
|
|
|
|
"#);
|
|
|
|
|
|
|
|
let target = alternate();
|
|
|
|
assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"),
|
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2015-01-29 06:28:31 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn plugin_build_script_right_arch() {
|
2015-01-29 06:28:31 +00:00
|
|
|
if disabled() { return }
|
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[lib]
|
|
|
|
name = "foo"
|
|
|
|
plugin = true
|
|
|
|
"#)
|
|
|
|
.file("build.rs", "fn main() {}")
|
|
|
|
.file("src/lib.rs", "");
|
|
|
|
|
|
|
|
assert_that(p.cargo_process("build").arg("-v").arg("--target").arg(alternate()),
|
|
|
|
execs().with_status(0)
|
2016-05-14 21:15:22 +00:00
|
|
|
.with_stderr("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.1 ([..])
|
2016-11-30 00:05:55 +00:00
|
|
|
[RUNNING] `rustc [..] build.rs [..]`
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] `[..][/]build-script-build`
|
2016-11-30 00:05:55 +00:00
|
|
|
[RUNNING] `rustc [..] src[/]lib.rs [..]`
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-05-12 17:06:36 +00:00
|
|
|
"));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2015-08-31 23:33:29 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn build_script_with_platform_specific_dependencies() {
|
2015-08-31 23:33:29 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let target = alternate();
|
2016-05-26 00:06:25 +00:00
|
|
|
let host = rustc_host();
|
2015-08-31 23:33:29 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[build-dependencies.d1]
|
|
|
|
path = "d1"
|
|
|
|
"#)
|
|
|
|
.file("build.rs", "extern crate d1; fn main() {}")
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.file("d1/Cargo.toml", &format!(r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[target.{}.dependencies]
|
|
|
|
d2 = {{ path = "../d2" }}
|
|
|
|
"#, host))
|
|
|
|
.file("d1/src/lib.rs", "extern crate d2;")
|
|
|
|
.file("d2/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d2"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
"#)
|
|
|
|
.file("d2/src/lib.rs", "");
|
|
|
|
|
|
|
|
assert_that(p.cargo_process("build").arg("-v").arg("--target").arg(&target),
|
|
|
|
execs().with_status(0)
|
2016-05-14 21:44:18 +00:00
|
|
|
.with_stderr(&format!("\
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] d2 v0.0.0 ([..])
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..]`
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] d1 v0.0.0 ([..])
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`
|
2016-05-11 16:55:43 +00:00
|
|
|
[COMPILING] foo v0.0.1 ([..])
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] build.rs [..]`
|
2016-11-06 02:14:16 +00:00
|
|
|
[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
|
2016-11-29 23:11:58 +00:00
|
|
|
[RUNNING] `rustc [..] src[/]lib.rs [..] --target {target} [..]`
|
2017-01-12 01:03:36 +00:00
|
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
2016-05-11 16:55:43 +00:00
|
|
|
", dir = p.root().display(), target = target)));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2015-08-31 23:33:29 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn platform_specific_dependencies_do_not_leak() {
|
2015-08-31 23:33:29 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let target = alternate();
|
2016-05-26 00:06:25 +00:00
|
|
|
let host = rustc_host();
|
2015-08-31 23:33:29 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[dependencies.d1]
|
|
|
|
path = "d1"
|
|
|
|
|
|
|
|
[build-dependencies.d1]
|
|
|
|
path = "d1"
|
|
|
|
"#)
|
|
|
|
.file("build.rs", "extern crate d1; fn main() {}")
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.file("d1/Cargo.toml", &format!(r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
|
|
|
|
[target.{}.dependencies]
|
|
|
|
d2 = {{ path = "../d2" }}
|
|
|
|
"#, host))
|
|
|
|
.file("d1/src/lib.rs", "extern crate d2;")
|
|
|
|
.file("d2/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d2"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
"#)
|
|
|
|
.file("d2/src/lib.rs", "");
|
|
|
|
|
|
|
|
assert_that(p.cargo_process("build").arg("-v").arg("--target").arg(&target),
|
|
|
|
execs().with_status(101)
|
2016-05-20 16:23:50 +00:00
|
|
|
.with_stderr_contains("\
|
2016-05-25 17:04:39 +00:00
|
|
|
[..] can't find crate for `d2`[..]"));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2015-08-31 23:33:29 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn platform_specific_variables_reflected_in_build_scripts() {
|
2015-08-31 23:33:29 +00:00
|
|
|
if disabled() { return }
|
|
|
|
|
|
|
|
let target = alternate();
|
2016-05-26 00:06:25 +00:00
|
|
|
let host = rustc_host();
|
2015-08-31 23:33:29 +00:00
|
|
|
let p = project("foo")
|
|
|
|
.file("Cargo.toml", &format!(r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
build = "build.rs"
|
|
|
|
|
|
|
|
[target.{host}.dependencies]
|
|
|
|
d1 = {{ path = "d1" }}
|
|
|
|
|
|
|
|
[target.{target}.dependencies]
|
|
|
|
d2 = {{ path = "d2" }}
|
|
|
|
"#, host = host, target = target))
|
|
|
|
.file("build.rs", &format!(r#"
|
|
|
|
use std::env;
|
|
|
|
|
|
|
|
fn main() {{
|
|
|
|
let platform = env::var("TARGET").unwrap();
|
|
|
|
let (expected, not_expected) = match &platform[..] {{
|
|
|
|
"{host}" => ("DEP_D1_VAL", "DEP_D2_VAL"),
|
|
|
|
"{target}" => ("DEP_D2_VAL", "DEP_D1_VAL"),
|
|
|
|
_ => panic!("unknown platform")
|
|
|
|
}};
|
|
|
|
|
Refactor Cargo's backend, again!
This commit started out identifying a relatively simple bug in Cargo. A recent
change made it such that the resolution graph included all target-specific
dependencies, relying on the structure of the backend to filter out those which
don't need to get built. This was unfortunately not accounted for in the portion
of the backend that schedules work, mistakenly causing spurious rebuilds if
different runs of the graph pulled in new crates. For example if `cargo build`
didn't build any target-specific dependencies but then later `cargo test` did
(e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would
cause a rebuild of the entire graph.
This class of bug is certainly not the first in a long and storied history of
the backend having multiple points where dependencies are calculated and those
often don't quite agree with one another. The purpose of this rewrite is
twofold:
1. The `Stage` enum in the backend for scheduling work and ensuring that maximum
parallelism is achieved is removed entirely. There is already a function on
`Context` which expresses the dependency between targets (`dep_targets`)
which takes a much finer grain of dependencies into account as well as
already having all the logic for what-depends-on-what. This duplication has
caused numerous problems in the past, an unifying these two will truly grant
maximum parallelism while ensuring that everyone agrees on what their
dependencies are.
2. A large number of locations in the backend have grown to take a (Package,
Target, Profile, Kind) tuple, or some subset of this tuple. In general this
represents a "unit of work" and is much easier to pass around as one
variable, so a `Unit` was introduced which references all of these variables.
Almost the entire backend was altered to take a `Unit` instead of these
variables specifically, typically providing all of the contextual information
necessary for an operation.
A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure
that everyone *also* agrees on what architecture they're compiling everything
for. There have been many bugs in the past where one part of the backend
determined that a package was built for one architecture and then another part
thought it was built for another. With the inclusion of `Kind` in dependency
management this is handled in a much cleaner fashion as it's only calculated in
one location.
Some other miscellaneous changes made were:
* The `Platform` enumeration has finally been removed. This has been entirely
subsumed by `Kind`.
* The hokey logic for "build this crate once" even though it may be depended on
by both the host/target kinds has been removed. This is now handled in a much
nicer fashion where if there's no target then Kind::Target is just never used,
and multiple requests for a package are just naturally deduplicated.
* There's no longer any need to build up the "requirements" for a package in
terms of what platforms it's compiled for, this now just naturally falls out
of the dependency graph.
* If a build script is overridden then its entire tree of dependencies are not
compiled, not just the build script itself.
* The `threadpool` dependency has been replaced with one on `crossbeam`. The
method of calculating dependencies has quite a few non-static lifetimes and
the scoped threads of `crossbeam` are now used instead of a thread pool.
* Once any thread fails to execute a command work is no longer scheduled unlike
before where some extra pending work may continue to start.
* Many functions used early on, such as `compile` and `build_map` have been
massively simplified by farming out dependency management to
`Context::dep_targets`.
* There is now a new profile to represent running a build script. This is used
to inject dependencies as well as represent that a library depends on running
a build script, not just building it.
This change has currently been tested against cross-compiling Servo to Android
and passes the test suite (which has quite a few corner cases for build scripts
and such), so I'm pretty confident that this refactoring won't have at least too
many regressions!
2015-10-02 06:48:47 +00:00
|
|
|
env::var(expected).ok()
|
|
|
|
.expect(&format!("missing {{}}", expected));
|
|
|
|
env::var(not_expected).err()
|
|
|
|
.expect(&format!("found {{}}", not_expected));
|
2015-08-31 23:33:29 +00:00
|
|
|
}}
|
|
|
|
"#, host = host, target = target))
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.file("d1/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d1"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
links = "d1"
|
|
|
|
build = "build.rs"
|
|
|
|
"#)
|
|
|
|
.file("d1/build.rs", r#"
|
|
|
|
fn main() { println!("cargo:val=1") }
|
|
|
|
"#)
|
|
|
|
.file("d1/src/lib.rs", "")
|
|
|
|
.file("d2/Cargo.toml", r#"
|
|
|
|
[package]
|
|
|
|
name = "d2"
|
|
|
|
version = "0.0.0"
|
|
|
|
authors = []
|
|
|
|
links = "d2"
|
|
|
|
build = "build.rs"
|
|
|
|
"#)
|
|
|
|
.file("d2/build.rs", r#"
|
|
|
|
fn main() { println!("cargo:val=1") }
|
|
|
|
"#)
|
|
|
|
.file("d2/src/lib.rs", "");
|
2017-02-15 14:16:41 +00:00
|
|
|
p.build();
|
2015-08-31 23:33:29 +00:00
|
|
|
|
2017-02-15 14:16:41 +00:00
|
|
|
assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
|
|
|
|
assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
|
2015-08-31 23:33:29 +00:00
|
|
|
execs().with_status(0));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|