2021-02-02 00:28:23 +00:00
|
|
|
use std::collections::{BTreeSet, HashMap};
|
2018-07-14 01:49:26 +00:00
|
|
|
use std::env;
|
2019-12-06 00:52:13 +00:00
|
|
|
use std::ffi::{OsStr, OsString};
|
2016-10-13 16:30:59 +00:00
|
|
|
use std::path::PathBuf;
|
2018-02-12 18:33:31 +00:00
|
|
|
|
2019-09-05 16:02:27 +00:00
|
|
|
use cargo_platform::CfgExpr;
|
2021-03-20 18:28:38 +00:00
|
|
|
use cargo_util::ProcessBuilder;
|
2014-08-25 12:40:47 +00:00
|
|
|
use semver::Version;
|
2014-08-07 00:50:55 +00:00
|
|
|
|
2018-11-27 22:05:31 +00:00
|
|
|
use super::BuildContext;
|
2021-02-02 00:28:23 +00:00
|
|
|
use crate::core::compiler::{CompileKind, Metadata, Unit};
|
2021-02-18 06:01:42 +00:00
|
|
|
use crate::core::Package;
|
2021-03-20 18:28:38 +00:00
|
|
|
use crate::util::{self, config, join_paths, CargoResult, Config};
|
2014-12-30 17:15:44 +00:00
|
|
|
|
2020-02-01 19:38:05 +00:00
|
|
|
/// Structure with enough information to run `rustdoc --test`.
|
2018-06-27 02:29:08 +00:00
|
|
|
pub struct Doctest {
|
2020-04-27 19:28:39 +00:00
|
|
|
/// What's being doctested
|
|
|
|
pub unit: Unit,
|
2019-12-06 00:52:13 +00:00
|
|
|
/// Arguments needed to pass to rustdoc to run this test.
|
|
|
|
pub args: Vec<OsString>,
|
|
|
|
/// Whether or not -Zunstable-options is needed.
|
|
|
|
pub unstable_opts: bool,
|
2020-06-14 04:19:22 +00:00
|
|
|
/// The -Clinker value to use.
|
|
|
|
pub linker: Option<PathBuf>,
|
2021-02-02 00:28:23 +00:00
|
|
|
/// The script metadata, if this unit's package has a build script.
|
|
|
|
///
|
|
|
|
/// This is used for indexing [`Compilation::extra_env`].
|
|
|
|
pub script_meta: Option<Metadata>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Information about the output of a unit.
|
|
|
|
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
pub struct UnitOutput {
|
|
|
|
/// The unit that generated this output.
|
|
|
|
pub unit: Unit,
|
|
|
|
/// Path to the unit's primary output (an executable or cdylib).
|
|
|
|
pub path: PathBuf,
|
|
|
|
/// The script metadata, if this unit's package has a build script.
|
|
|
|
///
|
|
|
|
/// This is used for indexing [`Compilation::extra_env`].
|
|
|
|
pub script_meta: Option<Metadata>,
|
2018-06-27 02:29:08 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 00:50:55 +00:00
|
|
|
/// A structure returning the result of a compilation.
|
2015-05-18 22:57:17 +00:00
|
|
|
pub struct Compilation<'cfg> {
|
2014-08-07 00:50:55 +00:00
|
|
|
/// An array of all tests created during this compilation.
|
2021-02-02 00:28:23 +00:00
|
|
|
pub tests: Vec<UnitOutput>,
|
2014-08-07 00:50:55 +00:00
|
|
|
|
|
|
|
/// An array of all binaries created.
|
2021-02-02 00:28:23 +00:00
|
|
|
pub binaries: Vec<UnitOutput>,
|
2014-08-07 00:50:55 +00:00
|
|
|
|
2020-06-24 21:45:55 +00:00
|
|
|
/// An array of all cdylibs created.
|
2021-02-02 00:28:23 +00:00
|
|
|
pub cdylibs: Vec<UnitOutput>,
|
2020-06-24 21:45:55 +00:00
|
|
|
|
2017-02-05 21:15:24 +00:00
|
|
|
/// All directories for the output of native build commands.
|
2014-08-07 00:50:55 +00:00
|
|
|
///
|
|
|
|
/// This is currently used to drive some entries which are added to the
|
|
|
|
/// LD_LIBRARY_PATH as appropriate.
|
2017-11-15 18:16:34 +00:00
|
|
|
///
|
|
|
|
/// The order should be deterministic.
|
|
|
|
pub native_dirs: BTreeSet<PathBuf>,
|
2014-08-07 00:50:55 +00:00
|
|
|
|
|
|
|
/// Root output directory (for the local package's artifacts)
|
2020-04-27 19:28:39 +00:00
|
|
|
pub root_output: HashMap<CompileKind, PathBuf>,
|
2014-08-07 00:50:55 +00:00
|
|
|
|
2017-08-30 22:16:52 +00:00
|
|
|
/// Output directory for rust dependencies.
|
|
|
|
/// May be for the host or for a specific target.
|
2020-04-27 19:28:39 +00:00
|
|
|
pub deps_output: HashMap<CompileKind, PathBuf>,
|
2014-08-07 15:42:16 +00:00
|
|
|
|
2020-04-27 19:28:39 +00:00
|
|
|
/// The path to the host libdir for the compiler used
|
|
|
|
sysroot_host_libdir: PathBuf,
|
2017-08-30 22:16:52 +00:00
|
|
|
|
2020-04-27 19:28:39 +00:00
|
|
|
/// The path to libstd for each target
|
|
|
|
sysroot_target_libdir: HashMap<CompileKind, PathBuf>,
|
2017-05-05 20:57:47 +00:00
|
|
|
|
2014-08-07 15:42:16 +00:00
|
|
|
/// Extra environment variables that were passed to compilations and should
|
|
|
|
/// be passed to future invocations of programs.
|
2021-02-02 00:28:23 +00:00
|
|
|
///
|
|
|
|
/// The key is the build script metadata for uniquely identifying the
|
|
|
|
/// `RunCustomBuild` unit that generated these env vars.
|
|
|
|
pub extra_env: HashMap<Metadata, Vec<(String, String)>>,
|
2014-10-03 01:57:33 +00:00
|
|
|
|
2018-06-26 01:00:04 +00:00
|
|
|
/// Libraries to test with rustdoc.
|
2018-06-27 02:29:08 +00:00
|
|
|
pub to_doc_test: Vec<Doctest>,
|
2015-02-09 19:14:27 +00:00
|
|
|
|
2020-06-14 03:56:29 +00:00
|
|
|
/// The target host triple.
|
|
|
|
pub host: String,
|
|
|
|
|
2015-05-18 22:57:17 +00:00
|
|
|
config: &'cfg Config,
|
2019-10-22 14:53:51 +00:00
|
|
|
|
|
|
|
/// Rustc process to be used by default
|
2018-04-14 08:49:13 +00:00
|
|
|
rustc_process: ProcessBuilder,
|
2019-10-22 14:53:51 +00:00
|
|
|
/// Rustc process to be used for workspace crates instead of rustc_process
|
|
|
|
rustc_workspace_wrapper_process: ProcessBuilder,
|
|
|
|
/// Optional rustc process to be used for primary crates instead of either rustc_process or
|
|
|
|
/// rustc_workspace_wrapper_process
|
|
|
|
primary_rustc_process: Option<ProcessBuilder>,
|
2017-04-26 00:16:17 +00:00
|
|
|
|
2020-04-27 19:28:39 +00:00
|
|
|
target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
|
2014-08-07 00:50:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-18 22:57:17 +00:00
|
|
|
impl<'cfg> Compilation<'cfg> {
|
2020-03-24 21:20:06 +00:00
|
|
|
pub fn new<'a>(bcx: &BuildContext<'a, 'cfg>) -> CargoResult<Compilation<'cfg>> {
|
2020-01-22 01:12:41 +00:00
|
|
|
let mut rustc = bcx.rustc().process();
|
2019-10-22 14:53:51 +00:00
|
|
|
let mut primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();
|
|
|
|
let mut rustc_workspace_wrapper_process = bcx.rustc().workspace_process();
|
2019-07-16 18:13:54 +00:00
|
|
|
|
2018-12-27 14:32:34 +00:00
|
|
|
if bcx.config.extra_verbose() {
|
|
|
|
rustc.display_env_vars();
|
2019-10-22 14:53:51 +00:00
|
|
|
rustc_workspace_wrapper_process.display_env_vars();
|
2019-07-18 22:52:05 +00:00
|
|
|
|
2019-10-22 14:53:51 +00:00
|
|
|
if let Some(rustc) = primary_rustc_process.as_mut() {
|
2019-07-16 18:13:54 +00:00
|
|
|
rustc.display_env_vars();
|
2019-07-18 22:52:05 +00:00
|
|
|
}
|
2018-12-27 14:32:34 +00:00
|
|
|
}
|
2019-07-16 17:52:40 +00:00
|
|
|
|
2018-07-14 01:49:26 +00:00
|
|
|
Ok(Compilation {
|
2019-02-03 04:01:23 +00:00
|
|
|
// TODO: deprecated; remove.
|
|
|
|
native_dirs: BTreeSet::new(),
|
2020-04-27 19:28:39 +00:00
|
|
|
root_output: HashMap::new(),
|
|
|
|
deps_output: HashMap::new(),
|
|
|
|
sysroot_host_libdir: bcx
|
2020-01-22 01:12:41 +00:00
|
|
|
.target_data
|
|
|
|
.info(CompileKind::Host)
|
|
|
|
.sysroot_host_libdir
|
|
|
|
.clone(),
|
2020-04-27 19:28:39 +00:00
|
|
|
sysroot_target_libdir: bcx
|
2021-01-05 01:31:57 +00:00
|
|
|
.all_kinds
|
2020-04-27 19:28:39 +00:00
|
|
|
.iter()
|
|
|
|
.map(|kind| {
|
|
|
|
(
|
|
|
|
*kind,
|
|
|
|
bcx.target_data.info(*kind).sysroot_target_libdir.clone(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect(),
|
2014-08-07 00:50:55 +00:00
|
|
|
tests: Vec::new(),
|
|
|
|
binaries: Vec::new(),
|
2020-06-24 21:45:55 +00:00
|
|
|
cdylibs: Vec::new(),
|
2014-08-07 15:42:16 +00:00
|
|
|
extra_env: HashMap::new(),
|
2015-07-16 20:35:40 +00:00
|
|
|
to_doc_test: Vec::new(),
|
2018-05-03 08:08:16 +00:00
|
|
|
config: bcx.config,
|
2020-06-14 03:56:29 +00:00
|
|
|
host: bcx.host_triple().to_string(),
|
2018-07-14 01:49:26 +00:00
|
|
|
rustc_process: rustc,
|
2019-10-22 14:53:51 +00:00
|
|
|
rustc_workspace_wrapper_process,
|
|
|
|
primary_rustc_process,
|
2020-04-27 19:28:39 +00:00
|
|
|
target_runners: bcx
|
|
|
|
.build_config
|
|
|
|
.requested_kinds
|
|
|
|
.iter()
|
|
|
|
.chain(Some(&CompileKind::Host))
|
|
|
|
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
|
|
|
|
.collect::<CargoResult<HashMap<_, _>>>()?,
|
2018-07-14 01:49:26 +00:00
|
|
|
})
|
2014-08-07 00:50:55 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 00:28:23 +00:00
|
|
|
/// Returns a [`ProcessBuilder`] for running `rustc`.
|
|
|
|
///
|
|
|
|
/// `is_primary` is true if this is a "primary package", which means it
|
|
|
|
/// was selected by the user on the command-line (such as with a `-p`
|
|
|
|
/// flag), see [`crate::core::compiler::Context::primary_packages`].
|
|
|
|
///
|
|
|
|
/// `is_workspace` is true if this is a workspace member.
|
2019-10-22 14:53:51 +00:00
|
|
|
pub fn rustc_process(
|
|
|
|
&self,
|
2020-04-27 19:28:39 +00:00
|
|
|
unit: &Unit,
|
2019-10-22 14:53:51 +00:00
|
|
|
is_primary: bool,
|
|
|
|
is_workspace: bool,
|
|
|
|
) -> CargoResult<ProcessBuilder> {
|
|
|
|
let rustc = if is_primary && self.primary_rustc_process.is_some() {
|
|
|
|
self.primary_rustc_process.clone().unwrap()
|
|
|
|
} else if is_workspace {
|
|
|
|
self.rustc_workspace_wrapper_process.clone()
|
2019-07-16 18:13:54 +00:00
|
|
|
} else {
|
|
|
|
self.rustc_process.clone()
|
|
|
|
};
|
|
|
|
|
2020-05-23 15:23:49 +00:00
|
|
|
let cmd = fill_rustc_tool_env(rustc, unit);
|
2021-02-02 00:28:23 +00:00
|
|
|
self.fill_env(cmd, &unit.pkg, None, unit.kind, true)
|
2014-12-30 17:15:44 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 00:28:23 +00:00
|
|
|
/// Returns a [`ProcessBuilder`] for running `rustdoc`.
|
|
|
|
pub fn rustdoc_process(
|
|
|
|
&self,
|
|
|
|
unit: &Unit,
|
|
|
|
script_meta: Option<Metadata>,
|
|
|
|
) -> CargoResult<ProcessBuilder> {
|
2021-03-20 18:28:38 +00:00
|
|
|
let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?);
|
2020-05-23 15:23:49 +00:00
|
|
|
let cmd = fill_rustc_tool_env(rustdoc, unit);
|
2021-02-02 00:28:23 +00:00
|
|
|
let mut p = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
|
2021-02-18 06:01:42 +00:00
|
|
|
unit.target.edition().cmd_edition_arg(&mut p);
|
2019-08-25 00:25:58 +00:00
|
|
|
|
2020-04-27 19:28:39 +00:00
|
|
|
for crate_type in unit.target.rustc_crate_types() {
|
2020-04-26 20:20:44 +00:00
|
|
|
p.arg("--crate-type").arg(crate_type.as_str());
|
2019-07-21 02:59:55 +00:00
|
|
|
}
|
|
|
|
|
2018-05-15 16:29:34 +00:00
|
|
|
Ok(p)
|
2014-12-30 17:15:44 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 00:28:23 +00:00
|
|
|
/// Returns a [`ProcessBuilder`] appropriate for running a process for the
|
|
|
|
/// host platform.
|
|
|
|
///
|
|
|
|
/// This is currently only used for running build scripts. If you use this
|
|
|
|
/// for anything else, please be extra careful on how environment
|
|
|
|
/// variables are set!
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn host_process<T: AsRef<OsStr>>(
|
|
|
|
&self,
|
|
|
|
cmd: T,
|
|
|
|
pkg: &Package,
|
|
|
|
) -> CargoResult<ProcessBuilder> {
|
2021-03-20 18:28:38 +00:00
|
|
|
self.fill_env(
|
|
|
|
ProcessBuilder::new(cmd),
|
|
|
|
pkg,
|
|
|
|
None,
|
|
|
|
CompileKind::Host,
|
|
|
|
false,
|
|
|
|
)
|
2014-12-30 17:15:44 +00:00
|
|
|
}
|
|
|
|
|
2020-04-27 19:28:39 +00:00
|
|
|
pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
|
|
|
|
self.target_runners.get(&kind).and_then(|x| x.as_ref())
|
2017-04-26 00:16:17 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 00:28:23 +00:00
|
|
|
/// Returns a [`ProcessBuilder`] appropriate for running a process for the
|
|
|
|
/// target platform. This is typically used for `cargo run` and `cargo
|
|
|
|
/// test`.
|
|
|
|
///
|
|
|
|
/// `script_meta` is the metadata for the `RunCustomBuild` unit that this
|
|
|
|
/// unit used for its build script. Use `None` if the package did not have
|
|
|
|
/// a build script.
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn target_process<T: AsRef<OsStr>>(
|
|
|
|
&self,
|
|
|
|
cmd: T,
|
2020-04-27 19:28:39 +00:00
|
|
|
kind: CompileKind,
|
2018-03-14 15:17:44 +00:00
|
|
|
pkg: &Package,
|
2021-02-02 00:28:23 +00:00
|
|
|
script_meta: Option<Metadata>,
|
2018-03-14 15:17:44 +00:00
|
|
|
) -> CargoResult<ProcessBuilder> {
|
2020-04-27 19:28:39 +00:00
|
|
|
let builder = if let Some((runner, args)) = self.target_runner(kind) {
|
2021-03-20 18:28:38 +00:00
|
|
|
let mut builder = ProcessBuilder::new(runner);
|
2017-05-12 22:07:42 +00:00
|
|
|
builder.args(args);
|
2017-04-26 00:16:17 +00:00
|
|
|
builder.arg(cmd);
|
|
|
|
builder
|
|
|
|
} else {
|
2021-03-20 18:28:38 +00:00
|
|
|
ProcessBuilder::new(cmd)
|
2017-04-26 00:16:17 +00:00
|
|
|
};
|
2021-02-02 00:28:23 +00:00
|
|
|
self.fill_env(builder, pkg, script_meta, kind, false)
|
2014-12-30 17:15:44 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 00:50:55 +00:00
|
|
|
/// Prepares a new process with an appropriate environment to run against
|
|
|
|
/// the artifacts produced by the build process.
|
2014-08-25 12:40:47 +00:00
|
|
|
///
|
|
|
|
/// The package argument is also used to configure environment variables as
|
|
|
|
/// well as the working directory of the child process.
|
2018-03-14 15:17:44 +00:00
|
|
|
fn fill_env(
|
|
|
|
&self,
|
|
|
|
mut cmd: ProcessBuilder,
|
|
|
|
pkg: &Package,
|
2021-02-02 00:28:23 +00:00
|
|
|
script_meta: Option<Metadata>,
|
2020-04-27 19:28:39 +00:00
|
|
|
kind: CompileKind,
|
|
|
|
is_rustc_tool: bool,
|
2018-03-14 15:17:44 +00:00
|
|
|
) -> CargoResult<ProcessBuilder> {
|
2020-04-27 19:28:39 +00:00
|
|
|
let mut search_path = Vec::new();
|
|
|
|
if is_rustc_tool {
|
|
|
|
search_path.push(self.deps_output[&CompileKind::Host].clone());
|
|
|
|
search_path.push(self.sysroot_host_libdir.clone());
|
2016-10-13 15:36:12 +00:00
|
|
|
} else {
|
2020-04-27 19:28:39 +00:00
|
|
|
search_path.extend(super::filter_dynamic_search_path(
|
|
|
|
self.native_dirs.iter(),
|
|
|
|
&self.root_output[&kind],
|
|
|
|
));
|
|
|
|
search_path.push(self.deps_output[&kind].clone());
|
|
|
|
search_path.push(self.root_output[&kind].clone());
|
2019-09-24 20:50:34 +00:00
|
|
|
// For build-std, we don't want to accidentally pull in any shared
|
|
|
|
// libs from the sysroot that ships with rustc. This may not be
|
|
|
|
// required (at least I cannot craft a situation where it
|
|
|
|
// matters), but is here to be safe.
|
|
|
|
if self.config.cli_unstable().build_std.is_none() {
|
2020-04-27 19:28:39 +00:00
|
|
|
search_path.push(self.sysroot_target_libdir[&kind].clone());
|
2019-09-24 20:50:34 +00:00
|
|
|
}
|
2020-04-27 19:28:39 +00:00
|
|
|
}
|
2016-10-13 15:36:12 +00:00
|
|
|
|
2019-04-16 23:37:46 +00:00
|
|
|
let dylib_path = util::dylib_path();
|
|
|
|
let dylib_path_is_empty = dylib_path.is_empty();
|
|
|
|
search_path.extend(dylib_path.into_iter());
|
|
|
|
if cfg!(target_os = "macos") && dylib_path_is_empty {
|
2019-02-04 04:22:40 +00:00
|
|
|
// These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't
|
2019-04-16 23:37:46 +00:00
|
|
|
// set or set to an empty string. Since Cargo is explicitly setting
|
|
|
|
// the value, make sure the defaults still work.
|
2019-04-16 01:17:26 +00:00
|
|
|
if let Some(home) = env::var_os("HOME") {
|
2019-02-04 04:22:40 +00:00
|
|
|
search_path.push(PathBuf::from(home).join("lib"));
|
|
|
|
}
|
|
|
|
search_path.push(PathBuf::from("/usr/local/lib"));
|
|
|
|
search_path.push(PathBuf::from("/usr/lib"));
|
|
|
|
}
|
2016-11-11 13:25:20 +00:00
|
|
|
let search_path = join_paths(&search_path, util::dylib_path_envvar())?;
|
2016-10-13 15:36:12 +00:00
|
|
|
|
2015-03-19 01:47:10 +00:00
|
|
|
cmd.env(util::dylib_path_envvar(), &search_path);
|
2021-02-02 00:28:23 +00:00
|
|
|
if let Some(meta) = script_meta {
|
|
|
|
if let Some(env) = self.extra_env.get(&meta) {
|
|
|
|
for (k, v) in env {
|
|
|
|
cmd.env(k, v);
|
|
|
|
}
|
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
|
|
|
}
|
2014-08-07 15:42:16 +00:00
|
|
|
}
|
2014-08-25 12:40:47 +00:00
|
|
|
|
2016-06-02 20:53:31 +00:00
|
|
|
let metadata = pkg.manifest().metadata();
|
2016-03-26 20:00:26 +00:00
|
|
|
|
2017-03-02 06:38:54 +00:00
|
|
|
let cargo_exe = self.config.cargo_exe()?;
|
2018-12-06 19:17:36 +00:00
|
|
|
cmd.env(crate::CARGO_ENV, cargo_exe);
|
2017-03-02 06:38:54 +00:00
|
|
|
|
2017-03-23 14:26:40 +00:00
|
|
|
// When adding new environment variables depending on
|
|
|
|
// crate properties which might require rebuild upon change
|
|
|
|
// consider adding the corresponding properties to the hash
|
2018-04-28 15:20:27 +00:00
|
|
|
// in BuildContext::target_metadata()
|
2015-02-27 01:04:25 +00:00
|
|
|
cmd.env("CARGO_MANIFEST_DIR", pkg.root())
|
2018-03-14 15:17:44 +00:00
|
|
|
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
|
|
|
|
.env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
|
|
|
|
.env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
|
|
|
|
.env(
|
|
|
|
"CARGO_PKG_VERSION_PRE",
|
|
|
|
&pre_version_component(pkg.version()),
|
|
|
|
)
|
|
|
|
.env("CARGO_PKG_VERSION", &pkg.version().to_string())
|
|
|
|
.env("CARGO_PKG_NAME", &*pkg.name())
|
|
|
|
.env(
|
|
|
|
"CARGO_PKG_DESCRIPTION",
|
|
|
|
metadata.description.as_ref().unwrap_or(&String::new()),
|
|
|
|
)
|
|
|
|
.env(
|
|
|
|
"CARGO_PKG_HOMEPAGE",
|
|
|
|
metadata.homepage.as_ref().unwrap_or(&String::new()),
|
|
|
|
)
|
2018-09-25 20:27:10 +00:00
|
|
|
.env(
|
|
|
|
"CARGO_PKG_REPOSITORY",
|
|
|
|
metadata.repository.as_ref().unwrap_or(&String::new()),
|
|
|
|
)
|
2020-06-04 00:51:16 +00:00
|
|
|
.env(
|
|
|
|
"CARGO_PKG_LICENSE",
|
|
|
|
metadata.license.as_ref().unwrap_or(&String::new()),
|
|
|
|
)
|
2020-06-20 10:01:35 +00:00
|
|
|
.env(
|
|
|
|
"CARGO_PKG_LICENSE_FILE",
|
|
|
|
metadata.license_file.as_ref().unwrap_or(&String::new()),
|
|
|
|
)
|
2018-03-14 15:17:44 +00:00
|
|
|
.env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
|
|
|
|
.cwd(pkg.root());
|
2021-02-15 23:17:00 +00:00
|
|
|
|
2021-02-16 04:21:22 +00:00
|
|
|
if self.config.cli_unstable().configurable_env {
|
|
|
|
// Apply any environment variables from the config
|
|
|
|
for (key, value) in self.config.env_config()?.iter() {
|
2021-03-01 03:03:06 +00:00
|
|
|
if value.is_force() || cmd.get_env(key).is_none() {
|
|
|
|
cmd.env(key, value.resolve(self.config));
|
2021-02-16 04:21:22 +00:00
|
|
|
}
|
2021-02-15 23:17:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-27 01:04:25 +00:00
|
|
|
Ok(cmd)
|
2014-08-25 12:40:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-23 15:23:49 +00:00
|
|
|
/// Prepares a rustc_tool process with additional environment variables
|
|
|
|
/// that are only relevant in a context that has a unit
|
|
|
|
fn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder {
|
|
|
|
if unit.target.is_bin() {
|
|
|
|
cmd.env("CARGO_BIN_NAME", unit.target.name());
|
|
|
|
}
|
|
|
|
cmd.env("CARGO_CRATE_NAME", unit.target.crate_name());
|
|
|
|
cmd
|
|
|
|
}
|
|
|
|
|
2015-02-27 01:04:25 +00:00
|
|
|
fn pre_version_component(v: &Version) -> String {
|
2014-08-25 12:40:47 +00:00
|
|
|
if v.pre.is_empty() {
|
2015-02-27 01:04:25 +00:00
|
|
|
return String::new();
|
2014-08-07 00:50:55 +00:00
|
|
|
}
|
2014-08-25 12:40:47 +00:00
|
|
|
|
|
|
|
let mut ret = String::new();
|
|
|
|
|
|
|
|
for (i, x) in v.pre.iter().enumerate() {
|
2018-03-14 15:17:44 +00:00
|
|
|
if i != 0 {
|
|
|
|
ret.push('.')
|
|
|
|
};
|
2015-02-06 08:06:39 +00:00
|
|
|
ret.push_str(&x.to_string());
|
2014-08-25 12:40:47 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 01:04:25 +00:00
|
|
|
ret
|
2014-08-07 00:50:55 +00:00
|
|
|
}
|
2018-09-01 16:01:47 +00:00
|
|
|
|
2019-09-24 17:53:32 +00:00
|
|
|
fn target_runner(
|
|
|
|
bcx: &BuildContext<'_, '_>,
|
2019-09-25 15:14:20 +00:00
|
|
|
kind: CompileKind,
|
2019-09-24 17:53:32 +00:00
|
|
|
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
|
2020-01-22 01:12:41 +00:00
|
|
|
let target = bcx.target_data.short_name(&kind);
|
2018-09-01 16:01:47 +00:00
|
|
|
|
|
|
|
// try target.{}.runner
|
|
|
|
let key = format!("target.{}.runner", target);
|
2020-08-17 17:23:49 +00:00
|
|
|
|
2019-11-24 17:43:59 +00:00
|
|
|
if let Some(v) = bcx.config.get::<Option<config::PathAndArgs>>(&key)? {
|
|
|
|
let path = v.path.resolve_program(bcx.config);
|
|
|
|
return Ok(Some((path, v.args)));
|
2018-09-01 16:01:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// try target.'cfg(...)'.runner
|
2020-01-22 01:12:41 +00:00
|
|
|
let target_cfg = bcx.target_data.info(kind).cfg();
|
2019-11-24 17:43:59 +00:00
|
|
|
let mut cfgs = bcx
|
|
|
|
.config
|
|
|
|
.target_cfgs()?
|
|
|
|
.iter()
|
|
|
|
.filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner)))
|
|
|
|
.filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg));
|
|
|
|
let matching_runner = cfgs.next();
|
|
|
|
if let Some((key, runner)) = cfgs.next() {
|
2020-01-07 22:30:15 +00:00
|
|
|
anyhow::bail!(
|
2019-11-24 17:43:59 +00:00
|
|
|
"several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`\n\
|
|
|
|
first match `{}` located in {}\n\
|
|
|
|
second match `{}` located in {}",
|
|
|
|
matching_runner.unwrap().0,
|
|
|
|
matching_runner.unwrap().1.definition,
|
|
|
|
key,
|
|
|
|
runner.definition
|
|
|
|
);
|
2018-09-01 16:01:47 +00:00
|
|
|
}
|
2019-11-24 17:43:59 +00:00
|
|
|
Ok(matching_runner.map(|(_k, runner)| {
|
|
|
|
(
|
|
|
|
runner.val.path.clone().resolve_program(bcx.config),
|
|
|
|
runner.val.args.clone(),
|
|
|
|
)
|
|
|
|
}))
|
2018-09-01 16:01:47 +00:00
|
|
|
}
|