From 7214ec6a8caf4cfd021a09527e7d17fb493729c6 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 21 Nov 2016 15:13:04 +0000 Subject: [CMake] Fix link order of LLVM libraries and required system libraries. Now LLVM libraries are added as imported targets and their link dependencies are explicitly stated so CMake can get the link order correct. --- cmake/find_llvm.cmake | 69 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) (limited to 'cmake') diff --git a/cmake/find_llvm.cmake b/cmake/find_llvm.cmake index 60d7b3e4..b1d3dc27 100644 --- a/cmake/find_llvm.cmake +++ b/cmake/find_llvm.cmake @@ -149,18 +149,69 @@ else() string_to_list("${_llvm_libs}" _llvm_libs_list) # Now find the system libs that are needed. - # FIXME: This is a hack. We should really create imported - # targets for the LLVM libraries and have them depend - # on the necessary system libraries. _run_llvm_config(_system_libs "--ldflags") string_to_list("${_system_libs}" _system_libs_list) - set(_filtered_system_libs_list "") - foreach (l ${_system_libs_list}) - # Filter out `-L`. - if ("${l}" MATCHES "^-l") - list(APPEND _filtered_system_libs_list "${l}") + + # Create an imported target for each LLVM library + # if it doesn't already exist. We need to do this + # so we can tell CMake that these libraries depend + # on the necessary libraries so that CMake + # can get the link order right. + set(targets_to_return "") + set(created_targets "") + foreach (llvm_lib ${_llvm_libs_list}) + get_filename_component(llvm_lib_file_name "${llvm_lib}" NAME) + string(REGEX REPLACE "^(lib)?(LLVM[a-zA-Z0-9]+)\\..+$" "\\2" target_name "${llvm_lib_file_name}") + list(APPEND targets_to_return "${target_name}") + if (NOT TARGET "${target_name}") + # DEBUG: message(STATUS "Creating imported target \"${target_name}\"" " for \"${llvm_lib}\"") + list(APPEND created_targets "${target_name}") + + set(import_library_type "STATIC") + if ("${llvm_lib_file_name}" MATCHES "(so|dylib|dll)$") + set(import_library_type "SHARED") + endif() + # Create an imported target for the library + add_library("${target_name}" "${import_library_type}" IMPORTED GLOBAL) + set_property(TARGET "${target_name}" PROPERTY + IMPORTED_LOCATION "${llvm_lib}" + ) endif() endforeach() - set(${OUTPUT_VAR} ${_llvm_libs_list} ${_system_libs} PARENT_SCOPE) + + # Now state the dependencies of the created imported targets which we + # assume to be for each imported target the libraries which appear after + # the library in `{_llvm_libs_list}` and then finally the system libs. + # It is **essential** that we do this otherwise CMake will get the + # link order of the imported targets wrong. + list(LENGTH targets_to_return length_targets_to_return) + if ("${length_targets_to_return}" GREATER 0) + math(EXPR targets_to_return_last_index "${length_targets_to_return} -1") + foreach (llvm_target_lib ${created_targets}) + # DEBUG: message(STATUS "Adding deps for target ${llvm_target_lib}") + # Find position in `targets_to_return` + list(FIND targets_to_return "${llvm_target_lib}" position) + if ("${position}" EQUAL "-1") + message(FATAL_ERROR "couldn't find \"${llvm_target_lib}\" in list of targets") + endif() + if ("${position}" LESS "${targets_to_return_last_index}") + math(EXPR position_plus_one "${position} + 1") + foreach (index RANGE ${position_plus_one} ${targets_to_return_last_index}) + # Get the target for this index + list(GET targets_to_return ${index} target_for_index) + # DEBUG: message(STATUS "${llvm_target_libs} depends on ${target_for_index}") + set_property(TARGET "${llvm_target_lib}" APPEND PROPERTY + INTERFACE_LINK_LIBRARIES "${target_for_index}" + ) + endforeach() + endif() + # Now finally add the system library dependencies. These must be last. + set_property(TARGET "${target_name}" APPEND PROPERTY + INTERFACE_LINK_LIBRARIES "${_system_libs_list}" + ) + endforeach() + endif() + + set(${OUTPUT_VAR} ${targets_to_return} PARENT_SCOPE) endfunction() endif() -- cgit 1.4.1