After I upgraded to Rust 1.97 (which enabled linker warnings by default), one of my projects outputs the following linker warning on Windows when compiling with Cargo and stable-x86_64-pc-windows-msvc:
warning: linker stdout: Library "C:\git\gitlab-time-report\target\debug\deps\gitlab_time_report_cli.lib" and object "C:\git\gitlab-time-report\target\debug\deps\gitlab_time_report_cli.exp" are created.β
LINK : warning LNK4098: library "libcmt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library.
|
= note: `#[warn(linker_messages)]` on by default
Now the program works fine, but I'm still intrested in what causes this. Is there a way I can investigate this?
/verbose is very verbose; it gave me 217k lines of output! A cursory search for libcmt.lib, gitlab_time_report_cli.lib and gitlab_time_report_cli.exp didn't give me any more insight that I have currently...
The only new thing I learnt was that the warning happens on pass 1 and not on pass 2.
I can't even show it to you, as pasting it into Pastebin crashes the tab in my browser :_)
libcmt.lib is apparently the static version of the MSVC library, but I checked "rustc -C target-feature=+crt-static src/main.rs" without reproducing the issue (as you'd expect).
If I try to repro with rustc -l libcmt src/main.rs I instead get:
warning: linker stdout: LINK : warning LNK4098: defaultlib 'msvcrt' conflicts with ...
Which is the default -crt-static, e.g. dynamically linked library as expected. Flipping it around, and using rustc -C target-feature=+crt-static -l libcmtd src/main.rs or -l msvcrt I can reproduce the issue.
It's possible some naughty dep could have added a CRT lib with it's build.rs,e.g. cargo::rustc-link-lib but I suspect it's more likely there's a library being built (e.g. with the cc crate) with the wrong flags, which transitively pulls in the wrong CRT.
Use cargo tree -i cc for a quick check, I'm not sure if there's an easier way to find crates that link native code in?
also, pay attention to the static-vcruntime crate, which, as the name suggests, links the static library of vcruntime, which is different from the +crt-static rustc feature.
did you try /VERBOSE:LIB? it should only print out the libraries the linker is looking for, and usually the line immediately precedding the libcmt.lib is the one that depends on it, which should at least give you a hint where to look at next.
openssl-sys is a pretty good candidate given how funky it's build is - though it is odd it doesn't show up on windows given the cc dependency isn't a target-specific dependency, nor any of the parents AFAIK?
I suppose you could blindly try building with OPENSSL_STATIC=0 and =1 envs but if it's not in the tree it shouldn't make a difference....
well, that is not helpful at all... msvcrt.lib is the very library in conflicts with libcmt.lib.
it seems the print order is different from what I recalled, and these runtime libraries are not pulled in as a direct dependency.
a last resort:
I believe the microsoft linker detects this kind of conflicts using the linker directives embedded in the objects themselves, which are emitted by the compiler based on the frontend specific flags. e.g. /MD or /MT for msvc, -C target-feature=+crt-static for rustc. a quick google search says the embedded linker directives are stored in a section named .drectve and can be examined via the dumpbin utility.
so, try examine every .obj and .lib files (presumably excluding those generated by rustc)
dumpbin /DIRECTIVES legacy_stdio_definitions.lib
you can write a script to specifically look for libcmt, something like:
Judging from it's build.rs, I would suspect rusty_v8 is responsible here. It uses precompiled lib files downloaded from their releases which I'd guess contain references to the static CRT.
You can either try passing /NODEFAULTLIB:libcmt.lib to the linker or use +crt-static for your whole build. I think the latter would be the safer option if the library is built for the static CRT. Well unless or until rusty_v8 can fix this.