-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[Cargo] let build scripts pass (arbitrary) linker arguments to rustc
#1766
Comments
I remember mentioning that, but I do not remember the exact context. There’s the |
I'm of two minds about this. On one hand this is a feature we're not exposing, and makes certain flavors of development very painful. On the other hand though, having less surface area to the compiler allows us to provide a uniform and solid interface that works across many platforms and situations. One example that comes to mind is the ability to select a subsystem on Windows. The actual way to do this is by passing a linker argument, but we're likely going to settle on #1665 which I personally view as a better alternative. If we allowed custom linker arguments, we may even break crates as a part of that change. I also personally feel that many linker arguments are best expressed via this style of crate attribute where possible. This doesn't cover all use cases, of course, but having a layer of abstraction between an intention and the actual linker argument allows us to easily change how it's implemented. The point about having less surface area also dove-tails into the ability to change how we call the linker at will without worrying about the impact. We relatively frequently tweak how we work with symbols and/or possibly link order, and with custom link arguments it means you could silently be relying on a previous compiler and we could break you as we update. Finally I've also often felt that if you truly want a robust stability guarantee here you should never use So all that's basically just a fancy way of saying that I can see a lot of downsides from allowing such easy propagation of custom linker arguments, but I'm not sure if they outweigh the benefits. |
@alexcrichton Doesn't |
@eddyb for now, maybe, but perhaps not always. There's certainly a possible future where we use no command line api of LLD but rather use it entirely as a library where CLI arguments make no sense. In any case though I think the point about being brittle would still stand regardless, and in general rustc is a pretty robust compiler across platforms and such. |
@alexcrichton I meant library + argument parsing. We do the same for LLVM, but yeah, no guarantees. |
OK. so I can compromise with a more constrained form of injection of linker arguments. Allowing crates and/or build script to inject linker arguments of the form {
// ..
"pre-link-args": [
"-mcpu=cortex-m4",
"-mthumb",
"-Tteensy3-sys/teensy3-core/mk20dx256.ld",
"-Os",
"-Wl,--gc-sections,--defsym=__rtc_localtime=0",
"--specs=nano.specs"
],
"post-link-args": [
"-lm", "-Wl,--start-group", "-lnosys", "-lc", "-lgcc", "-Wl,--end-group"
]
// ..
} (Although, I think some of those flags, like So, there's that to consider. (*) The other half of my problem is that I want to pass |
They probably are needed because of multilib support in the toolchain. Gotta choose the right libc etc. |
@japaric oh so to clarify I definitely don't believe all use cases for linker arguments can be moved to crate attributes (like linker scripts). Additionally, I also feel like Cargo is too strict today for what ends up amounting to unnecessary reasons. I just personally struggle to reconcile that with also knowing that Cargo is pretty user-friendly today and linker errors are about the most user-unfriendly thing, and I'd be quite sad if Rust newbies hit those kinds of errors early on in working with Rust. |
But that's because |
I think the obvious solution to these sorts of problems is perma-unstable features. The escape hatch is there because the workaround is worse, but none of it is really condoned. |
Yes, that's true. I may be misremebering but I think
I'm in favor of this with the additional condition that we should be looking for ways to stabilize some type of linker arguments (like the |
Today we are using, with success, I have opened a discussion on the rust-embedded/rfcs repo (see rust-embedded/wg#24) to compare the two existing options for linker customization and to hopefully settle on one of them through convention. Please comment over there if you have on opinion on this topic. |
I'm builing the static version of libui with bindings to it on Windows. The only way I have found it to build via GNU (cannot use MSVC for reasons) is to provide the linker params with Windows libraries manually via |
@japaric Even if we can submit all the linker arguments we need via |
Using (This flag is necessary to get a Darwin binary that can mmap below 4GB as required by LuaJIT). |
The problem with For example, I've just encountered a scenario where I need to add Ideally, I'd read the path from the environment, but it's not possible. (And I'm not alone) So one compromise might be to allow I managed to work around my problem by using |
I believe cross-compilation is one of the most important features a compiler should have. I dont understand why you said cargo is user friendly since it do not really works out of the box and it is even worst with tier3 targets. Besides, documentation for such cases is not really precise. my impression is that having support only for standard targets lock users to some specific architectures. Hope with some experience i will understand better what is really needed for making rust user-friendly specially during cross-compilation. |
Use cases
Bare metal embedded development
Linking Rust programs for bare metal targets always (unless there some C in the mix) require passing a linker script to the linker. This linker script specifies the memory layout of the target device and, if omitted, the resulting binary will not work on the target device (the device will not boot or crash during the boot process).
The current way to pass these flags to the linker (using rustc as a proxy) is via the
build.rustflags
ortarget.$triple.rustflags
key in .cargo/config:This is troublesome because:
.cargo/config
to its dependent crates. Every user of the library will have to manually copy the library.cargo/config
in their binary project.Other use cases
There are probably other use cases that I don't know about
Straw man proposal
Cargo will learn about a new "build script key":
rustc-link-arg
. Cargo will collect all the values under that key and pass those to all itsrustc
invocations via the-C link-arg
flag. For example, this build script output:Makes Cargo pass the
-C link-arg=-Tlayout.ld -C link-arg=-nostartfiles
to all itsrustc
invocations.As with other
cargo:$key
s, Cargo will collect these values from all the dependencies.Potential problems
#[export_name]
,#[no_mangle]
)?rustc
only supportsgcc
-style linkers. And if a crate needs to support two or more targets that use different linkers then the build.rs can simply pick different linker arguments based on the value of the$TARGET
env variable.-l
-style arguments to the linker and those are order sensitive.cc @nagisa @alexcrichton
@jamesmunns and @cbiffle may be interested as well
The text was updated successfully, but these errors were encountered: