diff --git a/libcxx/cmake/Modules/DefineLinkerScript.cmake b/libcxx/cmake/Modules/DefineLinkerScript.cmake --- a/libcxx/cmake/Modules/DefineLinkerScript.cmake +++ b/libcxx/cmake/Modules/DefineLinkerScript.cmake @@ -1,3 +1,85 @@ +# This function tries to find library file name without the prefix and the +# extension. +# +# Arguments: +# : Target name. +# : Output variable that the result be written into. + +function(get_imported_library_file_base_name tgt var) + get_target_property(imported_loc ${tgt} IMPORTED_LOCATION) + + if (NOT imported_loc) + get_target_property(imported_loc_debug ${tgt} IMPORTED_LOCATION_DEBUG) + get_target_property(imported_loc_release ${tgt} IMPORTED_LOCATION_RELEASE) + if (NOT imported_loc_debug AND NOT imported_loc_release) + message(FATAL_ERROR "Cannot determine import location for library ${tgt}") + endif() + set(imported_loc "$<$:${imported_loc_debug}>$<$:${imported_loc_release}>") + endif() + + get_filename_component(lib_name "${imported_loc}" NAME_WE) + unset(imported_loc) + string(LENGTH "${CMAKE_SHARED_LIBRARY_PREFIX}" prefix_length) + + if (prefix_length) + string(FIND "${lib_name}" "${CMAKE_SHARED_LIBRARY_PREFIX}" prefix_pos) + if (NOT prefix_pos EQUAL 0) + message(FATAL_ERROR "Library name '${tgt}' doesn't start with expected prefix") + endif(NOT prefix_pos EQUAL 0) + unset(prefix_pos) + string(SUBSTRING "${lib_name}" ${prefix_length} -1 dep_lib_base_name) + set(${var} "${dep_lib_base_name}" PARENT_SCOPE) + endif(prefix_length) +endfunction() + +# This function builds list of dependencies for given target. +# +# Arguments: +# : Target to build list of dependencies for. +# : Output variable that the list be written into. + +function(get_dependencies_recursive tgt var) + if (TARGET ${tgt}) + get_target_property(my_deps ${tgt} INTERFACE_LINK_LIBRARIES) + if (NOT my_deps) + return() + endif() + endif() + + foreach(dep ${my_deps}) + if (TARGET ${dep}) + get_target_property(lib_type ${dep} TYPE) + endif() + + if (lib_type STREQUAL "INTERFACE_LIBRARY" OR + lib_type STREQUAL "STATIC_LIBRARY" OR + lib_type STREQUAL "SHARED_LIBRARY") + set(transitive_deps) + get_dependencies_recursive(${dep} transitive_deps) + + list(APPEND result ${transitive_deps}) + + if (NOT lib_type STREQUAL "INTERFACE_LIBRARY") + get_target_property(is_imported ${dep} IMPORTED) + # The generator expression $ yields the + # target's name when applied to an imported target. We will try to get + # its imported location and do some post-processing to obtain a usable + # file name. + if (is_imported) + get_imported_library_file_base_name(${dep} dep_file_base_name) + list(APPEND result "${CMAKE_LINK_LIBRARY_FLAG}${dep_file_base_name}") + unset(dep_file_base_name) + else(is_imported) + list(APPEND result "${CMAKE_LINK_LIBRARY_FLAG}$") + endif(is_imported) + unset(is_imported) + endif() + endif() + unset(lib_type) + endforeach() + set(${var} ${result} PARENT_SCOPE) +endfunction() + # This function defines a linker script in place of the symlink traditionally # created for shared libraries. # @@ -34,7 +116,8 @@ if (TARGET "${lib}" OR (${lib} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI) OR (${lib} MATCHES "unwind(_static|_shared)?" AND HAVE_LIBUNWIND)) - list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$") + get_dependencies_recursive(${lib} recursive_deps) + list(APPEND link_libraries "${recursive_deps}") else() list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${lib}") endif() diff --git a/pstl/CMakeLists.txt b/pstl/CMakeLists.txt --- a/pstl/CMakeLists.txt +++ b/pstl/CMakeLists.txt @@ -42,6 +42,7 @@ find_package(TBB 2018 REQUIRED tbb OPTIONAL_COMPONENTS tbbmalloc) message(STATUS "Parallel STL uses TBB ${TBB_VERSION} (interface version: ${TBB_INTERFACE_VERSION})") target_link_libraries(ParallelSTL INTERFACE TBB::tbb) + set_target_properties(TBB::tbb PROPERTIES IMPORTED_GLOBAL TRUE) set(_PSTL_PAR_BACKEND_TBB ON) else() message(FATAL_ERROR "Requested unknown Parallel STL backend '${PSTL_PARALLEL_BACKEND}'.")