Skip to content

Commit 77e03cc

Browse files
committed
fix(run): Override arg0 for cargo scripts
Fixes #12870
1 parent f1c6b80 commit 77e03cc

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

crates/cargo-util/src/process_builder.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use std::process::{Command, ExitStatus, Output, Stdio};
2020
pub struct ProcessBuilder {
2121
/// The program to execute.
2222
program: OsString,
23+
/// Best-effort replacement for arg0
24+
arg0: Option<OsString>,
2325
/// A list of arguments to pass to the program.
2426
args: Vec<OsString>,
2527
/// Any environment variables that should be set for the program.
@@ -75,6 +77,7 @@ impl ProcessBuilder {
7577
pub fn new<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
7678
ProcessBuilder {
7779
program: cmd.as_ref().to_os_string(),
80+
arg0: None,
7881
args: Vec::new(),
7982
cwd: None,
8083
env: BTreeMap::new(),
@@ -92,6 +95,12 @@ impl ProcessBuilder {
9295
self
9396
}
9497

98+
/// (chainable) Overrides `arg0` for this program.
99+
pub fn arg0<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
100+
self.arg0 = Some(arg.as_ref().to_os_string());
101+
self
102+
}
103+
95104
/// (chainable) Adds `arg` to the args list.
96105
pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
97106
self.args.push(arg.as_ref().to_os_string());
@@ -142,6 +151,11 @@ impl ProcessBuilder {
142151
self.wrappers.last().unwrap_or(&self.program)
143152
}
144153

154+
/// Gets the program arg0.
155+
pub fn get_arg0(&self) -> Option<&OsStr> {
156+
self.arg0.as_deref()
157+
}
158+
145159
/// Gets the program arguments.
146160
pub fn get_args(&self) -> impl Iterator<Item = &OsString> {
147161
self.wrappers
@@ -483,6 +497,11 @@ impl ProcessBuilder {
483497
cmd.args(iter);
484498
cmd
485499
};
500+
#[cfg(unix)]
501+
if let Some(arg0) = self.get_arg0() {
502+
use std::os::unix::process::CommandExt as _;
503+
command.arg0(arg0);
504+
}
486505
if let Some(cwd) = self.get_cwd() {
487506
command.current_dir(cwd);
488507
}

src/cargo/ops/cargo_run.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt::Write as _;
33
use std::iter;
44
use std::path::Path;
55

6+
use crate::core::MaybePackage;
67
use crate::core::compiler::UnitOutput;
78
use crate::core::{TargetKind, Workspace};
89
use crate::ops;
@@ -105,6 +106,12 @@ pub fn run(
105106
let pkg = bins[0].0;
106107
let mut process = compile.target_process(exe, unit.kind, pkg, script_metas.as_ref())?;
107108

109+
if let MaybePackage::Package(pkg) = ws.root_maybe()
110+
&& pkg.manifest().is_embedded()
111+
{
112+
process.arg0(pkg.manifest_path());
113+
}
114+
108115
// Sets the working directory of the child process to the current working
109116
// directory of the parent process.
110117
// Overrides the default working directory of the `ProcessBuilder` returned

src/doc/src/reference/unstable.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,10 @@ Differences between `cargo run --manifest-path <path>` and `cargo <path>`
14961496
- `cargo <path>` runs with the config for `<path>` and not the current dir, more like `cargo install --path <path>`
14971497
- `cargo <path>` is at a verbosity level below the normal default. Pass `-v` to get normal output.
14981498

1499+
When running a package with an embedded manifest,
1500+
[`arg0`](https://doc.rust-lang.org/std/os/unix/process/trait.CommandExt.html#tymethod.arg0) will be the scripts path.
1501+
To get the executable's path, see [`current_exe`](https://doc.rust-lang.org/std/env/fn.current_exe.html).
1502+
14991503
### Documentation Updates
15001504

15011505
## Profile `trim-paths` option

tests/testsuite/script/cargo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn arg0() {
6262
.masquerade_as_nightly_cargo(&["script"])
6363
.with_stdout_data(str![[r#"
6464
current_exe: [ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE]
65-
arg0: [ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE]
65+
arg0: [ROOT]/foo/echo.rs
6666
args: []
6767
6868
"#]])

0 commit comments

Comments
 (0)