diff --git a/find-modules/FindClang.cmake b/find-modules/FindClang.cmake new file mode 100644 --- /dev/null +++ b/find-modules/FindClang.cmake @@ -0,0 +1,118 @@ +# Detect Clang libraries +# +# Defines the following variables: +# CLANG_FOUND - True if Clang was found +# CLANG_INCLUDE_DIRS - Where to find Clang includes +# CLANG_LIBRARY_DIRS - Where to find Clang libraries +# +# CLANG_LIBCLANG_LIB - Libclang C library +# +# CLANG_CLANGFRONTEND_LIB - Clang Frontend (C++) Library +# CLANG_CLANGDRIVER_LIB - Clang Driver (C++) Library +# ... +# +# CLANG_LIBS - All the Clang C++ libraries +# +# Uses the same include and library paths detected by FindLLVM.cmake +# +# See http://clang.llvm.org/docs/InternalsManual.html for full list of libraries + +#============================================================================= +# Copyright 2014-2015 Kevin Funk +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. + +#============================================================================= + +set(KNOWN_VERSIONS 4.0 3.9 3.8 3.7 3.6 3.5) + +foreach(version ${KNOWN_VERSIONS}) + if (LLVM_DIR OR (DEFINED Clang_FIND_VERSION AND Clang_FIND_VERSION VERSION_GREATER version)) + break() + endif () + + if (${Clang_FIND_REQUIRED}) + find_package(LLVM ${version} REQUIRED) + else () + find_package(LLVM ${version}) + endif () +endforeach() + +set(CLANG_FOUND FALSE) + +if (LLVM_FOUND AND LLVM_LIBRARY_DIRS) + macro(FIND_AND_ADD_CLANG_LIB _libname_) + string(TOUPPER ${_libname_} _prettylibname_) + find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_} HINTS ${LLVM_LIBRARY_DIRS}) + if(CLANG_${_prettylibname_}_LIB) + set(CLANG_LIBS ${CLANG_LIBS} ${CLANG_${_prettylibname_}_LIB}) + endif() + endmacro(FIND_AND_ADD_CLANG_LIB) + + # note: On Windows there's 'libclang.dll' instead of 'clang.dll' -> search for 'libclang', too + find_library(CLANG_LIBCLANG_LIB NAMES clang libclang HINTS ${LLVM_LIBRARY_DIRS}) # LibClang: high-level C interface + + FIND_AND_ADD_CLANG_LIB(clangFrontend) + FIND_AND_ADD_CLANG_LIB(clangDriver) + FIND_AND_ADD_CLANG_LIB(clangCodeGen) + FIND_AND_ADD_CLANG_LIB(clangSema) + FIND_AND_ADD_CLANG_LIB(clangChecker) + FIND_AND_ADD_CLANG_LIB(clangAnalysis) + FIND_AND_ADD_CLANG_LIB(clangRewriteFrontend) + FIND_AND_ADD_CLANG_LIB(clangRewrite) + FIND_AND_ADD_CLANG_LIB(clangAST) + FIND_AND_ADD_CLANG_LIB(clangParse) + FIND_AND_ADD_CLANG_LIB(clangLex) + FIND_AND_ADD_CLANG_LIB(clangBasic) + FIND_AND_ADD_CLANG_LIB(clangARCMigrate) + FIND_AND_ADD_CLANG_LIB(clangEdit) + FIND_AND_ADD_CLANG_LIB(clangFrontendTool) + FIND_AND_ADD_CLANG_LIB(clangRewrite) + FIND_AND_ADD_CLANG_LIB(clangSerialization) + FIND_AND_ADD_CLANG_LIB(clangTooling) + FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerCheckers) + FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerCore) + FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerFrontend) + FIND_AND_ADD_CLANG_LIB(clangSema) + FIND_AND_ADD_CLANG_LIB(clangRewriteCore) +endif() + +if(CLANG_LIBS OR CLANG_LIBCLANG_LIB) + set(CLANG_FOUND TRUE) +else() + message(STATUS "Could not find any Clang libraries in ${LLVM_LIBRARY_DIRS}") +endif() + +if(CLANG_FOUND) + set(CLANG_LIBRARY_DIRS ${LLVM_LIBRARY_DIRS}) + set(CLANG_INCLUDE_DIRS ${LLVM_INCLUDE_DIRS}) + + # check whether llvm-config comes from an install prefix + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --src-root + OUTPUT_VARIABLE _llvmSourceRoot + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + string(FIND "${LLVM_INCLUDE_DIRS}" "${_llvmSourceRoot}" _llvmIsInstalled) + if (NOT _llvmIsInstalled) + message(STATUS "Detected that llvm-config comes from a build-tree, adding more include directories for Clang") + list(APPEND CLANG_INCLUDE_DIRS + "${LLVM_INSTALL_PREFIX}/tools/clang/include" # build dir + "${_llvmSourceRoot}/tools/clang/include" # source dir + ) + endif() + + message(STATUS "Found Clang (LLVM version: ${LLVM_VERSION})") + message(STATUS " Include dirs: ${CLANG_INCLUDE_DIRS}") + message(STATUS " Clang libraries: ${CLANG_LIBS}") + message(STATUS " Libclang C library: ${CLANG_LIBCLANG_LIB}") +else() + if(Clang_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find Clang") + endif() +endif() diff --git a/find-modules/FindLLVM.cmake b/find-modules/FindLLVM.cmake new file mode 100644 --- /dev/null +++ b/find-modules/FindLLVM.cmake @@ -0,0 +1,157 @@ +# 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. + +#============================================================================= +# Copyright 2014 Kevin Funk +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +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) +elseif (NOT LLVM_CONFIG_EXECUTABLE) + # find llvm-config, prefer the one with a version suffix, e.g. llvm-config-3.5 + # note: FreeBSD installs llvm-config as llvm-config35 and so on + # note: on some distributions, only 'llvm-config' is shipped, so let's always try to fallback on that + 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 DOC "llvm-config executable") + + # other distributions don't ship llvm-config, but only some llvm-config-VERSION binary + # try to deduce installed LLVM version by looking up llvm-nm in PATH and *then* find llvm-config-VERSION via that + 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_EXECUTABLE}") + unset(LLVM_CONFIG_EXECUTABLE CACHE) + elseif (LLVM_FIND_VERSION VERSION_GREATER LLVM_VERSION) + set(_LLVM_ERROR_MESSAGE "${LLVM_CONFIG_EXECUTABLE} (version ${LLVM_VERSION}) unsuitable: too old for requested version ${LLVM_FIND_VERSION}") + unset(LLVM_CONFIG_EXECUTABLE CACHE) + 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 + ) + + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --prefix + OUTPUT_VARIABLE LLVM_INSTALL_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if (NOT ${LLVM_VERSION} VERSION_LESS "3.8.0") + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --shared-mode + OUTPUT_VARIABLE _LLVM_SHARED_MODE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if (_LLVM_SHARED_MODE STREQUAL "shared") + set(LLVM_SHARED_MODE ON) + else() + set(LLVM_SHARED_MODE OFF) + endif() + else() + set(LLVM_SHARED_MODE OFF) + endif() + + # potentially add include dir from binary dir for non-installed LLVM + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --src-root + 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() +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}") +endif() diff --git a/find-modules/FindPythonModuleGeneration.cmake b/find-modules/FindPythonModuleGeneration.cmake --- a/find-modules/FindPythonModuleGeneration.cmake +++ b/find-modules/FindPythonModuleGeneration.cmake @@ -179,28 +179,14 @@ endif() if (NOT libclang_LIBRARY) - set(_LIBCLANG_MAX_MAJOR_VERSION 7) - set(_LIBCLANG_MIN_MAJOR_VERSION 4) - - find_library(libclang_LIBRARY clang-${_LIBCLANG_MAX_MAJOR_VERSION}.0) - - if (libclang_LIBRARY) - message(FATAL_ERROR "The max libclang version in ${CMAKE_FIND_PACKAGE_NAME} must be updated.") - endif() - - set(_LIBCLANG_FIND_VERSION ${_LIBCLANG_MAX_MAJOR_VERSION}) - while(NOT libclang_LIBRARY AND NOT _LIBCLANG_FIND_VERSION EQUAL _LIBCLANG_MIN_MAJOR_VERSION) - math(EXPR _LIBCLANG_FIND_VERSION "${_LIBCLANG_FIND_VERSION} - 1") - set(_GPB_CLANG_SUFFIX ${_LIBCLANG_FIND_VERSION}.0) - find_library(libclang_LIBRARY clang-${_LIBCLANG_FIND_VERSION}.0) - endwhile() + find_package(Clang 3.8) + set_package_properties(Clang PROPERTIES + DESCRIPTION "Clang C library: libclang" + PURPOSE "Needed to generate the Python bindings for KDE Frameworks" + TYPE REQUIRED + ) - if (NOT libclang_LIBRARY) - find_library(libclang_LIBRARY clang-3.9) - if (NOT libclang_LIBRARY) - find_library(libclang_LIBRARY clang-3.8) - endif() - endif() + set(libclang_LIBRARY ${CLANG_LIBCLANG_LIB}) else() string(REGEX MATCH ".*clang-([0-9]+\\.[0-9]+).*" _GPB_CLANG_SUFFIX ${libclang_LIBRARY}) set(_GPB_CLANG_SUFFIX ${CMAKE_MATCH_1})