mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Added support for negative --jobs parameter, counting backwards from max CPUs.
This commit is contained in:
parent
0b2059e981
commit
07cc897a4f
@ -50,14 +50,14 @@ impl BuildConfig {
|
|||||||
/// * `target.$target.libfoo.metadata`
|
/// * `target.$target.libfoo.metadata`
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
jobs: Option<u32>,
|
jobs: Option<i32>,
|
||||||
requested_targets: &[String],
|
requested_targets: &[String],
|
||||||
mode: CompileMode,
|
mode: CompileMode,
|
||||||
) -> CargoResult<BuildConfig> {
|
) -> CargoResult<BuildConfig> {
|
||||||
let cfg = config.build_config()?;
|
let cfg = config.build_config()?;
|
||||||
let requested_kinds = CompileKind::from_requested_targets(config, requested_targets)?;
|
let requested_kinds = CompileKind::from_requested_targets(config, requested_targets)?;
|
||||||
if jobs == Some(0) {
|
if jobs == Some(0) {
|
||||||
anyhow::bail!("jobs must be at least 1")
|
anyhow::bail!("jobs must not be zero")
|
||||||
}
|
}
|
||||||
if jobs.is_some() && config.jobserver_from_env().is_some() {
|
if jobs.is_some() && config.jobserver_from_env().is_some() {
|
||||||
config.shell().warn(
|
config.shell().warn(
|
||||||
@ -66,7 +66,11 @@ impl BuildConfig {
|
|||||||
its environment, ignoring the `-j` parameter",
|
its environment, ignoring the `-j` parameter",
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
let jobs = jobs.or(cfg.jobs).unwrap_or(::num_cpus::get() as u32);
|
let jobs = match jobs.or(cfg.jobs) {
|
||||||
|
None => ::num_cpus::get() as u32,
|
||||||
|
Some(j) if j < 0 => (::num_cpus::get() as i32 + j).max(1) as u32,
|
||||||
|
Some(j) => j as u32,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(BuildConfig {
|
Ok(BuildConfig {
|
||||||
requested_kinds,
|
requested_kinds,
|
||||||
|
@ -95,8 +95,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||||||
let jobserver = match bcx.config.jobserver_from_env() {
|
let jobserver = match bcx.config.jobserver_from_env() {
|
||||||
Some(c) => c.clone(),
|
Some(c) => c.clone(),
|
||||||
None => {
|
None => {
|
||||||
let client = Client::new(bcx.build_config.jobs as usize)
|
let client =
|
||||||
.chain_err(|| "failed to create jobserver")?;
|
Client::new(bcx.jobs() as usize).chain_err(|| "failed to create jobserver")?;
|
||||||
client.acquire_raw()?;
|
client.acquire_raw()?;
|
||||||
client
|
client
|
||||||
}
|
}
|
||||||
@ -558,7 +558,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_jobserver(&mut self) -> CargoResult<Client> {
|
pub fn new_jobserver(&mut self) -> CargoResult<Client> {
|
||||||
let tokens = self.bcx.build_config.jobs as usize;
|
let tokens = self.bcx.jobs() as usize;
|
||||||
let client = Client::new(tokens).chain_err(|| "failed to create jobserver")?;
|
let client = Client::new(tokens).chain_err(|| "failed to create jobserver")?;
|
||||||
|
|
||||||
// Drain the client fully
|
// Drain the client fully
|
||||||
|
@ -461,7 +461,7 @@ impl<'cfg> Timings<'cfg> {
|
|||||||
self.total_dirty,
|
self.total_dirty,
|
||||||
self.total_fresh + self.total_dirty,
|
self.total_fresh + self.total_dirty,
|
||||||
max_concurrency,
|
max_concurrency,
|
||||||
bcx.build_config.jobs,
|
bcx.jobs(),
|
||||||
num_cpus::get(),
|
num_cpus::get(),
|
||||||
self.start_str,
|
self.start_str,
|
||||||
total_time,
|
total_time,
|
||||||
|
@ -27,7 +27,7 @@ pub struct PackageOpts<'cfg> {
|
|||||||
pub check_metadata: bool,
|
pub check_metadata: bool,
|
||||||
pub allow_dirty: bool,
|
pub allow_dirty: bool,
|
||||||
pub verify: bool,
|
pub verify: bool,
|
||||||
pub jobs: Option<u32>,
|
pub jobs: Option<i32>,
|
||||||
pub targets: Vec<String>,
|
pub targets: Vec<String>,
|
||||||
pub features: Vec<String>,
|
pub features: Vec<String>,
|
||||||
pub all_features: bool,
|
pub all_features: bool,
|
||||||
|
@ -47,7 +47,7 @@ pub struct PublishOpts<'cfg> {
|
|||||||
pub index: Option<String>,
|
pub index: Option<String>,
|
||||||
pub verify: bool,
|
pub verify: bool,
|
||||||
pub allow_dirty: bool,
|
pub allow_dirty: bool,
|
||||||
pub jobs: Option<u32>,
|
pub jobs: Option<i32>,
|
||||||
pub targets: Vec<String>,
|
pub targets: Vec<String>,
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
pub registry: Option<String>,
|
pub registry: Option<String>,
|
||||||
|
@ -67,7 +67,8 @@ pub trait AppExt: Sized {
|
|||||||
self._arg(
|
self._arg(
|
||||||
opt("jobs", "Number of parallel jobs, defaults to # of CPUs")
|
opt("jobs", "Number of parallel jobs, defaults to # of CPUs")
|
||||||
.short("j")
|
.short("j")
|
||||||
.value_name("N"),
|
.value_name("N")
|
||||||
|
.allow_hyphen_values(true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +288,16 @@ pub trait ArgMatchesExt {
|
|||||||
Ok(arg)
|
Ok(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_of_i32(&self, name: &str) -> CargoResult<Option<i32>> {
|
||||||
|
let arg = match self._value_of(name) {
|
||||||
|
None => None,
|
||||||
|
Some(arg) => Some(arg.parse::<i32>().map_err(|_| {
|
||||||
|
clap::Error::value_validation_auto(format!("could not parse `{}` as a number", arg))
|
||||||
|
})?),
|
||||||
|
};
|
||||||
|
Ok(arg)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns value of the `name` command-line argument as an absolute path
|
/// Returns value of the `name` command-line argument as an absolute path
|
||||||
fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
|
fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
|
||||||
self._value_of(name).map(|path| config.cwd().join(path))
|
self._value_of(name).map(|path| config.cwd().join(path))
|
||||||
@ -320,8 +331,8 @@ pub trait ArgMatchesExt {
|
|||||||
Ok(ws)
|
Ok(ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jobs(&self) -> CargoResult<Option<u32>> {
|
fn jobs(&self) -> CargoResult<Option<i32>> {
|
||||||
self.value_of_u32("jobs")
|
self.value_of_i32("jobs")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn targets(&self) -> Vec<String> {
|
fn targets(&self) -> Vec<String> {
|
||||||
|
@ -1874,7 +1874,7 @@ pub struct CargoBuildConfig {
|
|||||||
pub target_dir: Option<ConfigRelativePath>,
|
pub target_dir: Option<ConfigRelativePath>,
|
||||||
pub incremental: Option<bool>,
|
pub incremental: Option<bool>,
|
||||||
pub target: Option<ConfigRelativePath>,
|
pub target: Option<ConfigRelativePath>,
|
||||||
pub jobs: Option<u32>,
|
pub jobs: Option<i32>,
|
||||||
pub rustflags: Option<StringList>,
|
pub rustflags: Option<StringList>,
|
||||||
pub rustdocflags: Option<StringList>,
|
pub rustdocflags: Option<StringList>,
|
||||||
pub rustc_wrapper: Option<PathBuf>,
|
pub rustc_wrapper: Option<PathBuf>,
|
||||||
|
@ -138,32 +138,6 @@ Caused by:
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
|
||||||
fn bad_cargo_config_jobs() {
|
|
||||||
let p = project()
|
|
||||||
.file("src/lib.rs", "")
|
|
||||||
.file(
|
|
||||||
".cargo/config",
|
|
||||||
r#"
|
|
||||||
[build]
|
|
||||||
jobs = -1
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
p.cargo("build -v")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr(
|
|
||||||
"\
|
|
||||||
[ERROR] error in [..].cargo/config: \
|
|
||||||
could not load config key `build.jobs`
|
|
||||||
|
|
||||||
Caused by:
|
|
||||||
invalid value: integer `-1`, expected u32
|
|
||||||
",
|
|
||||||
)
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn invalid_global_config() {
|
fn invalid_global_config() {
|
||||||
let p = project()
|
let p = project()
|
||||||
|
@ -4719,6 +4719,18 @@ fn good_cargo_config_jobs() {
|
|||||||
p.cargo("build -v").run();
|
p.cargo("build -v").run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn good_jobs() {
|
||||||
|
let p = project()
|
||||||
|
.file("Cargo.toml", &basic_bin_manifest("foo"))
|
||||||
|
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
p.cargo("build --jobs 1").run();
|
||||||
|
|
||||||
|
p.cargo("build --jobs -1").run();
|
||||||
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn invalid_jobs() {
|
fn invalid_jobs() {
|
||||||
let p = project()
|
let p = project()
|
||||||
@ -4726,11 +4738,9 @@ fn invalid_jobs() {
|
|||||||
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
|
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
p.cargo("build --jobs -1")
|
p.cargo("build --jobs 0")
|
||||||
.with_status(1)
|
.with_status(101)
|
||||||
.with_stderr_contains(
|
.with_stderr_contains("error: jobs must not be zero")
|
||||||
"error: Found argument '-1' which wasn't expected, or isn't valid in this context",
|
|
||||||
)
|
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
p.cargo("build --jobs over9000")
|
p.cargo("build --jobs over9000")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user