From 6010092da74dd4bcf0c635e4fef645ff98858dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Thu, 7 Apr 2022 19:24:30 +0200 Subject: [PATCH] resolve and mount path dependencies --- src/cargo.rs | 37 ++++++++++++++++++++++++++++++++++++ src/docker.rs | 52 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/cargo.rs b/src/cargo.rs index e22b132b8..8589d380a 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -55,6 +55,40 @@ impl<'a> From<&'a str> for Subcommand { pub struct CargoMetadata { pub workspace_root: PathBuf, pub target_directory: PathBuf, + pub packages: Vec, + pub workspace_members: Vec, +} + +impl CargoMetadata { + fn non_workspace_members(&self) -> impl Iterator { + self.packages + .iter() + .filter(|p| !self.workspace_members.iter().any(|m| m == &p.id)) + } + + pub fn path_dependencies(&self) -> impl Iterator { + // TODO: Also filter out things that are in workspace, but not a workspace member + self.non_workspace_members().filter_map(|p| p.crate_path()) + } +} + +#[derive(Debug, Deserialize)] +pub struct Package { + id: String, + manifest_path: PathBuf, + source: Option, +} + +impl Package { + /// Returns the absolute path to the packages manifest "folder" + fn crate_path(&self) -> Option<&Path> { + // when source is none, this package is a path dependency or a workspace member + if self.source.is_none() { + self.manifest_path.parent() + } else { + None + } + } } /// Cargo metadata with specific invocation @@ -78,6 +112,9 @@ pub fn cargo_metadata_with_args( } else { command.arg("--no-deps"); } + if let Some(target) = args.and_then(|a| a.target.as_ref()) { + command.args(["--filter-platform", target.triple()]); + } let output = command.output()?; let manifest: Option = serde_json::from_slice(&output.stdout).wrap_err_with(|| { diff --git a/src/docker.rs b/src/docker.rs index 60ecc7fc0..e2f1170ee 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -52,6 +52,26 @@ pub fn register(target: &Target, verbose: bool) -> Result<()> { .run(verbose) } +pub fn mount(cmd: &mut Command, val: &Path, verbose: bool) -> Result { + let host_path = + file::canonicalize(&val).wrap_err_with(|| format!("when canonicalizing path `{val:?}`"))?; + let mount_path: PathBuf; + #[cfg(target_os = "windows")] + { + // On Windows, we can not mount the directory name directly. Instead, we use wslpath to convert the path to a linux compatible path. + mount_path = wslpath(&host_path, verbose)?; + } + #[cfg(not(target_os = "windows"))] + { + mount_path = host_path.clone(); + } + cmd.args(&[ + "-v", + &format!("{}:{}", host_path.display(), mount_path.display()), + ]); + Ok(mount_path) +} + #[allow(clippy::too_many_arguments)] // TODO: refactor pub fn run( target: &Target, @@ -147,38 +167,28 @@ pub fn run( // flag forwards the value from the parent shell docker.args(&["-e", var]); } - let mut env_volumes = false; + let mut mount_volumes = false; // FIXME(emilgardis 2022-04-07): This is a fallback so that if it's hard for use to do mounting logic, make it simple(r) // Preferably we would not have to do this. if cwd.strip_prefix(&metadata.workspace_root).is_err() { - env_volumes = true; + mount_volumes = true; } for ref var in config.env_volumes(target)? { validate_env_var(var)?; if let Ok(val) = env::var(var) { - let host_path = file::canonicalize(&val) - .wrap_err_with(|| format!("when canonicalizing path `{val}`"))?; - let mount_path: PathBuf; - #[cfg(target_os = "windows")] - { - // On Windows, we can not mount the directory name directly. Instead, we use wslpath to convert the path to a linux compatible path. - mount_path = wslpath(&host_path, verbose)?; - } - #[cfg(not(target_os = "windows"))] - { - mount_path = host_path.clone(); - } - docker.args(&[ - "-v", - &format!("{}:{}", host_path.display(), mount_path.display()), - ]); + let mount_path = mount(&mut docker, val.as_ref(), verbose)?; docker.args(&["-e", &format!("{}={}", var, mount_path.display())]); - env_volumes = true; + mount_volumes = true; } } + for path in metadata.path_dependencies() { + mount(&mut docker, path, verbose)?; + mount_volumes = true; + } + docker.args(&["-e", "PKG_CONFIG_ALLOW_CROSS=1"]); docker.arg("--rm"); @@ -232,7 +242,7 @@ pub fn run( .args(&["-v", &format!("{}:/cargo:Z", cargo_dir.display())]) // Prevent `bin` from being mounted inside the Docker container. .args(&["-v", "/cargo/bin"]); - if env_volumes { + if mount_volumes { docker.args(&[ "-v", &format!("{}:{}:Z", host_root.display(), mount_root.display()), @@ -244,7 +254,7 @@ pub fn run( .args(&["-v", &format!("{}:/rust:Z,ro", sysroot.display())]) .args(&["-v", &format!("{}:/target:Z", target_dir.display())]); - if env_volumes { + if mount_volumes { docker.args(&["-w".as_ref(), mount_cwd.as_os_str()]); } else if mount_cwd == metadata.workspace_root { docker.args(&["-w", "/project"]);