This is an archive of the discontinued LLVM Phabricator instance.

Driver: Remove custom MinGW linker detection
ClosedPublic

Authored by martell on Sep 11 2017, 7:16 PM.

Details

Summary

In rL289668 the ability to specify the default linker at compile time
was added but because the MinGW driver used custom detection we could
not take advantage of this new CMAKE flag CLANG_DEFAULT_LINKER.

Diff Detail

Repository
rL LLVM

Event Timeline

martell created this revision.Sep 11 2017, 7:16 PM
martell added a subscriber: cfe-commits.
martell edited the summary of this revision. (Show Details)Sep 11 2017, 7:19 PM

I'm not sure I like this direction. In my setups, a build-time default isn't right since I'm using the same clang builds for both native-on-linux building (with the default ld as linker) and cross-building targeting windows (using ldd), and keeping the code that reads -fuse-ld= is essential.

I haven't followed the changes closely on how this works with the build-time CLANG_DEFAULT_LINKER, but can't we just make the current code check this define if -fuse-ld isn't set?

lib/Driver/ToolChains/MinGW.cpp
107

This diff isn't based on the current master version, where this defaults to ld

236

So if you do a clang build that defaults to lld, this should suddenly be included?

mstorsjo edited edge metadata.Sep 12 2017, 4:00 AM

Actually, after testing this a bit more and looking at it, I withdraw my earlier complaints - this does indeed seem to work fine with my test setup. The generic TC.GetLinkerPath() picks up -fuse-ld=lld correctly and converts it into ld.lld which should be equivalent to lld -flavor gnu, at least in my linux cross compilation setup. And the extra AddLibGCC() call doesn't seem harmful for the lld setup.

martell added a comment.EditedSep 12 2017, 4:05 AM

I'm not sure I like this direction. In my setups, a build-time default isn't right since I'm using the same clang builds for both native-on-linux building (with the default ld as linker) and cross-building targeting windows (using ldd), and keeping the code that reads -fuse-ld= is essential.

The GetLinkerPath function in lib/Driver/ToolChain.cpp that I replaced this with already checks -fuse-ld and does everything we need correctly.

I haven't followed the changes closely on how this works with the build-time CLANG_DEFAULT_LINKER, but can't we just make the current code check this define if -fuse-ld isn't set?

If you specifically want a toolchain that uses lld by default for MINGW but ld for the platform and or host you should override the getDefaultLinker function in the Mingw driver with an out of tree patch.
This is now what I do in my own builds since applying this patch. Hopefully when the MinGW driver becomes more stable such a patch can land in tree :)

If you are happy with all being lld or all ld you should set CLANG_DEFAULT_LINKER.
Note that GetLinkerPath also gives us the extra option to pass -fuse-ld=platform to use the platform default instead of the compile time default.

lib/Driver/ToolChains/MinGW.cpp
107

Yeah the line was supposed to read
StringRef LinkerName = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "ld");
It was applied on top a commit for clang that changed ld -> lld here.
The reason I want to merge this is so that I can stop doing that :)
For the review because I am removing the line it does not matter much, I will update the diff to remove the extra l in the next revision.

236

The previous check was if not lld so it would include it if it was ld or anything else.
The MINGW lld driver does not complain about this, the behaviour should be the same for both.

I'm not sure I like this direction. In my setups, a build-time default isn't right since I'm using the same clang builds for both native-on-linux building (with the default ld as linker) and cross-building targeting windows (using ldd), and keeping the code that reads -fuse-ld= is essential.

The GetLinkerPath function in lib/Driver/ToolChain.cpp that I replaced this with already checks -fuse-ld and does everything we need correctly.

Yup, figured it out later after reading it more thorhoughly later.

I haven't followed the changes closely on how this works with the build-time CLANG_DEFAULT_LINKER, but can't we just make the current code check this define if -fuse-ld isn't set?

If you specifically want a toolchain that uses lld by default for MINGW but ld for the platform and or host you should override the getDefaultLinker function in the Mingw driver with an out of tree patch.
This is now what I do in my own builds since applying this patch.

I do the same by adding -rtlib=compiler-rt -stdlib=libc++ -fuse-ld=lld -Qunused-arguments in the frontend script wrapper (a wrapper named <arch>-w64-mingw32-clang that just calls clang -target <arch>-w64-mingw32 -rtlib=compiler-rt -stdlib=libc++ -fuse-ld=lld -Qunused-arguments.

martell updated this revision to Diff 114801.Sep 12 2017, 5:15 AM

update tests

Looks good to me (but maybe someone else should approve it as well)

martell added a comment.EditedSep 12 2017, 5:26 AM

I do the same by adding -rtlib=compiler-rt -stdlib=libc++ -fuse-ld=lld -Qunused-arguments in the frontend script wrapper (a wrapper named <arch>-w64-mingw32-clang that just calls clang -target <arch>-w64-mingw32 -rtlib=compiler-rt -stdlib=libc++ -fuse-ld=lld -Qunused-arguments.

I used to do this also but I didn't want to just disable warnings for unused arguments which left me with problems.

The following should work for that if you are happy with it being the default for your linux target also

-DCLANG_DEFAULT_RTLIB=compiler-rt
-DCLANG_DEFAULT_CXX_STDLIB=libc++
-CLANG_DEFAULT_LINKER=lld

Though adding something like this to Driver/MinGW.h

RuntimeLibType GetDefaultRuntimeLibType() const override {
  return RuntimeLibType::RLT_CompilerRT;
}

CXXStdlibType
GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
  return ToolChain::CST_Libcxx;
}

const char *getDefaultLinker() const override {
  return "lld";
}

should work for what you want more. (assuming you want your other targets to stay the same)

Yup, figured it out later after reading it more thorhoughly later.

We posted at roughly the same time so I missed it :)

Actually, after testing this a bit more and looking at it, I withdraw my earlier complaints - this does indeed seem to work fine with my test setup. The generic TC.GetLinkerPath() picks up -fuse-ld=lld correctly and converts it into ld.lld which should be equivalent to lld -flavor gnu, at least in my linux cross compilation setup. And the extra AddLibGCC() call doesn't seem harmful for the lld setup.

Great, I'll just wait for reid or peter to approve and merge then.

rnk accepted this revision.Sep 12 2017, 10:58 AM

Nice! IIUC, now that the gnu ld driver works on Windows we can remove this logic. Thanks!

This revision is now accepted and ready to land.Sep 12 2017, 10:58 AM
In D37727#868284, @rnk wrote:

Nice! IIUC, now that the gnu ld driver works on Windows we can remove this logic. Thanks!

We could have removed it before the addition of the gnu ld driver, I think the author just missed this target and possibly others when the original patch was created.

Regardless, this now enables us to make standalone mingw-w64 clang toolchains with only llvm+clang+lld+compiler-rt without having any out of tree patches :)