aboutsummaryrefslogtreecommitdiff
path: root/cmake/module/TestAppendRequiredLibraries.cmake
blob: 5352102c7a4854fd3c2e21a2363e7a40c3e28ee7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.

include_guard(GLOBAL)

# Illumos/SmartOS requires linking with -lsocket if
# using getifaddrs & freeifaddrs.
# See:
# - https://github.com/bitcoin/bitcoin/pull/21486
# - https://smartos.org/man/3socket/getifaddrs
function(test_append_socket_library target)
  if (NOT TARGET ${target})
    message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
  endif()

  set(check_socket_source "
    #include <sys/types.h>
    #include <ifaddrs.h>

    int main() {
      struct ifaddrs* ifaddr;
      getifaddrs(&ifaddr);
      freeifaddrs(ifaddr);
    }
  ")

  include(CheckSourceCompilesAndLinks)
  check_cxx_source_links("${check_socket_source}" IFADDR_LINKS_WITHOUT_LIBSOCKET)
  if(NOT IFADDR_LINKS_WITHOUT_LIBSOCKET)
    check_cxx_source_links_with_libs(socket "${check_socket_source}" IFADDR_NEEDS_LINK_TO_LIBSOCKET)
    if(IFADDR_NEEDS_LINK_TO_LIBSOCKET)
      target_link_libraries(${target} INTERFACE socket)
    else()
      message(FATAL_ERROR "Cannot figure out how to use getifaddrs/freeifaddrs.")
    endif()
  endif()
  set(HAVE_DECL_GETIFADDRS TRUE PARENT_SCOPE)
  set(HAVE_DECL_FREEIFADDRS TRUE PARENT_SCOPE)
endfunction()

# Clang, when building for 32-bit,
# and linking against libstdc++, requires linking with
# -latomic if using the C++ atomic library.
# Can be tested with: clang++ -std=c++20 test.cpp -m32
#
# Sourced from http://bugs.debian.org/797228
function(test_append_atomic_library target)
  if (NOT TARGET ${target})
    message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
  endif()

  set(check_atomic_source "
    #include <atomic>
    #include <cstdint>
    #include <chrono>

    using namespace std::chrono_literals;

    int main() {
      std::atomic<bool> lock{true};
      lock.exchange(false);

      std::atomic<std::chrono::seconds> t{0s};
      t.store(2s);
      auto t1 = t.load();
      t.compare_exchange_strong(t1, 3s);

      std::atomic<double> d{};
      d.store(3.14);
      auto d1 = d.load();

      std::atomic<int64_t> a{};
      int64_t v = 5;
      int64_t r = a.fetch_add(v);
      return static_cast<int>(r);
    }
  ")

  include(CheckSourceCompilesAndLinks)
  check_cxx_source_links("${check_atomic_source}" STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
  if(STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
    return()
  endif()

  check_cxx_source_links_with_libs(atomic "${check_atomic_source}" STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC)
  if(STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC)
    target_link_libraries(${target} INTERFACE atomic)
  else()
    message(FATAL_ERROR "Cannot figure out how to use std::atomic.")
  endif()
endfunction()