-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Meson appends incorrect linker flags to compiler invocation #6662
Comments
The reason this is happening is that meson doesn't take clang's |
The more I think about this, this may actually work with meson master already. The only thing I don't know about is whether the --allow-shlib-undefined will work correctly. |
I seem to be running into this with lld, which also doesn't support --allow-shlib-undefined :/. |
My hack for right now is to not pass -fuse-ld= through meson as it happens to work well enough to complete the build (there's no guarantee that meson's incorrect autodetection would work: it just so happens to for the configurations I'm building) and I don't actually really want meson linking anything anyway... but is there really no way that you can just run the linker command I provided and see what linker you got? I really don't want meson attempting to parse my commands or separate binaries from arguments in its attempt to autodetect things: the detection should be designed to work correctly even if the linker is something like "/usr/bin/env distcc crazy -Wl,-oh-no" where "crazy" is a shell script on a remote machine that happens to run clang with -fuse-ld=lld. Can I at least have a way to override the detection (fwiw, maybe this already exists and I don't know?)... like, this isn't even the first time I've run into a serious issue with this (I have to have the entire 0.52 release series of meson blacklisted for effectively not supporting cross compile linking at all due to #6057). :( |
Except now I need to use lld for my next target, so now I'm just stuck. I can't allow the default linker. If I try to override the default linker I get weird arguments being passed to it that aren't OK (like -no_weak_imports apparently... I'm using lld to cross compile from macOS to MIPS... I can't pass -no_weak_imports, which is an Apple ld64 flag of all things). |
I'm now running into this same problem "in reverse", in that I've been required to use a build of clang that has been forcibly configured to default to lld on all platforms... even though lld doesn't work on macOS (and I'm compiling for macOS on macOS). I thereby need to pass -fuse-ld=/usr/bin/ld in order to force it to compile correctly with ld64. Of course, meson is now insisting on passing lld-specific command line arguments (such as --start-group), due to the totally-incorrect way it attempts to detect the linker :(. Is this likely to ever get fixed? |
I just ran across #6650, wherein it is mentioned you can pass an array as the compiler... this is awesome, and should be documented as the primary way to configure the compiler. This does seem to fix the detection of the linker for flags that can be passed as part of the compiler, so I bet this will actually work correctly for people who merely need to get a default linker selected from --target (such as @jefftime)!! However, this isn't so easy for me, as while passing -fuse-ld= as part of the compiler does cause meson to correctly detect the linker, if you pass -fuse-ld= to a command that doesn't link it causes an unused-command-line-argument warning, which meson is explicitly turning on with -Werror= :/. HOWEVER, it turns out clang now supports "configuration files" which can take arguments--notably -fuse-ld=--that won't be considered an unused argument! I've thereby managed to make this work, though in a way that is frankly kind of obtuse, by dumping an additional file on disk that includes -fuse-ld=/usr/bin/ld and then passing that with --config to the compiler as part of the c/cpp/objc variables. :D |
@Cartman0 I am merely cross-compiling another project--glib--and thereby have no knowledge of or control over meson.build: I can only edit the --cross-file that is being passed to meson, and I'm doing exactly what I described to work around this seemingly-fundamental-at-this-point flaw in meson: I separate out certain flags--such as -fuse-ld=--into a different list which I pass using --config as part of the compiler instead of the linker. FWIW, my strong recommendation is that meson be avoided, as cross-compilation is simply too important for issues like this to just be sitting around un-addressed for years, and I find it extremely frustrating that I'm forced to use it for glib :/... if you are in a position to be editing meson.build, maybe you are in a position to use autoconf, which gets a bad reputation for being "old" (as if that's a bad thing) and yet has worked correctly for decades and continues to work correctly today. |
@saurik sorry, i missread i also have similar trouble when crosscompile with emscripten. |
@Cartman0 FWIW, in case it is helpful, these files are where I implement these behaviors for my build system. |
Oh dear, that was quite the workaround. :-/ Here I was convinced there must be some incantation to convince meson to do the right thing, but when even the mighty saurik must resort to such workarounds, it's a bad sign to me. Like saurik, I didn't even want meson to link in the first place, just compile a bunch of files. (We use a weird intermediate "linking" step to a regular .o file, so we don't actually have neither .so nor .a ) |
I'm not sure I understand this ticket overall, but can't you just use |
Not sure. I just tested, and it doesn't seem to do any difference in my setup. (I may have done something wrong.) |
Sure, the same thing is available in the machine file as |
Ah, thanks! Two questions if you have the time:
|
Due to legacy reasons, Meson calls C++ "cpp" (as in the C preprocessor) instead of "cxx". This manifests in:
|
I think the best you can do is static_library() which just |
Thank you so much! static_library() it is, then! If I get everything to work, I will report back here for posterity. |
It worked just fine. I set a variable x to what static_library() returned. To extract the obj files, I used:
customlink_command is script file which does the custom linking I needed
|
I agree with @saurik . It's unfortunate that more and more projects are switching to meson, which is not capable of handling cross-compilation in many cases and makes maintainers life very very difficult. At the very least, the ability to override the detected linker type should exist. I'm using clang with -fuse=lld but using ld64.lld because I'm cross-compiling for mac, meson insists on passing "-soname" and some other invalid flags because the linker is being detected as llvm and not as apple. |
I have mentioned this already, but you can absolutely override the detected linker. You always could, and you always will. |
On another note:
Can y'all try out #10654 and tell me if that makes things easier for you? With that PR, Meson will recognize I worked on this after a report from a Gentoo user that using -fuse-ld led to crashes, e.g. apparently on systems where the default linker is bfd, but bfd doesn't work with lto because of a missing plugin, you get errors and "use -v to see invocation", and then that triggers Apple ld64 of all things on a Linux system because that bizarre error message is "the" way to detect their liner due to $REASONS. |
I want to override the detected type. My linker is lld, but because I'm targeting As a result, flags like |
Okay. This is interesting and useful information. What's the output of lld when it does this? Is there some way to detect this when running |
The output of the If the linker is detected as LLVM, passing
In the help screen you'll see somewhere in the string after
And you could switch from LLVMDynamicLinker (which is what ld.ldd is) to AppleDynamicLinker or the ones for wasm or windows. In any case, being able to override the detected type in the machine with something along the lines of |
Having the ability to have a custom linker (CustomDynamicLinker?) specified in a machine file, where you can set all properties of the DynamicLinkerClass, like allow_undefined_args, ltd_args, pie_args, asneeded_args, etc would be useful. |
Oh hmm, that should work:
I'll try to take a look at this sometime next week.
The idea has been previously pondered to allow defining custom compilers/linkers via ini files such that they don't have to be coded into mesonbuild/compilers/*.py; what exactly that would entail hasn't been proposed with enough specificity to implement as of yet. It's certainly an intriguing thought. |
A custom linker option would be very nice. Otherwise meson must know how all linkers work and how they take their arguments. Maybe the workaround with custom_target I showed above could be inspiration for such a feature. Further on in our codebase (I am converting a legacy build system) I happened upon a place where we compile with LLVM but link with some crusty old linker which takes special linking commands on stdin. I created a wrapper for that linker and called it with custom_target I don't know what to suggest exactly because I don't know yet well enough how to use meson, let alone how to change its internals. But I'm wary of programs which try to detect everything without the option for a manually specified fallback mechanism. Some things can't be detected because the world is messy. |
Thanks!
While that's been decided, an option to override the detected type (or to skip detection) might be useful. There linkers meson implement work fine, but if detection is not correct there is no easy way to fix that. Being apple to just use that ld is
I agree. Even a "do nothing" or "system" linker type could help. If that's set then do nothing: there's no need to add flags based on options and what's set in LD, LDFLAGS, etc should be used instead. From what I have experienced, and I have seen others mention here, a source of issues with meson comes from integrating meson-buillt libraries into a foreign build system that, usually, uses autotools or autotools environment variables, and expects the tools to just blindly used the specified commands for compiling or linking. Meson aims to simplify all that, and its heart is in the right place, but unless there is some fallback when detection fails or a tool is used in a way that the meson devs haven't added support for, the user is completely blocked. When that happens, extremely hacky measures (like writing a shell script called |
Any update/workaround for this? I hit this while crosscompiling some c++
But it detects
And finally passes
To clang while linking which causes the issues that other people have already complained about |
I am not sure if I am right... but meson/mesonbuild/linkers/detect.py Line 179 in 4a96ad0
currently it seems the code logic is based on error catch, and if error message meet some specific value then go to macOS logic. I want to know if we have any comments if we change the logic basing on platform information get from code blocks below?
|
That would be unreliable when operating on a cross compiler. A cross compiler could be targeting macOS without platform.platform() being macOS, and I believe there are a few alternative compiler toolchains that act like and identify as macOS ld64 and have this precise quirk. |
I guess in theory we could use the machine info value for the machine we’re targeting. It feels like there’s a lot of macOS bugs that aren’t getting fixed because no one has a Mac anymore (mine is a really old Intel Mac not getting updates anymore). |
System Information
$ meson --version
: 0.53.1$ ninja --version
: 1.8.2$ uname -srmo
: Linux 4.15.0-88-generic x86_64 GNU/LinuxIssue
When cross compiling, meson appends incorrect linker flags to the linking stage of the build
Reproduction
main.c:
meson.build:
wasm.meson:
With the above files, running
$ meson --cross-file wasm.meson bin && ninja -C bin
returns withMeson says it's configured to use
clang-9 lld
for the host linker, but on my system,clang-9
actually useswasm-ld
under the hood. As you can see inwasm.meson
, settingld = 'wasm-ld'
doesn't seem to help the issue.Meson proceeds to add the
-Wl,--allow-shlib-undefined
flag to the linker flags, butwasm-ld
doesn't recognize this option. The proper flag should be-Wl,--allow-undefined
or-Wl,--allow-undefined-file=<some_file>
.I would like to prohibit meson from adding flags on its own, but I couldn't seem to find a way to do this. I could disable the
-Wl,--as-needed
flag from being added, but I didn't have any luck on removing-Wl,--allow-shlib-undefined
The text was updated successfully, but these errors were encountered: