Repository navigation
Description
Describe the bug
When compiling with LTO on gcc, it is necessary to use gcc-ar instead of ar, as the latter doesn't have the linker plugin enabled. Meson thus looks for it preferentially if using gcc:
meson/mesonbuild/compilers/detect.py
Lines 165 to 167 in 9b83789
| elif compiler.id == 'gcc': | |
| # Use gcc-ar if available; needed for LTO | |
| trials = [defaults['gcc_static_linker']] + default_linkers |
However, when looking for the static linker, Meson looks in $AR first.
With the conda-forge compilers, they set AR=/path/to/env/bin/x86_64-conda-linux-gnu-ar and GCC_AR=/path/to/env/bin/x86_64-conda-linux-gnu-gcc-ar. This means that Meson will find the static linker without the LTO linker plugin. Because the linker just emits the missing plugin as a warning, this will either cause executables to fail building with missing symbols, or worse, shared libraries to build fine, but then not load with mysterious errors.
I know that I can myself set AR=$GCC_AR, but when building a Python package with LTO enabled by default (as we do in Matplotlib since before using Meson), the problem is quite buried and annoying to explain to new developers, and it'd be nice if Meson just worked correctly out-of-the-box.
So I wonder if Meson should (if using gcc) check GCC_AR first? I don't know how standard this environment variable is, but that's what they seem to be using.
To Reproduce
In this case, I use one of the test cases with static libraries, and enable LTO:
$ micromamba create -n meson-gcc-ar -c conda-forge meson compilers
$ micromamba activate meson-gcc-ar
$ meson setup -Db_lto=true test\ cases/common/5\ linkstatic/ work\ area
$ ninja -C work\ area/
ninja: Entering directory `work area/'
[6/7] Linking static target libmylib.a
/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-ar: libmylib.a.p/libfile.c.o: plugin needed to handle lto object
[7/7] Linking target prog
FAILED: prog
/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-cc -o prog prog.p/main.c.o -L/home/elliott/micromamba/envs/meson-gcc-ar/lib -flto -Wl,--as-needed -Wl,--no-undefined -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,--allow-shlib-undefined -Wl,-rpath,/home/elliott/micromamba/envs/meson-gcc-ar/lib -Wl,-rpath-link,/home/elliott/micromamba/envs/meson-gcc-ar/lib -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/elliott/micromamba/envs/meson-gcc-ar/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/elliott/micromamba/envs/meson-gcc-ar/include libmylib.a
/home/elliott/micromamba/envs/meson-gcc-ar/bin/../lib/gcc/x86_64-conda-linux-gnu/12.3.0/../../../../x86_64-conda-linux-gnu/bin/ld: /tmp/cciBMYVO.ltrans0.ltrans.o: in function `main':
/home/elliott/code/meson/work area/<artificial>:4: undefined reference to `func'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Expected behavior
When LTO is enabled using the conda-forge compilers, the build succeeds.
system parameters
- Is this a cross build or just a plain native build (for the same computer)? Native
- what operating system (e.g. MacOS Catalina, Windows 10, CentOS 8.0, Ubuntu 18.04, etc.): Fedora 40
- what Python version are you using: 3.12.3
- what
meson --version: 1.4.0 - what
ninja --versionif it's a Ninja build: 1.12.1
Activity
QuLogic commentedon Jun 15, 2024
Also perhaps of note is that the conda-forge package sets
CMAKE_ARGSas:I don't know how CMake works, but I guess it picks these
CMAKE_<lang>_COMPILER_ARvariables over theCMAKE_ARvariable, giving it thegcc-arvariant.eli-schwartz commentedon Jun 16, 2024
Setting an environment variable usually means you definitely absolutely want to use it. Of course if you also define something else in a native file then that takes precedence.
I'm hesitant to start looking at an environment variable such as $GCC_AR which I've never heard of before and seems like it may be specific to conda-forge. It's not clear to me what is supposed to read this anyway.
Do you happen to know why the two are defined differently?
QuLogic commentedon Jun 17, 2024
I don't know why it's set that way, only that it is and it makes it so that things don't work out-of-the-box.
@jakirkham do you know why there's this separate
$GCC_AR, or who to ask about it?jakirkham commentedon Jun 24, 2024
Feel free to raise another question issue on this feedstock
thesamesam commentedon May 15, 2025
I was looking into this for the benefit of autoconf and automake then came across this bug in Meson, and found we seem to do the right thing if everything is unset indeed.
I find it hard for us to justify ignoring
ARif set in the environment, if it's being set to something which doesn't do the right thing. What're you proposing we do here?EDIT: But maybe we can view it a bit differently in the context of cross and machine files, where people may set
artrying to do the right thing, like in https://embeddedartistry.com/blog/2020/04/13/prefer-gcc-ar-to-ar-in-your-buildsystems/.EDIT 2: I see you mentioned
GCC_ARnow, oops. But that won't help the cross case, and I don't think it's a standard variable.thesamesam commentedon Nov 10, 2025
Somewhat related to #8831 and definitely #1646.