diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-06-21 13:58:49 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-06-23 06:49:09 +0000 |
commit | f0179e7e9c19415f1142b366a248ecfce09ad006 (patch) | |
tree | 301a65550c8e5bb977fc4431c97ac7d170b72bb4 /sources/shiboken2/ApiExtractor | |
parent | cf4dc77a973fa488594a818381cc9f0941a4f940 (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>
Diffstat (limited to 'sources/shiboken2/ApiExtractor')
-rw-r--r-- | sources/shiboken2/ApiExtractor/CMakeLists.txt | 7 | ||||
-rw-r--r-- | sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp | 91 |
2 files changed, 82 insertions, 16 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. |