|
1 | 1 | #===============================================================================
|
2 |
| -# Add an ABI library if appropriate |
| 2 | +# Define targets for linking against the selected ABI library |
| 3 | +# |
| 4 | +# After including this file, the following targets are defined: |
| 5 | +# - libcxx-abi-headers: An interface target that allows getting access to the |
| 6 | +# headers of the selected ABI library. |
| 7 | +# - libcxx-abi-shared: A target representing the selected shared ABI library. |
| 8 | +# - libcxx-abi-static: A target representing the selected static ABI library. |
3 | 9 | #===============================================================================
|
4 | 10 |
|
5 | 11 | include(GNUInstallDirs)
|
6 | 12 |
|
| 13 | +# This function copies the provided headers to a private directory and adds that |
| 14 | +# path to the given INTERFACE target. That target can then be linked against to |
| 15 | +# get access to those headers (and only those). |
7 | 16 | #
|
8 |
| -# _setup_abi: Set up the build to use an ABI library |
9 |
| -# |
10 |
| -# Parameters: |
11 |
| -# abidefines: A list of defines needed to compile libc++ with the ABI library |
12 |
| -# abishared : The shared ABI library to link against. |
13 |
| -# abistatic : The static ABI library to link against. |
14 |
| -# abifiles : A list of files (which may be relative paths) to copy into the |
15 |
| -# libc++ build tree for the build. These files will be copied |
16 |
| -# twice: once into include/, so the libc++ build itself can find |
17 |
| -# them, and once into include/c++/v1, so that a clang built into |
18 |
| -# the same build area will find them. |
19 |
| -# abidirs : A list of relative paths to create under an include directory |
20 |
| -# in the libc++ build directory. |
21 |
| -# |
22 |
| - |
23 |
| -macro(setup_abi_lib abidefines abishared abistatic abifiles abidirs) |
24 |
| - list(APPEND LIBCXX_COMPILE_FLAGS ${abidefines}) |
25 |
| - set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" |
26 |
| - CACHE PATH |
27 |
| - "Paths to C++ ABI header directories separated by ';'." FORCE |
28 |
| - ) |
29 |
| - set(LIBCXX_CXX_ABI_LIBRARY_PATH "${LIBCXX_CXX_ABI_LIBRARY_PATH}" |
30 |
| - CACHE PATH |
31 |
| - "Paths to C++ ABI library directory" |
32 |
| - ) |
33 |
| - set(LIBCXX_CXX_SHARED_ABI_LIBRARY ${abishared}) |
34 |
| - set(LIBCXX_CXX_STATIC_ABI_LIBRARY ${abistatic}) |
35 |
| - set(LIBCXX_ABILIB_FILES ${abifiles}) |
36 |
| - |
37 |
| - foreach(fpath ${LIBCXX_ABILIB_FILES}) |
| 17 | +# The problem this solves is that when building against a system-provided ABI library, |
| 18 | +# the ABI headers might live side-by-side with an actual C++ Standard Library |
| 19 | +# installation. For that reason, we can't just add `-I <path-to-ABI-headers>`, |
| 20 | +# since we would end up also adding the system-provided C++ Standard Library to |
| 21 | +# the search path. Instead, what we do is copy just the ABI library headers to |
| 22 | +# a private directory and add just that path when we build libc++. |
| 23 | +function(import_private_headers target include_dirs headers) |
| 24 | + foreach(header ${headers}) |
38 | 25 | set(found FALSE)
|
39 |
| - foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS}) |
40 |
| - message(STATUS "Looking for ${fpath} in ${incpath}") |
41 |
| - if (EXISTS "${incpath}/${fpath}") |
| 26 | + foreach(incpath ${include_dirs}) |
| 27 | + if (EXISTS "${incpath}/${header}") |
42 | 28 | set(found TRUE)
|
43 |
| - message(STATUS "Looking for ${fpath} in ${incpath} - found") |
44 |
| - get_filename_component(dstdir ${fpath} PATH) |
45 |
| - get_filename_component(ifile ${fpath} NAME) |
46 |
| - set(src ${incpath}/${fpath}) |
47 |
| - |
48 |
| - set(dst ${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}/${ifile}) |
49 |
| - add_custom_command(OUTPUT ${dst} |
50 |
| - DEPENDS ${src} |
51 |
| - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} |
52 |
| - COMMENT "Copying C++ ABI header ${fpath}...") |
53 |
| - list(APPEND abilib_headers "${dst}") |
| 29 | + message(STATUS "Looking for ${header} in ${incpath} - found") |
| 30 | + get_filename_component(dstdir ${header} PATH) |
| 31 | + get_filename_component(header_file ${header} NAME) |
| 32 | + set(src ${incpath}/${header}) |
| 33 | + set(dst "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}/${header_file}") |
54 | 34 |
|
55 |
| - # TODO: libc++ shouldn't be responsible for copying the libc++abi |
56 |
| - # headers into the right location. |
57 |
| - set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${dstdir}/${fpath}") |
58 | 35 | add_custom_command(OUTPUT ${dst}
|
59 | 36 | DEPENDS ${src}
|
| 37 | + COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}" |
60 | 38 | COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
61 |
| - COMMENT "Copying C++ ABI header ${fpath}...") |
| 39 | + COMMENT "Copying C++ ABI header ${header}") |
62 | 40 | list(APPEND abilib_headers "${dst}")
|
63 | 41 | else()
|
64 |
| - message(STATUS "Looking for ${fpath} in ${incpath} - not found") |
| 42 | + message(STATUS "Looking for ${header} in ${incpath} - not found") |
65 | 43 | endif()
|
66 | 44 | endforeach()
|
67 | 45 | if (NOT found)
|
68 |
| - message(WARNING "Failed to find ${fpath} in ${LIBCXX_CXX_ABI_INCLUDE_PATHS}") |
| 46 | + message(WARNING "Failed to find ${header} in ${include_dirs}") |
69 | 47 | endif()
|
70 | 48 | endforeach()
|
71 | 49 |
|
72 |
| - include_directories("${LIBCXX_BINARY_INCLUDE_DIR}") |
73 |
| - add_custom_target(cxx_abi_headers ALL DEPENDS ${abilib_headers}) |
74 |
| - set(LIBCXX_CXX_ABI_HEADER_TARGET "cxx_abi_headers") |
75 |
| -endmacro() |
76 |
| - |
77 |
| - |
78 |
| -# Configure based on the selected ABI library. |
79 |
| -if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR |
80 |
| - "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++") |
81 |
| - set(_LIBSUPCXX_INCLUDE_FILES |
82 |
| - cxxabi.h bits/c++config.h bits/os_defines.h bits/cpu_defines.h |
83 |
| - bits/cxxabi_tweaks.h bits/cxxabi_forced.h |
84 |
| - ) |
85 |
| - if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++") |
86 |
| - set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") |
87 |
| - set(_LIBSUPCXX_LIBNAME stdc++) |
88 |
| - else() |
89 |
| - set(_LIBSUPCXX_DEFINES "") |
90 |
| - set(_LIBSUPCXX_LIBNAME supc++) |
| 50 | + # Work around https://gitlab.kitware.com/cmake/cmake/-/issues/18399 |
| 51 | + add_library(${target}-generate-private-headers OBJECT ${abilib_headers}) |
| 52 | + set_target_properties(${target}-generate-private-headers PROPERTIES LINKER_LANGUAGE CXX) |
| 53 | + |
| 54 | + target_link_libraries(${target} INTERFACE ${target}-generate-private-headers) |
| 55 | + target_include_directories(${target} INTERFACE "${LIBCXX_BINARY_DIR}/private-abi-headers") |
| 56 | +endfunction() |
| 57 | + |
| 58 | +# This function creates an imported library named <target> of the given <kind> (SHARED|STATIC). |
| 59 | +# It imports a library named <name> searched at the given <path>. |
| 60 | +function(imported_library target kind path name) |
| 61 | + add_library(${target} ${kind} IMPORTED GLOBAL) |
| 62 | + set(libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}${CMAKE_${kind}_LIBRARY_SUFFIX}") |
| 63 | + # Make sure we find .tbd files on macOS |
| 64 | + if (kind STREQUAL "SHARED") |
| 65 | + list(APPEND libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}.tbd") |
91 | 66 | endif()
|
92 |
| - setup_abi_lib( |
93 |
| - "-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}" |
94 |
| - "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits" |
95 |
| - ) |
96 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") |
97 |
| - if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS) |
98 |
| - set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_SOURCE_DIR}/../libcxxabi/include") |
| 67 | + find_library(file |
| 68 | + NAMES ${libnames} |
| 69 | + PATHS "${path}" |
| 70 | + NO_CACHE) |
| 71 | + set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${file}") |
| 72 | +endfunction() |
| 73 | + |
| 74 | +# Link against a system-provided libstdc++ |
| 75 | +if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++") |
| 76 | + add_library(libcxx-abi-headers INTERFACE) |
| 77 | + import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" |
| 78 | + "cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h") |
| 79 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBSTDCXX" "-D__GLIBCXX__") |
| 80 | + |
| 81 | + imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++) |
| 82 | + target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) |
| 83 | + |
| 84 | + imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++) |
| 85 | + target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) |
| 86 | + |
| 87 | +# Link against a system-provided libsupc++ |
| 88 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libsupc++") |
| 89 | + add_library(libcxx-abi-headers INTERFACE) |
| 90 | + import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" |
| 91 | + "cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h") |
| 92 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-D__GLIBCXX__") |
| 93 | + |
| 94 | + imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++) |
| 95 | + target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) |
| 96 | + |
| 97 | + imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++) |
| 98 | + target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) |
| 99 | + |
| 100 | +# Link against the in-tree libc++abi |
| 101 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxabi") |
| 102 | + add_library(libcxx-abi-headers INTERFACE) |
| 103 | + target_link_libraries(libcxx-abi-headers INTERFACE cxxabi-headers) |
| 104 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI") |
| 105 | + |
| 106 | + if (TARGET cxxabi_shared) |
| 107 | + add_library(libcxx-abi-shared ALIAS cxxabi_shared) |
99 | 108 | endif()
|
100 | 109 |
|
101 |
| - if(LIBCXX_STANDALONE_BUILD AND NOT (LIBCXX_CXX_ABI_INTREE OR HAVE_LIBCXXABI)) |
102 |
| - set(shared c++abi) |
103 |
| - set(static c++abi) |
104 |
| - else() |
105 |
| - set(shared cxxabi_shared) |
106 |
| - set(static cxxabi_static) |
| 110 | + if (TARGET cxxabi_static) |
| 111 | + add_library(libcxx-abi-static ALIAS cxxabi_static) |
107 | 112 | endif()
|
108 | 113 |
|
109 |
| - setup_abi_lib( |
110 |
| - "-DLIBCXX_BUILDING_LIBCXXABI" |
111 |
| - "${shared}" "${static}" "cxxabi.h;__cxxabi_config.h" "") |
112 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "system-libcxxabi") |
113 |
| - setup_abi_lib( |
114 |
| - "-DLIBCXX_BUILDING_LIBCXXABI" |
115 |
| - "c++abi" "c++abi" "cxxabi.h;__cxxabi_config.h" "") |
116 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") |
| 114 | +# Link against a system-provided libc++abi |
| 115 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi") |
| 116 | + add_library(libcxx-abi-headers INTERFACE) |
| 117 | + import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" "cxxabi.h;__cxxabi_config.h") |
| 118 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI") |
| 119 | + |
| 120 | + imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi) |
| 121 | + target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) |
| 122 | + |
| 123 | + imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi) |
| 124 | + target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) |
| 125 | + |
| 126 | +# Link against a system-provided libcxxrt |
| 127 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxrt") |
| 128 | + # libcxxrt does not provide aligned new and delete operators |
| 129 | + # TODO: We're keeping this for backwards compatibility, but this doesn't belong here. |
| 130 | + set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) |
| 131 | + |
117 | 132 | if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
|
| 133 | + message(STATUS "LIBCXX_CXX_ABI_INCLUDE_PATHS not set, using /usr/include/c++/v1") |
118 | 134 | set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1")
|
119 | 135 | endif()
|
120 |
| - # libcxxrt does not provide aligned new and delete operators |
121 |
| - set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) |
122 |
| - setup_abi_lib( |
123 |
| - "-DLIBCXXRT" |
124 |
| - "cxxrt" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" |
125 |
| - ) |
126 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "vcruntime") |
127 |
| - # Nothing to do |
128 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none") |
129 |
| - list(APPEND LIBCXX_COMPILE_FLAGS "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY") |
130 |
| -elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "default") |
131 |
| - # Nothing to do |
132 |
| -else() |
133 |
| - message(FATAL_ERROR |
134 |
| - "Unsupported c++ abi: '${LIBCXX_CXX_ABI_LIBNAME}'. \ |
135 |
| - Currently libstdc++, libsupc++, libcxxabi, libcxxrt, default and none are |
136 |
| - supported for c++ abi." |
137 |
| - ) |
138 |
| -endif () |
| 136 | + add_library(libcxx-abi-headers INTERFACE) |
| 137 | + import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" |
| 138 | + "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h") |
| 139 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXXRT") |
| 140 | + |
| 141 | + imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt) |
| 142 | + target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) |
| 143 | + |
| 144 | + imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt) |
| 145 | + target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) |
| 146 | + |
| 147 | +# Link against a system-provided vcruntime |
| 148 | +# FIXME: Figure out how to configure the ABI library on Windows. |
| 149 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "vcruntime") |
| 150 | + add_library(libcxx-abi-headers INTERFACE) |
| 151 | + add_library(libcxx-abi-shared INTERFACE) |
| 152 | + add_library(libcxx-abi-static INTERFACE) |
| 153 | + |
| 154 | +# Don't link against any ABI library |
| 155 | +elseif ("${LIBCXX_CXX_ABI}" STREQUAL "none") |
| 156 | + add_library(libcxx-abi-headers INTERFACE) |
| 157 | + target_compile_definitions(libcxx-abi-headers INTERFACE "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY") |
| 158 | + |
| 159 | + add_library(libcxx-abi-shared INTERFACE) |
| 160 | + target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) |
| 161 | + |
| 162 | + add_library(libcxx-abi-static INTERFACE) |
| 163 | + target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) |
| 164 | +endif() |
0 commit comments