Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom runner without specifying target #13381

Closed
WVAviator opened this issue Feb 1, 2024 · 5 comments
Closed

Custom runner without specifying target #13381

WVAviator opened this issue Feb 1, 2024 · 5 comments
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.

Comments

@WVAviator
Copy link

Problem

Custom runners are currently available to be specified for certain targets in .cargo/config, for example:

[target.x86_64-unknown-uefi]
runner = "./scripts/run.sh"

I would like to specify a custom runner script without specifying a target. This will allow me to perform some other setup and initialization in that script before building and executing the binary. This will be especially useful in workspace setups where the runner could be specified in the root workspace without forcing all crates to use a certain target.

I encountered this issue in working with multiple crates in a workspace - the crates run under different targets (for example, a bin crate that runs under a no_std target and has a custom runner script, and a lib crate that runs without a specified target to maintain the std library for tests). I want to be able to execute cargo run in the workspace root, but I cannot specify a custom runner there because custom runners are tied to targets, and it would enforce the same target for all crates in the workspace.

Proposed Solution

Allow the specification of a default-runner in either Cargo.toml as package.default-runner or workspace.default-runner, or in .cargo/config as build.default-runner. Exactly as it currently works with the existing target.runner option, this would specify a command or path to executable that is run whenever cargo run, cargo test, or cargo bench is executed, with the output binary path (or paths for multiple targets) provided as arguments to that command.

Notes

There is an unstable feature per-package-targets that would sort-of solve my problem in a less elegant way, but it's not ideal because I would need to override the workspace target with another specific target (I'd rather leave it unspecified, because I might be developing on different machines). I also tried this feature in my project anyway and could not get it to work (likely due to its instability).

@WVAviator WVAviator added C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage. labels Feb 1, 2024
@weihanglo
Copy link
Member

Does cargo run --config "target.'cfg(all())'.runner=['echo']" work for you?

Or within .cargo/config.toml:

[target.'cfg(all())']
runner = ['echo']

You could also use --config <path-to-a-config-toml-file> flag to do a one-off config loading.

@weihanglo weihanglo added S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request. and removed S-triage Status: This issue is waiting on initial triage. labels Feb 1, 2024
@WVAviator
Copy link
Author

WVAviator commented Feb 1, 2024

@weihanglo That works, but actually does not solve my issue specifically - but I think it's because the runner script is not what was causing my issue in the first place. I effectively have the following setup:

.
└── workspace_root/
    ├── .cargo/
    │   └── config.toml
    ├── bin_crate/
    │   ├── .cargo/
    │   │   └── config.toml
    │   ├── src/
    │   │   └── main.rs
    │   └── Cargo.toml
    ├── lib_crate/
    │   ├── src/
    │   │   └── lib.rs
    │   └── Cargo.toml
    ├── scripts/
    │   └── run.sh
    └── Cargo.toml

In my above structure, the bin crate is a #![no_std] crate with the following in the .cargo/config.toml:

[build]
target = "x86_64-unknown-uefi"

[unstable]
build-std = ["core", "compiler_builtins"]
build-std-features = ["compiler-builtins-mem"]

[target.x86_64-unknown-uefi]
runner = "../scripts/run.sh"

The lib crate is just a regular crate, no special config except for a #![cfg_attr(not(test), no_std)] annotation in the lib.rs.

I'm finding that no matter what kind of config I use in the workspace root, I cannot get it to build the project from there. I'm getting errors from other external crates failing to compile, unless the workspace config exactly matches the bin config - but then my issue with the lib crate not being no_std pops up again.

Ideally, what I want is for cargo run in the workspace root to be identical to cd bin_crate && cargo run, where bin_crate is either the only bin crate, or one specified as the default in the workspace. That is how I am currently running it and it works for now.

I guess maybe a default runner is not the goal then - as it would seem runners first build the crate, and then pass the crate path as an arg to the runner. If I could specify a custom build command as well, that would be ideal. Then I could wire something up that fits my use case.

Something like this maybe:

[build]
build_command = "cd bin_crate && cargo build && cd .."

Or provide some other kind of configuration option, specifically for workspaces even, that enables building and running from the default crate, honoring its configuration.

@weihanglo
Copy link
Member

Thanks for sharing! I can see where you're from. Cargo's configuration discovery always starts from the current working directory, regardless what you're building. This umm… feature, is not going to change anytime soon. However, we have some alternative for this.

  • Command-line overrides. Let's say you have a .cargo/no-std.config.toml at workspace root. You can read it via --config <path>. Since it's not named .cargo/config.toml, it'll never be picked up by Cargo automatically.
  • You can combine --config with user-defined [alias], such as
    [alias]
    build-bin = "build -p bin_crate --config .cargo/bin-crate.config.toml"
    So that can save some keystrokes for you.
  • There is an unstable -C <dir> flag to switch to a directory. Cargo will start the config discovery from the given <dir>.
  • Your proposed solution looks pretty much like Extend aliases: allow arbitrary commands #6575, which proposes to extend alias to allow arbitrary commands.
  • There is a plan of moving some project-specific config to manifest (Cargo.toml). This is pretty relevant to this issue.

Granted, things above are not all “alternatives”. Some of them are still in design stages. Yet I think we can instead track those issues and close this one. Do you have any specific request that is not covered by aforementioned issues?

@WVAviator
Copy link
Author

@weihanglo Fair enough! Thanks for your help, and that alias solution and proposal sounds great, it aligns pretty much with what I'm doing anyway which is running a custom script instead of cargo run. The alias solution is cleaner, not sure how I missed that in my research.

@weihanglo
Copy link
Member

Thanks! Closing in favor of #6575. Feel free to comment there or elsewhere :)

@weihanglo weihanglo closed this as not planned Won't fix, can't repro, duplicate, stale Feb 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.
Projects
None yet
Development

No branches or pull requests

2 participants