Change:
The recently landed introduced a heuristic to search for the system MinGW libraries relative to the cross-gcc (used as linker) itself. However, there are systems that do not follow this pattern. For example, on my Gentoo system: is a symlink to is the directory with the actual libraries in the sysroot It would be useful to have a way of overriding the heuristics and informing about the correct library path manually. In the current configuration even does not help because the rustc-provided libraries have higher priority.
cc My comment in the PR:
My hope is that this would be of far lesser urgency than because this only affects the startup object files which ideally change far less in the gcc toolchain than the rest of the toolchain. The main issue was that we'd prefer our own import libraries and such, which really was only effective if they came from the same toolchain as the host toolchain, which they rarely did.
It'd be nice to have Rust's MinGW follow latest MinGW release but it's not backwards compatible: Although it's worth mentioning the last breaking change to the CRT happened 2 years ago. This means using newer MinGW would already increase amount of systems where it just works. How does target work in regard of CRT? It doesn't ship startup objects unlike and targets.
The toolchain used for MinGW has historically been "whatever is on the builders", so it's not strictly kept in sync with something or intentionally held back. It should be updateable at any time! The non-MinGW targets all rely on the linker to pull in the CRT. None of them work without a preinstalled toolchain, though, whereas one of the purposes of the MinGW toolchain is to work without a preinstalled toolchain.
there is another case of nonstandard path. This time on Windows when MinGW is installed through Chocolatey Chocolatey install wrappers so there is really no way to get location of original executable.
Sorry I don't know of a great way to fix things, I know very little about MinGW myself.
, On AppVeyor CI (which uses a choco install of mingw), while testing, I used the relative path "..libmingwtoolsinstallmingw64" from the wrapper to the main directory of the install. I believe that should be a relatively stable path. It should be at least testable.
, After a bit of googling and stackoverflow search, I found a second, more robust, though more complicated/slower, method of finding the installation main directory (ref: ). Using the option to returns a reference to the true installation path (see ). I hope that's helpful.
Rust could get library path from itself but calling executables on Windows is slow. I was about to add Chocolatey structure as one of the paths (and fix Cygwin as well) but there was a lot going on for me this week.
, yep, I think using the "usual" relative path (ie, "..libmingwtoolsinstallmingw64") would be the better choice. I guess you could fall back to parsing the output, but that's a lot of effort for a low percentage occurrence. I do want to say thanks for your efforts on this problem.
Still, how about a fallback to some config item or environment variable so that it can be made work on unsupported layouts too without rebuilding rustc?
calling would be better than but it's still calling external executable which is slow on Windows. This was one of the concerns of regarding my PR. I'm not member of compiler team so I cannot tell but I think they'd accept unstable flag. I don't know that part of the compiler and would love if somebody else did it (if compiler team agrees). Another option would be upgrading mingw-w64 which Rust CI is using but I don't know which team "controls" it.
, slow execution speed is an understandable concern, but "works slowly" is slightly better than "doesn't work". If is on the PATH and requested as a compiler, I do think that searching via faster known-path methods with a fallback to the slower would be very reasonable. That would also essentially solve the "unsupported layouts" issue raised by .
I'm not decisive here. Maybe it'd be feasible to do it only when cross compiling but you would need to discuss it with the team.
Hello! After a false start of confusing myself on another issue thread :(, I've now realized that this is actually what is going on and thereby the issue I should be commenting on ;P. In my case, this is my "linker" (which is a command, per ): The main things to notice are that 1) I'm using clang and 2) I have a custom sysroot. I really need to be using my sysroot here for multiple reasons: 1) it is just more correct to have a consistent sysroot that I build myself; 2) the linker's default sysroot doesn't work due to (all of the MinGW toolchains I work with--macOS Homebrew and Ubuntu--default to SjLj); and 3) the ones that come with Rust don't work due to (the __onexit* symbols). So what I really need is to just get Rust to not break the usage of my sysroot somehow. As I'm cross compiling with a sysroot, the path of my linker really has absolutely nothing at all to do with the path of the binary being run as my linker (not even my underlying linker program, much less the wrapper script I have to generate to run my linker and pass it the right flags, are going to be inside of my sysroot). Of the options presented here, --shimgen-noop will not work as I'm not using gcc, but -print-file-name=dllcrt2.o does work as expected. FWIW, I would also be perfectly happy to provide the path manually if I had some way to do so: I don't really need this to be automated.
, , how would I go about asking about adding such a feature when cross-compiling (especially on windows)?
FWIW, I would argue that the "known path" methods without an explicit override mechanism are "wrong", as the compiler--which you are accepting as a "linker"--is itself providing an override (in the form of --sysroot) in addition to defaulting that to some relative path (meaning I might in fact have a sysroot that came with the compiler that I am explicitly not using), and so if the user is using gcc/clang for a linker you can't use alternative approaches only as a "fallback": if you want it to work automatically and correctly the most often I would think you should thereby ask the compiler for the path even if that is slow and then allow people who want to link faster to specify it manually, or if you want it to always be fast but sometimes wrong then you definitely need to provide the manual override for those people who overrode their compiler (personally, I would vote for the former with some caching, as my experiencing is that the MinGW linker--even when not run on Windows--is so much slower than any other linker I use that if you run an external program once or even "every now and then" I can't imagine that having much of an impact on overall build time: if it really really actually matters to someone they can then provide an override as an optimization).
So, I am now also running into this problem with libmsvcrt.a, which is manifesting as the issue from :(. Is there anything I can do to help get this solution to run worked on? My company is willing to sponsor this work, as frankly I'm now at the point of just regretting even trying to use any Rust libraries in my program :(. I'm over a month in and still just fighting with basic stuff like "compiling things at all" (not just for MinGW), when I'm pretty sure there are even deeper issues in the Rust build system with respect to secure reproducible builds that I thought I'd be spending my time diagnosing. FWIW, I really just need a way to set the sysroot here: it doesn't have to be automatic... if nothing else, I'd seriously suggest deleting all of the libraries that Rust is shipping with, as those are pretty much never going to be correct and seem to be leading to some kind of unsafe assumed coupling. (cc
if you simply delete them the linker won't be able to find them. I'll try to find the time to fix it next week.
Thanks!! FWIW, I really am willing to make sure you can get compensated for the time to stare at this; like, this is the kind of fix I'd normally try to do myself, but I honestly don't know where to begin with respect to "if I change this in the code, what do I have to rebuild to test the change", as I am only right now at the stage of "beginning to integrate Rust" as opposed to "coding in Rust". At it's simplest, if have just like a PayPal account or something, I could at least donate/contribute. I also had written another comment last night that I thought I'd sent but am not finding anywhere, which is that I finally decided to try setting LINKER to "true" out of despair, and that actually "worked", in that the cruel irony here is that I don't even want this linker output: I'm linking these libraries into a larger application (hence why I need to use specific compilers and sysroots to be compatible with the rest of the object files) and so just want the staticlib, but Cargo has no way to override crate-types without editing the upstream file, and so I end up getting a bunch of side outputs of cdylibs and the such that I have no real use for, but need to not fail ;P. I had had a plan to maybe write a wrapper to set as LINKER that would attempt to figure out which arguments were using Rust toolchain paths and rewrite them using a sysroot passed from the environment, but the realization that I didn't even want the linker output anyway (while writing up a comment in defense of one of those Cargo issues that had stagnated years ago) I realized maybe the build system would "just work" if I passed "true" and then I could get my staticlib, which I end up linking myself anyway, and that did in fact work great ;P. (In the end, though, getting this library to link is blocked on a bunch of other things; like, there is a simple-looking issue with bindgen not supporting iOS--it is passing the wrong --target to clang, as the iPhone uses arm64, not aarch64--and even if that were fixed, the dependency from bindgen needing access to llvm-config, which Apple doesn't ship, is also looking like it adds just enough operational complexity to what I'm doing here that I took a long and serious look last night at why I am using this library at all and finally decided I was stretching to need it in the first place.) So like, long story short: I still think this should really be fixed, as I've now seen a bunch of people strewn across many comments where people are running into this problem on both 32-bit and 64-bit MinGW (manifesting in different ways), and it seems like the -print-file-name fix will work; so, I'd thereby love to help sponsor getting it fixed to help all those people, and would definitely help test anything you come up with; but, since I finally decided I should just go with a different protocol that wouldn't require the usage of anything that indirectly depends on the Rust nettle-sys package, and don't really need to support 32-bit Windows, I'm personally no longer blocked on this issue.
This issue is related to , so the solution should ideally cover all of the targets for which we provide "self-contained experience for simple programs", i.e. mingw, musl and wasi. The common thing for these targets is that rustc need to support two modes - native toolchain mode, and self-contained mode. For these two modes to work libraries and objects distributed with rustc for the self-contained mode should reside in a separate directory, like , rather than just in , so rustc could easily include or exclude this directory from the library and object search paths. Native toolchain mode: rustc doesn't pass CRT objects to the linker, linker pulls them on their own ( is not passed to gcc) the directory is not included into the search paths users add search paths to whatever location they want with is also found in linker-provided or user-provided directories once is fixed. Self-contained mode: rustc passes CRT objects to the linker ( is passed to gcc) the directory is included into the search paths is also found in the directory once is fixed. So the main question is "how to enable/disable the self-contained mode", the two alternatives are: Some rules and heuristics based on already existing options and environment (probing specific paths, running processes (), checking whether the linker path has "musl" in it, checking whether the linker was passed explicitly, checking whether the linker is a path rather than just a name , comparing host with the target, etc). An new explicit option to set the mode - or something like that, probably still with defaults based on heuristics above. EDIT: prepared some groundwork, so I planned to improve the heuristics () next.
I knew somebody will ask for that once I start working on MinGW side of that issue Sounds great but I'd make it in separate PR so users could already play with (unstable) option to prefer (force?) own path for CRT. Musl declares itself to be both backward and forward compatible so it's users are fine when mixing different CRT versions. That would need discussion. Mingw-w64 tries to be backward compatible but things are not always easy. Preferring user installed CRT over the shipped one is the only way to make objects built different compilers (like Rust crate linking to C library) compatible. I think I've never used wasi so I have no clue about it. I think I saw all your linkage PR's and was hoping to see "even more magic".
Status update for anybody who follows this issue: With merged can be moved forward. As described in Rust will rely on the linker to provide correct paths. That will make option to override MinGW library path unnecessary.
I just tried using the homebrew-provided mingw64 and it fails linking with this error:
could you try with ? I wanted to make an "announcement" here asking people to try nightly with right after the nightly with has been published but forgot about it. Detection improvements will come in next PR but I wanted to gather some data first. Short summary: is meant for native Windows only with component installed. It allows to build crates without C dependencies even with MinGW C toolchain not installed. forces to use external MinGW C toolchain so you always want to use this option when external MinGW C toolchain is available. no option right now behaves exactly the same as it did before so it's a mix of and . In 2 weeks branching will happen and once it's done I want to land PR that will rework MinGW detection and stabilise option.
Let me undo my evil hack and I'll do, is it fine if I get you the tests results tomorrow?
Sure, there are 2 weeks left to the branching .
Works as intended for a target with crate type.
Thanks! could you test if Rust nighty with fixes the issue for you?
The code compiled successfully so I'd assume it's ok.
worked so well--for both 64-bit and 32-bit--that I was even able to use clang as a wrapper for the linker instead of having to directly specify mingw's ld! o/ I guess the question I have now is: if the user is specifying LINKER, shouldn't link-self-contained default to no? (I'm assuming the idea of having this self-contained environment in the first place is to avoid people having to bring their own install of MinGW, and so one is being shipped with rustc?) If you have an overridden LINKER, it seems like the probability that the libraries that come with rustc will be exactly compatible is "slim" (and so I'd expect "user brought their own linker, but wants to roll the die with the rustc embedded libraries" to be the corner case scenario that should require a flag override, not "user brought their own linker and thereby probably the linker works"; I didn't bring this up before because I had assumed there was some reason all these flags had to be passed manually, and thereby the paths needed to be known, but now seeing that "just call the linker" was an option from the beginning it seems like it should be the default in cases when the user provided the linker).
the plan is to always disable self contained mode when cross compiling and on Windows when the linker location is outside of Rust sysroot. To do it properly we need to stabilise first but that requires MCP. There is open MCP already for what did and if it's not approved all the changes made so far will be probably reverted:
Status update: MCP was seconded and since the beta was cut I've opened to completely ignore shipped CRT objects when cross compiling.
To verify, by "cross compiling" here we mean "when the user is using a toolchain that isn't the system default toolchain (and thereby has provided their own LINKER)", not "when the user happens to be compiling for a host/target architecture that is different from the build/host architecture" (to use x/y as gnu/cargo naming)? (Like, if I am on Win32 compiling for Win32, many people would not call that "cross compiling"--though I can see an argument that it is, and it is obvious to see that when one considers one things like "I am on Linux and am compiling a binary for Linux but I am on a system with glibc 2.23 and need the resulting binary to run on a system with glibc 2.17 and so I have a sysroot for an old version of CentOS that is my host/target system while a very recent build of Ubuntu is my build/host system": in some sense I am "cross compiling" from Ubuntu bionic to CentOS 7--but if I am specifying the linker and thereby have a sysroot I would need to not have these shipped objects injected no matter the architectures involved. I mostly ask this question as I ran into a really annoying bug in Cargo wherein it incorrectly makes assumptions about toolchains based on architecture.)
that's a good point. Until option is stabilised and heuristic for automatic external linker detection is , it's expected when user provides own linker self-contained mode makes no sense. Do you want to open PR yourself?
FWIW, "it's expected when user provides own linker self-contained mode makes no sense" is what I agree with / want, so if you are saying that will be the behavior I have no issue? My belief is just that "self contained mode" is the "narrow" (even if very common) case that only makes sense if the user is using the rust-provided linker (and that that has nothing to do with "cross compiling").
My proposal for now: takes precedence over anything else, it will become stable flag at some point host != target: self-contained mode is disabled user manually specified the linker: for now just disable self-contained mode, later this will change to "is external linker available in the PATH?" Would you like to implement and open PR for "user manually specified the linker: for now just disable self-contained mode" (since it's your idea) or want me to do it?
My proposal would be: if LINKER is set, then use that linker and assume it isn't self-contained (as the user should not even know where that linker is located to specify it manually... and if they do, honestly, I bet they are doing something epic and want all the magic behavior to go away); otherwise if target is a platform for which rust ships a self-contained toolchain (I know of Win32 and Linux+musl or whatever) then use self-contained toolchain; otherwise (if the user didn't specify LINKER and is expecting rust to just guess at a linker, but rust also doesn't ship its own preferable linker) if the user has a useful-looking linker on their path then use that linker without self-contained and hope (really hard) that it works well enough to make a useful binary (and if the user wants this linker over the default preferable self-contained one they should specify it manually with LINKER, which would throw them into the earlier case); otherwise, throw an error to the user telling them they need to provide a linker. I don't see why host != target is relevant at all... :(. But, I will note that as I have said in passing a couple times, I am making an assumption about what this self-contained mode is even for and who is using it: my assumption is that this is essentially a compete toolchain with sysroot/libraries that ships with rust so the compiler can do builds for a handful of platforms that are common targets for which the user is unlikely to have a toolchain installed on their current computer, such as for non-standard libc on Linux, Win32, or maybe emscripten or something. If so, I would expect this to be purely a "fallback" option that would always be available for these targets regardless of the host and the tooling for which might cause "unwelcome" command line arguments if the user manually specified LINKER to use a linker they brought, and which would cause mix-and-march issues--like we are seeing in these various ones I have run into--were you to attempt to use the rust libraries with a linker that came from someone else, no matter where that linker is located... like, my confusion on the use case here is so strong I honestly don't see why you would have this as a -C flag: either you are using the self-container linker or you aren't, and there doesn't seem like there should be any grey area where we have to ask the user. Is the issue that rust isn't shipping a linker, and is only shipping the libraries? If so, I feel like that just needs to be fixed, as otherwise that is going to just keep causing problems forever; like, there is simply no forward compatibility guarantee for libraries: even on macOS old linkers can't link against new libraries as the load commands at the head of the binary are extended with new features every year. A linker and a sysroot aren't exactly glued together, but there is at least a loose level of coupling between them and it isn't safe to just mix and match them: either don't ship libraries and expect the user to bring them or ship a full toolchain. My confusion with PATH might be that I don't know if you are saying this is for linkers found on the path by rust without LINKER or linkers found on the path that were manually specified with LINKER. In the former case I see the relevance, but then "later" is strange as both rules are relevant, as custom linkers are often--but not always--not on your path and adding them to the path to be found might not work a seat the name might be strange. In the latter case, I am just really confused as most of my time on this issue I was actually using the system copy of MinGW that I installed from homebrew/Ubuntu: I only switched to an off-PATH linker at the very end when I "could" (as I happen to prefer using an off-path copy of clang from the Android SDK as a wrapper for the on-PATH copy of mingw-ld... but I could just as easily be using the distribution's default install of clang and maybe even lld instead of mingw and now everything is both on path and strange); but even to the extent to which my toolchain is off-PATH today doesn't mean I might not be setting my PATH differently tomorrow (and sometimes I do this) so that weird folder is on my path. Taking a further step back, once I saw how the command line being passed to my linker was complete "vanilla" and it worked, I don't even understand what this option does: why not pass the vanilla options to your own self-contained linker? If the paths are internally wrong on that linker and it can't find it's sysroot, why not fix that in the self-contained linker? I would expect the self-contained linker to work just like my linker does, and my linker "just works". Why does the rust self contained linker fail to "just work" in a way that requires the crt objects to be manually passed in? (As for a PR, I am not in a position to test this without some maybe-hopefully-minimal instruction. I would be willing to accept said instruction, and maybe that will mean you get more patches out of me in the future ;P, but I just don't know what all I need to recompile to make this kind of change or then how to use that alternative copy: I have been "using" the rust toolchain, but I have so far not developed on it myself. Note that I continue to be willing to provide some compensation for you doing changes--assuming you agree with them, of course--in addition to paying for your time on this already that I might have caused, as me doing my job to pay you to do these tasks probably is arguably efficient for the world than me doing this directly; but again: if there is some minimal-investment-to-you way to tell me what I need to rebuild to make a change and test it, given that I seem to be resourceful enough to understand how to use the tooling itself and have been a maintainer of compilers in the past, I am definitely willing to do that and maybe seeing what I am suggesting manifested concretely will make more sense, or the process of me editing the code will help me understand the use case and thereby come up with a more reasonable suggestion for what to change.)
I'll get to that wall of text later . For now I'll address only For MinGW the linker is shipped only when it's the host compiler and is preferred over external linkers in the PATH. So we assume that if user overridden the linker they don't want self contained mode. However when cross compiling users don't need to specify the linker because it will be taken from the PATH. Hence self contained mode is disabled entirely.
Apologies, I was quite busy recently. The change itself is trivial and comes to adding condition that check if linker option is none, similarly to: There is a (big) catch however, testing this change is complicated. You have to modify to always return , then copy and paste few lines in CI config to create dist archive for windows-gnu. Finally you need to run it on Windows machine with MinGW compiler to the PATH and test that: if was not specified rustc picks CRT objects from the sysroot if was specified rustc picks CRT objects from the MinGW in the system
has been stabilised in nightly and MinGW detection was reworked in the next nightly. If somebody still encounters the issue with tomorrow's nightly, please open new report.

Discussion:
} } <del> // Because windows-gnu target is meant to be self-contained for pure Rust code it bundles // own mingw-w64 libraries. These libraries are usually not compatible with mingw-w64 // installed in the system. This breaks many cases where Rust is mixed with other languages // (e.g. *-sys crates). // We prefer system mingw-w64 libraries if they are available to avoid this issue. fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> { fn find_exe_in_path<P>(exe_name: P) -> Option<PathBuf> where P: AsRef<Path>, { for dir in env::split_paths(&env::var_os("PATH")?) { let full_path = dir.join(&exe_name); if full_path.is_file() { return Some(fix_windows_verbatim_for_gcc(&full_path)); } } None } fn probe(sess: &Session) -> Option<PathBuf> { if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) { let linker_path = if cfg!(windows) && linker.extension().is_none() { linker.with_extension("exe") } else { linker }; if let Some(linker_path) = find_exe_in_path(linker_path) { let mingw_arch = match &sess.target.target.arch { x if x == "x86" => "i686", x => x, }; let mingw_bits = &sess.target.target.target_pointer_width; let mingw_dir = format!("{}-w64-mingw32", mingw_arch); // Here we have path/bin/gcc but we need path/ let mut path = linker_path; path.pop(); path.pop(); // Loosely based on Clang MinGW driver let probe_paths = vec![ path.join(&mingw_dir).join("lib"),                // Typical path path.join(&mingw_dir).join("sys-root/mingw/lib"), // Rare path path.join(format!( "lib/mingw/tools/install/mingw{}/{}/lib", &mingw_bits, &mingw_dir )), // Chocolatey is creative ]; for probe_path in probe_paths { if probe_path.join("crt2.o").exists() { return Some(probe_path); }; } }; }; None } let mut system_library_path = sess.system_library_path.borrow_mut(); match &*system_library_path { Some(Some(compiler_libs_path)) => Some(compiler_libs_path.clone()), Some(None) => None, None => { let path = probe(sess); *system_library_path = Some(path.clone()); path } } } </del> fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf { <del> // prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details if sess.opts.debugging_opts.link_self_contained.is_none() && sess.target.target.llvm_target.contains("windows-gnu") { if let Some(compiler_libs_path) = get_crt_libs_path(sess) { let file_path = compiler_libs_path.join(name); if file_path.exists() { return file_path; } } } </del> let fs = sess.target_filesearch(PathKind::Native); let file_path = fs.get_lib_path().join(name); if file_path.exists() {

} } <ins> // Returns true if linker is located within sysroot fn detect_self_contained_mingw(sess: &Session) -> bool { let (linker, _) = linker_and_flavor(&sess); // Assume `-C linker=rust-lld` as self-contained mode if linker == Path::new("rust-lld") { return true; } let linker_with_extension = if cfg!(windows) && linker.extension().is_none() { linker.with_extension("exe") } else { linker }; for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); // If linker comes from sysroot assume self-contained mode if full_path.is_file() && !full_path.starts_with(&sess.sysroot) { return false; } } true } </ins> /// Whether we link to our own CRT objects instead of relying on gcc to pull them. /// We only provide such support for a very limited number of targets. fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool { <del> if let Some(self_contained) = sess.opts.debugging_opts.link_self_contained { </del> <ins> if let Some(self_contained) = sess.opts.cg.link_self_contained { </ins> return self_contained; }

// based on host and linker path, for example. // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237). Some(CrtObjectsFallback::Musl) => sess.crt_static(Some(crate_type)), <del> // FIXME: Find some heuristic for "native mingw toolchain is available", // likely based on `get_crt_libs_path` (https://github.com/rust-lang/rust/pull/67429). </del> Some(CrtObjectsFallback::Mingw) => { <del> sess.host == sess.target.target && sess.target.target.target_vendor != "uwp" </del> <ins> sess.host == sess.target.target && sess.target.target.target_vendor != "uwp" && detect_self_contained_mingw(&sess) </ins> } // FIXME: Figure out cases in which WASM needs to link with a native toolchain. Some(CrtObjectsFallback::Wasm) => true,

/// Add sysroot and other globally set directories to the directory search list. fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) { <del> // Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details. if sess.opts.debugging_opts.link_self_contained.is_none() && cfg!(windows) && sess.target.target.llvm_target.contains("windows-gnu") { if let Some(compiler_libs_path) = get_crt_libs_path(sess) { cmd.include_path(&compiler_libs_path); } } </del> // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();

// `link_arg` is omitted because it just forwards to `link_args`. untracked!(link_args, vec![String::from("abc"), String::from("def")]); untracked!(link_dead_code, Some(true)); <ins> untracked!(link_self_contained, Some(true)); </ins> untracked!(linker, Some(PathBuf::from("linker"))); untracked!(linker_flavor, Some(LinkerFlavor::Gcc)); untracked!(no_stack_check, true);

"extra arguments to append to the linker invocation (space separated)"), link_dead_code: Option<bool> = (None, parse_opt_bool, [UNTRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), <ins> link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED], "control whether to link Rust provided C objects/libraries or rely on C toolchain installed in the system"), </ins> linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],

"keep hygiene data after analysis (default: no)"), link_native_libraries: bool = (true, parse_bool, [UNTRACKED], "link native libraries in the linker invocation (default: yes)"), <del> link_self_contained: Option<bool> = (None, parse_opt_bool, [TRACKED], "control whether to link Rust provided C objects/libraries or rely on C toolchain installed in the system"), </del> link_only: bool = (false, parse_bool, [TRACKED], "link the `.rlink` file generated by `-Z no-link` (default: no)"), llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],

## control-flow-guard <del> This flag controls whether LLVM enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) platform security feature. This flag is currently ignored for non-Windows targets. </del> <ins> This flag controls whether LLVM enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) platform security feature. This flag is currently ignored for non-Windows targets. </ins> It takes one of the following values: * `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard. <del> * `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this </del> <ins> * `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this </ins> should only be used for testing purposes as it does not provide security enforcement). * `n`, `no`, `off`: do not enable Control Flow Guard (the default).

An example of when this flag might be useful is when trying to construct code coverage metrics. <ins> ## link-self-contained On targets that support it this flag controls whether the linker will use libraries and objects shipped with Rust instead or those in the system. It takes one of the following values: * no value: rustc will use heuristic to disable self-contained mode if system has necessary tools. * `y`, `yes`, `on`: use only libraries/objects shipped with Rust. * `n`, `no`, or `off`: rely on the user or the linker to provide non-Rust libraries/objects. This allows overriding cases when detection fails or user wants to use shipped libraries. </ins> ## linker This flag controls which linker `rustc` invokes to link your code. It takes a