diff --git a/qbs/imports/QtcClangInstallation/functions.js b/qbs/imports/QtcClangInstallation/functions.js index d2b9736f3b1..f00b109a63c 100644 --- a/qbs/imports/QtcClangInstallation/functions.js +++ b/qbs/imports/QtcClangInstallation/functions.js @@ -1,6 +1,17 @@ var File = loadExtension("qbs.File") +var MinimumLLVMVersion = "3.6.0" -function llvmConfig(qbs) +function isSuitableLLVMConfig(llvmConfigCandidate, qtcFunctions, processOutputReader) +{ + if (File.exists(llvmConfigCandidate)) { + var candidateVersion = version(llvmConfigCandidate, processOutputReader); + if (candidateVersion && candidateVersion.length) + return qtcFunctions.versionIsAtLeast(candidateVersion, MinimumLLVMVersion) + } + return false; +} + +function llvmConfig(qbs, qtcFunctions, processOutputReader) { var llvmInstallDirFromEnv = qbs.getEnv("LLVM_INSTALL_DIR") var llvmConfigVariants = [ @@ -12,7 +23,7 @@ function llvmConfig(qbs) if (llvmInstallDirFromEnv) { for (var i = 0; i < llvmConfigVariants.length; ++i) { var variant = llvmInstallDirFromEnv + "/bin/" + llvmConfigVariants[i]; - if (File.exists(variant)) + if (isSuitableLLVMConfig(variant, qtcFunctions, processOutputReader)) return variant; } } @@ -24,7 +35,7 @@ function llvmConfig(qbs) for (var i = 0; i < llvmConfigVariants.length; ++i) { for (var j = 0; j < pathList.length; ++j) { var variant = pathList[j] + "/" + llvmConfigVariants[i]; - if (File.exists(variant)) + if (isSuitableLLVMConfig(variant, qtcFunctions, processOutputReader)) return variant; } } diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index ad6d25dda0f..cc41d8ebd2d 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -1,6 +1,7 @@ import qbs import qbs.File import QtcClangInstallation as Clang +import QtcFunctions import QtcProcessOutputReader QtcPlugin { @@ -23,7 +24,7 @@ QtcPlugin { property bool clangHighlighting: true property bool clangIndexing: false - property string llvmConfig: Clang.llvmConfig(qbs) + property string llvmConfig: Clang.llvmConfig(qbs, QtcFunctions, QtcProcessOutputReader) property string llvmIncludeDir: Clang.includeDir(llvmConfig, QtcProcessOutputReader) property string llvmLibDir: Clang.libDir(llvmConfig, QtcProcessOutputReader) property string llvmLibs: Clang.libraries(qbs.targetOS) diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index 8a3df51e3d2..7ce74635ee5 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -3,6 +3,25 @@ LLVM_INSTALL_DIR = $$clean_path($$LLVM_INSTALL_DIR) isEmpty(LLVM_INSTALL_DIR): error("No LLVM_INSTALL_DIR provided") !exists($$LLVM_INSTALL_DIR): error("LLVM_INSTALL_DIR does not exist: $$LLVM_INSTALL_DIR") +defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+)$, \\1)) } +defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+$, \\1)) } +defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+$, \\1)) } + +defineTest(versionIsAtLeast) { + actual_major_version = $$extractMajorVersion($$1) + actual_minor_version = $$extractMinorVersion($$1) + required_min_major_version = $$2 + required_min_minor_version = $$3 + + isEqual(actual_major_version, $$required_min_major_version) { + isEqual(actual_minor_version, $$required_min_minor_version): return(true) + greaterThan(actual_minor_version, $$required_min_minor_version): return(true) + } + greaterThan(actual_major_version, $$required_min_major_version): return(true) + + return(false) +} + defineReplace(findLLVMVersionFromLibDir) { libdir = $$1 version_dirs = $$files($$libdir/clang/*) @@ -60,7 +79,7 @@ unix { LLVM_LIBDIR = $$system($$llvm_config --libdir 2>/dev/null) LLVM_INCLUDEPATH = $$system($$llvm_config --includedir 2>/dev/null) output = $$system($$llvm_config --version 2>/dev/null) - LLVM_VERSION = $$replace(output, ^(\\d+\\.\\d+\\.\\d+)$, \\1) + LLVM_VERSION = $$extractVersion($$output) } else { #message("llvm-config not found, concluding paths and version from LLVM_INSTALL_DIR") LLVM_INCLUDEPATH = $$LLVM_INSTALL_DIR/include @@ -70,9 +89,13 @@ unix { !exists($$LLVM_INCLUDEPATH): error("Cannot detect include dir for clang, candidate: $$LLVM_INCLUDEPATH") !exists($$LLVM_LIBDIR): error("Cannot detect lib dir for clang, candidate: $$LLVM_LIBDIR") - isEmpty(LLVM_VERSION): error("Cannot determine clang version at $$LLVM_INSTALL_DIR") clang_lib = $$findClangLibInLibDir($$LLVM_LIBDIR) isEmpty(clang_lib): error("Cannot find Clang shared library in $$LLVM_LIBDIR") LLVM_LIBS = -L$${LLVM_LIBDIR} -l$${clang_lib} } + +isEmpty(LLVM_VERSION): error("Cannot determine clang version at $$LLVM_INSTALL_DIR") +!versionIsAtLeast($$LLVM_VERSION, 3, 6): { + error("LLVM/Clang version >= 3.6.0 required, version provided: $$LLVM_VERSION") +} diff --git a/src/tools/clangbackend/clangbackend.qbs b/src/tools/clangbackend/clangbackend.qbs index 04499e75d04..c46534240d8 100644 --- a/src/tools/clangbackend/clangbackend.qbs +++ b/src/tools/clangbackend/clangbackend.qbs @@ -1,5 +1,6 @@ import qbs 1.0 import QtcClangInstallation as Clang +import QtcFunctions import QtcProcessOutputReader QtcTool { @@ -17,7 +18,7 @@ QtcTool { files: [ "clangbackendmain.cpp" ] - property string llvmConfig: Clang.llvmConfig(qbs) + property string llvmConfig: Clang.llvmConfig(qbs, QtcFunctions, QtcProcessOutputReader) property string llvmIncludeDir: Clang.includeDir(llvmConfig, QtcProcessOutputReader) property string llvmLibDir: Clang.libDir(llvmConfig, QtcProcessOutputReader) property string llvmLibs: Clang.libraries(qbs.targetOS)