Skip to content

Commit d4e790b

Browse files
committed
Pass trailing x run -- arguments to launch command
If you want to pass string "extras" into an Android intent via `am start`, call `x run ... -- -e extraKey "extra string"` (and similar for other types like `--ez key bool` for booleans, or `-d URI` for data URIs). [All arguments listed by `am help` under the `start` command] (including the `INTENT` specification) are supported. On the host, this passes the arguments as-is to the running executable, similar to `cargo run .. -- <launch_args>`. For iOS, these are passed to [`idevicedebug run`]. [All arguments listed by `am help` under the `start` command]: https://developer.android.com/tools/adb#am [`idevicedebug run`]: https://manpages.debian.org/testing/libimobiledevice-utils/idevicedebug.1.en.html
1 parent 0269a1f commit d4e790b

File tree

7 files changed

+51
-15
lines changed

7 files changed

+51
-15
lines changed

xbuild/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ quick-xml = { version = "0.26.0", features = ["serialize"] }
3232
reqwest = { version = "0.11.13", default-features = false, features = ["blocking", "rustls-tls"] }
3333
serde = { version = "1.0.151", features = ["derive"] }
3434
serde_yaml = "0.9.16"
35+
shlex = "1"
3536
symlink = "0.1.0"
3637
tar = "0.4.38"
3738
toml = "0.5.10"

xbuild/src/command/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ pub fn devices() -> Result<()> {
2626
Ok(())
2727
}
2828

29-
pub fn run(env: &BuildEnv) -> Result<()> {
29+
pub fn run(env: &BuildEnv, launch_args: &[String]) -> Result<()> {
3030
let out = env.executable();
3131
if let Some(device) = env.target().device() {
32-
device.run(env, &out)?;
32+
device.run(env, &out, launch_args)?;
3333
} else {
3434
anyhow::bail!("no device specified");
3535
}

xbuild/src/devices/adb.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,17 @@ impl Adb {
9393
}
9494

9595
/// To run a native activity use "android.app.NativeActivity" as the activity name
96-
fn start(&self, device: &str, package: &str, activity: &str) -> Result<()> {
96+
fn start(
97+
&self,
98+
device: &str,
99+
package: &str,
100+
activity: &str,
101+
launch_args: &[String],
102+
) -> Result<()> {
103+
// Quote arguments for `am` so that they don't already get parsed by `adb`.
104+
let launch_args = shlex::try_join(launch_args.iter().map(String::as_str))
105+
.context("Failed to re-quote launch arguments")?;
106+
97107
let status = self
98108
.shell(device, None)
99109
.arg("am")
@@ -102,6 +112,7 @@ impl Adb {
102112
.arg("android.intent.action.MAIN")
103113
.arg("-n")
104114
.arg(format!("{package}/{activity}"))
115+
.arg(launch_args)
105116
.status()?;
106117
anyhow::ensure!(
107118
status.success(),
@@ -340,6 +351,7 @@ impl Adb {
340351
&self,
341352
device: &str,
342353
path: &Path,
354+
launch_args: &[String],
343355
debug_config: &AndroidDebugConfig,
344356
debug: bool,
345357
) -> Result<()> {
@@ -355,7 +367,7 @@ impl Adb {
355367
self.install(device, path)?;
356368
self.forward_reverse(device, debug_config)?;
357369
let last_timestamp = self.logcat_last_timestamp(device)?;
358-
self.start(device, package, activity)?;
370+
self.start(device, package, activity, launch_args)?;
359371
let uid = self.uidof(device, package)?;
360372
let logcat = self.logcat(device, uid, &last_timestamp)?;
361373
for line in logcat {

xbuild/src/devices/host.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ impl Host {
4646
}
4747
}
4848

49-
pub fn run(&self, path: &Path) -> Result<()> {
50-
Command::new(path).status()?;
49+
pub fn run(&self, path: &Path, launch_args: &[String]) -> Result<()> {
50+
Command::new(path).args(launch_args).status()?;
5151
Ok(())
5252
}
5353

xbuild/src/devices/imd.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ impl IMobileDevice {
4848
Ok(())
4949
}
5050

51-
fn start(&self, device: &str, bundle_identifier: &str) -> Result<()> {
51+
fn start(&self, device: &str, bundle_identifier: &str, launch_args: &[String]) -> Result<()> {
5252
let status = Command::new(&self.idevicedebug)
5353
.arg("--udid")
5454
.arg(device)
5555
.arg("run")
5656
.arg(bundle_identifier)
57+
.args(launch_args)
5758
.status()?;
5859
anyhow::ensure!(status.success(), "failed to run idevicedebug");
5960
Ok(())
@@ -92,11 +93,17 @@ impl IMobileDevice {
9293
Ok(())
9394
}
9495

95-
pub fn run(&self, env: &BuildEnv, device: &str, path: &Path) -> Result<()> {
96+
pub fn run(
97+
&self,
98+
env: &BuildEnv,
99+
device: &str,
100+
path: &Path,
101+
launch_args: &[String],
102+
) -> Result<()> {
96103
let bundle_identifier = appbundle::app_bundle_identifier(path)?;
97104
self.mount_disk_image(env, device)?;
98105
self.install(device, path)?;
99-
self.start(device, &bundle_identifier)?;
106+
self.start(device, &bundle_identifier, launch_args)?;
100107
Ok(())
101108
}
102109

xbuild/src/devices/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,17 @@ impl Device {
110110
}
111111
}
112112

113-
pub fn run(&self, env: &BuildEnv, path: &Path) -> Result<()> {
113+
pub fn run(&self, env: &BuildEnv, path: &Path, launch_args: &[String]) -> Result<()> {
114114
match &self.backend {
115-
Backend::Adb(adb) => adb.run(&self.id, path, &env.config.android().debug, false),
116-
Backend::Host(host) => host.run(path),
117-
Backend::Imd(imd) => imd.run(env, &self.id, path),
115+
Backend::Adb(adb) => adb.run(
116+
&self.id,
117+
path,
118+
launch_args,
119+
&env.config.android().debug,
120+
false,
121+
),
122+
Backend::Host(host) => host.run(path, launch_args),
123+
Backend::Imd(imd) => imd.run(env, &self.id, path, launch_args),
118124
}?;
119125
Ok(())
120126
}

xbuild/src/main.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ enum Commands {
4646
Run {
4747
#[clap(flatten)]
4848
args: BuildArgs,
49+
50+
/// Platform-specific arguments to pass to the launch command:
51+
/// - **Host**: Passed to the running executable, similar to `cargo run -- <launch_args>`.
52+
/// - **Android**: Passed to [`am start`], after the `-a MAIN` and `-n package/.Activity` flags.
53+
/// - **iOS**: Passed to [`idevicedebug`] after `run <bundleid>`.
54+
///
55+
/// [`am start`]: https://developer.android.com/tools/adb#am
56+
/// [`idevicedebug`]: https://manpages.debian.org/testing/libimobiledevice-utils/idevicedebug.1.en.html
57+
#[clap(last = true)]
58+
launch_args: Vec<String>,
4959
},
5060
/// Launch app in a debugger on an attached device
5161
Lldb {
@@ -104,10 +114,10 @@ impl Commands {
104114
let env = BuildEnv::new(args)?;
105115
command::build(&env)?;
106116
}
107-
Self::Run { args } => {
117+
Self::Run { args, launch_args } => {
108118
let env = BuildEnv::new(args)?;
109119
command::build(&env)?;
110-
command::run(&env)?;
120+
command::run(&env, &launch_args)?;
111121
}
112122
Self::Lldb { args } => {
113123
let env = BuildEnv::new(args)?;

0 commit comments

Comments
 (0)