Skip to content
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

Boost rewrite breaks build #7110

Closed
fiesh opened this issue May 9, 2020 · 17 comments
Closed

Boost rewrite breaks build #7110

fiesh opened this issue May 9, 2020 · 17 comments
Labels
Milestone

Comments

@fiesh
Copy link

fiesh commented May 9, 2020

Consider the following meson.build file

project('test_link', 'cpp', default_options : ['cpp_std=c++17'])

boost_dep = dependency('boost', modules : ['system'])

sources = files(
        'main.cpp'
)

a_out = executable('a.out', sources, dependencies : [boost_dep])

(the file main.cpp can just contain int main(){}.)

This no longer builds. The behavior was introduced with 08224da.

The problem is that instead of -lboost_system, the file /usr/lib/libboost_system.so.1.72.0 is passed as such to the linker:

[2/2] c++  -o a.out 'a.out@exe/main.cpp.o' -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group /usr/lib/libboost_system.so.1.72.0 -Wl,--end-group
FAILED: a.out 
c++  -o a.out 'a.out@exe/main.cpp.o' -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group /usr/lib/libboost_system.so.1.72.0 -Wl,--end-group
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld: error: /usr/lib/libboost_system.so.1.72.0: incompatible target
collect2: error: ld returned 1 exit status
@fiesh
Copy link
Author

fiesh commented May 9, 2020

I should add that this only happens on our Gentoo system, not the Ubuntu one. It happens with gcc-9, gcc-10, and clang-10. Please let me know what I should provide to make it more reproducible, ideally in a CI test.

One difference is that the Gentoo system features Boost 1.72, the Ubuntu one Boost 1.71.
The two meson-log.txt files do not show any significant differences except for library paths.

@mensinda mensinda added the boost label May 9, 2020
@mensinda
Copy link
Member

mensinda commented May 9, 2020

What is the output of ldd <your exe> when built with -lboost_system and can you reproduce the bug when compiling your exe manually (without all the -Wl, stuff)?

Also can you post the output of find / -name "*boost_system*" -type f?

This looks like a really weird bug since the /usr/lib/libboost_system.so.1.72.0 seems to be the correct library...

@fiesh
Copy link
Author

fiesh commented May 9, 2020

(To keep the linker from dropping the shared library altogether, I changed main.cpp to

#include <boost/filesystem.hpp>

int main()
{
        return boost::filesystem::path("/path/to/something").filename().size() != 0;
}

and added filesystem as a boost dependency to meson.build.)

fiesh@wsbox /tmp/working % ldd a.out
        linux-vdso.so.1 (0x00007fffbf9f7000)
        libboost_filesystem.so.1.72.0 => /usr/lib64/libboost_filesystem.so.1.72.0 (0x00007f5305d7e000)
        libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/libstdc++.so.6 (0x00007f5305b05000)
        libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/libgcc_s.so.1 (0x00007f5305aec000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f5305933000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f5305929000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5305909000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f53057d1000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5305df8000)

I suppose by "compiling by hand" you mean the following?

fiesh@wsbox /tmp/notworking % c++  -o a.out 'a.out@exe/main.cpp.o' /usr/lib/libboost_system.so.1.72.0 /usr/lib/libboost_filesystem.so.1.72.0
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld: error: /usr/lib/libboost_system.so.1.72.0: incompatible target
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld: error: /usr/lib/libboost_filesystem.so.1.72.0: incompatible target
../t/main.cpp:5: error: undefined reference to 'boost::filesystem::path::filename() const'
collect2: error: ld returned 1 exit status

Unlike with static libraries, I don't think it is possible to specify a shared library by its name, one has to use the -llibname mechanism.

Running find / -name "*boost_system*" -type f is a bit difficult since it's a rather big server. But I suppose this should suffice:

% find /usr -name "*boost_system*" -type f 2>/dev/null
/usr/lib/libboost_system.so.1.72.0
/usr/lib/debug/usr/lib64/libboost_system.so.1.72.0.debug
/usr/lib/debug/usr/lib/libboost_system.so.1.72.0.debug
/usr/lib/libboost_system.a
/usr/share/aclocal/ax_boost_system.m4
/usr/lib64/libboost_system.so.1.72.0
/usr/lib64/libboost_system.a

@mensinda
Copy link
Member

mensinda commented May 9, 2020

Ah, seems like meson uses lib instead of lib64. Thanks, I now know where the problem is.

@fiesh
Copy link
Author

fiesh commented May 9, 2020

Ah, seems like meson uses lib instead of lib64. Thanks, I now know where the problem is.

Oh wow awesome! I was just about to prepare a Dockerfile to reproduce it. But I guess I'll put that on halt for now.

@mensinda mensinda added this to the 0.54.2 milestone May 9, 2020
@eli-schwartz
Copy link
Member

The two meson-log.txt files do not show any significant differences except for library paths.

Library paths seem to be extremely important! Since meson uses full paths to shared libraries always, one must assume this works. However, you're getting an error message from ld.gold stating that it tried to link a file which doesn't share the same architecture/os ABI. Hence @mensinda's conclusion that it's incorrectly using /usr/lib on your system.

I can trivially reproduce the error message on archlinux by trying to relink a random program using meson's command line but switching one lib to use /usr/lib32 and adding -fuse-ld=gold.

$ cc -fuse-ld=gold  -o libalpm.so.12.0.1 'common@sta/src_common_ini.c.o' 'common@sta/src_common_util-common.c.o' 'alpm_objlib@sta/lib_libalpm_add.c.o' 'alpm_objlib@sta/lib_libalpm_alpm.c.o' 'alpm_objlib@sta/lib_libalpm_alpm_list.c.o' 'alpm_objlib@sta/lib_libalpm_backup.c.o' 'alpm_objlib@sta/lib_libalpm_base64.c.o' 'alpm_objlib@sta/lib_libalpm_be_local.c.o' 'alpm_objlib@sta/lib_libalpm_be_package.c.o' 'alpm_objlib@sta/lib_libalpm_be_sync.c.o' 'alpm_objlib@sta/lib_libalpm_conflict.c.o' 'alpm_objlib@sta/lib_libalpm_db.c.o' 'alpm_objlib@sta/lib_libalpm_deps.c.o' 'alpm_objlib@sta/lib_libalpm_diskspace.c.o' 'alpm_objlib@sta/lib_libalpm_dload.c.o' 'alpm_objlib@sta/lib_libalpm_error.c.o' 'alpm_objlib@sta/lib_libalpm_filelist.c.o' 'alpm_objlib@sta/lib_libalpm_graph.c.o' 'alpm_objlib@sta/lib_libalpm_group.c.o' 'alpm_objlib@sta/lib_libalpm_handle.c.o' 'alpm_objlib@sta/lib_libalpm_hook.c.o' 'alpm_objlib@sta/lib_libalpm_log.c.o' 'alpm_objlib@sta/lib_libalpm_package.c.o' 'alpm_objlib@sta/lib_libalpm_pkghash.c.o' 'alpm_objlib@sta/lib_libalpm_rawstr.c.o' 'alpm_objlib@sta/lib_libalpm_remove.c.o' 'alpm_objlib@sta/lib_libalpm_signing.c.o' 'alpm_objlib@sta/lib_libalpm_sync.c.o' 'alpm_objlib@sta/lib_libalpm_trans.c.o' 'alpm_objlib@sta/lib_libalpm_util.c.o' 'alpm_objlib@sta/lib_libalpm_version.c.o' -Wl,--as-needed -Wl,--no-undefined -shared -fPIC -Wl,--start-group -Wl,-soname,libalpm.so.12 /usr/lib/libcrypto.so /usr/lib/libarchive.so /usr/lib32/libcurl.so -lgpgme -lassuan -lgpg-error -Wl,--end-group
/usr/bin/ld.gold: error: /usr/lib32/libcurl.so: incompatible target

Using the boring old non-gold linker I get the error message:

/usr/bin/ld: /usr/lib32/libcurl.so: error adding symbols: file in wrong format

@floppym
Copy link
Contributor

floppym commented May 10, 2020

This happens when boost is installed for multiple ABIs (eg. 32-bit and 64-bit). The 32-bit boost libraries end up in either /usr/lib or /usr/lib32, and the 64-bit libraries are in /usr/lib64.

The new boost dependency code has a very naive algorithm for finding valid libdirs; it basically just uses anything that starts with "lib". There is probably some better code elsewhere in meson to enumerate valid libdirs for the host toolchain.

@mensinda
Copy link
Member

Should be fixed with #7117. @fiesh Could you please test if the PR works on your system?

@floppym I have searched the meson code for something existing that I could reuse, but haven't found anything.

@fiesh
Copy link
Author

fiesh commented May 11, 2020

Should be fixed with #7117. @fiesh Could you please test if the PR works on your system?

Tested and works! Nice, thank you very much for looking into this so quickly.

@floppym
Copy link
Contributor

floppym commented May 11, 2020

Using the CLikeCompiler.get_library_dirs() method would be better than iterating over any directory that starts with "lib" and making horrible assumptions based on machines.cpu_family.

If you want to find a library, you need to use the compiler toolchain to do it.

@floppym
Copy link
Contributor

floppym commented May 11, 2020

Some additional corner-cases:

x86_64 has a special ABI called "x32" that uses 32-bit pointers on an otherwise 64-bit system. This ABI uses "libx32" on Gentoo.

https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/arch/amd64/make.defaults#n20

RISC-V has separate libdirs depending whether or not hardware floating-point is used in the library ABI. These appear as subdirectories under lib64. I think this is true of both Gentoo and Debian.

https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/arch/riscv/rv64gc/make.defaults#n15

# Library directories
LIBDIR_lp64d="lib64/lp64d"
LIBDIR_lp64="lib64/lp64"

@floppym
Copy link
Contributor

floppym commented May 11, 2020

MIPS has 2 separate 32-bit ABIs, that get installed in lib and lib32.

https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/arch/mips/make.defaults#n14

@mensinda
Copy link
Member

Thanks for the pointers, but I am reluctant to add support for all these corner-cases since the directory layout might be different on other distributions. Also, meson currently does not distinguish between most of them anyway (I only found riscv32 and riscv64 in the Reference tables).

I would say that it would be fair to require BOOST_LIBRARYDIR if such a setup in a non-standard path is used. Otherwise, we would have to support all library layouts for all Distributions.

@Arfrever
Copy link

List of RISC-V ABIs is here.
Here and here it is seen that lib64/lp64 and lib64/lp64d are standard paths for glibc RISC-V systems, and anything else would be non-standard.
(Support for 32-bit RISC-V is not yet implemented in glibc.)

@Arfrever
Copy link

A quite reliable way to find library directories would be to ask compiler:

$ gcc -print-search-dirs | grep ^libraries:
libraries: =/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib64/:/lib/x86_64-pc-linux-gnu/10.1.0/:/lib/../lib64/:/usr/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../:/lib/:/usr/lib/
$ clang -print-search-dirs | grep ^libraries:
libraries: =/usr/lib64/llvm/10/bin/../../../../lib/clang/10.0.0:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../lib64:/usr/lib64/llvm/10/bin/../lib64:/lib/../lib64:/usr/lib/../lib64:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../x86_64-pc-linux-gnu/lib:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../..:/lib:/usr/lib

Then you would just search for requested library in these directories.

@mensinda
Copy link
Member

@Arfrever Thanks, that's what I am currently doing in #7117 now. There was some further discussion about this here: mensinda@41397e5#comments.

@Arfrever
Copy link

I forgot to mention that ${CFLAGS} need to be passed to compiler, because options like -m32 and -m64 (for x86_64) or -mabi=lp64 and -mabi=lp64d (for RISC-V) affect answer:

$ gcc -m32 -print-search-dirs | grep ^libraries:
libraries: =/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/32/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/10.1.0/32/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/../lib32/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../x86_64-pc-linux-gnu/10.1.0/32/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib32/:/lib/x86_64-pc-linux-gnu/10.1.0/32/:/lib/../lib32/:/usr/lib/x86_64-pc-linux-gnu/10.1.0/32/:/usr/lib/../lib32/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../:/lib/x86_64-pc-linux-gnu/10.1.0/:/lib/:/usr/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/
$ gcc -m64 -print-search-dirs | grep ^libraries:
libraries: =/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../x86_64-pc-linux-gnu/10.1.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib64/:/lib/x86_64-pc-linux-gnu/10.1.0/:/lib/../lib64/:/usr/lib/x86_64-pc-linux-gnu/10.1.0/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../:/lib/:/usr/lib/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants