about summary refs log tree commit diff homepage
path: root/cmake
diff options
context:
space:
mode:
authorDan Liew <daniel.liew@imperial.ac.uk>2016-11-21 15:13:04 +0000
committerDan Liew <delcypher@gmail.com>2016-11-22 20:23:22 +0000
commit7214ec6a8caf4cfd021a09527e7d17fb493729c6 (patch)
tree7c03e1c96ca6eb6c2a45d71a99d610b023d30076 /cmake
parentba6963ce1e4b84bf4bdb7bb5ab7e9a683db14b63 (diff)
downloadklee-7214ec6a8caf4cfd021a09527e7d17fb493729c6.tar.gz
[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.
Diffstat (limited to 'cmake')
-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()