From cebff5786d6a245d5da5f1175e9c358a9973f43b Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Sat, 9 Jul 2022 07:32:03 -0400 Subject: [PATCH] cmake: link librados applications against ceph-common to address link failures like: [100%] Linking CXX executable ../../../bin/unittest_global_doublefree /opt/rh/gcc-toolset-12/root/usr/bin/ld: /opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/libstdc++_nonshared.a(sstream-inst80.o): undefined reference to symbol '_ZTVNSt7__cxx1119basic_ostringstreamIwSt11char_traitsIwESaIwEEE@@GLIBCXX_3.4.21' /opt/rh/gcc-toolset-12/root/usr/bin/ld: /usr/lib64/libstdc++.so.6: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status this happens when using gcc-toolset to build the tree. because neither librados.so nor libcephfs exposes libstdc++ symbols to executable linking against it. while CMake uses "c++" to link C++ executables. the "c++" executable comes from GTS links the C++ executables agaist /opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/libstdc++.so, which in turn is a ld script: ``` $ cat /opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/libstdc++.so /* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-x86-64) INPUT ( /usr/lib64/libstdc++.so.6 -lstdc++_nonshared ) ``` but the thing is, stdc++_nonshared references some symbols provided by libstdc++.so.6, and it is listed before it. that's why "ld" is not able to resolve the referenced symbols used by the executable, despite that they are provided by libstdc++ in this case. in this change, ceph-common is added to the linkage of executables linked against librados and/or libcephfs, even the executables in question does not reference ceph-common symbols. unlike librados, libcephfs and librgw, ceph-common is an internal library, which does not hide *any* symbols from its consumer, it is also able to provide symbols from C++ standard library linked by it. so, in our case, we can link the C++ executables against ceph-common for accessing the C++ standard library. the reason why we don't link aginst libstdc++ explictly is that, we should leave this to the C++ compiler instead of referencing a specific C++ standard library explictly by its name. what if user wants to link against libc++ instead of libstdc++? another fix could be to remove '-Wl,--as-needed' linker options from the command line linking the librados applications, so the linker does not ignore the symbols from libstdc++ when resolving the ones referenced by stdc++_nonshared, but that would be complicated. please note, linking against ceph-common does not change the linkage of * Ceph executables compiled using non-gcc-toolset toolchain, because we always pass '-Wl,--as-needed' to "c++" when linking executables, so "ld" should be able to drop ceph-common even we instruct it to link against ceph-common. so it would be a no-op in this case. * 3rd party librados executables compiled using non-gcc-toolset toolchain, but linked against librados compiled using gcc-toolset toolchain. because they still link against the /usr/lib64/libstdc++.so.6, when these executables are compiled and linked. and librados is always able to access libceph-common. so librados is safe. Signed-off-by: Kefu Chai --- src/test/CMakeLists.txt | 2 +- src/test/common/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 54c49970ebc..d61ee22dfd6 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -134,7 +134,7 @@ endif(WITH_RADOSGW) if(WITH_LIBCEPHFS) # From src/test/Makefile-client.am: I dont get this one... testing the osdc build but link in libcephfs? add_executable(test_build_libcephfs buildtest_skeleton.cc) - target_link_libraries(test_build_libcephfs cephfs pthread ${CRYPTO_LIBS} ${EXTRALIBS}) + target_link_libraries(test_build_libcephfs cephfs pthread ceph-common ${CRYPTO_LIBS} ${EXTRALIBS}) endif(WITH_LIBCEPHFS) add_executable(test_build_librados buildtest_skeleton.cc) diff --git a/src/test/common/CMakeLists.txt b/src/test/common/CMakeLists.txt index dba313ac396..28738c09085 100644 --- a/src/test/common/CMakeLists.txt +++ b/src/test/common/CMakeLists.txt @@ -300,7 +300,7 @@ if(WITH_CEPHFS) test_global_doublefree.cc ) add_ceph_unittest(unittest_global_doublefree) - target_link_libraries(unittest_global_doublefree cephfs librados) + target_link_libraries(unittest_global_doublefree cephfs librados ceph-common) endif(WITH_CEPHFS) if(NOT WIN32) -- 2.39.5