| //! Tests for cross compiling with --target. |
| //! |
| //! See `cargo_test_support::cross_compile` for more detail. |
| |
| use cargo_test_support::prelude::*; |
| use cargo_test_support::rustc_host; |
| use cargo_test_support::str; |
| use cargo_test_support::{basic_bin_manifest, basic_manifest, cross_compile, project}; |
| |
| #[cargo_test] |
| fn simple_cross() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| "#, |
| ) |
| .file( |
| "build.rs", |
| &format!( |
| r#" |
| fn main() {{ |
| assert_eq!(std::env::var("TARGET").unwrap(), "{}"); |
| }} |
| "#, |
| cross_compile::alternate() |
| ), |
| ) |
| .file( |
| "src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("build -v --target").arg(&target).run(); |
| assert!(p.target_bin(target, "foo").is_file()); |
| |
| if cross_compile::can_run_on_host() { |
| p.process(&p.target_bin(target, "foo")).run(); |
| } |
| } |
| |
| #[cargo_test] |
| fn simple_cross_config() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| ".cargo/config.toml", |
| &format!( |
| r#" |
| [build] |
| target = "{}" |
| "#, |
| cross_compile::alternate() |
| ), |
| ) |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| "#, |
| ) |
| .file( |
| "build.rs", |
| &format!( |
| r#" |
| fn main() {{ |
| assert_eq!(std::env::var("TARGET").unwrap(), "{}"); |
| }} |
| "#, |
| cross_compile::alternate() |
| ), |
| ) |
| .file( |
| "src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("build -v").run(); |
| assert!(p.target_bin(target, "foo").is_file()); |
| |
| if cross_compile::can_run_on_host() { |
| p.process(&p.target_bin(target, "foo")).run(); |
| } |
| } |
| |
| #[cargo_test] |
| fn simple_deps() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2015" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file("src/main.rs", "extern crate bar; fn main() { bar::bar(); }") |
| .build(); |
| let _p2 = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) |
| .file("src/lib.rs", "pub fn bar() {}") |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("build --target").arg(&target).run(); |
| assert!(p.target_bin(target, "foo").is_file()); |
| |
| if cross_compile::can_run_on_host() { |
| p.process(&p.target_bin(target, "foo")).run(); |
| } |
| } |
| |
| /// Always take care of setting these so that |
| /// `cross_compile::alternate()` is the actually-picked target |
| fn per_crate_target_test( |
| default_target: Option<&'static str>, |
| forced_target: Option<&'static str>, |
| arg_target: Option<&'static str>, |
| ) { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| cargo-features = ["per-package-target"] |
| |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| {} |
| {} |
| "#, |
| default_target |
| .map(|t| format!(r#"default-target = "{}""#, t)) |
| .unwrap_or(String::new()), |
| forced_target |
| .map(|t| format!(r#"forced-target = "{}""#, t)) |
| .unwrap_or(String::new()), |
| ), |
| ) |
| .file( |
| "build.rs", |
| &format!( |
| r#" |
| fn main() {{ |
| assert_eq!(std::env::var("TARGET").unwrap(), "{}"); |
| }} |
| "#, |
| cross_compile::alternate() |
| ), |
| ) |
| .file( |
| "src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let mut cmd = p.cargo("build -v"); |
| if let Some(t) = arg_target { |
| cmd.arg("--target").arg(&t); |
| } |
| cmd.masquerade_as_nightly_cargo(&["per-package-target"]) |
| .run(); |
| assert!(p.target_bin(cross_compile::alternate(), "foo").is_file()); |
| |
| if cross_compile::can_run_on_host() { |
| p.process(&p.target_bin(cross_compile::alternate(), "foo")) |
| .run(); |
| } |
| } |
| |
| #[cargo_test] |
| fn per_crate_default_target_is_default() { |
| per_crate_target_test(Some(cross_compile::alternate()), None, None); |
| } |
| |
| #[cargo_test] |
| fn per_crate_default_target_gets_overridden() { |
| per_crate_target_test( |
| Some(cross_compile::unused()), |
| None, |
| Some(cross_compile::alternate()), |
| ); |
| } |
| |
| #[cargo_test] |
| fn per_crate_forced_target_is_default() { |
| per_crate_target_test(None, Some(cross_compile::alternate()), None); |
| } |
| |
| #[cargo_test] |
| fn per_crate_forced_target_does_not_get_overridden() { |
| per_crate_target_test( |
| None, |
| Some(cross_compile::alternate()), |
| Some(cross_compile::unused()), |
| ); |
| } |
| |
| #[cargo_test] |
| fn workspace_with_multiple_targets() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["native", "cross"] |
| "#, |
| ) |
| .file( |
| "native/Cargo.toml", |
| r#" |
| cargo-features = ["per-package-target"] |
| |
| [package] |
| name = "native" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| "#, |
| ) |
| .file( |
| "native/build.rs", |
| &format!( |
| r#" |
| fn main() {{ |
| assert_eq!(std::env::var("TARGET").unwrap(), "{}"); |
| }} |
| "#, |
| cross_compile::native() |
| ), |
| ) |
| .file( |
| "native/src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::native_arch() |
| ), |
| ) |
| .file( |
| "cross/Cargo.toml", |
| &format!( |
| r#" |
| cargo-features = ["per-package-target"] |
| |
| [package] |
| name = "cross" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| default-target = "{}" |
| "#, |
| cross_compile::alternate(), |
| ), |
| ) |
| .file( |
| "cross/build.rs", |
| &format!( |
| r#" |
| fn main() {{ |
| assert_eq!(std::env::var("TARGET").unwrap(), "{}"); |
| }} |
| "#, |
| cross_compile::alternate() |
| ), |
| ) |
| .file( |
| "cross/src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let mut cmd = p.cargo("build -v"); |
| cmd.masquerade_as_nightly_cargo(&["per-package-target"]) |
| .run(); |
| |
| assert!(p.bin("native").is_file()); |
| assert!(p.target_bin(cross_compile::alternate(), "cross").is_file()); |
| |
| p.process(&p.bin("native")).run(); |
| if cross_compile::can_run_on_host() { |
| p.process(&p.target_bin(cross_compile::alternate(), "cross")) |
| .run(); |
| } |
| } |
| |
| #[cargo_test] |
| fn linker() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let p = project() |
| .file( |
| ".cargo/config.toml", |
| &format!( |
| r#" |
| [target.{}] |
| linker = "my-linker-tool" |
| "#, |
| target |
| ), |
| ) |
| .file("Cargo.toml", &basic_bin_manifest("foo")) |
| .file( |
| "src/foo.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| p.cargo("build -v --target") |
| .arg(&target) |
| .with_status(101) |
| .with_stderr_data(str![[r#" |
| [WARNING] path `src/foo.rs` was erroneously implicitly accepted for binary `foo`, |
| please set bin.path in Cargo.toml |
| [COMPILING] foo v0.5.0 ([ROOT]/foo) |
| [RUNNING] `rustc --crate-name foo --edition=2015 src/foo.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..] -C metadata=[..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] -C linker=my-linker-tool -L dependency=[ROOT]/foo/target/[ALT_TARGET]/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` |
| [ERROR] linker `my-linker-tool` not found |
| ... |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn cross_tests() { |
| if !cross_compile::can_run_on_host() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| authors = [] |
| version = "0.0.0" |
| edition = "2015" |
| |
| [[bin]] |
| name = "bar" |
| "#, |
| ) |
| .file( |
| "src/bin/bar.rs", |
| &format!( |
| r#" |
| #[allow(unused_extern_crates)] |
| extern crate foo; |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| #[test] fn test() {{ main() }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .file( |
| "src/lib.rs", |
| &format!( |
| r#" |
| use std::env; |
| pub fn foo() {{ assert_eq!(env::consts::ARCH, "{}"); }} |
| #[test] fn test_foo() {{ foo() }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("test --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [COMPILING] foo v0.0.0 ([ROOT]/foo) |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]) |
| [RUNNING] unittests src/bin/bar.rs (target/[ALT_TARGET]/debug/deps/bar-[HASH][EXE]) |
| |
| "#]]) |
| .with_stdout_data(str![[r#" |
| |
| running 1 test |
| test test_foo ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| running 1 test |
| test test ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_cross_doctests() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "src/lib.rs", |
| r#" |
| //! ``` |
| //! extern crate foo; |
| //! assert!(true); |
| //! ``` |
| "#, |
| ) |
| .build(); |
| |
| let host_output = "\ |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) |
| [DOCTEST] foo |
| "; |
| |
| println!("a"); |
| p.cargo("test").with_stderr_data(host_output).run(); |
| |
| println!("b"); |
| let target = rustc_host(); |
| p.cargo("test -v --target") |
| .arg(&target) |
| // Unordered since the two `rustc` invocations happen concurrently. |
| .with_stderr_data( |
| str![[r#" |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [RUNNING] `rustc --crate-name foo [..]--crate-type lib[..] |
| [RUNNING] `rustc --crate-name foo [..]--test[..] |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [RUNNING] `[ROOT]/foo/target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE]` |
| [DOCTEST] foo |
| [RUNNING] `rustdoc [..]--target [HOST_TARGET][..]` |
| |
| "#]] |
| .unordered(), |
| ) |
| .with_stdout_data(str![[r#" |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| running 1 test |
| test src/lib.rs - (line 2) ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| "#]]) |
| .run(); |
| |
| println!("c"); |
| let target = cross_compile::alternate(); |
| |
| // This will build the library, but does not build or run doc tests. |
| // This should probably be a warning or error. |
| p.cargo("test -v --doc --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [RUNNING] `rustc --crate-name foo [..] |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported |
| See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. |
| |
| "#]]) |
| .run(); |
| |
| if !cross_compile::can_run_on_host() { |
| return; |
| } |
| |
| // This tests the library, but does not run the doc tests. |
| p.cargo("test -v --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [RUNNING] `rustc --crate-name foo [..]--test[..] |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [RUNNING] `[ROOT]/foo/target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]` |
| [NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported |
| See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. |
| |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn simple_cargo_run() { |
| if !cross_compile::can_run_on_host() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "src/main.rs", |
| &format!( |
| r#" |
| use std::env; |
| fn main() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("run --target").arg(&target).run(); |
| } |
| |
| #[cargo_test] |
| fn cross_with_a_build_script() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = 'build.rs' |
| "#, |
| ) |
| .file( |
| "build.rs", |
| &format!( |
| r#" |
| use std::env; |
| use std::path::PathBuf; |
| fn main() {{ |
| 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"); |
| path.pop(); |
| assert!(path.file_name().unwrap().to_str().unwrap() |
| .starts_with("foo-")); |
| path.pop(); |
| assert_eq!(path.file_name().unwrap().to_str().unwrap(), "build"); |
| path.pop(); |
| assert_eq!(path.file_name().unwrap().to_str().unwrap(), "debug"); |
| path.pop(); |
| assert_eq!(path.file_name().unwrap().to_str().unwrap(), "{0}"); |
| path.pop(); |
| assert_eq!(path.file_name().unwrap().to_str().unwrap(), "target"); |
| }} |
| "#, |
| target |
| ), |
| ) |
| .file("src/main.rs", "fn main() {}") |
| .build(); |
| |
| p.cargo("build -v --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [COMPILING] foo v0.0.0 ([ROOT]/foo) |
| [RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..] |
| [RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` |
| [RUNNING] `rustc [..] src/main.rs [..] --target [ALT_TARGET] [..]` |
| [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn build_script_needed_for_host_and_target() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = 'build.rs' |
| |
| [dependencies.d1] |
| path = "d1" |
| [build-dependencies.d2] |
| path = "d2" |
| "#, |
| ) |
| .file( |
| "build.rs", |
| r#" |
| #[allow(unused_extern_crates)] |
| extern crate d2; |
| fn main() { d2::d2(); } |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| " |
| #[allow(unused_extern_crates)] |
| extern crate d1; |
| fn main() { d1::d1(); } |
| ", |
| ) |
| .file( |
| "d1/Cargo.toml", |
| r#" |
| [package] |
| name = "d1" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = 'build.rs' |
| "#, |
| ) |
| .file("d1/src/lib.rs", "pub fn d1() {}") |
| .file( |
| "d1/build.rs", |
| r#" |
| use std::env; |
| fn main() { |
| let target = env::var("TARGET").unwrap(); |
| println!("cargo::rustc-flags=-L /path/to/{}", target); |
| } |
| "#, |
| ) |
| .file( |
| "d2/Cargo.toml", |
| r#" |
| [package] |
| name = "d2" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| |
| [dependencies.d1] |
| path = "../d1" |
| "#, |
| ) |
| .file( |
| "d2/src/lib.rs", |
| " |
| #[allow(unused_extern_crates)] |
| extern crate d1; |
| pub fn d2() { d1::d1(); } |
| ", |
| ) |
| .build(); |
| |
| p.cargo("build -v --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [LOCKING] 2 packages to latest compatible versions |
| [COMPILING] d1 v0.0.0 ([ROOT]/foo/d1) |
| [RUNNING] `rustc [..] d1/build.rs [..] --out-dir [ROOT]/foo/target/debug/build/d1-[HASH] [..] |
| [RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build` |
| [RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build` |
| [RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..] |
| [RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps [..] |
| [COMPILING] d2 v0.0.0 ([ROOT]/foo/d2) |
| [RUNNING] `rustc [..] d2/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..] |
| [COMPILING] foo v0.0.0 ([ROOT]/foo) |
| [RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..] |
| [RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` |
| [RUNNING] `rustc [..] src/main.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..] |
| [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| |
| "#]].unordered()) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn build_deps_for_the_right_arch() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| |
| [dependencies.d2] |
| path = "d2" |
| "#, |
| ) |
| .file("src/main.rs", "extern crate d2; fn main() {}") |
| .file("d1/Cargo.toml", &basic_manifest("d1", "0.0.0")) |
| .file("d1/src/lib.rs", "pub fn d1() {}") |
| .file( |
| "d2/Cargo.toml", |
| r#" |
| [package] |
| name = "d2" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| |
| [build-dependencies.d1] |
| path = "../d1" |
| "#, |
| ) |
| .file("d2/build.rs", "extern crate d1; fn main() {}") |
| .file("d2/src/lib.rs", "") |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("build -v --target").arg(&target).run(); |
| } |
| |
| #[cargo_test] |
| fn build_script_only_host() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.0" |
| edition = "2015" |
| 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" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| "#, |
| ) |
| .file("d1/src/lib.rs", "pub fn d1() {}") |
| .file( |
| "d1/build.rs", |
| r#" |
| use std::env; |
| |
| fn main() { |
| assert!(env::var("OUT_DIR").unwrap().replace("\\", "/") |
| .contains("target/debug/build/d1-"), |
| "bad: {:?}", env::var("OUT_DIR")); |
| } |
| "#, |
| ) |
| .build(); |
| |
| let target = cross_compile::alternate(); |
| p.cargo("build -v --target").arg(&target).run(); |
| } |
| |
| #[cargo_test] |
| fn build_script_with_platform_specific_dependencies() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let host = rustc_host(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2015" |
| authors = [] |
| build = "build.rs" |
| |
| [build-dependencies.d1] |
| path = "d1" |
| "#, |
| ) |
| .file( |
| "build.rs", |
| " |
| #[allow(unused_extern_crates)] |
| extern crate d1; |
| fn main() {} |
| ", |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "d1/Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "d1" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| |
| [target.{}.dependencies] |
| d2 = {{ path = "../d2" }} |
| "#, |
| host |
| ), |
| ) |
| .file( |
| "d1/src/lib.rs", |
| "#[allow(unused_extern_crates)] extern crate d2;", |
| ) |
| .file("d2/Cargo.toml", &basic_manifest("d2", "0.0.0")) |
| .file("d2/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("build -v --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [LOCKING] 2 packages to latest compatible versions |
| [COMPILING] d2 v0.0.0 ([ROOT]/foo/d2) |
| [RUNNING] `rustc [..] d2/src/lib.rs [..]` |
| [COMPILING] d1 v0.0.0 ([ROOT]/foo/d1) |
| [RUNNING] `rustc [..] d1/src/lib.rs [..]` |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [RUNNING] `rustc [..] build.rs [..]` |
| [RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` |
| [RUNNING] `rustc [..] src/lib.rs [..] --target [ALT_TARGET] [..]` |
| [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn platform_specific_dependencies_do_not_leak() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let host = rustc_host(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2015" |
| 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" |
| edition = "2015" |
| authors = [] |
| |
| [target.{}.dependencies] |
| d2 = {{ path = "../d2" }} |
| "#, |
| host |
| ), |
| ) |
| .file("d1/src/lib.rs", "extern crate d2;") |
| .file("d1/Cargo.toml", &basic_manifest("d1", "0.0.0")) |
| .file("d2/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("build -v --target") |
| .arg(&target) |
| .with_status(101) |
| .with_stderr_data(str![[r#" |
| ... |
| error[E0463]: can't find crate for `d2` |
| ... |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn platform_specific_variables_reflected_in_build_scripts() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let host = rustc_host(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2015" |
| 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") |
| }}; |
| |
| env::var(expected).ok() |
| .expect(&format!("missing {{}}", expected)); |
| env::var(not_expected).err() |
| .expect(&format!("found {{}}", not_expected)); |
| }} |
| "#, |
| host = host, |
| target = target |
| ), |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "d1/Cargo.toml", |
| r#" |
| [package] |
| name = "d1" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| links = "d1" |
| build = "build.rs" |
| "#, |
| ) |
| .file( |
| "d1/build.rs", |
| r#"fn main() { println!("cargo::metadata=val=1") }"#, |
| ) |
| .file("d1/src/lib.rs", "") |
| .file( |
| "d2/Cargo.toml", |
| r#" |
| [package] |
| name = "d2" |
| version = "0.0.0" |
| edition = "2015" |
| authors = [] |
| links = "d2" |
| build = "build.rs" |
| "#, |
| ) |
| .file( |
| "d2/build.rs", |
| r#"fn main() { println!("cargo::metadata=val=1") }"#, |
| ) |
| .file("d2/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("build -v").run(); |
| p.cargo("build -v --target").arg(&target).run(); |
| } |
| |
| #[cargo_test] |
| #[cfg_attr( |
| target_os = "macos", |
| ignore = "don't have a dylib cross target on macos" |
| )] |
| fn cross_test_dylib() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2015" |
| authors = [] |
| |
| [lib] |
| name = "foo" |
| crate-type = ["dylib"] |
| |
| [dependencies.bar] |
| path = "bar" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| extern crate bar as the_bar; |
| |
| pub fn bar() { the_bar::baz(); } |
| |
| #[test] |
| fn foo() { bar(); } |
| "#, |
| ) |
| .file( |
| "tests/test.rs", |
| r#" |
| extern crate foo as the_foo; |
| |
| #[test] |
| fn foo() { the_foo::bar(); } |
| "#, |
| ) |
| .file( |
| "bar/Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| edition = "2015" |
| authors = [] |
| |
| [lib] |
| name = "bar" |
| crate-type = ["dylib"] |
| "#, |
| ) |
| .file( |
| "bar/src/lib.rs", |
| &format!( |
| r#" |
| use std::env; |
| pub fn baz() {{ |
| assert_eq!(env::consts::ARCH, "{}"); |
| }} |
| "#, |
| cross_compile::alternate_arch() |
| ), |
| ) |
| .build(); |
| |
| p.cargo("test --target") |
| .arg(&target) |
| .with_stderr_data(str![[r#" |
| [LOCKING] 1 package to latest compatible version |
| [COMPILING] bar v0.0.1 ([ROOT]/foo/bar) |
| [COMPILING] foo v0.0.1 ([ROOT]/foo) |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]) |
| [RUNNING] tests/test.rs (target/[ALT_TARGET]/debug/deps/test-[HASH][EXE]) |
| |
| "#]]) |
| .with_stdout_data(str![[r#" |
| |
| running 1 test |
| test foo ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| running 1 test |
| test foo ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s |
| |
| |
| "#]]) |
| .run(); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] |
| fn doctest_xcompile_linker() { |
| if cross_compile::disabled() { |
| return; |
| } |
| |
| let target = cross_compile::alternate(); |
| let p = project() |
| .file( |
| ".cargo/config.toml", |
| &format!( |
| r#" |
| [target.{}] |
| linker = "my-linker-tool" |
| "#, |
| target |
| ), |
| ) |
| .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) |
| .file( |
| "src/lib.rs", |
| r#" |
| /// ``` |
| /// assert_eq!(1, 1); |
| /// ``` |
| pub fn foo() {} |
| "#, |
| ) |
| .build(); |
| |
| // Fails because `my-linker-tool` doesn't actually exist. |
| p.cargo("test --doc -v -Zdoctest-xcompile --target") |
| .arg(&target) |
| .with_status(101) |
| .masquerade_as_nightly_cargo(&["doctest-xcompile"]) |
| .with_stderr_data(str![[r#" |
| [COMPILING] foo v0.1.0 ([ROOT]/foo) |
| [RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..] |
| [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s |
| [DOCTEST] foo |
| [RUNNING] `rustdoc [..] src/lib.rs [..] |
| [ERROR] doctest failed, to rerun pass `--doc` |
| |
| "#]]) |
| .run(); |
| } |