Skip to content

Commit b524682

Browse files
committed
Auto merge of #4440 - nisargthakkar:publish_target, r=alexcrichton
Adding target support to cargo package and cargo publish Fixing Issue #4012 Same as #4077 but couldn't reopen the PR due to force push after rebasing from master
2 parents 814c389 + 0a4e04c commit b524682

File tree

10 files changed

+360
-243
lines changed

10 files changed

+360
-243
lines changed

src/bin/package.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct Options {
88
flag_verbose: u32,
99
flag_quiet: Option<bool>,
1010
flag_color: Option<String>,
11+
flag_target: Option<String>,
1112
flag_manifest_path: Option<String>,
1213
flag_no_verify: bool,
1314
flag_no_metadata: bool,
@@ -32,6 +33,7 @@ Options:
3233
--no-verify Don't verify the contents by building them
3334
--no-metadata Ignore warnings about a lack of human-usable metadata
3435
--allow-dirty Allow dirty working directories to be packaged
36+
--target TRIPLE Build for the target triple
3537
--manifest-path PATH Path to the manifest to compile
3638
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
3739
-v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
@@ -57,6 +59,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult {
5759
list: options.flag_list,
5860
check_metadata: !options.flag_no_metadata,
5961
allow_dirty: options.flag_allow_dirty,
62+
target: options.flag_target.as_ref().map(|t| &t[..]),
6063
jobs: options.flag_jobs,
6164
})?;
6265
Ok(())

src/bin/publish.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct Options {
88
flag_index: Option<String>,
99
flag_host: Option<String>, // TODO: Deprecated, remove
1010
flag_token: Option<String>,
11+
flag_target: Option<String>,
1112
flag_manifest_path: Option<String>,
1213
flag_verbose: u32,
1314
flag_quiet: Option<bool>,
@@ -35,6 +36,7 @@ Options:
3536
--token TOKEN Token to use when uploading
3637
--no-verify Don't verify package tarball before publish
3738
--allow-dirty Allow publishing with a dirty source directory
39+
--target TRIPLE Build for the target triple
3840
--manifest-path PATH Path to the manifest of the package to publish
3941
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
4042
--dry-run Perform all checks without uploading
@@ -64,6 +66,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult {
6466
flag_allow_dirty: allow_dirty,
6567
flag_jobs: jobs,
6668
flag_dry_run: dry_run,
69+
flag_target: target,
6770
..
6871
} = options;
6972

@@ -94,6 +97,7 @@ about this warning.";
9497
else { config.shell().warn(&msg)?; host }, // TODO: Deprecated, remove
9598
verify: !no_verify,
9699
allow_dirty: allow_dirty,
100+
target: target.as_ref().map(|t| &t[..]),
97101
jobs: jobs,
98102
dry_run: dry_run,
99103
})?;

src/cargo/ops/cargo_package.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct PackageOpts<'cfg> {
2222
pub allow_dirty: bool,
2323
pub verify: bool,
2424
pub jobs: Option<u32>,
25+
pub target: Option<&'cfg str>,
2526
}
2627

2728
pub fn package(ws: &Workspace,
@@ -298,7 +299,7 @@ fn run_verify(ws: &Workspace, tar: &File, opts: &PackageOpts) -> CargoResult<()>
298299
ops::compile_ws(&ws, None, &ops::CompileOptions {
299300
config: config,
300301
jobs: opts.jobs,
301-
target: None,
302+
target: opts.target,
302303
features: &[],
303304
no_default_features: false,
304305
all_features: false,

src/cargo/ops/registry.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct PublishOpts<'cfg> {
3434
pub verify: bool,
3535
pub allow_dirty: bool,
3636
pub jobs: Option<u32>,
37+
pub target: Option<&'cfg str>,
3738
pub dry_run: bool,
3839
}
3940

@@ -61,6 +62,7 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> {
6162
list: false,
6263
check_metadata: true,
6364
allow_dirty: opts.allow_dirty,
65+
target: opts.target,
6466
jobs: opts.jobs,
6567
})?.unwrap();
6668

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
use std::env;
2+
use std::process::Command;
3+
use std::sync::{Once, ONCE_INIT};
4+
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
5+
6+
use support::{project, main_file, basic_bin_manifest};
7+
8+
pub fn disabled() -> bool {
9+
// First, disable if ./configure requested so
10+
match env::var("CFG_DISABLE_CROSS_TESTS") {
11+
Ok(ref s) if *s == "1" => return true,
12+
_ => {}
13+
}
14+
15+
// Right now the windows bots cannot cross compile due to the mingw setup,
16+
// so we disable ourselves on all but macos/linux setups where the rustc
17+
// install script ensures we have both architectures
18+
if !(cfg!(target_os = "macos") ||
19+
cfg!(target_os = "linux") ||
20+
cfg!(target_env = "msvc")) {
21+
return true;
22+
}
23+
24+
// It's not particularly common to have a cross-compilation setup, so
25+
// try to detect that before we fail a bunch of tests through no fault
26+
// of the user.
27+
static CAN_RUN_CROSS_TESTS: AtomicBool = ATOMIC_BOOL_INIT;
28+
static CHECK: Once = ONCE_INIT;
29+
30+
let cross_target = alternate();
31+
32+
CHECK.call_once(|| {
33+
let p = project("cross_test")
34+
.file("Cargo.toml", &basic_bin_manifest("cross_test"))
35+
.file("src/cross_test.rs", &main_file(r#""testing!""#, &[]));
36+
37+
let result = p.cargo_process("build")
38+
.arg("--target").arg(&cross_target)
39+
.exec_with_output();
40+
41+
if result.is_ok() {
42+
CAN_RUN_CROSS_TESTS.store(true, Ordering::SeqCst);
43+
}
44+
});
45+
46+
if CAN_RUN_CROSS_TESTS.load(Ordering::SeqCst) {
47+
// We were able to compile a simple project, so the user has the
48+
// necessary std:: bits installed. Therefore, tests should not
49+
// be disabled.
50+
return false;
51+
}
52+
53+
// We can't compile a simple cross project. We want to warn the user
54+
// by failing a single test and having the remainder of the cross tests
55+
// pass. We don't use std::sync::Once here because panicing inside its
56+
// call_once method would poison the Once instance, which is not what
57+
// we want.
58+
static HAVE_WARNED: AtomicBool = ATOMIC_BOOL_INIT;
59+
60+
if HAVE_WARNED.swap(true, Ordering::SeqCst) {
61+
// We are some other test and somebody else is handling the warning.
62+
// Just disable the current test.
63+
return true;
64+
}
65+
66+
// We are responsible for warning the user, which we do by panicing.
67+
let rustup_available = Command::new("rustup").output().is_ok();
68+
69+
let linux_help = if cfg!(target_os = "linux") {
70+
"
71+
72+
You may need to install runtime libraries for your Linux distribution as well.".to_string()
73+
} else {
74+
"".to_string()
75+
};
76+
77+
let rustup_help = if rustup_available {
78+
format!("
79+
80+
Alternatively, you can install the necessary libraries for cross-compilation with
81+
82+
rustup target add {}{}", cross_target, linux_help)
83+
} else {
84+
"".to_string()
85+
};
86+
87+
panic!("Cannot cross compile to {}.
88+
89+
This failure can be safely ignored. If you would prefer to not see this
90+
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \"1\".{}
91+
", cross_target, rustup_help);
92+
}
93+
94+
pub fn alternate() -> String {
95+
let platform = match env::consts::OS {
96+
"linux" => "unknown-linux-gnu",
97+
"macos" => "apple-darwin",
98+
"windows" => "pc-windows-msvc",
99+
_ => unreachable!(),
100+
};
101+
let arch = match env::consts::ARCH {
102+
"x86" => "x86_64",
103+
"x86_64" => "i686",
104+
_ => unreachable!(),
105+
};
106+
format!("{}-{}", arch, platform)
107+
}
108+
109+
pub fn alternate_arch() -> &'static str {
110+
match env::consts::ARCH {
111+
"x86" => "x86_64",
112+
"x86_64" => "x86",
113+
_ => unreachable!(),
114+
}
115+
}
116+
117+
pub fn host() -> String {
118+
let platform = match env::consts::OS {
119+
"linux" => "unknown-linux-gnu",
120+
"macos" => "apple-darwin",
121+
"windows" => "pc-windows-msvc",
122+
_ => unreachable!(),
123+
};
124+
let arch = match env::consts::ARCH {
125+
"x86" => "i686",
126+
"x86_64" => "x86_64",
127+
_ => unreachable!(),
128+
};
129+
format!("{}-{}", arch, platform)
130+
}

tests/cargotest/support/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ macro_rules! t {
3030
pub mod paths;
3131
pub mod git;
3232
pub mod registry;
33+
pub mod cross_compile;
34+
pub mod publish;
3335

3436
/*
3537
*

tests/cargotest/support/publish.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::path::PathBuf;
2+
use std::io::prelude::*;
3+
use std::fs::{self, File};
4+
5+
use support::paths;
6+
use support::git::repo;
7+
8+
use url::Url;
9+
10+
pub fn setup() {
11+
let config = paths::root().join(".cargo/config");
12+
t!(fs::create_dir_all(config.parent().unwrap()));
13+
t!(t!(File::create(&config)).write_all(br#"
14+
[registry]
15+
token = "api-token"
16+
"#));
17+
t!(fs::create_dir_all(&upload_path().join("api/v1/crates")));
18+
19+
repo(&registry_path())
20+
.file("config.json", &format!(r#"{{
21+
"dl": "{0}",
22+
"api": "{0}"
23+
}}"#, upload()))
24+
.build();
25+
}
26+
27+
fn registry_path() -> PathBuf { paths::root().join("registry") }
28+
pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
29+
pub fn upload_path() -> PathBuf { paths::root().join("upload") }
30+
fn upload() -> Url { Url::from_file_path(&*upload_path()).ok().unwrap() }

0 commit comments

Comments
 (0)