-
Notifications
You must be signed in to change notification settings - Fork 12.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc++] Overhaul how we select the ABI library
This patch overhauls how we pick up the ABI library. Instead of setting ad-hoc flags, it creates interface targets that can be linked against by the rest of the build, which is easier to follow and extend to support new ABI libraries. This is intended to be a NFC change, however there are some additional simplifications and improvements we can make in the future that would require a slight behavior change. Differential Revision: https://reviews.llvm.org/D120727
- Loading branch information
Showing
14 changed files
with
178 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,164 @@ | ||
#=============================================================================== | ||
# Add an ABI library if appropriate | ||
# Define targets for linking against the selected ABI library | ||
# | ||
# After including this file, the following targets are defined: | ||
# - libcxx-abi-headers: An interface target that allows getting access to the | ||
# headers of the selected ABI library. | ||
# - libcxx-abi-shared: A target representing the selected shared ABI library. | ||
# - libcxx-abi-static: A target representing the selected static ABI library. | ||
#=============================================================================== | ||
|
||
include(GNUInstallDirs) | ||
|
||
# This function copies the provided headers to a private directory and adds that | ||
# path to the given INTERFACE target. That target can then be linked against to | ||
# get access to those headers (and only those). | ||
# | ||
# _setup_abi: Set up the build to use an ABI library | ||
# | ||
# Parameters: | ||
# abidefines: A list of defines needed to compile libc++ with the ABI library | ||
# abishared : The shared ABI library to link against. | ||
# abistatic : The static ABI library to link against. | ||
# abifiles : A list of files (which may be relative paths) to copy into the | ||
# libc++ build tree for the build. These files will be copied | ||
# twice: once into include/, so the libc++ build itself can find | ||
# them, and once into include/c++/v1, so that a clang built into | ||
# the same build area will find them. | ||
# abidirs : A list of relative paths to create under an include directory | ||
# in the libc++ build directory. | ||
# | ||
|
||
macro(setup_abi_lib abidefines abishared abistatic abifiles abidirs) | ||
list(APPEND LIBCXX_COMPILE_FLAGS ${abidefines}) | ||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" | ||
CACHE PATH | ||
"Paths to C++ ABI header directories separated by ';'." FORCE | ||
) | ||
set(LIBCXX_CXX_ABI_LIBRARY_PATH "${LIBCXX_CXX_ABI_LIBRARY_PATH}" | ||
CACHE PATH | ||
"Paths to C++ ABI library directory" | ||
) | ||
set(LIBCXX_CXX_SHARED_ABI_LIBRARY ${abishared}) | ||
set(LIBCXX_CXX_STATIC_ABI_LIBRARY ${abistatic}) | ||
set(LIBCXX_ABILIB_FILES ${abifiles}) | ||
|
||
foreach(fpath ${LIBCXX_ABILIB_FILES}) | ||
# The problem this solves is that when building against a system-provided ABI library, | ||
# the ABI headers might live side-by-side with an actual C++ Standard Library | ||
# installation. For that reason, we can't just add `-I <path-to-ABI-headers>`, | ||
# since we would end up also adding the system-provided C++ Standard Library to | ||
# the search path. Instead, what we do is copy just the ABI library headers to | ||
# a private directory and add just that path when we build libc++. | ||
function(import_private_headers target include_dirs headers) | ||
foreach(header ${headers}) | ||
set(found FALSE) | ||
foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS}) | ||
message(STATUS "Looking for ${fpath} in ${incpath}") | ||
if (EXISTS "${incpath}/${fpath}") | ||
foreach(incpath ${include_dirs}) | ||
if (EXISTS "${incpath}/${header}") | ||
set(found TRUE) | ||
message(STATUS "Looking for ${fpath} in ${incpath} - found") | ||
get_filename_component(dstdir ${fpath} PATH) | ||
get_filename_component(ifile ${fpath} NAME) | ||
set(src ${incpath}/${fpath}) | ||
|
||
set(dst ${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}/${ifile}) | ||
add_custom_command(OUTPUT ${dst} | ||
DEPENDS ${src} | ||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} | ||
COMMENT "Copying C++ ABI header ${fpath}...") | ||
list(APPEND abilib_headers "${dst}") | ||
message(STATUS "Looking for ${header} in ${incpath} - found") | ||
get_filename_component(dstdir ${header} PATH) | ||
get_filename_component(header_file ${header} NAME) | ||
set(src ${incpath}/${header}) | ||
set(dst "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}/${header_file}") | ||
|
||
# TODO: libc++ shouldn't be responsible for copying the libc++abi | ||
# headers into the right location. | ||
set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${dstdir}/${fpath}") | ||
add_custom_command(OUTPUT ${dst} | ||
DEPENDS ${src} | ||
COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}" | ||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} | ||
COMMENT "Copying C++ ABI header ${fpath}...") | ||
COMMENT "Copying C++ ABI header ${header}") | ||
list(APPEND abilib_headers "${dst}") | ||
else() | ||
message(STATUS "Looking for ${fpath} in ${incpath} - not found") | ||
message(STATUS "Looking for ${header} in ${incpath} - not found") | ||
endif() | ||
endforeach() | ||
if (NOT found) | ||
message(WARNING "Failed to find ${fpath} in ${LIBCXX_CXX_ABI_INCLUDE_PATHS}") | ||
message(WARNING "Failed to find ${header} in ${include_dirs}") | ||
endif() | ||
endforeach() | ||
|
||
include_directories("${LIBCXX_BINARY_INCLUDE_DIR}") | ||
add_custom_target(cxx_abi_headers ALL DEPENDS ${abilib_headers}) | ||
set(LIBCXX_CXX_ABI_HEADER_TARGET "cxx_abi_headers") | ||
endmacro() | ||
|
||
|
||
# Configure based on the selected ABI library. | ||
if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR | ||
"${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++") | ||
set(_LIBSUPCXX_INCLUDE_FILES | ||
cxxabi.h bits/c++config.h bits/os_defines.h bits/cpu_defines.h | ||
bits/cxxabi_tweaks.h bits/cxxabi_forced.h | ||
) | ||
if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++") | ||
set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") | ||
set(_LIBSUPCXX_LIBNAME stdc++) | ||
else() | ||
set(_LIBSUPCXX_DEFINES "") | ||
set(_LIBSUPCXX_LIBNAME supc++) | ||
# Work around https://gitlab.kitware.com/cmake/cmake/-/issues/18399 | ||
add_library(${target}-generate-private-headers OBJECT ${abilib_headers}) | ||
set_target_properties(${target}-generate-private-headers PROPERTIES LINKER_LANGUAGE CXX) | ||
|
||
target_link_libraries(${target} INTERFACE ${target}-generate-private-headers) | ||
target_include_directories(${target} INTERFACE "${LIBCXX_BINARY_DIR}/private-abi-headers") | ||
endfunction() | ||
|
||
# This function creates an imported library named <target> of the given <kind> (SHARED|STATIC). | ||
# It imports a library named <name> searched at the given <path>. | ||
function(imported_library target kind path name) | ||
add_library(${target} ${kind} IMPORTED GLOBAL) | ||
set(libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}${CMAKE_${kind}_LIBRARY_SUFFIX}") | ||
# Make sure we find .tbd files on macOS | ||
if (kind STREQUAL "SHARED") | ||
list(APPEND libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}.tbd") | ||
endif() | ||
setup_abi_lib( | ||
"-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}" | ||
"${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits" | ||
) | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") | ||
if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS) | ||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_SOURCE_DIR}/../libcxxabi/include") | ||
find_library(file | ||
NAMES ${libnames} | ||
PATHS "${path}" | ||
NO_CACHE) | ||
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${file}") | ||
endfunction() | ||
|
||
# Link against a system-provided libstdc++ | ||
if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" | ||
"cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h") | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBSTDCXX" "-D__GLIBCXX__") | ||
|
||
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++) | ||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) | ||
|
||
imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++) | ||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) | ||
|
||
# Link against a system-provided libsupc++ | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libsupc++") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" | ||
"cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h") | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-D__GLIBCXX__") | ||
|
||
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++) | ||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) | ||
|
||
imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++) | ||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) | ||
|
||
# Link against the in-tree libc++abi | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxabi") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
target_link_libraries(libcxx-abi-headers INTERFACE cxxabi-headers) | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI") | ||
|
||
if (TARGET cxxabi_shared) | ||
add_library(libcxx-abi-shared ALIAS cxxabi_shared) | ||
endif() | ||
|
||
if(LIBCXX_STANDALONE_BUILD AND NOT (LIBCXX_CXX_ABI_INTREE OR HAVE_LIBCXXABI)) | ||
set(shared c++abi) | ||
set(static c++abi) | ||
else() | ||
set(shared cxxabi_shared) | ||
set(static cxxabi_static) | ||
if (TARGET cxxabi_static) | ||
add_library(libcxx-abi-static ALIAS cxxabi_static) | ||
endif() | ||
|
||
setup_abi_lib( | ||
"-DLIBCXX_BUILDING_LIBCXXABI" | ||
"${shared}" "${static}" "cxxabi.h;__cxxabi_config.h" "") | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "system-libcxxabi") | ||
setup_abi_lib( | ||
"-DLIBCXX_BUILDING_LIBCXXABI" | ||
"c++abi" "c++abi" "cxxabi.h;__cxxabi_config.h" "") | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") | ||
# Link against a system-provided libc++abi | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" "cxxabi.h;__cxxabi_config.h") | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI") | ||
|
||
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi) | ||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) | ||
|
||
imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi) | ||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) | ||
|
||
# Link against a system-provided libcxxrt | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxrt") | ||
# libcxxrt does not provide aligned new and delete operators | ||
# TODO: We're keeping this for backwards compatibility, but this doesn't belong here. | ||
set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) | ||
|
||
if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS) | ||
message(STATUS "LIBCXX_CXX_ABI_INCLUDE_PATHS not set, using /usr/include/c++/v1") | ||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1") | ||
endif() | ||
# libcxxrt does not provide aligned new and delete operators | ||
set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) | ||
setup_abi_lib( | ||
"-DLIBCXXRT" | ||
"cxxrt" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" | ||
) | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "vcruntime") | ||
# Nothing to do | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none") | ||
list(APPEND LIBCXX_COMPILE_FLAGS "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY") | ||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "default") | ||
# Nothing to do | ||
else() | ||
message(FATAL_ERROR | ||
"Unsupported c++ abi: '${LIBCXX_CXX_ABI_LIBNAME}'. \ | ||
Currently libstdc++, libsupc++, libcxxabi, libcxxrt, default and none are | ||
supported for c++ abi." | ||
) | ||
endif () | ||
add_library(libcxx-abi-headers INTERFACE) | ||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" | ||
"cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h") | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXXRT") | ||
|
||
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt) | ||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) | ||
|
||
imported_library(libcxx-abi-static STATIC "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt) | ||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) | ||
|
||
# Link against a system-provided vcruntime | ||
# FIXME: Figure out how to configure the ABI library on Windows. | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "vcruntime") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
add_library(libcxx-abi-shared INTERFACE) | ||
add_library(libcxx-abi-static INTERFACE) | ||
|
||
# Don't link against any ABI library | ||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "none") | ||
add_library(libcxx-abi-headers INTERFACE) | ||
target_compile_definitions(libcxx-abi-headers INTERFACE "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY") | ||
|
||
add_library(libcxx-abi-shared INTERFACE) | ||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers) | ||
|
||
add_library(libcxx-abi-static INTERFACE) | ||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.