xref: /DragonOS/user/apps/test_ebpf/syscall_ebpf/xtask/src/run.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 use std::process::Command;
2 
3 use anyhow::Context as _;
4 use clap::Parser;
5 
6 use crate::{build::{build, Options as BuildOptions}, build_ebpf::Architecture};
7 
8 #[derive(Debug, Parser)]
9 pub struct Options {
10     /// Set the endianness of the BPF target
11     #[clap(default_value = "bpfel-unknown-none", long)]
12     pub bpf_target: Architecture,
13     /// Build and run the release target
14     #[clap(long)]
15     pub release: bool,
16     /// The command used to wrap your application
17     #[clap(short, long, default_value = "sudo -E")]
18     pub runner: String,
19     /// Arguments to pass to your application
20     #[clap(name = "args", last = true)]
21     pub run_args: Vec<String>,
22 }
23 
24 
25 /// Build and run the project
26 pub fn run(opts: Options) -> Result<(), anyhow::Error> {
27     // Build our ebpf program and the project
28     build(BuildOptions{
29         bpf_target: opts.bpf_target,
30         release: opts.release,
31     }).context("Error while building project")?;
32 
33     // profile we are building (release or debug)
34     let profile = if opts.release { "release" } else { "debug" };
35     let bin_path = format!("target/{profile}/syscall_ebpf");
36 
37     // arguments to pass to the application
38     let mut run_args: Vec<_> = opts.run_args.iter().map(String::as_str).collect();
39 
40     // configure args
41     let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect();
42     args.push(bin_path.as_str());
43     args.append(&mut run_args);
44 
45     // run the command
46     let status = Command::new(args.first().expect("No first argument"))
47         .args(args.iter().skip(1))
48         .status()
49         .expect("failed to run the command");
50 
51     if !status.success() {
52         anyhow::bail!("Failed to run `{}`", args.join(" "));
53     }
54     Ok(())
55 }
56