-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
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
bintools-wrapper: support lld
's -flavor
argument
#231960
base: staging
Are you sure you want to change the base?
Conversation
see: NixOS@1ad1edb#diff-1e2a7a7a59ec6654236ae711952684e8117c50b9cf76f9b9613f6ae392e26f38 this was originally on the purity check
Also, Does not inspire confidence. I don't think LLVM wants us to be adding new uses of this. If they did, they would fix the wacky flag-ordering constraint. |
It makes sense to me — it completely changes how argument parsing works. In Windows-style linking, "-flavor" wouldn't even look like a flag, right? |
Correct, because this is the Windows driver for LLD which switches the whole parsing in a Windows-style.
We can invoke I'm not sure this is tractable for the near future to fix everyone doing it wrong at the moment. |
The rustc documentation also mentions that it always uses |
I mean then it isn't really a flag, is it? It sounds like this flavor business is really part of |
We went down this route first but my understanding is that |
> Can't you folks just make four different `lld-${flavor}` wrappers for the four approved flavors?
We went down this route first but my understanding is that `rustc` makes this a little more annoying to use; i.e. you have to specify `-C linker` and `-C linker-flavor` because (AIUI) there's no way to nudge `rustc` into using `lld-link` via `-C linker-flavor` (as mentioned in the [docs Alyssa linked](https://doc.rust-lang.org/nightly/rustc/codegen-options/index.html#linker-flavor)).
Yeah, I don't like this interface either, but I don't like lots of interfaces that are out there in the world. We don't get to decide which interfaces get adopted, and this one sadly has been.
|
I'm not quite understanding this. If that flag needs to go first, and affects all subsequent flags, then it's really part of #!${runtimeShell}
exec lld -C linker-flavor=windows-slashy-flags "$@" Now What goes wrong if you simply tell |
You are confusing
This would be a new "linker-flavor" which would not be "lld" per se I believe.
So if we say We would need to fix |
Thanks, updated:
Simply have the script check for an extra flag and drop it. Since it's guaranteed to be the first flag this is easy to check for. Unlike this PR that would:
|
if [[ ${#params[@]} -ge 2 ]] && [[ ${params[0]} == "-flavor" ]]; then | ||
# As per the link above, only `-flavor <flavor name>` is supported. Not | ||
# `--flavor`, `-flavor=...`, `/flavor:...`, etc. | ||
linkFlavor="${params[1]}" | ||
extraBefore=(-flavor "$linkFlavor" "${extraBefore[@]}") | ||
|
||
params=("${params[@]:2}") | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment.
We should re-evaluate this now in the context of rust-lang/rust#112910. |
Unfortunately, even if we do this and this works for the ld-wrapper, I am not exactly sure this will work for Rust bootstrap. As you suggested me in #231951 I went in the rabbit-hole and my understanding is that bootstrapping Rust for the UEFI target will induce the same issue where we need rustc to understand what is the linker flavor to properly produce the libcompiler_builtins.rlib in COFF format, otherwise, it will produce ELF, making all the bootstrap process fails. We have few knobs here, we usually pass: # We need rust to build rust. If we don't provide it, configure will try to download it.
# Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py
configureFlags = let
setBuild = "--set=target.${rust.toRustTarget stdenv.buildPlatform}";
setHost = "--set=target.${rust.toRustTarget stdenv.hostPlatform}";
setTarget = "--set=target.${rust.toRustTarget stdenv.targetPlatform}";
ccForBuild = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}cc";
cxxForBuild = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}c++";
ccForHost = "${pkgsBuildHost.targetPackages.stdenv.cc}/bin/${pkgsBuildHost.targetPackages.stdenv.cc.targetPrefix}cc";
cxxForHost = "${pkgsBuildHost.targetPackages.stdenv.cc}/bin/${pkgsBuildHost.targetPackages.stdenv.cc.targetPrefix}c++";
ccForTarget = "${pkgsBuildTarget.targetPackages.stdenv.cc}/bin/${pkgsBuildTarget.targetPackages.stdenv.cc.targetPrefix}cc";
cxxForTarget = "${pkgsBuildTarget.targetPackages.stdenv.cc}/bin/${pkgsBuildTarget.targetPackages.stdenv.cc.targetPrefix}c++";
lldForTarget = "${pkgsBuildTarget.targetPackages.stdenv.cc}/bin/${pkgsBuildTarget.targetPackages.stdenv.cc.targetPrefix}ld.lld";
in [
"--release-channel=stable"
"--set=build.rustc=${rustc}/bin/rustc"
"--set=build.cargo=${cargo}/bin/cargo"
"--enable-rpath"
"--enable-vendor"
"--build=${rust.toRustTargetSpec stdenv.buildPlatform}"
"--host=${rust.toRustTargetSpec stdenv.hostPlatform}"
# std is built for all platforms in --target.
"--target=${concatStringsSep "," ([
(rust.toRustTargetSpec stdenv.targetPlatform)
# (build!=target): When cross-building a compiler we need to add
# the build platform as well so rustc can compile build.rs
# scripts.
] ++ optionals (stdenv.buildPlatform != stdenv.targetPlatform) [
(rust.toRustTargetSpec stdenv.buildPlatform)
# (host!=target): When building a cross-targeting compiler we
# need to add the host platform as well so rustc can compile
# build.rs scripts.
] ++ optionals (stdenv.hostPlatform != stdenv.targetPlatform) [
(rust.toRustTargetSpec stdenv.hostPlatform)
])}"
"${setBuild}.cc=${ccForBuild}"
"${setHost}.cc=${ccForHost}"
"${setTarget}.cc=${ccForTarget}"
"${setBuild}.linker=${ccForBuild}"
"${setHost}.linker=${ccForHost}"
${setTarget}.linker=${ccForTarget}")
"${setBuild}.cxx=${cxxForBuild}"
"${setHost}.cxx=${cxxForHost}"
"${setTarget}.cxx=${cxxForTarget}"
... So the linkers for: build=x86_64-unknown-gnu-linux will be, e.g. build=gcc cc-wrapped, host=llvm cc-wrapped, target=llvm's cc-wrapped, which all uses I am not knowledgeable enough again about cc-wrappers to understand how I can swap the linker backend under the hood of the cc-wrapper and pass it back, otherwise, I will have to hack platform-specifics inside the rustc.nix derivation to build a modified linker with ld.lld, it seems undesirable because the domain knowledge should not really end there I believe. The easiest seems again to get a ld-wrapper that knows about -flavor, I just build the right CC from the get-go with a ld.lld linker rather than binutils's ld, and… this should work, I imagine now. I spent more almost 10 hours non-stop on that issue, reading the source code of Rust, asking Rust developers and so on and so forth, I just don't know what to do anymore. :) |
It seems like you're moving the goalposts a bit here. The stated motivation for this PR is to get I suggested a simple and straightforward way to accomplish this, which would impose no ongoing maintenance burden on the rest of Nixpkgs. You've posted about how you're struggling with getting Rust to bootstrap itself for a COFF target. I don't doubt that's difficult, but I think it's a bit unreasonable to use that as a justification for pushing this workaround all the way down into Compilers' built-in bootstrapping routines are often inflexible; we moved away from using
I have some advice specific to your problem which I've posted over in #231951. Let's try to keep this PR on track as dealing with |
OK, I apologize for my "despair" reply, you're right. I am solving slowly the issues without this PR. We will see when I arrive at the ld-wrapper issue with the tool. :) |
Description of changes
lld
supports specifying the linker flavor with-flavor
however this must be the first argument passed. This PR updatesbintools-wrapper
'dld-wrapper
to hoist-flavor
beforeNIX_LDFLAGS_BEFORE
/extraBefore
when passed as the first argument to the wrapped linker.Note: I'm pretty sure this patch does not interact correctly with
cc-wrapper
's use ofld-wrapper
; IIUCcc-wrapper
will handleNIX_LDFLAGS_BEFORE
in lieu ofld-wrapper
which makes it so that we cannot distinguish between "injected" linker args and pre-existing linker args withinld-wrapper
.For the use case that prompted this PR (#231951) this isn't an issue (we were only trying to work around linker hardening flags which always get handled by
linker-wrapper
I believe) but this still seems like something we should fix.If we're okay "incorrectly" hoisting
-flavor
(i.e. when not passed as the first argument) then havinglink-wrapper
scanparams
would be an easy fix for this.I'm still waiting for stuff to rebuild locally so I can test this; marking this PR as a draft for now.
cc @RaitoBezarius
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)