about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--cmake/find_llvm.cmake69
1 files changed, 60 insertions, 9 deletions
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<path>`.
-      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()