rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.63k stars 2.4k forks source link

Allow specifying a set of supported target platforms in Cargo.toml #6179

Open luser opened 5 years ago

luser commented 5 years ago

Spun off from the specific proposal in https://github.com/rust-lang/cargo/issues/4544#issuecomment-357371733 "A random solution which may help solve this though is to perhaps list the valid targets for a project in a workspace root Cargo.toml. That way Cargo could be smarter and just vendor dependencies for those targets (and alter resolution so it won't include winapi in the lock file)"

This would help projects like Firefox and Fuchsia that vendor their dependencies by allowing them to avoid vendoring crates that are only necessary for platforms that the project does not support (see also #7058).

cc @cramertj

See also

alexcrichton commented 5 years ago

This seems plausible to me! Cargo has to execute rustc to learn about cfg information for targets, so that may be one roadblock to getting this working but otherwise I think it in theory shouldn't be too too hard to plumb through what we've got today

cramertj commented 5 years ago

Similarly, it seems like you could also plumb through the set of features with which each library will be built, so that there's no need to pull in optional dependencies.

luser commented 5 years ago

I poked around that a bit and that already seems to work. If you have a dependency on crate A and A has an optional dependency on B, you won't wind up with B in your Cargo.lock unless you enable that feature.

alexcrichton commented 5 years ago

cc @Eh2406, we were just talking about this!

We talked a bit in person about this and envisioned something like:

We've already basically got the support for all of this, it'd just need some wiring up and stabilization!

mankinskin commented 4 years ago

I had another use-case for this #8645

Problem: It is difficult to recognize what targets a crate is compatible with. With WASM coming about, it has become more important to know if a crate is WASM-compatible or not, i.e. builds and runs on a wasm32 architecture. One has to try building the crate for the target manually, and if there are issues one needs to find the dependency which may be causing incompatibility by recursing down the dependency tree, following the compiler errors.

Solution:

[build]
targets = [
    "wasm32-unknown-unknown",
    "wasm32-wasi",
    "x86_64-unknown-linux-gnu",
    "i586-pc-windows-msvc",
]
  • Allow crate authors to define compatible targets in the crate configuration
  • check those targets when publishing the crate
  • let cargo make a suggestion to add a target to the list, after target has been checked successfully
  • check the compatible targets of dependencies and point out compatibility conflicts

This would make the compatibility visible in the crate, and make it easier to find compatibility issues. Another idea is to show the compatible targets in the documentation on docs.rs, to make it even easier to see what targets a crate can be run on.

@alexcrichton I don't understand why this should be bound to workspaces though? Wouldn't this make sense for any crate?

mankinskin commented 4 years ago

Another idea is to declare something like non-targets to explicitly exclude targets from compatibility for a crate. This could for example be useful when you never intend a crate to target something special like Wasm.

kvark commented 3 years ago

This would help a problem we have in Firefox, where some of the dependencies may have WASM-specific dependencies (https://github.com/grovesNL/glow), which are dragged into the 3rd party sources by cargo vendor.

flukejones commented 2 years ago

I've just recently hit on a circumstance where this functionality would be very useful: preventing cargo (and vendoring by extension) from pulling in crates that will never be built on the intended target.

Or at least that would be my hope.

An example is that I build and maintain a particular project, and this project has many dependencies. Various of these dependencies have winapi as a dependency themselves. This in itself is not an issue really, as the winapi crate is behind a target.cfg flag, so it never gets built on Linux or Macos.

However! winapi and its own chain of dependencies pulls in close to 350MB of stuff for Windows. Stuff that will never ever be built (on my target). The side effect of this is that when I do vendoring and compress the artifacts, the result with this is a 17MB archive - if I remove the windows crates, it's 3.5MB. It has an impact all the way down the distribution chain where a Linux distro might be using vendoring, and now has to account for 13.5MB of wasted space.

My hope for this issue is that by specifying a a target that the crate is for it would prevent the above scenario by never resolving the windows target. With a default of no target specified defaulting back to current behaviour.

scottlamb commented 1 year ago

Just came here from #5220, which was closed in favor of this issue.

Do the supported targets need to be workspace-wide (as suggested by the initial comment here), or could they apply crate-by-crate? Currently e.g. https://github.com/sportsball-ai/av-rs has one workspace with some crates that are portable, some that are macOS-only, and some that are Linux-only. I was following #5220 because I was hoping to be able to just have cargo build do the right thing on the workspace. That seems possible via #6179 if the intended state is you can set supported targets for each crate, but not if you can only do it at the workspace level.

epage commented 1 year ago

My expectation is we'd have something like

[package]
name = "cargo-credential-macos-keychain"
# ...
required-targets = [
  "aarch64-apple-darwin",
  "aarch64-apple-ios",
  "aarch64-apple-ios-sim",
  "x86_64-apple-darwin",
  "x86_64-apple-ios",
]
LunNova commented 1 year ago

Please include some escape hatch that lets you ignore a requirement in a crate you depend on if it's incorrectly too strict.

I expect people will get this wrong with the design suggested above which uses a full target triple by failing to enumerate every possible triple it works on. Something like an option to exclude all windows targets without then enumerating all unixy targets would encourage people to restrict correctly/allow for future new target triples to work.

flukejones commented 1 year ago

Something like an option to exclude all windows targets without then enumerating all unixy targets would encourage people to restrict correctly/allow for future new target triples to work.

I think the exclude-targets option may well be best. Currently there are two scenarios for myself where I might want this:

Perhaps it would be wise to allow wild-carding of parts of a triple like *-apple-darwin, aarch64-*?

epage commented 11 months ago

btw there is #9208 for doing this on the build-target / crate level

stormshield-guillaumed commented 9 months ago

We open sourced a tool that allows you to specify the supported targets of a crate in the Cargo.toml named cargo-ft. Unfortunately, it doesn't solve the Cargo.lock problem which is probably only reasonably doable in cargo directly. Nevertheless, it simplifies building, checking and testing your code when your workspace consist of multiple binary crates with various target platform support. Hope it can help at least a few other people than us.

hishamhm commented 7 months ago

Perhaps it would be wise to allow wild-carding of parts of a triple like -apple-darwin, aarch64-?

Ergonomically specifying that a crate is Wasm-incompatible would require both this and exclude-targets, to allow for something like exclude-targets = [ "wasm32-*" ], as positive lists would be very hard to maintain (and often end up incorrect).

That feature would be most welcome since Wasm-incompatible crates often build but fail at runtime in ways that aren't obviously a platform incompatibility — in the case of typetag, for example, one has to dig down the errors they get in the runtime logs until they find discussions that ultimately mention that the crate doesn't actually work on Wasm.