cmake/FindLLVM.cmake (176 lines of code) (raw):
# Find the native LLVM includes and libraries
#
# Defines the following variables
# LLVM_INCLUDE_DIRS - where to find llvm include files
# LLVM_LIBRARY_DIRS - where to find llvm libs
# LLVM_CFLAGS - llvm compiler flags
# LLVM_LFLAGS - llvm linker flags
# LLVM_MODULE_LIBS - list of llvm libs for working with modules.
# LLVM_INSTALL_PREFIX - LLVM installation prefix
# LLVM_FOUND - True if llvm found.
# LLVM_VERSION - Version string ("llvm-config --version")
#
# This module reads hints about search locations from variables
# LLVM_ROOT - Preferred LLVM installation prefix (containing bin/, lib/, ...)
#
# Note: One may specify these as environment variables if they are not specified as
# CMake variables or cache entries.
#=============================================================================
# SPDX-FileCopyrightText: 2014 Kevin Funk <kfunk@kde.org>
# SPDX-FileCopyrightText: 2024 Shivan Kunwar <shivam.kunwar@kdab.com>
#
# SPDX-License-Identifier: BSD-2-Clause
#=============================================================================
if (NOT LLVM_ROOT AND DEFINED ENV{LLVM_ROOT})
file(TO_CMAKE_PATH "$ENV{LLVM_ROOT}" LLVM_ROOT)
endif()
# if the user specified LLVM_ROOT, use that and fail otherwise
if (LLVM_ROOT)
find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config HINTS ${LLVM_ROOT}/bin DOC "llvm-config executable" NO_DEFAULT_PATH)
else()
# find llvm-config, prefer the one with a version suffix, e.g. llvm-config-14
string(REPLACE "." "" LLVM_FIND_VERSION_CONCAT ${LLVM_FIND_VERSION})
find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config-${LLVM_FIND_VERSION} llvm-config${LLVM_FIND_VERSION_CONCAT} llvm-config-14 llvm-config-15 llvm-config-16 llvm-config-17 llvm-config-18 llvm-config-19 llvm-config DOC "llvm-config executable")
if (NOT LLVM_CONFIG_EXECUTABLE)
find_program(_llvmNmExecutable llvm-nm)
if (_llvmNmExecutable)
execute_process(COMMAND ${_llvmNmExecutable} --version OUTPUT_VARIABLE _out)
string(REGEX REPLACE ".*LLVM version ([^ \n]+).*" "\\1" _versionString "${_out}")
find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config-${_versionString} DOC "llvm-config executable")
endif()
endif()
endif()
set(LLVM_FOUND FALSE)
if (LLVM_CONFIG_EXECUTABLE)
# verify that we've found the correct version of llvm-config
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --version
OUTPUT_VARIABLE LLVM_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (NOT LLVM_VERSION)
set(_LLVM_ERROR_MESSAGE "Failed to parse version from llvm-config")
elseif (LLVM_VERSION VERSION_LESS "14.0")
set(_LLVM_ERROR_MESSAGE "LLVM version too old: ${LLVM_VERSION}")
else()
set(LLVM_FOUND TRUE)
endif()
else()
set(_LLVM_ERROR_MESSAGE "Could NOT find 'llvm-config' executable")
endif()
if (LLVM_FOUND)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --includedir
OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --libdir
OUTPUT_VARIABLE LLVM_LIBRARY_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --cppflags
OUTPUT_VARIABLE LLVM_CFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --ldflags
OUTPUT_VARIABLE LLVM_LFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --libs core bitreader asmparser analysis
OUTPUT_VARIABLE LLVM_MODULE_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --libfiles
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REPLACE " " ";" LLVM_LIBS ${LLVM_LIBS})
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --system-libs
OUTPUT_VARIABLE LLVM_SYSTEM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --prefix
OUTPUT_VARIABLE LLVM_INSTALL_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --bindir
OUTPUT_VARIABLE LLVM_BIN_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(CLANG_EXECUTABLE_PATH "${LLVM_BIN_DIR}/clang")
if(EXISTS ${CLANG_EXECUTABLE_PATH})
message(STATUS "Clang found: ${CLANG_EXECUTABLE_PATH}")
set(CLANG_EXECUTABLE ${CLANG_EXECUTABLE_PATH})
else()
message(WARNING "Clang not found in LLVM bin directory: ${LLVM_BIN_DIR}")
endif()
# potentially add include dir from binary dir for non-installed LLVM
set(LLVM_CONFIG_INCLUDE_FLAG "--src-root")
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 16)
set(LLVM_CONFIG_INCLUDE_FLAG "--includedir")
endif()
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} ${LLVM_CONFIG_INCLUDE_FLAG}
OUTPUT_VARIABLE _llvmSourceRoot
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(FIND "${LLVM_INCLUDE_DIRS}" "${_llvmSourceRoot}" _llvmIsInstalled)
if (NOT _llvmIsInstalled)
list(APPEND LLVM_INCLUDE_DIRS "${LLVM_INSTALL_PREFIX}/include")
endif()
# LLVM 19 specific handling
if (LLVM_VERSION VERSION_GREATER_EQUAL "19.0")
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --libs all
OUTPUT_VARIABLE LLVM_LIBS_19
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REPLACE " " ";" LLVM_LIBS_19 ${LLVM_LIBS_19})
list(APPEND LLVM_LIBS ${LLVM_LIBS_19})
endif()
endif()
if (LLVM_FIND_REQUIRED AND NOT LLVM_FOUND)
message(FATAL_ERROR "Could not find LLVM: ${_LLVM_ERROR_MESSAGE}")
elseif(_LLVM_ERROR_MESSAGE)
message(STATUS "Could not find LLVM: ${_LLVM_ERROR_MESSAGE}")
endif()
if (LLVM_FOUND)
message(STATUS "Found LLVM (version: ${LLVM_VERSION}): (using ${LLVM_CONFIG_EXECUTABLE})")
message(STATUS " Include dirs: ${LLVM_INCLUDE_DIRS}")
message(STATUS " LLVM libraries: ${LLVM_LIBS}")
message(STATUS " LLVM System libraries: ${LLVM_SYSTEM_LIBS}")
if (LLVM_VERSION VERSION_GREATER_EQUAL "19.0")
message(STATUS " LLVM 19+ detected, additional libraries may be available")
endif()
endif()
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags
OUTPUT_VARIABLE LLVM_DEFINITIONS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "[ \t]+" ";" LLVM_DEFINITIONS "${LLVM_DEFINITIONS}")
if(LLVM_FIND_COMPONENTS)
foreach(component ${LLVM_FIND_COMPONENTS})
string(TOUPPER ${component} component_upcase)
set(LLVM_${component_upcase}_FOUND TRUE)
set(LLVM_${component_upcase}_LIBRARY ${component})
endforeach()
endif()
if (LLVM_VERSION VERSION_GREATER_EQUAL "14.0")
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --has-rtti
OUTPUT_VARIABLE LLVM_HAS_RTTI
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (LLVM_HAS_RTTI)
message(STATUS " LLVM built with RTTI: ${LLVM_HAS_RTTI}")
endif()
endif()
set(LLVM_VERSION "${LLVM_VERSION}" CACHE STRING "LLVM version")
mark_as_advanced(LLVM_INCLUDE_DIRS LLVM_LIBRARY_DIRS LLVM_CFLAGS LLVM_LFLAGS LLVM_MODULE_LIBS LLVM_LIBS LLVM_DEFINITIONS)