365 lines
13 KiB
Diff
365 lines
13 KiB
Diff
|
From 4fda68a948ee9e525ec6a5a5b08daaf9b32ac954 Mon Sep 17 00:00:00 2001
|
||
|
From: Heiko Becker <heirecka@exherbo.org>
|
||
|
Date: Tue, 4 Apr 2017 20:16:59 +0200
|
||
|
Subject: [PATCH] Import Find{Clang,LLVM} from KDevelop for Python bindings
|
||
|
generation
|
||
|
|
||
|
Summary:
|
||
|
On non Debian-based systems libclang is mostly installed as
|
||
|
libclang.so.<version>, evading detection by
|
||
|
clang-${_LIBCLANG_FIND_VERSION}.0. Instead of specyfing and maintaing
|
||
|
a list of library names I imported FindClang from KDevelop, which
|
||
|
finds the correct library here and, one would assume, also works on
|
||
|
Debian and distros based on it.
|
||
|
|
||
|
I didn't use ClangConfig.cmake from upstream because it doesn't allow
|
||
|
discovery of a certain version.
|
||
|
|
||
|
Test Plan: Successfully built kconfig with Python bindings
|
||
|
|
||
|
Reviewers: #frameworks, #build_system, skelly, kfunk
|
||
|
|
||
|
Subscribers: rdieter, shaheed, kde-buildsystem, lbeltrame
|
||
|
|
||
|
Tags: #frameworks, #build_system
|
||
|
|
||
|
Differential Revision: https://phabricator.kde.org/D5289
|
||
|
---
|
||
|
find-modules/FindClang.cmake | 118 +++++++++++++++++++
|
||
|
find-modules/FindLLVM.cmake | 157 ++++++++++++++++++++++++++
|
||
|
find-modules/FindPythonModuleGeneration.cmake | 28 ++---
|
||
|
3 files changed, 282 insertions(+), 21 deletions(-)
|
||
|
create mode 100644 find-modules/FindClang.cmake
|
||
|
create mode 100644 find-modules/FindLLVM.cmake
|
||
|
|
||
|
diff --git a/find-modules/FindClang.cmake b/find-modules/FindClang.cmake
|
||
|
new file mode 100644
|
||
|
index 0000000..2b539d2
|
||
|
--- /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 <kfunk@kde.org>
|
||
|
+#
|
||
|
+# 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
|
||
|
index 0000000..2d6085e
|
||
|
--- /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 <kfunk@kde.org>
|
||
|
+#
|
||
|
+# 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
|
||
|
index 012f806..7129b96 100644
|
||
|
--- a/find-modules/FindPythonModuleGeneration.cmake
|
||
|
+++ b/find-modules/FindPythonModuleGeneration.cmake
|
||
|
@@ -179,28 +179,14 @@ if (NOT GPB_PYTHON2_COMMAND)
|
||
|
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})
|
||
|
--
|
||
|
2.12.0
|
||
|
|