sonos / dinghy

Easier cross-compilation for phones and single boards computers
Other
367 stars 44 forks source link

Support cargo-dinghy as a cargo test runner #210

Closed briansmith closed 7 months ago

briansmith commented 9 months ago

Now, cargo-dinghy controls the build and basically the entire cargo invocation, as the cargo dinghy command replaces (wraps) the command the user is trying to run. It would be nice to support an alternative mode where we continue to use cargo test, etc., but where cargo-dinghy is invoked by cargo as needed as a test runner.

In https://github.com/sonos/dinghy/pull/203, @simlay a way of approximating this with the current feature set, with their cargo.config that looked like this:

[target.aarch64-apple-watchos-sim]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-watchos-aarch64-sim runner"

[target.x86_64-apple-watchos-sim]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-watchos-x86_64-sim runner"

[target.aarch64-apple-tvos-sim]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-tvos-aarch64-sim runner"

[target.x86_64-apple-tvos]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-tvos-x86_64 runner"

[target.aarch64-apple-ios-sim]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-ios-aarch64-sim runner"

[target.x86_64-apple-ios]
runner = "cargo run --manifest-path ../../Cargo.toml --bin cargo-dinghy -- -p auto-ios-x86_64 runner"

Imagine that we had an argument cargo-runner so that when invoked like cargo-dinghy cargo-runner, cargo-dinghy would use the environment variables set by Cargo to detect what the --target passed to cargo test was. Then it would use the cargo target to derive the-p argument automatically. Then the above config.toml could be reduced reduce to something like (for most projects):

[target.'cfg(all(any(target_arch="aarch64",target_arch="x86_64"),target_vendor="apple",any(target_os="ios",target_os="tvos",target_os="-apple-watchos")))']
runner = "cargo-dinghy cargo-runner"

For more complex projects, such a mode would may need a configuration mechanism (file) that would take over the duty of the command line arguments.

fredszaq commented 9 months ago

The problem with this sort of approach is that cargo only calls the runner once it has finished building the binary.

In the case of apple targets, I'm guessing this works automagically because cargo knows where to find the linker for the target (I don't have a mac handy to test right now).

For other targets, like android, where dinghy setups quite a few things for the build to succeed (having the linker properly configured is one of those things dinghy does for you), the runner won't get the called at all before the build fails.

Dinghy already sets itself up as a runner during the configuration it does before actually calling cargo. @simlay's config in #203 leverages the existing cargo dinghy runner subcommand to get this working. Some of the complexity in said config comes from the fact that he's making sure to use the fresh cargo-dinghy from the repo and not the system one. On a normal project the config would be a bit simpler

[target.aarch64-apple-watchos-sim]
runner = "cargo dinghy  -p auto-watchos-aarch64-sim runner --"

[target.x86_64-apple-watchos-sim]
runner = "cargo dinghy -p auto-watchos-x86_64-sim runner --"

[target.aarch64-apple-tvos-sim]
runner = "cargo dinghy -p auto-tvos-aarch64-sim runner --"

[target.x86_64-apple-tvos]
runner = "cargo-dinghy -p auto-tvos-x86_64 runner --"

[target.aarch64-apple-ios-sim]
runner = "cargo dinghy -p auto-ios-aarch64-sim runner --"

[target.x86_64-apple-ios]
runner = "cargo-dinghy -p auto-ios-x86_64 runner --"

(note the -- after the runner to be sure you can pass arguments to you binary)

We could potentially add some clever stuff in the runner command to infer the -p so that the command could be called without arguments as you said

I'm however not sure that's something that is desirable as it would

briansmith commented 9 months ago

Good points. I think which way is best depends on what the users' goal is.

In any case, when I tried to sketch this out, I immediately ran into a problem: I expected cargo would set (an) environment variable(s) for the runner indicating the target. But...there is no such environment variable. So, the idea of automatically picking the dinghy platform seems impractical.

In my case, my goal is to do everything up and including cargo test --no-run without dinghy, and use dinghy for deployment to the devices, and managing the devices, only. In this way, I ensure there is no surprising dependency on what dinghy does behind the scenes. This way, I can demonstrate to users who can't use dinghy how to cross-compile my projects. This is particularly important for users who don't even use cargo to build; they need every build step explicitly spelled out so they can translate it to their build system (Bazel, for example). (Some of my users aren't even allowed to run my build.rs; they have to translate that to Bazel or similar too.) As I'm working on my CI configuration for these targets, I'm trying to avoid even having dinghy installed until after cargo test --no-run has succeeded. I would really like a way to tell dinghy to never try to rebuild or try to interject in the building step in any way. (My current plan is to use the verbosity options and look at the build logs to ensure a rebuild isn't done.)

fredszaq commented 9 months ago

Maybe a proxy to the environment variable could be to look in the path of the given executable, you should have the platform somewhere in there. Not ideal but then again pretty much in line with lots of things already done in dinghy...

Le jeu. 22 févr. 2024 à 01:13, Brian Smith @.***> a écrit :

Good points. I think which way is best depends on what the users' goal is.

In any case, when I tried to sketch this out, I immediately ran into a problem: I expected cargo would set (an) environment variable(s) for the runner indicating the target. But...there is no such environment variable. So, the idea of automatically picking the dinghy platform seems impractical.

In my case, my goal is to do everything up and including cargo test --no-run without dinghy, and use dinghy for deployment to the devices, and managing the devices, only. In this way, I ensure there is no surprising dependency on what dinghy does behind the scenes. This way, I can demonstrate to users who can't use dinghy how to cross-compile my projects. This is particularly important for users who don't even use cargo to build; they need every build step explicitly spelled out so they can translate it to their build system (Bazel, for example). (Some of my users aren't even allowed to run my build.rs; they have to translate that to Bazel or similar too.) As I'm working on my CI configuration for these targets, I'm trying to avoid even having dinghy installed until after cargo test --no-run has succeeded. I would really like a way to tell dinghy to never try to rebuild or try to interject in the building step in any way. (My current plan is to use the verbosity options and look at the build logs to ensure a rebuild isn't done.)

— Reply to this email directly, view it on GitHub https://github.com/sonos/dinghy/issues/210#issuecomment-1958430123, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALKUOAJUTB2W54KHOVKLUDYU2ERFAVCNFSM6AAAAABDTY7KYSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNJYGQZTAMJSGM . You are receiving this because you commented.Message ID: @.***>

fredszaq commented 9 months ago

I gave it a try in #213

@briansmith could you try it (especially the example conf I gave in the readme, I have no macos device to test)