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

Stabilize target-applies-to-host feature. #9753

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jameshilliard
Copy link
Contributor

Details: #9453, #9322

@rust-highfive
Copy link

r? @alexcrichton

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 1, 2021
@jameshilliard jameshilliard force-pushed the stabilize-target-applies-to-host branch from 0a3c506 to d5ebab6 Compare August 1, 2021 23:44
@alexcrichton
Copy link
Member

#9322 is quite sprawling and I may not have also made this clear enough, but I personally do not think that this is a candidate for stabilization until the issue fixed in #9634 is resolved. Otherwise this flag I don't believe works with cargo build since the same configuration will be used for all units.

@jameshilliard
Copy link
Contributor Author

Otherwise this flag I don't believe works with cargo build since the same configuration will be used for all units.

I think it works well enough for cross builds since the host build always ends up being used with a non-triple target directory and the target with the triple target directory, they shouldn't really conflict there at least.

@jameshilliard
Copy link
Contributor Author

FYI I've integrated the target-applies-to-host fix into the buildroot ripgrep package build using the recently released stable 1.54.0 toolchain to fix the build script failure and it seems to work fine so far, this should increase the testing coverage for this feature a good bit. I don't think #9634 is required for properly supporting this flag, however #9634 may be needed for some complex multi-target scenarios I think(buildroot does not use cargo's multi-target build capability so I don't expect we will hit issues there).

@alexcrichton
Copy link
Member

I, uh, stand by my previous comment. I don't dispute that the feature works for --target-based builds nor that it's useful for those builds. I want this fixed for cargo build before we stabilize it.

@jameshilliard
Copy link
Contributor Author

I don't dispute that the feature works for --target-based builds nor that it's useful for those builds. I want this fixed for cargo build before we stabilize it.

What issue are we hitting there? Shared dependencies conflicting?

@bors
Copy link
Collaborator

bors commented Aug 6, 2021

☔ The latest upstream changes (presumably #9613) made this pull request unmergeable. Please resolve the merge conflicts.

@jameshilliard jameshilliard force-pushed the stabilize-target-applies-to-host branch 2 times, most recently from 9c61466 to e2b82bf Compare August 20, 2021 12:29
@nitsky
Copy link

nitsky commented Nov 15, 2021

Hi, thank you to everyone here for working on this feature. What is the planned behavior for cargo build without specifying a --target? At the moment I observe that with target-applies-to-host = false, cargo build of a bin ignores both the host and target configuration. In my particular usage, the ideal behavior would be to use the host configuration not just for the build scripts and tests but for the bin as well, because I consider cargo build to be "targeting the host". Is this what is planned? Thank you!

@jameshilliard
Copy link
Contributor Author

jameshilliard commented Nov 15, 2021

What is the planned behavior for cargo build without specifying a --target?

I think it eventually was supposed to be to have the target config only to apply to target artifact builds, currently they apply to host and target builds unless target-applies-to-host = false is set.

It seems progress has stalled a bit here however since it seems nobody doing review really has all that good of an understanding of this area of the codebase.

At the moment I observe that with target-applies-to-host = false, cargo build of a bin ignores both the host and target configuration.

Are you setting both -Zhost-config and -Ztarget-applies-to-host as well? The bin should always use the target configuration either way, the host config is only ever used for host targets like build-scripts and requires the appropriate nightly flags to enable.

In my particular usage, the ideal behavior would be to use the host configuration not just for the build scripts and tests but for the bin as well, because I consider cargo build to be "targeting the host". Is this what is planned?

No, I don't think that makes much sense, the target bin should always IMO pick up its build configuration from the [target] config, even if the target is the same as the host. The purpose of the host configuration is to allow one to configure settings for the build tools(like build-script-build) for the host, it's not intended to be used to configure anything for target artifact builds(whether they will run on the build host or a different system).

@alex-berger
Copy link

Any progress on this? We rely on this feature for cross compiling and I do not feel comfortable with having to set RUSTC_BOOTSTRAP=1 to use this feature from stable Rust. That said, this feature works quite well for us so far.

@jameshilliard
Copy link
Contributor Author

I do not feel comfortable with having to set RUSTC_BOOTSTRAP=1 to use this feature from stable Rust.

IMO setting __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS is probably safer, since it's only picked up/used in essentially one place(which is sufficient to enable this one nightly only feature we need) while RUSTC_BOOTSTRAP=1 is getting used in other places including in rustc.

This seems to have fixed things for us:
https://github.com/buildroot/buildroot/blob/ac573c55aac3cbb4257f5388c91321c81095c654/package/pkg-cargo.mk#L26-L50

Be aware that hacks to enable nightly features like this are likely to break, we can manage this easily since we pin our rust toolchain versions(we do this with our non-rust toolchains as well to various degrees) and have auto-builders that would likely catch any related regressions quickly, we just really don't want to be pinning rust/cargo toolchains to nightly toolchains since we really only want to enable stable features(this one is just not really optional in practice as even basic x86_64 cross compilation breaks without it).

@saurik
Copy link

saurik commented Jan 27, 2022

FWIW, I also ran out of workarounds a month ago after I wanted to upgrade something (either Rust/Cargo or one of the couple Rust libraries I still haven't ported away from... I don't remember the situation, but it involved yet another place where flags were being incorrectly applied to the wrong part of the build process) and have been able to switch to this feature and it is working great (and I will note that even using __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS this is way more stable and less likely to break than all of my prior hacks that were required to make Rust even semi-usable for serious compilation; I also, though, have somewhat controlled toolchain versions). OrchidTechnologies/orchid@3ced403

@bors
Copy link
Collaborator

bors commented Feb 28, 2022

☔ The latest upstream changes (presumably #10395) made this pull request unmergeable. Please resolve the merge conflicts.

@jameshilliard jameshilliard force-pushed the stabilize-target-applies-to-host branch 3 times, most recently from c3f3ef8 to a5f2401 Compare March 1, 2022 08:28
@jameshilliard
Copy link
Contributor Author

rebased

@alexcrichton
Copy link
Member

Thanks for the PR, but I'm going to be stepping down from the Cargo team so I'm going to un-assign myself from this. The Cargo team will help review this when they get a chance.

@alexcrichton alexcrichton removed their assignment Mar 8, 2022
@bors
Copy link
Collaborator

bors commented Jul 16, 2022

☔ The latest upstream changes (presumably #10868) made this pull request unmergeable. Please resolve the merge conflicts.

@jameshilliard jameshilliard force-pushed the stabilize-target-applies-to-host branch from a5f2401 to 0cc2206 Compare October 21, 2022 16:52
@jameshilliard
Copy link
Contributor Author

rebased

@jameshilliard jameshilliard force-pushed the stabilize-target-applies-to-host branch from 0cc2206 to 3c7652c Compare December 3, 2022 22:10
@jameshilliard
Copy link
Contributor Author

@joshtriplett Does this look good to merge?

It would be nice if cross compilation build systems could drop hacks like __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly".

Having unstable env variables as a hard requirement for a functional cross compilation environment isn't exactly ideal.

@bors
Copy link
Collaborator

bors commented Feb 20, 2024

☔ The latest upstream changes (presumably #13409) made this pull request unmergeable. Please resolve the merge conflicts.

@sdir
Copy link

sdir commented Apr 16, 2024

@jameshilliard conflicts.

The config: &Config change gctx: &GlobalContext from #13759 in function get_target_applies_to_host

@gmorenz
Copy link
Contributor

gmorenz commented May 8, 2024

I don't dispute that the feature works for --target-based builds nor that it's useful for those builds. I want this fixed for cargo build before we stabilize it.

What issue are we hitting there? Shared dependencies conflicting?

I am building a static binary (not interpreted by ld-linux.so, the kind that ldd prints not a dynamic executable for). As a result I need -C relocation-model=static. Proc macros cannot be built with -C relocation-model=static, because they are dylibs. cargo build --target x86_64-unknown-linux-gnu works to build my project because it builds the executable with the relocation-model passed by rustflags, and the proc macros with the default rust flags. This flag, as designed, should do the same (if I understand the proposal correctly). This flag, as implemented, does not, because it builds the binary with the host-flags so I am once again in the situation where the proc-macros and the final binary cannot have different relocation-models.

I believe that if this is stabilized before fixing this issue, it would be backwards incompatible to change. Moreover it would move the situation from we have two ways things are built (cargo build --target <host> and cargo build) to we have three ways (those two, and a new third way where host flags are applied to everything), instead of simplifying things by making this flag be a way to reduce the two ways of building things into one way.

@gmorenz
Copy link
Contributor

gmorenz commented May 8, 2024

@rustbot label: +Z-target-applies-to-host

@rustbot rustbot added the Z-target-applies-to-host Nightly: target-applies-to-host label May 8, 2024
@gmorenz
Copy link
Contributor

gmorenz commented May 8, 2024

There's some important discussion about eventual stabilization in this review comment, and the discussion on the main thread of that PR after the review. To summarize:

Should target-applies-to-host = true do what current cargo does, or what the name naively implies it does, because those turn out to be different things. If it does what the name naively implies it does, do we add a third option (e.g. = "mixed") that does what cargo currently does?

Because of complexity Alex Crichton (not tagging as they have chosen to step down from this) and @jonhoo appear to have been leaning towards "stabilize directly to target-applies-to-host = false as a breaking change, potentially not even exposing an option to opt in to other behavior". Gating stabilization on fixing the bug that "that cargo build is "all host" rather than the expected "some host some target" builds", and host-config. I'm unclear if the further discussion that they suggested was necessary ever actually occurred.

@saurik
Copy link

saurik commented May 9, 2024

@gmorenz It isn't clear to me, in the three-state idea, why anyone would ever use =true: new code should use =false, and some older scripts might temporarily need =mixed, but no one should ever be using =true? I can see renaming the flag, but it seems kind of silly and will just cause even more churn, given that I would expect that no one should ever opt into that behavior: at least with this name, the few people who might care are likely to find these issues and the now years of discussion on various forums with people talking about this flag as fixing the current broken behavior and explaining why you might want to turn this legacy behavior back on.

I would then document the flag, explaining merely that =true opts into quickly/legacy behavior. I frankly would not try to document that behavior, as it was, is, and will continue to be nonsensical and the goal of keeping it in the codebase only makes sense for people whose code already happened to work before, and those people do not need documentation of the behavior that is already confusing: they just need to be told to stop relying on it. I would also state that the flag might go away in the future, and so no one should start writing new code that uses =true or ever consider turning it on unless they are doing so to temporarily work around an issue.

At that point, the name seems almost irrelevant. As far as I can tell, all of this discussion about a tri-state flag happened due to a misunderstanding of the intended future of the flag, not due to any real interest in actually having =true be a supported configuration. As such, it seems silly to implement the tri-state feature merely to make the name make more sense, but it also seems silly to lose sleep over the name given that the flag is only to be used in a way where the name can be confusing in exceptional scenarios by people who already rely on whatever that behavior might be, and the flag is coming into existence with the goal of then rapidly phasing out.

Remember: in its current state, cargo does not work! The most common way for serious integrators to build software is using host==target cross-compiling, and so an increasingly-large number of projects are turning to the crazy workaround of using the DO_NOT_USE_THIS nightly override env and are already pushing this flag into production as without it cargo simply doesn't work. It would behoove everyone to push this flag--whatever the default--sooner rather than later, as it isn't clear to me that the people whose code right now could break even if the default were changed should matter more than the people who are using this flag to fix the bug.

@gmorenz
Copy link
Contributor

gmorenz commented May 9, 2024

@saurik I'm sympathetic to that argument with regards to =true, the docs definitely need updating with regards to it though, and the alternative of "stabilize =false behavior without a flag" seems like something whatever cargo team member that eventually picks this up should see and consider.

As currently implemented it seems to me that cargo is just as broken with =false as without it. Either way it's building the artifacts differently depending on whether you're cross compiling or not, it's just the difference between "host artifacts get extra rust-flags" and "target artifacts are missing rust-flags". I'm looking at the diff you linked above for instance, and while I haven't tried to build your codebase it's my understanding that line 135(incoming)/137(outgoing) is only applied when you are cross compiling (passing --target x) despite having turned on target-applies-to-host = false.

I've started poking at the cargo code in an attempt to fix the flag, but no promises.

Edit: Apparently rust-lang/rust wanted target-applies-to-host=true (not mixed) at one point: rust-lang/rust#94556

@gmorenz
Copy link
Contributor

gmorenz commented May 9, 2024

@saurik - Correcting my previous comment, since that build script is always passing a --target flag, my understanding of the current behavior is that target-applies-to-host=false should be doing nothing (both as documented and implemented), so I probably misunderstand something.

What is the difference in behavior that you see by enabling the flag in that context?

Edit: It's that linker arguments isn't used to build host artifacts

bors added a commit that referenced this pull request Jul 4, 2024
…ihanglo

Pass rustflags to artifacts built with implicit targets when using target-applies-to-host

## What this PR does

This fixes #10744, a long-standing bug with `target-applies-to-host=false` where `RUSTFLAGS` are not being passed to artifact-units when built with `cargo build` (as opposed to `cargo build --target <host>`).

It doesn't fix a similar problem with `linker` and `links`. If the architecture in this PR is accepted, I expect I will be able to fix `linker` and `links` in the same way in a subsequent PR.

Below is a hopefully useful table of what flags are passed when, with new behavior bolded (without these changes the flag is not passed). I've only changed values in the top right cell, I've included the whole table for completeness and to hopefully make clear what exactly this feature is doing (which took me awhile to understand).

The table was generated with a host of x86_64-unknown-linux-gnu. "Flag" refers to values in RUSTFLAGS. "Linker" refers to the value of `--config target.<host>.linker` . The table was built with [this repo](https://github.com/gmorenz/target_application_to_host_matrix) and then hand modify to bold changed values.

| | target_applies_to_host=true | target_applies_to_host=false |
|-|-|-|
| no --target flag | Flag passed to bin<br/>Flag passed to shared dep from bin<br/>Linker passed to bin<br/><br/>Flag passed to proc macro<br/>Flag passed to shared dep from proc macro<br/>Linker passed to proc macro<br/><br/>Built with 5 invocations<br/>Without rustflags, built with 5 invocations<br/> | **Flag passed to bin**<br/>**Flag passed to shared dep from bin**<br/>Linker not passed to bin<br/><br/>Flag not passed to proc macro<br/>Flag not passed to shared dep from proc macro<br/>Linker not passed to proc macro<br/><br/>**Built with 6 invocations**<br/>Without rustflags, built with 5 invocations<br/> |
| --target x86_64-unknown-linux-gnu | Flag passed to bin<br/>Flag passed to shared dep from bin<br/>Linker passed to bin<br/><br/>Flag not passed to proc macro<br/>Flag not passed to shared dep from proc macro<br/>Linker passed to proc macro<br/><br/>Built with 6 invocations<br/>Without rustflags, built with 6 invocations<br/> | Flag passed to bin<br/>Flag passed to shared dep from bin<br/>Linker passed to bin<br/><br/>Flag not passed to proc macro<br/>Flag not passed to shared dep from proc macro<br/>Linker not passed to proc macro<br/><br/>Built with 6 invocations<br/>Without rustflags, built with 6 invocations<br/> |
| --target i686-unknown-linux-gnu | Flag passed to bin<br/>Flag passed to shared dep from bin<br/>Linker not passed to bin<br/><br/>Flag not passed to proc macro<br/>Flag not passed to shared dep from proc macro<br/>Linker passed to proc macro<br/><br/>Built with 6 invocations<br/>Without rustflags, built with 6 invocations<br/> | Flag passed to bin<br/>Flag passed to shared dep from bin<br/>Linker not passed to bin<br/><br/>Flag not passed to proc macro<br/>Flag not passed to shared dep from proc macro<br/>Linker not passed to proc macro<br/><br/>Built with 6 invocations<br/>Without rustflags, built with 6 invocations<br/> |

 ## How it is implemented

There are two stages in the `UnitGraph`'s life. It gets built, with correct `CompileKind`: `CompileKind::Host` for host units, `CompileKind::Target(HostTriple)` for artifact units. Then it gets rebuilt with artifact units that are intended for the host  having their kind changed to `CompileKind::Host`.

This rebuilding step serves to de-duplicate host and artifact units. A step that we want to maintain where possible. Because de-duplicating host and artifact dependencies is only possible if their `rustflags` don't differ we must calculate `rustflags` for units before this step, and this step necessarily throws away the information necessary to calculate them.

The possible rustflags have already been determined before creating units. "Calculating rustflags for units" just means determining which set of rustflags go with a particular unit, and storing that somewhere. The obvious place to do that is in the unit itself, so that's what this PR does, which has the convenient side affect of also handing the de-duplication logic for us. If the rustflags are the same, two units can be merged, if they differ, they cannot.

In the above table that's why it takes 5 invocations to build the repo without rustflags, but 6 with them. The shared_dependency merges when it is built without rustflags, and not when it is built with rustflags.

 ## Related PRs, comments and issues

fixes #10744

#9453 - Tracking issue

#9753 - Stabilization PR

#9634 - I believe this was another attempt (going down another implementation route) to fix the same issue

Comments from Alex Crichton noting that this must be fixed [1](#10395 (comment)) [2](#9753 (comment))

[My own comment describing exactly how I ran into this](#9753 (comment))

[Documentation for the feature](https://doc.rust-lang.org/cargo/reference/unstable.html#target-applies-to-host)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. Z-target-applies-to-host Nightly: target-applies-to-host
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants