aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-06-21 13:58:49 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-06-23 06:49:09 +0000
commitf0179e7e9c19415f1142b366a248ecfce09ad006 (patch)
tree301a65550c8e5bb977fc4431c97ac7d170b72bb4
parentcf4dc77a973fa488594a818381cc9f0941a4f940 (diff)
shiboken: Search for Clang builtin-includes at runtime
Replace the search executed at build time by CMake by a run time search in shiboken since the location at build time typically won't match any more for the deployment case. Task-number: PYSIDE-693 Change-Id: Ib15fbba5d8c3fecf30aaae7195b88a648a7ed0fe Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt7
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp91
-rw-r--r--sources/shiboken2/CMakeLists.txt40
3 files changed, 82 insertions, 56 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt
index a3301a068..b67a352f0 100644
--- a/sources/shiboken2/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -31,13 +31,6 @@ add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
add_definitions(-DRXX_ALLOCATOR_INIT_0)
-# Pass the path to the clang includes dir, so it headers like stdarg.h.
-if(UNIX AND NOT APPLE)
- add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="${CLANG_BUILTIN_INCLUDES_DIR}")
-else()
- add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="")
-endif()
-
set(apiextractor_SRC
apiextractor.cpp
abstractmetabuilder.cpp
diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
index e7de8fdb3..9f4f7dc03 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
@@ -29,8 +29,14 @@
#include "compilersupport.h"
#include "header_paths.h"
+#include <reporthandler.h>
+
#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
+#include <QtCore/QStandardPaths>
#include <QtCore/QStringList>
#include <QtCore/QVersionNumber>
@@ -155,6 +161,68 @@ static inline bool isRedHat74()
static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); }
#endif
+// The clang builtin includes directory is used to find the definitions for
+// intrinsic functions and builtin types. It is necessary to use the clang
+// includes to prevent redefinition errors. The default toolchain includes
+// should be picked up automatically by clang without specifying
+// them implicitly.
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+# define NEED_CLANG_BUILTIN_INCLUDES 1
+#else
+# define NEED_CLANG_BUILTIN_INCLUDES 0
+#endif
+
+#if NEED_CLANG_BUILTIN_INCLUDES
+static QString findClang()
+{
+ for (const char *envVar : {"LLVM_INSTALL_DIR", "CLANG_INSTALL_DIR"}) {
+ if (qEnvironmentVariableIsSet(envVar)) {
+ const QString path = QFile::decodeName(qgetenv(envVar));
+ if (QFileInfo::exists(path))
+ return path;
+ }
+ }
+ const QString llvmConfig =
+ QStandardPaths::findExecutable(QLatin1String("llvm-config"));
+ if (!llvmConfig.isEmpty()) {
+ QByteArray stdOut;
+ if (runProcess(llvmConfig, QStringList{QLatin1String("--prefix")}, &stdOut)) {
+ const QString path = QFile::decodeName(stdOut.trimmed());
+ if (QFileInfo::exists(path))
+ return path;
+ }
+ }
+ return QString();
+}
+
+static QString findClangBuiltInIncludesDir()
+{
+ // Find the include directory of the highest version.
+ const QString clangPath = findClang();
+ if (!clangPath.isEmpty()) {
+ QString candidate;
+ QVersionNumber lastVersionNumber(1, 0, 0);
+ QDir clangDir(clangPath + QLatin1String("/lib/clang"));
+ const QFileInfoList versionDirs =
+ clangDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ for (const QFileInfo &fi : versionDirs) {
+ const QString fileName = fi.fileName();
+ if (fileName.at(0).isDigit()) {
+ const QVersionNumber versionNumber = QVersionNumber::fromString(fileName.at(0));
+ if (!versionNumber.isNull() && versionNumber > lastVersionNumber) {
+ candidate = fi.absoluteFilePath();
+ lastVersionNumber = versionNumber;
+ }
+ }
+ }
+ if (!candidate.isEmpty())
+ return candidate + QStringLiteral("/include");
+ }
+ return QString();
+}
+#endif // NEED_CLANG_BUILTIN_INCLUDES
+
// Returns clang options needed for emulating the host compiler
QByteArrayList emulatedCompilerOptions()
{
@@ -169,16 +237,21 @@ QByteArrayList emulatedCompilerOptions()
#elif defined(Q_CC_GNU)
HeaderPaths headerPaths;
- // The clang builtin includes directory is used to find the definitions for intrinsic functions
- // and builtin types. It is necessary to use the clang includes to prevent redefinition errors.
- // The default toolchain includes should be picked up automatically by clang without specifying
- // them implicitly.
- QByteArray clangBuiltinIncludesDir(CLANG_BUILTIN_INCLUDES_DIR);
-
- if (!clangBuiltinIncludesDir.isEmpty()) {
- result.append(QByteArrayLiteral("-isystem"));
- result.append(clangBuiltinIncludesDir);
+#if NEED_CLANG_BUILTIN_INCLUDES
+ const QString clangBuiltinIncludesDir =
+ QDir::toNativeSeparators(findClangBuiltInIncludesDir());
+ if (clangBuiltinIncludesDir.isEmpty()) {
+ qCWarning(lcShiboken, "Unable to locate Clang's built-in include directory "
+ "(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR "
+ " nor running llvm-config). This may lead to parse errors.");
+ } else {
+ qCInfo(lcShiboken, "CLANG builtins includes directory: %s",
+ qPrintable(clangBuiltinIncludesDir));
+ headerPaths.append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir),
+ HeaderType::System});
}
+#endif // NEED_CLANG_BUILTIN_INCLUDES
+
// Append the c++ include paths since Clang is unable to find <list> etc
// on RHEL 7.4 with g++ 6.3. A fix for this has been added to Clang 5.0,
// so, the code can be removed once Clang 5.0 is the minimum version.
diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt
index 852e14c1a..1af84fca1 100644
--- a/sources/shiboken2/CMakeLists.txt
+++ b/sources/shiboken2/CMakeLists.txt
@@ -113,46 +113,6 @@ endif()
message(STATUS "CLANG: ${CLANG_DIR}, ${CLANG_LIBRARY} detected by ${CLANG_DIR_SOURCE}")
-# Find highest version clang builtin includes folder to pass along to shiboken.
-set(CLANG_BUILTIN_INCLUDES_DIR_PREFIX ${CLANG_DIR}/lib/clang)
-file(GLOB CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES "${CLANG_BUILTIN_INCLUDES_DIR_PREFIX}/*")
-
-# Collect only directories, and not files, and only directories starting with a number.
-set(CLANG_BUILTIN_INCLUDES_DIR_VERSIONS "")
-foreach(candidate ${CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES})
- get_filename_component(candidate_basename ${candidate} NAME)
- if (IS_DIRECTORY ${candidate} AND ${candidate_basename} MATCHES "^[0-9]") # starts with number
- list(APPEND CLANG_BUILTIN_INCLUDES_DIR_VERSIONS ${candidate})
- endif()
-endforeach()
-
-# Sort in alphabetical order the list of version folders.
-list(SORT CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
-
-# Reverse it so the first element is the highest version.
-list(REVERSE CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
-
-message(STATUS
- "Found the following CLANG builtins includes directories: ${CLANG_BUILTIN_INCLUDES_DIR_VERSIONS} \
- Considered the following directories: ${CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES}")
-if(CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
- # Get highest version.
- list(GET CLANG_BUILTIN_INCLUDES_DIR_VERSIONS 0 CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION)
- if (CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION)
- # Set the final variable to the full include path to pass along to shiboken.
- set(CLANG_BUILTIN_INCLUDES_DIR "${CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION}/include")
- endif()
-endif()
-
-message(STATUS "CLANG builtins includes directory chosen: ${CLANG_BUILTIN_INCLUDES_DIR}")
-
-# We don't exit with a hard error here, because it is uncertain whether all clang extra include
-# paths follow the same layout across OSes and distros.
-if (NOT CLANG_BUILTIN_INCLUDES_DIR)
- message(WARNING "No CLANG builtins includes directory found. This may lead to shiboken \
- execution failure.")
-endif()
-
set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include)
set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY})