mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.38k stars 1.55k forks source link

Prefer $GCC_AR over $AR with gcc? #13324

Open QuLogic opened 2 weeks ago

QuLogic commented 2 weeks ago

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: https://github.com/mesonbuild/meson/blob/9b8378985dbdc0112d11893dd42b33b7bc8d1e62/mesonbuild/compilers/detect.py#L165-L167

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

QuLogic commented 2 weeks ago

Also perhaps of note is that the conda-forge package sets CMAKE_ARGS as:

-DCMAKE_AR=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-ar
-DCMAKE_CXX_COMPILER_AR=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-gcc-ar
-DCMAKE_C_COMPILER_AR=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-gcc-ar
-DCMAKE_RANLIB=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-ranlib
-DCMAKE_CXX_COMPILER_RANLIB=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-gcc-ranlib
-DCMAKE_C_COMPILER_RANLIB=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-gcc-ranlib
-DCMAKE_LINKER=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-ld
-DCMAKE_STRIP=/home/elliott/micromamba/envs/meson-gcc-ar/bin/x86_64-conda-linux-gnu-strip
-DCMAKE_BUILD_TYPE=Release

I don't know how CMake works, but I guess it picks these CMAKE_<lang>_COMPILER_AR variables over the CMAKE_AR variable, giving it the gcc-ar variant.

eli-schwartz commented 2 weeks ago

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 commented 2 weeks ago

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 commented 1 week ago

Feel free to raise another question issue on this feedstock