From 77b039a139a747609b6cc2edd9e15bfc3a0c1bf1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Oct 2016 18:36:12 +0300 Subject: [PATCH 1/2] Remove CommandType struct --- src/cargo/ops/cargo_rustc/compilation.rs | 98 +++++++++++------------ src/cargo/ops/cargo_rustc/custom_build.rs | 3 +- src/cargo/ops/cargo_rustc/mod.rs | 21 +---- src/cargo/ops/cargo_test.rs | 2 +- 4 files changed, 50 insertions(+), 74 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/compilation.rs b/src/cargo/ops/cargo_rustc/compilation.rs index 0c60751698f..88a935247f5 100644 --- a/src/cargo/ops/cargo_rustc/compilation.rs +++ b/src/cargo/ops/cargo_rustc/compilation.rs @@ -1,10 +1,10 @@ use std::collections::{HashMap, HashSet}; -use std::ffi::{OsStr, OsString}; -use std::path::PathBuf; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; use semver::Version; use core::{PackageId, Package, Target}; -use util::{self, CargoResult, Config, ProcessBuilder, process}; +use util::{self, CargoResult, Config, ProcessBuilder, process, join_paths}; /// A structure returning the result of a compilation. pub struct Compilation<'cfg> { @@ -47,18 +47,6 @@ pub struct Compilation<'cfg> { config: &'cfg Config, } -#[derive(Clone, Debug)] -pub enum CommandType { - Rustc, - Rustdoc, - - /// The command is to be executed for the target architecture. - Target(OsString), - - /// The command is to be executed for the host architecture. - Host(OsString), -} - impl<'cfg> Compilation<'cfg> { pub fn new(config: &'cfg Config) -> Compilation<'cfg> { Compilation { @@ -77,26 +65,27 @@ impl<'cfg> Compilation<'cfg> { } /// See `process`. - pub fn rustc_process(&self, pkg: &Package) -> CargoResult { - self.process(CommandType::Rustc, pkg) + pub fn rustc_process(&self, pkg: &Package, host_dylib_path: &Path) + -> CargoResult { + self.fill_env(try!(self.config.rustc()).process(), pkg, Some(host_dylib_path)) } /// See `process`. - pub fn rustdoc_process(&self, pkg: &Package) + pub fn rustdoc_process(&self, pkg: &Package, host_dylib_path: Option<&Path>) -> CargoResult { - self.process(CommandType::Rustdoc, pkg) + self.fill_env(process(&*try!(self.config.rustdoc())), pkg, host_dylib_path) } /// See `process`. pub fn target_process>(&self, cmd: T, pkg: &Package) -> CargoResult { - self.process(CommandType::Target(cmd.as_ref().to_os_string()), pkg) + self.fill_env(process(cmd), pkg, None) } /// See `process`. - pub fn host_process>(&self, cmd: T, pkg: &Package) + pub fn host_process>(&self, cmd: T, pkg: &Package, host_dylib_path: &Path) -> CargoResult { - self.process(CommandType::Host(cmd.as_ref().to_os_string()), pkg) + self.fill_env(process(cmd), pkg, Some(host_dylib_path)) } /// Prepares a new process with an appropriate environment to run against @@ -104,39 +93,42 @@ impl<'cfg> Compilation<'cfg> { /// /// The package argument is also used to configure environment variables as /// well as the working directory of the child process. - pub fn process(&self, cmd: CommandType, pkg: &Package) - -> CargoResult { - let mut search_path = vec![]; - - // Add -L arguments, after stripping off prefixes like "native=" or "framework=". - for dir in self.native_dirs.iter() { - let dir = match dir.to_str() { - Some(s) => { - let mut parts = s.splitn(2, '='); - match (parts.next(), parts.next()) { - (Some("native"), Some(path)) | - (Some("crate"), Some(path)) | - (Some("dependency"), Some(path)) | - (Some("framework"), Some(path)) | - (Some("all"), Some(path)) => path.into(), - _ => dir.clone(), + fn fill_env(&self, mut cmd: ProcessBuilder, pkg: &Package, host_dylib_path: Option<&Path>) + -> CargoResult { + + let mut search_path = if let Some(host_dylib_path) = host_dylib_path { + // When invoking a tool, we need the *host* deps directory in the dynamic + // library search path for plugins and such which have dynamic dependencies. + vec![host_dylib_path.to_path_buf()] + } else { + let mut search_path = vec![]; + + // Add -L arguments, after stripping off prefixes like "native=" or "framework=". + for dir in self.native_dirs.iter() { + let dir = match dir.to_str() { + Some(s) => { + let mut parts = s.splitn(2, '='); + match (parts.next(), parts.next()) { + (Some("native"), Some(path)) | + (Some("crate"), Some(path)) | + (Some("dependency"), Some(path)) | + (Some("framework"), Some(path)) | + (Some("all"), Some(path)) => path.into(), + _ => dir.clone(), + } } - } - None => dir.clone(), - }; - search_path.push(dir); - } - search_path.push(self.root_output.clone()); - search_path.push(self.deps_output.clone()); - search_path.extend(util::dylib_path().into_iter()); - let search_path = try!(util::join_paths(&search_path, - util::dylib_path_envvar())); - let mut cmd = match cmd { - CommandType::Rustc => try!(self.config.rustc()).process(), - CommandType::Rustdoc => process(&*try!(self.config.rustdoc())), - CommandType::Target(ref s) | - CommandType::Host(ref s) => process(s), + None => dir.clone(), + }; + search_path.push(dir); + } + search_path.push(self.root_output.clone()); + search_path.push(self.deps_output.clone()); + search_path }; + + search_path.extend(util::dylib_path().into_iter()); + let search_path = try!(join_paths(&search_path, util::dylib_path_envvar())); + cmd.env(util::dylib_path_envvar(), &search_path); if let Some(env) = self.extra_env.get(pkg.package_id()) { for &(ref k, ref v) in env { diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index 73dd34e6dd2..bca5d018d11 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -10,7 +10,6 @@ use util::{internal, ChainError, profile, paths}; use super::job::Work; use super::{fingerprint, Kind, Context, Unit}; -use super::compilation::CommandType; /// Contains the parsed output of a custom build script. #[derive(Clone, Debug, Hash)] @@ -98,7 +97,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) // package's library profile. let profile = cx.lib_profile(unit.pkg.package_id()); let to_exec = to_exec.into_os_string(); - let mut cmd = try!(super::process(CommandType::Host(to_exec), unit.pkg, cx)); + let mut cmd = try!(cx.compilation.host_process(to_exec, unit.pkg, cx.host_dylib_path())); cmd.env("OUT_DIR", &build_output) .env("CARGO_MANIFEST_DIR", unit.pkg.root()) .env("NUM_JOBS", &cx.jobs().to_string()) diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 88328cb9911..459fb81dd1b 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -16,7 +16,7 @@ use util::{Config, internal, ChainError, profile, join_paths, short_hash}; use self::job::{Job, Work}; use self::job_queue::JobQueue; -pub use self::compilation::{Compilation, CommandType}; +pub use self::compilation::Compilation; pub use self::context::{Context, Unit}; pub use self::layout::{Layout, LayoutProxy}; pub use self::custom_build::{BuildOutput, BuildMap, BuildScripts}; @@ -415,7 +415,7 @@ fn add_plugin_deps(rustc: &mut ProcessBuilder, fn prepare_rustc(cx: &Context, crate_types: Vec<&str>, unit: &Unit) -> CargoResult { - let mut base = try!(process(CommandType::Rustc, unit.pkg, cx)); + let mut base = try!(cx.compilation.rustc_process(unit.pkg, cx.host_dylib_path())); build_base_args(cx, &mut base, unit, &crate_types); build_plugin_args(&mut base, cx, unit); try!(build_deps_args(&mut base, cx, unit)); @@ -424,7 +424,7 @@ fn prepare_rustc(cx: &Context, fn rustdoc(cx: &mut Context, unit: &Unit) -> CargoResult { - let mut rustdoc = try!(process(CommandType::Rustdoc, unit.pkg, cx)); + let mut rustdoc = try!(cx.compilation.rustdoc_process(unit.pkg, Some(cx.host_dylib_path()))); rustdoc.arg(&root_path(cx, unit)) .cwd(cx.config.cwd()) .arg("--crate-name").arg(&unit.target.crate_name()); @@ -673,21 +673,6 @@ fn build_deps_args(cmd: &mut ProcessBuilder, cx: &Context, unit: &Unit) } } -pub fn process(cmd: CommandType, pkg: &Package, - cx: &Context) -> CargoResult { - // When invoking a tool, we need the *host* deps directory in the dynamic - // library search path for plugins and such which have dynamic dependencies. - let mut search_path = util::dylib_path(); - search_path.push(cx.host_dylib_path().to_path_buf()); - - // We want to use the same environment and such as normal processes, but we - // want to override the dylib search path with the one we just calculated. - let search_path = try!(join_paths(&search_path, util::dylib_path_envvar())); - let mut cmd = try!(cx.compilation.process(cmd, pkg)); - cmd.env(util::dylib_path_envvar(), &search_path); - Ok(cmd) -} - fn envify(s: &str) -> String { s.chars() .flat_map(|c| c.to_uppercase()) diff --git a/src/cargo/ops/cargo_test.rs b/src/cargo/ops/cargo_test.rs index 71a22d4e461..aa4a23ba02b 100644 --- a/src/cargo/ops/cargo_test.rs +++ b/src/cargo/ops/cargo_test.rs @@ -128,7 +128,7 @@ fn run_doc_tests(options: &TestOptions, for (package, tests) in libs { for (lib, name, crate_name) in tests { try!(config.shell().status("Doc-tests", name)); - let mut p = try!(compilation.rustdoc_process(package)); + let mut p = try!(compilation.rustdoc_process(package, None)); p.arg("--test").arg(lib) .arg("--crate-name").arg(&crate_name); From 7165bd584bb3d2112661f67394c82e34b477f2d2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Oct 2016 19:30:59 +0300 Subject: [PATCH 2/2] Store host dylib path in compilation --- src/cargo/ops/cargo_rustc/compilation.rs | 37 ++++++++++++----------- src/cargo/ops/cargo_rustc/context.rs | 7 ++--- src/cargo/ops/cargo_rustc/custom_build.rs | 2 +- src/cargo/ops/cargo_rustc/mod.rs | 4 +-- src/cargo/ops/cargo_test.rs | 2 +- 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/compilation.rs b/src/cargo/ops/cargo_rustc/compilation.rs index 88a935247f5..89dfd12daa2 100644 --- a/src/cargo/ops/cargo_rustc/compilation.rs +++ b/src/cargo/ops/cargo_rustc/compilation.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use semver::Version; use core::{PackageId, Package, Target}; @@ -33,6 +33,10 @@ pub struct Compilation<'cfg> { /// Output directory for rust dependencies pub deps_output: PathBuf, + /// Library search path for compiler plugins and build scripts + /// which have dynamic dependencies. + pub plugins_dylib_path: PathBuf, + /// Extra environment variables that were passed to compilations and should /// be passed to future invocations of programs. pub extra_env: HashMap>, @@ -54,6 +58,7 @@ impl<'cfg> Compilation<'cfg> { native_dirs: HashSet::new(), // TODO: deprecated, remove root_output: PathBuf::from("/"), deps_output: PathBuf::from("/"), + plugins_dylib_path: PathBuf::from("/"), tests: Vec::new(), binaries: Vec::new(), extra_env: HashMap::new(), @@ -65,27 +70,25 @@ impl<'cfg> Compilation<'cfg> { } /// See `process`. - pub fn rustc_process(&self, pkg: &Package, host_dylib_path: &Path) - -> CargoResult { - self.fill_env(try!(self.config.rustc()).process(), pkg, Some(host_dylib_path)) + pub fn rustc_process(&self, pkg: &Package) -> CargoResult { + self.fill_env(try!(self.config.rustc()).process(), pkg, true) } /// See `process`. - pub fn rustdoc_process(&self, pkg: &Package, host_dylib_path: Option<&Path>) - -> CargoResult { - self.fill_env(process(&*try!(self.config.rustdoc())), pkg, host_dylib_path) + pub fn rustdoc_process(&self, pkg: &Package) -> CargoResult { + self.fill_env(process(&*try!(self.config.rustdoc())), pkg, true) } /// See `process`. - pub fn target_process>(&self, cmd: T, pkg: &Package) - -> CargoResult { - self.fill_env(process(cmd), pkg, None) + pub fn host_process>(&self, cmd: T, pkg: &Package) + -> CargoResult { + self.fill_env(process(cmd), pkg, true) } /// See `process`. - pub fn host_process>(&self, cmd: T, pkg: &Package, host_dylib_path: &Path) - -> CargoResult { - self.fill_env(process(cmd), pkg, Some(host_dylib_path)) + pub fn target_process>(&self, cmd: T, pkg: &Package) + -> CargoResult { + self.fill_env(process(cmd), pkg, false) } /// Prepares a new process with an appropriate environment to run against @@ -93,13 +96,11 @@ impl<'cfg> Compilation<'cfg> { /// /// The package argument is also used to configure environment variables as /// well as the working directory of the child process. - fn fill_env(&self, mut cmd: ProcessBuilder, pkg: &Package, host_dylib_path: Option<&Path>) + fn fill_env(&self, mut cmd: ProcessBuilder, pkg: &Package, is_host: bool) -> CargoResult { - let mut search_path = if let Some(host_dylib_path) = host_dylib_path { - // When invoking a tool, we need the *host* deps directory in the dynamic - // library search path for plugins and such which have dynamic dependencies. - vec![host_dylib_path.to_path_buf()] + let mut search_path = if is_host { + vec![self.plugins_dylib_path.clone()] } else { let mut search_path = vec![]; diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index e7f57fe57d2..59aa170212c 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -110,6 +110,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { None => {} } + self.compilation.plugins_dylib_path = self.host.deps().to_path_buf(); + let layout = self.target.as_ref().unwrap_or(&self.host); self.compilation.root_output = layout.dest().to_path_buf(); self.compilation.deps_output = layout.deps().to_path_buf(); @@ -280,11 +282,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } } - /// Returns the path for plugin/dylib dependencies - pub fn host_dylib_path(&self) -> &Path { - self.host.deps() - } - /// Returns the appropriate output directory for the specified package and /// target. pub fn out_dir(&self, unit: &Unit) -> PathBuf { diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index bca5d018d11..6a324a378a1 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -97,7 +97,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) // package's library profile. let profile = cx.lib_profile(unit.pkg.package_id()); let to_exec = to_exec.into_os_string(); - let mut cmd = try!(cx.compilation.host_process(to_exec, unit.pkg, cx.host_dylib_path())); + let mut cmd = try!(cx.compilation.host_process(to_exec, unit.pkg)); cmd.env("OUT_DIR", &build_output) .env("CARGO_MANIFEST_DIR", unit.pkg.root()) .env("NUM_JOBS", &cx.jobs().to_string()) diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 459fb81dd1b..33f86c0ef1b 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -415,7 +415,7 @@ fn add_plugin_deps(rustc: &mut ProcessBuilder, fn prepare_rustc(cx: &Context, crate_types: Vec<&str>, unit: &Unit) -> CargoResult { - let mut base = try!(cx.compilation.rustc_process(unit.pkg, cx.host_dylib_path())); + let mut base = try!(cx.compilation.rustc_process(unit.pkg)); build_base_args(cx, &mut base, unit, &crate_types); build_plugin_args(&mut base, cx, unit); try!(build_deps_args(&mut base, cx, unit)); @@ -424,7 +424,7 @@ fn prepare_rustc(cx: &Context, fn rustdoc(cx: &mut Context, unit: &Unit) -> CargoResult { - let mut rustdoc = try!(cx.compilation.rustdoc_process(unit.pkg, Some(cx.host_dylib_path()))); + let mut rustdoc = try!(cx.compilation.rustdoc_process(unit.pkg)); rustdoc.arg(&root_path(cx, unit)) .cwd(cx.config.cwd()) .arg("--crate-name").arg(&unit.target.crate_name()); diff --git a/src/cargo/ops/cargo_test.rs b/src/cargo/ops/cargo_test.rs index aa4a23ba02b..71a22d4e461 100644 --- a/src/cargo/ops/cargo_test.rs +++ b/src/cargo/ops/cargo_test.rs @@ -128,7 +128,7 @@ fn run_doc_tests(options: &TestOptions, for (package, tests) in libs { for (lib, name, crate_name) in tests { try!(config.shell().status("Doc-tests", name)); - let mut p = try!(compilation.rustdoc_process(package, None)); + let mut p = try!(compilation.rustdoc_process(package)); p.arg("--test").arg(lib) .arg("--crate-name").arg(&crate_name);