[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
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@359571 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt
index 11e3f99..906ffa4 100644
--- a/benchmarks/CMakeLists.txt
+++ b/benchmarks/CMakeLists.txt
@@ -137,7 +137,6 @@
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()
diff --git a/cmake/Modules/HandleLibcxxFlags.cmake b/cmake/Modules/HandleLibcxxFlags.cmake
index cde2c29..b0fb98b 100644
--- a/cmake/Modules/HandleLibcxxFlags.cmake
+++ b/cmake/Modules/HandleLibcxxFlags.cmake
@@ -220,3 +220,27 @@
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()
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 0564ee6..410912f 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -76,40 +76,60 @@
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(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 @@
# 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 @@
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 @@
# 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 @@
-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)