[libc++][CMake] Refactor how we link against system libraries

Summary:
Instead of populating the global LIBCXX_LIBRARIES, we use the link-time
dependency management built into CMake to propagate link flags. This
leads to a cleaner and easier-to-follow build.

Reviewers: phosek, smeenai, EricWF

Subscribers: mgorny, christof, jkorous, dexonsmith, jfb, mstorsjo, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D60969

llvm-svn: 359571
This commit is contained in:
Louis Dionne 2019-04-30 15:44:19 +00:00
parent 2e78c5a883
commit 68924e6be7
3 changed files with 79 additions and 40 deletions

View File

@ -137,7 +137,6 @@ function(add_benchmark_test name source_file)
add_executable(${libcxx_target} EXCLUDE_FROM_ALL ${source_file})
add_dependencies(${libcxx_target} cxx cxx-headers google-benchmark-libcxx)
add_dependencies(cxx-benchmarks ${libcxx_target})
target_link_libraries(${libcxx_target} ${LIBCXX_LIBRARIES})
if (LIBCXX_ENABLE_SHARED)
target_link_libraries(${libcxx_target} cxx_shared)
else()

View File

@ -220,3 +220,27 @@ endmacro()
macro(split_list listname)
string(REPLACE ";" " " ${listname} "${${listname}}")
endmacro()
# For each specified flag, add that link flag to the provided target.
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
function(target_add_link_flags_if_supported target visibility)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
if (LIBCXX_SUPPORTS_${flagname}_FLAG)
target_link_libraries(${target} ${visibility} ${flag})
endif()
endforeach()
endfunction()
# For each specified flag, add that compile flag to the provided target.
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
function(target_add_compile_flags_if_supported target visibility)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
if (LIBCXX_SUPPORTS_${flagname}_FLAG)
target_compile_options(${target} ${visibility} ${flag})
endif()
endforeach()
endfunction()

View File

@ -76,40 +76,60 @@ if (APPLE AND LLVM_USE_SANITIZER)
endif()
endif()
# Generate private library list.
add_library_flags_if(LIBCXX_HAS_PTHREAD_LIB pthread)
add_library_flags_if(LIBCXX_HAS_C_LIB c)
add_library_flags_if(LIBCXX_HAS_M_LIB m)
add_library_flags_if(LIBCXX_HAS_RT_LIB rt)
if (LIBCXX_USE_COMPILER_RT)
find_compiler_rt_library(builtins LIBCXX_BUILTINS_LIBRARY)
add_library_flags_if(LIBCXX_BUILTINS_LIBRARY "${LIBCXX_BUILTINS_LIBRARY}")
else()
add_library_flags_if(LIBCXX_HAS_GCC_S_LIB gcc_s)
endif()
add_library_flags_if(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB atomic)
add_library_flags_if(MINGW "${MINGW_LIBRARIES}")
function(cxx_link_system_libraries target)
target_add_link_flags_if_supported(${target} PRIVATE "-nodefaultlibs")
target_add_compile_flags_if_supported(${target} PRIVATE "/Zl")
target_add_link_flags_if_supported(${target} PRIVATE "/nodefaultlib")
# Setup flags.
add_link_flags_if_supported(-nodefaultlibs)
if (LIBCXX_TARGETING_MSVC)
if (LIBCXX_DEBUG_BUILD)
set(LIB_SUFFIX "d")
else()
set(LIB_SUFFIX "")
if (LIBCXX_HAS_PTHREAD_LIB)
target_link_libraries(${target} PUBLIC pthread)
endif()
add_compile_flags(/Zl)
add_link_flags(/nodefaultlib)
add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime
add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime
add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files
add_library_flags(msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
# Required for standards-complaint wide character formatting functions
# (e.g. `printfw`/`scanfw`)
add_library_flags(iso_stdio_wide_specifiers)
endif()
if (LIBCXX_HAS_C_LIB)
target_link_libraries(${target} PUBLIC c)
endif()
if (LIBCXX_HAS_M_LIB)
target_link_libraries(${target} PUBLIC m)
endif()
if (LIBCXX_HAS_RT_LIB)
target_link_libraries(${target} PUBLIC rt)
endif()
if (LIBCXX_USE_COMPILER_RT)
find_compiler_rt_library(builtins LIBCXX_BUILTINS_LIBRARY)
if (LIBCXX_BUILTINS_LIBRARY)
target_link_libraries(${target} PUBLIC "${LIBCXX_BUILTINS_LIBRARY}")
endif()
elseif (LIBCXX_HAS_GCC_S_LIB)
target_link_libraries(${target} PUBLIC gcc_s)
endif()
if (LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB)
target_link_libraries(${target} PUBLIC atomic)
endif()
if (MINGW)
target_link_libraries(${target} PUBLIC "${MINGW_LIBRARIES}")
endif()
if (LIBCXX_TARGETING_MSVC)
if (LIBCXX_DEBUG_BUILD)
set(LIB_SUFFIX "d")
else()
set(LIB_SUFFIX "")
endif()
target_link_libraries(${target} PUBLIC ucrt${LIB_SUFFIX}) # Universal C runtime
target_link_libraries(${target} PUBLIC vcruntime${LIB_SUFFIX}) # C++ runtime
target_link_libraries(${target} PUBLIC msvcrt${LIB_SUFFIX}) # C runtime startup files
target_link_libraries(${target} PUBLIC msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
# Required for standards-complaint wide character formatting functions
# (e.g. `printfw`/`scanfw`)
target_link_libraries(${target} PUBLIC iso_stdio_wide_specifiers)
endif()
endfunction()
function(cxx_set_common_defines name)
if(LIBCXX_CXX_ABI_HEADER_TARGET)
@ -148,6 +168,7 @@ if (LIBCXX_ENABLE_SHARED)
if(COMMAND llvm_setup_rpath)
llvm_setup_rpath(cxx_shared)
endif()
cxx_link_system_libraries(cxx_shared)
target_link_libraries(cxx_shared PRIVATE ${LIBCXX_LIBRARIES})
set_target_properties(cxx_shared
PROPERTIES
@ -163,7 +184,7 @@ if (LIBCXX_ENABLE_SHARED)
# Link against LLVM libunwind
if (LIBCXXABI_USE_LLVM_UNWINDER)
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
target_link_libraries(cxx_shared PRIVATE unwind_shared)
target_link_libraries(cxx_shared PUBLIC unwind_shared)
list(APPEND LIBCXX_INTERFACE_LIBRARIES unwind_shared) # For the linker script
elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
# libunwind is already included in libc++abi
@ -181,9 +202,8 @@ if (LIBCXX_ENABLE_SHARED)
target_link_libraries(cxx_shared PRIVATE "-Wl,--whole-archive,-Bstatic" "${LIBCXX_CXX_STATIC_ABI_LIBRARY}" "-Wl,-Bdynamic,--no-whole-archive")
endif()
else()
target_link_libraries(cxx_shared PRIVATE "${LIBCXX_CXX_SHARED_ABI_LIBRARY}")
target_link_libraries(cxx_shared PUBLIC "${LIBCXX_CXX_SHARED_ABI_LIBRARY}")
list(APPEND LIBCXX_INTERFACE_LIBRARIES "${LIBCXX_CXX_SHARED_ABI_LIBRARY}") # For the linker script
list(APPEND LIBCXX_LIBRARIES "${LIBCXX_CXX_SHARED_ABI_LIBRARY}") # For the benchmarks
endif()
# Maybe re-export symbols from libc++abi
@ -253,6 +273,7 @@ endif()
# Build the static library.
if (LIBCXX_ENABLE_STATIC)
add_library(cxx_static STATIC ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS})
cxx_link_system_libraries(cxx_static)
target_link_libraries(cxx_static PRIVATE ${LIBCXX_LIBRARIES})
set(CMAKE_STATIC_LIBRARY_PREFIX "lib")
set_target_properties(cxx_static
@ -388,8 +409,3 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR
-P "${LIBCXX_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-libcxx DEPENDS install-cxx)
endif()
# TODO: This is needed by cxx-benchmarks but this variable isn't
# available outside of the scope of this file so we need to export
# it. This is not necessarily the cleanest solution.
set(LIBCXX_LIBRARIES ${LIBCXX_LIBRARIES} PARENT_SCOPE)