Skip to content

Commit 07178ce

Browse files
authored
Try #684: --target x86_64-unknown-linux-gnu
2 parents 416548a + 7860d47 commit 07178ce

File tree

9 files changed

+221
-87
lines changed

9 files changed

+221
-87
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
77

8+
- #494 - Parse Cargo's --manifest-path option to determine mounted docker root
89
- #629 - Update Android NDK version and API version
910
- #681 - Warn on unknown fields and confusable targets
1011
- #665 - when not using [env.volumes](https://github.com/cross-rs/cross#mounting-volumes-into-the-build-environment), mount project in /project

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ $ QEMU_STRACE=1 cross run --target aarch64-unknown-linux-gnu
355355
- path dependencies (in Cargo.toml) that point outside the Cargo project won't
356356
work because `cross` use docker containers only mounts the Cargo project so
357357
the container doesn't have access to the rest of the filesystem.
358+
However, you may use Cargo's `--manifest-path` option to reference your
359+
target crate, executed from a common root directory from which all your
360+
dependencies are available.
358361

359362
## Minimum Supported Rust Version (MSRV)
360363

ci/test.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ EOF
135135
popd
136136

137137
rm -rf "${td}"
138+
td=$(mktemp -d)
139+
git clone \
140+
--depth 1 \
141+
--recursive \
142+
https://github.com/cross-rs/test-workspace "${td}"
143+
144+
pushd "${td}"
145+
cross run --target "${TARGET}" -p binary --manifest-path="./workspace/Cargo.toml"
146+
pushd "workspace"
147+
cross run --target "${TARGET}" -p binary
148+
pushd "binary"
149+
cross run --target "${TARGET}"
150+
popd
151+
popd
152+
popd
138153
;;
139154
esac
140155

src/cargo.rs

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use serde::Deserialize;
12
use std::path::{Path, PathBuf};
23
use std::process::{Command, ExitStatus};
3-
use std::{env, fs};
44

5+
use crate::cli::Args;
56
use crate::errors::*;
67
use crate::extensions::CommandExt;
78

@@ -52,38 +53,96 @@ impl<'a> From<&'a str> for Subcommand {
5253
}
5354
}
5455

55-
#[derive(Debug)]
56-
pub struct Root {
57-
path: PathBuf,
56+
#[derive(Debug, Deserialize)]
57+
pub struct CargoMetadata {
58+
pub workspace_root: PathBuf,
59+
pub target_directory: PathBuf,
60+
pub packages: Vec<Package>,
61+
pub workspace_members: Vec<String>,
5862
}
5963

60-
impl Root {
61-
pub fn path(&self) -> &Path {
62-
&self.path
64+
impl CargoMetadata {
65+
fn non_workspace_members(&self) -> impl Iterator<Item = &Package> {
66+
self.packages
67+
.iter()
68+
.filter(|p| !self.workspace_members.iter().any(|m| m == &p.id))
6369
}
64-
}
6570

66-
/// Cargo project root
67-
pub fn root() -> Result<Option<Root>> {
68-
let cd = env::current_dir().wrap_err("couldn't get current directory")?;
71+
pub fn path_dependencies(&self) -> impl Iterator<Item = &Path> {
72+
// TODO: Also filter out things that are in workspace, but not a workspace member
73+
self.non_workspace_members().filter_map(|p| p.crate_path())
74+
}
75+
}
6976

70-
let mut dir = &*cd;
71-
loop {
72-
let toml = dir.join("Cargo.toml");
77+
#[derive(Debug, Deserialize)]
78+
pub struct Package {
79+
id: String,
80+
manifest_path: PathBuf,
81+
source: Option<String>,
82+
}
7383

74-
if fs::metadata(&toml).is_ok() {
75-
return Ok(Some(Root {
76-
path: dir.to_owned(),
77-
}));
84+
impl Package {
85+
/// Returns the absolute path to the packages manifest "folder"
86+
fn crate_path(&self) -> Option<&Path> {
87+
// when source is none, this package is a path dependency or a workspace member
88+
if self.source.is_none() {
89+
self.manifest_path.parent()
90+
} else {
91+
None
7892
}
93+
}
94+
}
7995

80-
match dir.parent() {
81-
Some(p) => dir = p,
82-
None => break,
96+
/// Cargo metadata with specific invocation
97+
pub fn cargo_metadata_with_args(
98+
cd: Option<&Path>,
99+
args: Option<&Args>,
100+
) -> Result<Option<CargoMetadata>> {
101+
let mut command = std::process::Command::new(
102+
std::env::var("CARGO")
103+
.ok()
104+
.unwrap_or_else(|| "cargo".to_string()),
105+
);
106+
command.arg("metadata").arg("--format-version=1");
107+
if let Some(cd) = cd {
108+
command.current_dir(cd);
109+
}
110+
if let Some(config) = args {
111+
if let Some(ref manifest_path) = config.manifest_path {
112+
command.args(["--manifest-path".as_ref(), manifest_path.as_os_str()]);
83113
}
114+
} else {
115+
command.arg("--no-deps");
84116
}
85-
86-
Ok(None)
117+
if let Some(target) = args.and_then(|a| a.target.as_ref()) {
118+
command.args(["--filter-platform", target.triple()]);
119+
}
120+
let output = command.output()?;
121+
let manifest: Option<CargoMetadata> =
122+
serde_json::from_slice(&output.stdout).wrap_err_with(|| {
123+
format!(
124+
"{command:?} returned nothing. {:?}",
125+
String::from_utf8(output.stderr)
126+
)
127+
})?;
128+
manifest
129+
.map(|m| -> Result<_> {
130+
Ok(CargoMetadata {
131+
target_directory: args
132+
.and_then(|a| a.target_dir.clone())
133+
.map(|p| {
134+
if p.is_relative() {
135+
cd.expect("this is a bug, working directory should be provided here")
136+
.join(p)
137+
} else {
138+
p
139+
}
140+
})
141+
.unwrap_or(m.target_directory),
142+
..m
143+
})
144+
})
145+
.transpose()
87146
}
88147

89148
/// Pass-through mode

src/cli.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ pub struct Args {
1313
pub target: Option<Target>,
1414
pub target_dir: Option<PathBuf>,
1515
pub docker_in_docker: bool,
16+
pub manifest_path: Option<PathBuf>,
1617
}
1718

1819
pub fn parse(target_list: &TargetList) -> Args {
1920
let mut channel = None;
2021
let mut target = None;
22+
let mut manifest_path: Option<PathBuf> = None;
2123
let mut target_dir = None;
2224
let mut sc = None;
2325
let mut all: Vec<String> = Vec::new();
@@ -28,7 +30,21 @@ pub fn parse(target_list: &TargetList) -> Args {
2830
if arg.is_empty() {
2931
continue;
3032
}
31-
if let ("+", ch) = arg.split_at(1) {
33+
if arg == "--manifest-path" {
34+
all.push(arg);
35+
if let Some(m) = args.next() {
36+
let p = PathBuf::from(&m);
37+
all.push(m);
38+
manifest_path = env::current_dir().ok().map(|cwd| cwd.join(p));
39+
}
40+
} else if arg.starts_with("--manifest-path=") {
41+
manifest_path = arg
42+
.split_once('=')
43+
.map(|x| x.1)
44+
.map(PathBuf::from)
45+
.and_then(|p| env::current_dir().ok().map(|cwd| cwd.join(p)));
46+
all.push(arg);
47+
} else if let ("+", ch) = arg.split_at(1) {
3248
channel = Some(ch.to_string());
3349
} else if arg == "--target" {
3450
all.push(arg);
@@ -73,5 +89,6 @@ pub fn parse(target_list: &TargetList) -> Args {
7389
target,
7490
target_dir,
7591
docker_in_docker,
92+
manifest_path,
7693
}
7794
}

0 commit comments

Comments
 (0)