You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FindLLVM.cmake 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #===------------------------------------------------------------------------===#
  2. #
  3. # The KLEE Symbolic Virtual Machine
  4. #
  5. # This file is distributed under the University of Illinois Open Source
  6. # License. See LICENSE.TXT for details.
  7. #
  8. #===------------------------------------------------------------------------===#
  9. #
  10. # This file provides multiple methods to detect LLVM.
  11. #
  12. # * llvm-config executable. This method is portable across LLVM build systems
  13. # (i.e. works if LLVM was built with autoconf/Makefile or with CMake).
  14. #
  15. # * find_package(LLVM CONFIG). This method only works if LLVM was built with
  16. # CMake or with LLVM >= 3.5 when built with the autoconf/Makefile build system
  17. # This method relies on the `LLVMConfig.cmake` file generated to be generated
  18. # by LLVM's build system.
  19. #
  20. #===------------------------------------------------------------------------===#
  21. function(string_to_list s output_var)
  22. string(REPLACE " " ";" _output "${s}")
  23. set(${output_var} ${_output} PARENT_SCOPE)
  24. endfunction()
  25. option(USE_CMAKE_FIND_PACKAGE_LLVM "Use find_package(LLVM CONFIG) to find LLVM" OFF)
  26. if (USE_CMAKE_FIND_PACKAGE_LLVM)
  27. find_package(LLVM CONFIG REQUIRED)
  28. # Provide function to map LLVM components to libraries.
  29. function(klee_get_llvm_libs output_var)
  30. if (${LLVM_PACKAGE_VERSION} VERSION_LESS "3.5")
  31. llvm_map_components_to_libraries(${output_var} ${ARGN})
  32. else()
  33. llvm_map_components_to_libnames(${output_var} ${ARGN})
  34. endif()
  35. set(${output_var} ${${output_var}} PARENT_SCOPE)
  36. endfunction()
  37. # HACK: This information is not exported so just pretend its OFF for now.
  38. set(LLVM_ENABLE_VISIBILITY_INLINES_HIDDEN OFF)
  39. else()
  40. # Use the llvm-config binary to get the information needed.
  41. # Try to detect it in the user's environment. The user can
  42. # force a particular binary by passing `-DLLVM_CONFIG_BINARY=/path/to/llvm-config`
  43. # to CMake.
  44. find_program(LLVM_CONFIG_BINARY
  45. NAMES llvm-config)
  46. message(STATUS "LLVM_CONFIG_BINARY: ${LLVM_CONFIG_BINARY}")
  47. if (NOT LLVM_CONFIG_BINARY)
  48. message(FATAL_ERROR
  49. "Failed to find llvm-config.\n"
  50. "Try passing -DLLVM_CONFIG_BINARY=/path/to/llvm-config to cmake")
  51. endif()
  52. function(_run_llvm_config output_var)
  53. set(_command "${LLVM_CONFIG_BINARY}" ${ARGN})
  54. execute_process(COMMAND ${_command}
  55. RESULT_VARIABLE _exit_code
  56. OUTPUT_VARIABLE ${output_var}
  57. OUTPUT_STRIP_TRAILING_WHITESPACE
  58. ERROR_STRIP_TRAILING_WHITESPACE
  59. )
  60. if (NOT ("${_exit_code}" EQUAL "0"))
  61. message(FATAL_ERROR "Failed running ${_command}")
  62. endif()
  63. set(${output_var} ${${output_var}} PARENT_SCOPE)
  64. endfunction()
  65. # Get LLVM version
  66. _run_llvm_config(LLVM_PACKAGE_VERSION "--version")
  67. # Try x.y.z patern
  68. set(_llvm_version_regex "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(svn)?$")
  69. if ("${LLVM_PACKAGE_VERSION}" MATCHES "${_llvm_version_regex}")
  70. string(REGEX REPLACE
  71. "${_llvm_version_regex}"
  72. "\\1"
  73. LLVM_VERSION_MAJOR
  74. "${LLVM_PACKAGE_VERSION}")
  75. string(REGEX REPLACE
  76. "${_llvm_version_regex}"
  77. "\\2"
  78. LLVM_VERSION_MINOR
  79. "${LLVM_PACKAGE_VERSION}")
  80. string(REGEX REPLACE
  81. "${_llvm_version_regex}"
  82. "\\3"
  83. LLVM_VERSION_PATCH
  84. "${LLVM_PACKAGE_VERSION}")
  85. else()
  86. # try x.y pattern
  87. set(_llvm_version_regex "^([0-9]+)\\.([0-9]+)(svn)?$")
  88. if ("${LLVM_PACKAGE_VERSION}" MATCHES "${_llvm_version_regex}")
  89. string(REGEX REPLACE
  90. "${_llvm_version_regex}"
  91. "\\1"
  92. LLVM_VERSION_MAJOR
  93. "${LLVM_PACKAGE_VERSION}")
  94. string(REGEX REPLACE
  95. "${_llvm_version_regex}"
  96. "\\2"
  97. LLVM_VERSION_MINOR
  98. "${LLVM_PACKAGE_VERSION}")
  99. set(LLVM_VERSION_PATCH 0)
  100. else()
  101. message(FATAL_ERROR
  102. "Failed to parse LLVM version from \"${LLVM_PACKAGE_VERSION}\"")
  103. endif()
  104. endif()
  105. set(LLVM_DEFINITIONS "")
  106. _run_llvm_config(_llvm_cpp_flags "--cppflags")
  107. string_to_list("${_llvm_cpp_flags}" _llvm_cpp_flags_list)
  108. foreach (flag ${_llvm_cpp_flags_list})
  109. # Filter out -I flags by only looking for -D flags.
  110. if ("${flag}" MATCHES "^-D" AND NOT ("${flag}" STREQUAL "-D_DEBUG"))
  111. list(APPEND LLVM_DEFINITIONS "${flag}")
  112. endif()
  113. endforeach()
  114. set(LLVM_ENABLE_ASSERTIONS ON)
  115. set(LLVM_ENABLE_EH ON)
  116. set(LLVM_ENABLE_RTTI ON)
  117. set(LLVM_ENABLE_VISIBILITY_INLINES_HIDDEN OFF)
  118. _run_llvm_config(_llvm_cxx_flags "--cxxflags")
  119. string_to_list("${_llvm_cxx_flags}" _llvm_cxx_flags_list)
  120. foreach (flag ${_llvm_cxx_flags_list})
  121. if ("${flag}" STREQUAL "-DNDEBUG")
  122. # Note we don't rely on `llvm-config --build-mode` because
  123. # that seems broken when LLVM is built with CMake.
  124. set(LLVM_ENABLE_ASSERTIONS OFF)
  125. elseif ("${flag}" STREQUAL "-fno-exceptions")
  126. set(LLVM_ENABLE_EH OFF)
  127. elseif ("${flag}" STREQUAL "-fno-rtti")
  128. set(LLVM_ENABLE_RTTI OFF)
  129. elseif ("${flag}" STREQUAL "-fvisibility-inlines-hidden")
  130. set(LLVM_ENABLE_VISIBILITY_INLINES_HIDDEN ON)
  131. endif()
  132. endforeach()
  133. set(LLVM_INCLUDE_DIRS "")
  134. foreach (flag ${_llvm_cpp_flags_list})
  135. # Filter out -D flags by only looking for -I flags.
  136. if ("${flag}" MATCHES "^-I")
  137. string(REGEX REPLACE "^-I(.+)$" "\\1" _include_dir "${flag}")
  138. list(APPEND LLVM_INCLUDE_DIRS "${_include_dir}")
  139. endif()
  140. endforeach()
  141. _run_llvm_config(LLVM_LIBRARY_DIRS "--libdir")
  142. _run_llvm_config(LLVM_TOOLS_BINARY_DIR "--bindir")
  143. _run_llvm_config(TARGET_TRIPLE "--host-target")
  144. # Provide function to map LLVM components to libraries.
  145. function(klee_get_llvm_libs OUTPUT_VAR)
  146. _run_llvm_config(_llvm_libs "--libfiles" ${ARGN})
  147. string_to_list("${_llvm_libs}" _llvm_libs_list)
  148. # Now find the system libs that are needed.
  149. if (${LLVM_PACKAGE_VERSION} VERSION_LESS "3.5")
  150. # For LLVM 3.4 and older system libraries
  151. # appeared in the output of `--ldflags`.
  152. _run_llvm_config(_system_libs "--ldflags")
  153. # TODO: Filter out `-L<path>` flag.
  154. else()
  155. _run_llvm_config(_system_libs "--system-libs")
  156. endif()
  157. string_to_list("${_system_libs}" _system_libs_list)
  158. # Create an imported target for each LLVM library
  159. # if it doesn't already exist. We need to do this
  160. # so we can tell CMake that these libraries depend
  161. # on the necessary libraries so that CMake
  162. # can get the link order right.
  163. set(targets_to_return "")
  164. set(created_targets "")
  165. foreach (llvm_lib ${_llvm_libs_list})
  166. # a bug in llvm-config from LLVM 3.9
  167. string(REGEX REPLACE "lib(libLLVM[-.a-zA-Z0-9]+\\.so)\\.so$" "\\1" llvm_lib "${llvm_lib}")
  168. get_filename_component(llvm_lib_file_name "${llvm_lib}" NAME)
  169. string(REGEX REPLACE "^(lib)?(LLVM[-.a-zA-Z0-9]+)\\..+$" "\\2" target_name "${llvm_lib_file_name}")
  170. list(APPEND targets_to_return "${target_name}")
  171. if (NOT TARGET "${target_name}")
  172. # DEBUG: message(STATUS "Creating imported target \"${target_name}\"" " for \"${llvm_lib}\"")
  173. list(APPEND created_targets "${target_name}")
  174. set(import_library_type "STATIC")
  175. if ("${llvm_lib_file_name}" MATCHES "(so|dylib|dll)$")
  176. set(import_library_type "SHARED")
  177. endif()
  178. # Create an imported target for the library
  179. add_library("${target_name}" "${import_library_type}" IMPORTED GLOBAL)
  180. set_property(TARGET "${target_name}" PROPERTY
  181. IMPORTED_LOCATION "${llvm_lib}"
  182. )
  183. endif()
  184. endforeach()
  185. # Now state the dependencies of the created imported targets which we
  186. # assume to be for each imported target the libraries which appear after
  187. # the library in `{_llvm_libs_list}` and then finally the system libs.
  188. # It is **essential** that we do this otherwise CMake will get the
  189. # link order of the imported targets wrong.
  190. list(LENGTH targets_to_return length_targets_to_return)
  191. if ("${length_targets_to_return}" GREATER 0)
  192. math(EXPR targets_to_return_last_index "${length_targets_to_return} -1")
  193. foreach (llvm_target_lib ${created_targets})
  194. # DEBUG: message(STATUS "Adding deps for target ${llvm_target_lib}")
  195. # Find position in `targets_to_return`
  196. list(FIND targets_to_return "${llvm_target_lib}" position)
  197. if ("${position}" EQUAL "-1")
  198. message(FATAL_ERROR "couldn't find \"${llvm_target_lib}\" in list of targets")
  199. endif()
  200. if ("${position}" LESS "${targets_to_return_last_index}")
  201. math(EXPR position_plus_one "${position} + 1")
  202. foreach (index RANGE ${position_plus_one} ${targets_to_return_last_index})
  203. # Get the target for this index
  204. list(GET targets_to_return ${index} target_for_index)
  205. # DEBUG: message(STATUS "${llvm_target_libs} depends on ${target_for_index}")
  206. set_property(TARGET "${llvm_target_lib}" APPEND PROPERTY
  207. INTERFACE_LINK_LIBRARIES "${target_for_index}"
  208. )
  209. endforeach()
  210. endif()
  211. # Now finally add the system library dependencies. These must be last.
  212. set_property(TARGET "${target_name}" APPEND PROPERTY
  213. INTERFACE_LINK_LIBRARIES "${_system_libs_list}"
  214. )
  215. endforeach()
  216. endif()
  217. set(${OUTPUT_VAR} ${targets_to_return} PARENT_SCOPE)
  218. endfunction()
  219. endif()
  220. # Filter out `-DNEBUG` from LLVM_DEFINITIONS. The caller can use
  221. # `LLVM_ENABLE_ASSERTIONS` to decide how to set their defines.
  222. set(_new_llvm_definitions "")
  223. foreach (llvm_define ${LLVM_DEFINITIONS})
  224. if ("${llvm_define}" STREQUAL "-DNDEBUG")
  225. # Skip
  226. else()
  227. list(APPEND _new_llvm_definitions "${llvm_define}")
  228. endif()
  229. endforeach()
  230. set(LLVM_DEFINITIONS "${_new_llvm_definitions}")
  231. unset(_new_llvm_definitions)