Description
On Unix, relative paths to the exe are interpreted after cd'ing to the current_dir
, but on Windows they're interpreted before. Here's an example test (1 test file, and 1 little binary that the test needs to build) that demonstrates this if you run cargo test
on the two different platforms:
src/lib.rs
#[test]
fn execute_binary_from_another_dir() {
// Run `cargo build` to make sure the associated `foo` binary gets built.
std::process::Command::new("cargo").arg("build").status().unwrap();
// Shell out to `foo`, just to confirm that this works fine.
std::process::Command::new("target/debug/foo")
.status()
.unwrap();
// Now try to shell out to `foo` again while also setting the current_dir.
// This fails on Unix, because the path to the binary is resolved *after*
// changing directories, but it works on Windows.
std::process::Command::new("target/debug/foo")
.current_dir("..")
.status()
.unwrap();
}
src/bin/foo.rs
fn main() {
println!("foo!");
}
I ran into a similar difference when I tried this with Python's subprocess.run(..., cwd=...)
. It looks like it's an artifact of Windows supporting an lpCurrentDirectory
arg natively, while Unix has to fork
and then chdir
in the child before it calls exec
. I prefer the semantics that we're getting on Windows right now*, but this issue is mainly that they're not the same.
* My main reason for preferring the current-Windows-style "current_dir
does not affect the exe location" semantics: Emulating the current-Unix-style only requires a Path::join
, which always works. But going the other way requires a Path::canonicalize
, which can fail.