/ cmake / module / TestAppendRequiredLibraries.cmake
TestAppendRequiredLibraries.cmake
 1  # Copyright (c) 2023-present The Bitcoin Core developers
 2  # Distributed under the MIT software license, see the accompanying
 3  # file COPYING or https://opensource.org/license/mit/.
 4  
 5  include_guard(GLOBAL)
 6  
 7  # Illumos/SmartOS requires linking with -lsocket if
 8  # using getifaddrs & freeifaddrs.
 9  # See:
10  # - https://github.com/bitcoin/bitcoin/pull/21486
11  # - https://smartos.org/man/3socket/getifaddrs
12  function(test_append_socket_library target)
13    if (NOT TARGET ${target})
14      message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
15    endif()
16  
17    set(check_socket_source "
18      #include <sys/types.h>
19      #include <ifaddrs.h>
20  
21      int main() {
22        struct ifaddrs* ifaddr;
23        getifaddrs(&ifaddr);
24        freeifaddrs(ifaddr);
25      }
26    ")
27  
28    include(CheckCXXSourceCompiles)
29    check_cxx_source_compiles("${check_socket_source}" IFADDR_LINKS_WITHOUT_LIBSOCKET)
30    if(NOT IFADDR_LINKS_WITHOUT_LIBSOCKET)
31      include(CheckSourceCompilesWithFlags)
32      check_cxx_source_compiles_with_flags("${check_socket_source}" IFADDR_NEEDS_LINK_TO_LIBSOCKET
33        LINK_LIBRARIES socket
34      )
35      if(IFADDR_NEEDS_LINK_TO_LIBSOCKET)
36        target_link_libraries(${target} INTERFACE socket)
37      else()
38        message(FATAL_ERROR "Cannot figure out how to use getifaddrs/freeifaddrs.")
39      endif()
40    endif()
41    set(HAVE_IFADDRS TRUE PARENT_SCOPE)
42  endfunction()
43  
44  # Clang, when building for 32-bit,
45  # and linking against libstdc++, requires linking with
46  # -latomic if using the C++ atomic library.
47  # Can be tested with: clang++ -std=c++20 test.cpp -m32
48  #
49  # Sourced from http://bugs.debian.org/797228
50  function(test_append_atomic_library target)
51    if (NOT TARGET ${target})
52      message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
53    endif()
54  
55    set(check_atomic_source "
56      #include <atomic>
57      #include <cstdint>
58      #include <chrono>
59  
60      using namespace std::chrono_literals;
61  
62      int main() {
63        std::atomic<bool> lock{true};
64        lock.exchange(false);
65  
66        std::atomic<std::chrono::seconds> t{0s};
67        t.store(2s);
68        auto t1 = t.load();
69        t.compare_exchange_strong(t1, 3s);
70  
71        std::atomic<double> d{};
72        d.store(3.14);
73        auto d1 = d.load();
74  
75        std::atomic<int64_t> a{};
76        int64_t v = 5;
77        int64_t r = a.fetch_add(v);
78        return static_cast<int>(r);
79      }
80    ")
81  
82    include(CheckCXXSourceCompiles)
83    check_cxx_source_compiles("${check_atomic_source}" STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
84    if(NOT STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
85      include(CheckSourceCompilesWithFlags)
86      check_cxx_source_compiles_with_flags("${check_atomic_source}" STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC
87        LINK_LIBRARIES atomic
88      )
89      if(STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC)
90        target_link_libraries(${target} INTERFACE atomic)
91      else()
92        message(FATAL_ERROR "Cannot figure out how to use std::atomic.")
93      endif()
94    endif()
95  endfunction()