CMake:在配置时按CMAKE_REQUIRED_LIBRARY中的库顺序测试最小程序

2022-04-18 00:00:00 raspbian atomic cmake c++ c++11

我编写了这段小代码,以确保我的软件在必要时可以链接到libatics。通常,只有在覆盆子PI上才需要链接到脂组学。目前,我使用的是Raspberry PI 4,64位Raspbian Bullseye。

以下是cmake代码:

set(ATOMIC32_TEST_CODE "
    #include <atomic>
    #include <stdint.h>
    int main() {
        std::atomic<int32_t> x;
        x.store(1);
        x--;
        return x.load();
    }")

set(ATOMIC64_TEST_CODE "
    #include <atomic>
    #include <stdint.h>
    int main() {
        std::atomic<int64_t> x;
        x.store(1);
        x--;
        return x.load();
    }")

macro(ATOMIC_CHECK)

    # test whether atomic works
    check_cxx_source_compiles("${ATOMIC32_TEST_CODE}" atomic32_test)
    check_cxx_source_compiles("${ATOMIC64_TEST_CODE}" atomic64_test)

    # if doesn't work, attempt to find the atomic library, link with it and try again
    if(NOT atomic32_test OR NOT atomic64_test)
        find_library(ATOMIC NAMES libatomic.so.1
        HINTS
          $ENV{HOME}/local/lib64
          $ENV{HOME}/local/lib
          /usr/local/lib64
          /usr/local/lib
          /opt/local/lib64
          /opt/local/lib
          /usr/lib64
          /usr/lib
          /lib64
          /lib
          /usr/lib/arm-linux-gnueabihf
        )

        if(ATOMIC)
            set(LIBATOMIC ${ATOMIC})
            message(STATUS "Found libatomic: ${LIBATOMIC}")
            message(STATUS "Attempting to test atomic with atomic library linked")

            get_filename_component(atomic_lib_dir ${LIBATOMIC} DIRECTORY)

            # Before setting CMAKE_REQUIRED_FLAGS, we preserve the current state
            cmake_push_check_state()

            set(CMAKE_REQUIRED_LIBRARIES "-L${atomic_lib_dir} -latomic")
            check_cxx_source_compiles("${ATOMIC32_TEST_CODE}" atomic32_test_with_atomic_linking)
            check_cxx_source_compiles("${ATOMIC64_TEST_CODE}" atomic64_test_with_atomic_linking)

            cmake_pop_check_state()

            if(NOT atomic32_test_with_atomic_linking)
                message(FATAL_ERROR "Even after linking with the atomic library, atomic 32-bit compilation failed.")
            endif()

            if(NOT atomic64_test_with_atomic_linking)
                message(FATAL_ERROR "Even after linking with the atomic library, atomic 64-bit compilation failed.")
            endif()

            set(ATOMIC_LINKER_LIBS "-L${atomic_lib_dir} -latomic")
        else()
            message(FATAL_ERROR "Failed to find libatomic even though it seems to be required")
        endif()
    endif()

endmacro()

ATOMIC_CHECK()

此代码的作用如下:

  1. 尝试编译32位和64位版本的代码,并确保它们在退出时返回0。
  2. 如果它们中的任何一个没有编译,则查找libatics,如果找不到,则查找错误。
  3. 如果找到,请尝试链接到它并重新编译相同的小源代码
  4. 如果它们成功了,很好,我们将使用新找到的库作为编译其他一切的基础。如果不是,cmake配置将停止。

最近,我的PI上突然出现了链接错误。所以我调查了一下,结果我找到了this problem。 在CMakeError.log中,我看到以下链接错误:

/usr/bin/c++ -Wall -Wextra -Wno-unused-variable -Wno-unused-function -Wno-unused-private-field -Wno-class-memacces>
/usr/bin/ld: CMakeFiles/cmTC_7285b.dir/src.cxx.o: in function `main':
src.cxx:(.text+0x40): undefined reference to `__atomic_store_8'
/usr/bin/ld: src.cxx:(.text+0x80): undefined reference to `__atomic_load_8'
/usr/bin/ld: CMakeFiles/cmTC_7285b.dir/src.cxx.o: in function `std::__atomic_base<long long>::operator--(int)':
src.cxx:(.text._ZNSt13__atomic_baseIxEmmEi[_ZNSt13__atomic_baseIxEmmEi]+0x40): undefined reference to `__atomic_fetch_s>
collect2: error: ld returned 1 exit status

最终,我发现唯一的问题是链接顺序。Cmake所要做的就是将-latomic放在它试图编译的源文件之后。

如何告诉cmake将链接命令放在源文件之后,而不是放在它之前?


解决方案

正如其他地方有人指出的,改变

set(CMAKE_REQUIRED_LIBRARIES "-L${atomic_lib_dir} -latomic")

收件人:

set(CMAKE_REQUIRED_LIBRARIES "-L${atomic_lib_dir}" "-latomic")

已修复该问题。CMake显然可以识别前缀。

相关文章