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

Allow workspaces/crates to limit support to an explicit set of targets #11313

Closed
djc opened this issue Oct 31, 2022 · 6 comments
Closed

Allow workspaces/crates to limit support to an explicit set of targets #11313

djc opened this issue Oct 31, 2022 · 6 comments
Labels
A-lockfile Area: Cargo.lock issues A-manifest Area: Cargo.toml issues C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` E-hard Experience: Hard S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

Comments

@djc
Copy link
Contributor

djc commented Oct 31, 2022

Problem

(I looked for existing issues that cover something like this, since it feels like this must have come up before, let me know if this is a duplicate of something else.)

Motivation

A Cargo.lock file currently tracks the dependency graph for a crate across all possible compilation targets, including target-conditional dependencies. This means that a Cargo.lock file (and related commands such as cargo update) must cover dependencies across targets that are unlikely to be used for a given project, creating substantial cognitive substantial overhead as well as likely different kinds of computational overhead.

Examples

The windows-rs crate is now split in a bunch of different crates, so that any workspace pulling in windows platform support might end up tracking the versions of all of these crates:

  • windows_aarch64_gnullvm
  • windows_aarch64_msvc
  • windows_i686_gnu
  • windows_i686_msvc
  • windows_x86_64_gnu
  • windows_x86_64_gnullvm
  • windows_x86_64_msvc

Windows is a pretty widespread and mature platform. But any workspace depending on dirs-next pulls in redox_users, which is arguably not a widespread platform today. Similarly, iana-time-zone is a chrono dependency providing platform support, and one of the platforms it supports is haiku for which it pulls in the cxx and cxx-build crates, which in turn depend on cxxbridge-flags, cxxbridge-macros and link-cplusplus.

Proposed Solution

Provide a supported-targets table in a crate or workspace manifest that constrains the supported platforms to an explicit set, analogous to the support that cargo-deny has today:

supported-targets = [
    { triple = "x86_64-apple-darwin" },
    { triple = "x86_64-unknown-linux-musl" },
    { triple = "x86_64-unknown-linux-gnu" },
]

This will allow Cargo to avoid including dependencies exclusive to other platforms in the Cargo.lock file and any dependency resolution considerations. In turn, Cargo will error out when something does try to build the workspace or crate with an unsupported target.

Notes

I would be willing to implement this feature if a similarly scoped feature is accepted by the Cargo team. I am aware that the Cargo team has limited review capacity, but I think this is a relatively small feature with a well-targeted solution.

@djc djc added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label Oct 31, 2022
@ChrisDenton
Copy link
Member

Possibly related: #10801

Not that if affects the point of this issue but the windows-rs issue may be solved by the (soon to be stabilized) raw-dylib feature. Unfortunately the feature is not yet available for windows_i686_gnu and windows_i686_msvc targets but that will hopefully change in the future.

@Eh2406
Copy link
Contributor

Eh2406 commented Oct 31, 2022

I am enthusiastic for this idea. Informally Cargo team members have discussed this many times, but no one has taken the time to see it through. The beautiful part of this idea is that the existing invariant is that "the lock file specifies how a bill should work for any system". With this change the invariant is still true, it's just that instead of specifying what dependencies to use for Windows it specifies to give an error for those systems.

Off the top of my head I can see some issues that still need to be designed:

  • Does this work the same for a lib as it does for a bin?
  • How does this work with artifact dependencies?
  • Should it be an opt in list or an opt out list?
  • Does there need to be some way to override the configuration? (The maintainers say this platform is unsupported, but I want to give it a try and see if it's working.)
  • Should this be config full target triples, arbitrary CFG's, or something in the middle. It would be nice to say not windows, without either having to specify all of the flavors of windows not supported, or all of the flavors of Linux that are supported.
  • How does this work for custom targets?
  • What amount of logic is applied to combine the restrictions with target specific dependencies? Obviously some the entire point is to exclude winapi from the tree. But there are hazards involved in making things too smart, does only supporting M1 architecture imply Mac OS? On one hand that's the only operating system that supports that target, on the other hand that could change at anytime.
  • How does this interact with resolution? If I say that I only support Linux and I unconditionally depend on winapi do I resolve to the most recent version and get a build error Or do I resolve to some older version that is not marked windows only?

It could be that if I thought about it more deeply each of these would have a simple correct answer. But when we're done documenting why each has an answer, we've written an RFC length document at that point. So I think an RFC may be needed.

@Muscraft
Copy link
Member

Another thing to consider is what should happen in a workspace if one member specifies supported_targets but the rest of the workspace does not. Should it throw an error when building the whole workspace on an "unsupported" platform, or could it be ignored since it is a local crate?

@djc
Copy link
Contributor Author

djc commented Nov 2, 2022

There might be an interaction with the vendor command as well:

https://github.com/coreos/cargo-vendor-filterer

@jerrywrice
Copy link

Before finding this issue discussion, I've been exploring the implementation of a new custom rust utility that scans a crate's project source folder and makes a best effort attempt to determines which platforms the crate's implementer planned it to run on (those it was targeted for). In my brief evaluation of the current status quo, it appears such a tool might not be fully comprehensive, and would almost certainly involve the use of some interesting heuristics (TBD). I hope that a potential solution which addresses this Github issue would make this software utility possible, and hopefully fully deterministic and comprehensive. While clearly beyond the scope of this issue, if the specific platforms a given crate is intended to be targeted/run on is known, then this would make it feasible to also (optionally) have a release document provided for each software release of the crate that indicates the actual targets that the new software release was actually tested with.

@epage
Copy link
Contributor

epage commented Jun 12, 2024

This appears to be a duplicate of #6179, closing in favor of that. If there is something I missed that we should keep this open separately, let us know!

@epage epage closed this as not planned Won't fix, can't repro, duplicate, stale Jun 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lockfile Area: Cargo.lock issues A-manifest Area: Cargo.toml issues C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` E-hard Experience: Hard S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Projects
None yet
Development

No branches or pull requests

8 participants