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

rustc-book: Document -C target-feature=+crt-static #71586

Closed
wants to merge 1 commit into from

Conversation

petrochenkov
Copy link
Contributor

@petrochenkov petrochenkov commented Apr 26, 2020

A preliminary for #70740.

@rust-highfive
Copy link
Collaborator

r? @matthewjasper

(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 Apr 26, 2020
@petrochenkov
Copy link
Contributor Author

cc @alexcrichton

- Unknown CPU features go straight to LLVM and appear as LLVM warnings.
- At configure time `crt-static` predicate is set even if the target doesn't support `crt-static`.
- At link time `crt-static` is sometimes ignored
if the target doesn't support it and sometimes not.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I strongly suspect that #69519 was a hack rather than a proper solution, but I need some time to prepare a musl setup and verify things. (Proc-macros shouldn't be any different to cdylibs and dylibs with regards to linking behavior.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proc-macros shouldn't be any different to cdylibs and dylibs with regards to linking behavior

That was the problem 😉

TL;DR It's a hack.

Musl target is a "weirdo". Because of the legacy decisions it defaults to static linking so it cannot produce dylibs, cdylibs and proc-macros. Now lack of proc-macro support doesn't matter when cross-compiling from the host which supports them to musl.
It becomes difficult when using musl as the host toolchain. Since it defaults to static linking proc-macros don't work. To build them one had to use target-feature=-crt-static and lose ability to statically link binaries.

Copy link
Contributor Author

@petrochenkov petrochenkov Apr 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mati865
First, musl toolchain actually supports statically linking self-contained .sos, despite the flag in rustc target spec saying otherwise, I tried it (at least with "hello world"-like examples).

Second, that doesn't mean that we want to use it for proc macros (as well as cdylibs and dylibs) at the same time as we are building a statically linked executable.

So, one common RUSTFLAGS="-Ctarget-feature=+crt-static" (or a target spec default) in this case brings collateral damage on the crates which it is not supposed to apply to.

I see multiple possible solutions here some of which could be more principled than what #69519 did.

  • Automatically enable -Ctarget-feature=-crt-static for proc macro crates or all libraries in Cargo, modifying RUSTFLAGS. Question: how to opt-out?
  • Introduce a new options -Ctarget-feature=+crt-static-dylib controlling static linking of libraries instead of -Ctarget-feature=-crt-static. It would almost never be used on Linux (not sure about windows-msvc and wasm).
  • Keep the existing meaning of crt-static, but introduce a new option -C disable-crt-static-for-dylibs or something. Cargo would then use it for proc macro crates or all libraries. Question: how to opt-out?
  • Ignore +crt-static for dylibs if the target doesn't support it. This is fragile, musl actually supports it despite the current value of the flag of the musl target spec. If the flag is enabled, proc macros will break.
  • Ignore +crt-static for dylibs always. They are almost never used on Linux (not sure about windows-msvc and wasm). +crt-static-dylib looks strictly better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Have two crt-static defaults in target specs - one for executables and one for libraries. Solves one half of the problem, but explicit +crt-static in RUSTFLAGS will still cause collateral damage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll turn this into a proper issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steveklabnik
Copy link
Member

This includes more than just documentation changes, but also implementation changes ,was that intended?

@petrochenkov
Copy link
Contributor Author

@steveklabnik

Based on #71490, only the last commit is new.

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating the docs, they are a big improvement!

src/doc/rustc/src/codegen-options/index.md Outdated Show resolved Hide resolved
src/doc/rustc/src/codegen-options/index.md Outdated Show resolved Hide resolved
src/doc/rustc/src/codegen-options/index.md Outdated Show resolved Hide resolved
@bors

This comment has been minimized.

@alexcrichton
Copy link
Member

I haven't looked too too closely at this, but my main recommendation would be to not try to exhaustively document the state of things without a disclaimer. There's basically always one reason or another that +/-crt-static is still buggy, so I think it'd be worthwhile to place a disclaimer in the docs saying that things can be tweaked over time and if someone is overly surprised it's recommended they file an issue.


- PE-based executables (Windows).
The produced executable will contain code from all the user-level libraries, including
[C Run-Time Libraries (CRT)](https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What user-level libraries will it statically link to other than the CRT? For windows-msvc crt-static only controls whether the CRT (consisting of the VC Runtime and the UCRT) is statically linked and nothing else is affected. Also it only applies to windows-msvc while windows-gnu does not support crt-static.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@retep998

What user-level libraries will it statically link to other than the CRT?

Rust crates.
And it should do that for native dependencies as well (#71647), but that doesn't make any difference on Windows since there's no libmylib.a/libmylib.so separation.

If after that anything is still linked dynamically, then we get into the *WARNING!* clause below. It's not as dangerous in the Windows case though, since the goal there is not to produce a fully statically linked executable, like in the ELF case.

Also it only applies to windows-msvc while windows-gnu does not support crt-static.

Good catch.
This paragraph needs the same "If the target supports..." condition as the ELF paragraphs above.

Copy link
Member

@retep998 retep998 Apr 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me crt-static on Windows always had the impression that the only thing it controlled (and ever intended to control) was whether it linked to the static or dynamic CRT. I was not aware that it had any effect on whether a rust crate was linked statically or dynamically, as by default it will link rust crates statically unless you specify -Cprefer-dynamic.

@petrochenkov
Copy link
Contributor Author

TODO: Mention that +crt-static overpowers -C prefer-dynamic.

@petrochenkov
Copy link
Contributor Author

This is kind of blocked on #71651 now.

@petrochenkov petrochenkov added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 30, 2020
@petrochenkov
Copy link
Contributor Author

petrochenkov commented May 2, 2020

TODO: Figure out what gcc/clang/ld/lld do on Linux if libc is linked statically, but something else is linked dynamically.

@smaeul
Copy link
Contributor

smaeul commented May 2, 2020

TODO: Figure out what gcc/clang/ld/lld do on Linux if libc is linked statically, but something else is linked dynamically.

We send both -static and -Bdynamic -lfoo to the linker, causing it to produce a nonfunctional dynamic ELF.

From #55566 (comment) quoting #40113 (comment):

  1. The current problem is that, when base.dynamic_linking = true, base.crt_static_default = true is not enough to enforce that binaries are statically linked by default.
    • It does not enforce that all linked libraries must also be statically linked, so when gcc sees dynamic libraries, it creates a dynamic executable (i.e. an ELF with DT_NEEDED entries).
    • But because you told it you were creating a static executable, gcc not pass -dynamic-linker to ld to add the correct PT_INTERP header to the ELF, and therefore ld uses its hardcoded default for the architecture, e.g. /lib/ld64.so.1 on x86_64.

@bors
Copy link
Contributor

bors commented May 10, 2020

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

@petrochenkov
Copy link
Contributor Author

Bibliography 🙂:
#11937 - Link using the linker directly
#31322 - How to compile rust in a musl libc based linux system
#34987 - MUSL dynamic linking support
rust-lang/libc#290 - Can't statically link MSVC runtime
rust-lang/rfcs#1684 - Choosing which CRT to link to
rust-lang/rfcs#1721 - Enable customizing the linkage of a platform's C runtime
#36710 - link: failed to static link to c++ library when global variable is used
#37406 - Tracking issue for customizing CRT linkage
#37545 - rustc: Implement #[link(cfg(..))] and crt-static
#38075 - x86_64-musl: allow building dylibs with -crt-static
#39998 - A new compiler flag: "link everything statically or die, dammit!"
#40113 - Support dynamically-linked and/or native musl targets
#40174 - Unable to find crate proc_macro on musl target
https://internals.rust-lang.org/t/refining-cross-platform-crt-static-semantics/5085 - Refining cross-platform crt-static semantics
#50105 - Use the correct crt*.o files when linking musl targets
#50709 - Revert #50105 until regression is fixed
#51063 - Fix building rustc on and for musl hosts
#53968 - static-pie for musl target (remove crt1.o)
#54243 - x86_64-unknown-linux-musl target and main-returning-Result produces a dynamically-linked executable instead of a statically linked one
#55566 - Require static native libraries when linking static executables
#58575 - Musl host toolchain
#59302 - Tracking issue for musl host toolchain
#64547 - mips-linux-musleab is broken again because it uses the wrong crt for static pie
#65447 - Statically link against glibc
#65760 - musl staticlib builds include all of the musl symbols
#69519 - Don't use static crt by default when build proc-macro
#70693 - RFE: x86_64-unknown-linux-musl static-pie target for ASLR
#71586 - rustc-book: Document -C target-feature=+crt-static
#71647 - rustc should prefer statically linking native dependencies with unspecified kind if crt-static is enabled
#71651 - Enabling +crt-static in a blanket way breaks dynamic libraries including proc macros
#71804 - linker: Support -static-pie and -static -shared
rust-lang/libc#1327 - Don't bundle static libc
rust-lang/cargo#7563 - cannot produce proc-macro when --target is set on musl host toolchain
https://gcc.gnu.org/legacy-ml/gcc/2015-06/msg00008.html - Static PIE support in GCC
https://www.openwall.com/lists/musl/2012/12/08/2 - static linking and dlopen
https://www.openwall.com/lists/musl/2016/07/14/1 - Regarding whole-archive linking libc.a into a shared lib

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jun 4, 2020
rustc_target: Remove `pre_link_args_crt`

To regain some more control over the definition of `+crt-static` (rust-lang#71586).

After rust-lang#71769 this target option wasn't used anywhere except for VxWorks, and I suspect that for VxWorks its use may be redundant as well.
@petrochenkov
Copy link
Contributor Author

I'll reopen this once the related issues are addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants