Is the `rpath` option unrecognized?
My makefile passes the rpath option to the linker, even if the target does not use any shared objects. This works fine on Linux, where my project uses either static or dynamic linking, and it has worked fine on Cygwin, where my project uses only static linking.
I have recently tried llvm-mingw. It seems that the rpath option in the linker ld.lld.exe is not recognized, regardless of the whether any shared objects are used or not.
$ ld --version
GNU ld (GNU Binutils) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
ld.lld.exe --version
LLD 14.0.0 (compatible with GNU linkers)
Of course, these are different linkers, but according to https://lld.llvm.org/
LLD is a drop-in replacement for the GNU linkers that accepts the same command line arguments and linker scripts as GNU.
While it is still possible that lld and ld subtly differ in their behavior, I am wondering whether not accepting the rpath option is a deliberate modification for the LLVM port to Windows. If so, I suggest that accepting but ignoring the rpath option is a better policy.
Of course, these are different linkers, but according to https://lld.llvm.org/
LLD is a drop-in replacement for the GNU linkers that accepts the same command line arguments and linker scripts as GNU.
While it’s meant to be a drop-in replacement, it’s not 100% identical in all cases.
While it is still possible that
lldandldsubtly differ in their behavior, I am wondering whether not accepting therpathoption is a deliberate modification for the LLVM port to Windows. If so, I suggest that accepting but ignoring therpathoption is a better policy.
These cases come up for discussion semi regularly; lld does ignore a bunch of options that are used commonly, but also intentionally doesn’t ignore some options (that aren’t used frequently). E.g. GNU ld does accept the option --allow-shlib-undefined, and meson did accidentally try to call the linker with that option, but upstream lld didn’t want to silently accept that option. If a user explicitly requests that, lld prefers to error out, because PE files simply can’t have undefined references.
As for rpath, I don’t think that one has come up for discussion so far, because it’s not commonly passed to the linker in windows contexts. That’s also a concept that simply doesn’t exist on windows, but maybe a less fatal contradiction than --allow-shlib-undefined.
It’d be best of course to not pass the options that don’t make sense for the platform you’re building for, but maybe I should check upstream what others think about ignoring rpath.
The behavior of lld and therefore llvm-mingw is different from gcc-mingw.
Here is the output of gcc-mingw (toolchain generated from crosstool-ng) compiling the simple program [1] with -rpath option:
# /xgcc-x86_64-w64-mingw32/bin/x86_64-w64-mingw32-g++ test.cc -Wl,-rpath,anything
<no error>
And here is the llvm-mingw toolchain failing on the same inputs:
# /xllvm-x86_64-w64-mingw32/bin/x86_64-w64-mingw32-g++ test.cc -Wl,-rpath,anything
lld: error: unknown argument: -rpath
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This is unfortunate because a huge number of existing packages assume mingw supports -rpath. It would be ideal if llvm-mingw was a drop-in replacement for gcc-mingw.
What about stripping rpath in clang-target-wrapper.sh?
[1]
#include <iostream>
int main(int argc, const char** argv) {
std::cout<<"hello world!"<<std::endl;
*(volatile int*)0 = 0;
return 0;
}
This is unfortunate because a huge number of existing packages assume mingw supports -rpath.
Which are these huge numbers of packages that does this?
It would be ideal if llvm-mingw was a drop-in replacement for gcc-mingw.
Yes, that would be the ideal. There's a long tail of uncommon options that aren't supported though, so it will never be a 100% drop-in replacement for all uncommon cases though.
In general, lld does ignore a number of options that otherwise aren't implemented, for compatibility purposes, especially if they are common. For -rpath, I haven't really ran into any packages doing this, so it hasn't been a priority so far.
Ignoring unimplemented but generally harmless options within LLD generally is fine, but for the purpose of -rpath, it's slightly a different thing because it's really not something that is possible to do on Windows - even if we ask for -rpath, you'll never get this.
Now we could implement ignoring it in LLD - it's all a tradeoff of how common this use is (thus, references to these uses does help).
But we shouldn't implement ignoring in the wrapper. We should work towards reducing the amount of magic in the wrapper, not increase it.
Huge is a stretch, probably. But in particular, I've come across it when porting mingw packages under conan. The pkg-config generator there generates .pc files containing rpath (specifically when build environment is configured to gcc-mingw), e.g.,
prefix=/local2/b/.conan/data/openh264/2.1.1/_/_/package/b5e157b9e013331c0a6bdf018a60633d6751961f
libdir=${prefix}/lib
includedir=${prefix}/include
Name: openh264
Description: Open Source H.264 Codec
Version: 2.1.1
Libs: -L"${libdir}" -lopenh264 -Wl,-rpath,"${libdir}"
Cflags: -I"${includedir}"
I'm sure there are other cases as well. Of course, conan and other places this occurs can be patched, but I think it would be nicer for users if llvm-mingw "just worked" as a drop-in replacement for gcc-mingw.
I agree lld is a better place to implement dummy -rpath. Though I would suggest the wrapper magic here could act as interim fix.
Huge is a stretch, probably. But in particular, I've come across it when porting mingw packages under conan. The pkg-config generator there generates .pc files containing rpath (specifically when build environment is configured to gcc-mingw), e.g.,
prefix=/local2/b/.conan/data/openh264/2.1.1/_/_/package/b5e157b9e013331c0a6bdf018a60633d6751961f libdir=${prefix}/lib includedir=${prefix}/include Name: openh264 Description: Open Source H.264 Codec Version: 2.1.1 Libs: -L"${libdir}" -lopenh264 -Wl,-rpath,"${libdir}" Cflags: -I"${includedir}"I'm sure there are other cases as well.
Can you dig up a reference to where this is generated? I don't see anything relating to rpaths in the upstream OpenH264 pkg-config files, so I presume this is done by the conan pkg-config file generator, right?
The more references we have to this option being (mis)used this way, the better argument we have for getting the fix upstream.
Of course, conan and other places this occurs can be patched,
Overall, that would generally be appreciated too - although doing that doesn't necessarily exclude fixing it upstream in LLD either.
but I think it would be nicer for users if llvm-mingw "just worked" as a drop-in replacement for gcc-mingw.
It generally does, in a whole lot of places, TBH.
This particular option isn't the make/break deal for whether it's a full drop-in replacement or not - but it's of course yet another small step towards further improving compatibility.
I agree lld is a better place to implement dummy -rpath. Though I would suggest the wrapper magic here could act as interim fix.
Sorry, I'm not very keen on taking the filtering in the wrapper, even as an interim fix. (As you're noticing in your PR, it's also apparently less trivial to do than initially thought.) But patching the wrapper in that way is of course an easy way to patch around the issue in your own local installation, until fixed upstream.
Yes, it works quite well as is-- this is an amazing project that I think will get wide use.
I will chase down where the rpath is being injected in conan. I'm porting about 3 dozen packages from gcc-mingw, mostly for the pdb and debug improvements that llvm offers. So far mostly minor issues, almost all of them variations on hardcoding of mingw implies gcc and vise versa.
My rpath is apparently coming from https://github.com/conan-io/conan/blob/17c58f0c61931f9de218ac571cd97a8e0befa68e/conans/client/generators/pkg_config.py#L104 but we are stuck on quite an old version.
I can't find a similar obvious injection in latest conan, so possibly it's not an issue any longer. Nevertheless it would still be nice if the behavior matched gcc-mingw.
I posted a patch for review, for this issue now, at https://github.com/llvm/llvm-project/pull/102886.
This issue should have been fixed by the upstream fix in https://github.com/llvm/llvm-project/commit/69f76c782b554a004078af6909c19a11e3846415, which was backported to the 19.x release branch, and should be included in the latest prerelease at https://github.com/mstorsjo/llvm-mingw/releases/tag/20240820.