diff --git a/README.md b/README.md index 4376e79d924..0aef21f25c3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ The installed toolchains have to match the one Qt was compiled with. You can build Qt Creator with - # Optional, needed for the Clang Code Model: + # Optional, needed for the Clang Code Model if llvm-config is not in PATH: export LLVM_INSTALL_DIR=/path/to/llvm (or "set" on Windows) # Optional, needed to let the QbsProjectManager plugin use system Qbs: export QBS_INSTALL_DIR=/path/to/qbs @@ -129,7 +129,7 @@ For detailed information on the supported compilers, see * Install LLVM/Clang - see the section "Get LLVM/Clang for the Clang Code Model". * Set the environment variable LLVM_INSTALL_DIR to the LLVM/Clang - installation directory. + installation directory if llvm-config is not in PATH. * When you launch Qt Creator, activate the Clang Code Model plugin as described in doc/src/editors/creator-clang-codemodel.qdoc. diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index 55a3bf45720..bd10d49e207 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -3,6 +3,8 @@ include(../../shared/clang/clang_installation.pri) include(../../shared/clang/clang_defines.pri) +requires(!isEmpty(LLVM_VERSION)) + SOURCES += \ clangactivationsequencecontextprocessor.cpp \ clangactivationsequenceprocessor.cpp \ diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index d1c774128bb..b01145d3a61 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -96,21 +96,15 @@ exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \ SUBDIRS += \ qbsprojectmanager -# prefer qmake variable set on command line over env var -isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) -exists($$LLVM_INSTALL_DIR) { - SUBDIRS += clangcodemodel +SUBDIRS += \ + clangcodemodel - QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) - isEmpty(QTC_NO_CLANG_LIBTOOLING) { - SUBDIRS += clangrefactoring - SUBDIRS += clangpchmanager - } else { - warning("Building the Clang refactoring and the pch manager plugins are disabled.") - } +QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) +isEmpty(QTC_NO_CLANG_LIBTOOLING) { + SUBDIRS += clangrefactoring + SUBDIRS += clangpchmanager } else { - warning("Set LLVM_INSTALL_DIR to build the Clang Code Model. " \ - "For details, see doc/src/editors/creator-clang-codemodel.qdoc.") + warning("Building the Clang refactoring and the pch manager plugins are disabled.") } isEmpty(IDE_PACKAGE_MODE) { diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index 572d0441b25..63ad0ad538c 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -1,7 +1,18 @@ isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) 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") + +!isEmpty(LLVM_INSTALL_DIR):!exists($$LLVM_INSTALL_DIR) { + error("Explicitly given LLVM_INSTALL_DIR does not exist: $$LLVM_INSTALL_DIR") +} + +defineReplace(llvmWarningOrError) { + warningText = $$1 + errorText = $$2 + isEmpty(errorText): errorText = $$warningText + isEmpty(LLVM_INSTALL_DIR): warning($$warningText) + else: error($$errorText) + return(false) +} # Expected input: "3.9.1", "5.0.0svn", "5.0.1git-81029f14223" defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+).*$, \\1)) } @@ -69,20 +80,6 @@ defineReplace(findClangLibInLibDir) { } } -defineReplace(findClangOnWindows) { - FILE_EXTS = a dll - msvc: FILE_EXTS = lib dll - for (suffix, $$list(lib bin)) { - for (libname, $$list(clang libclang)) { - for (ext, FILE_EXTS) { - exists("$${LLVM_INSTALL_DIR}/$${suffix}/$${libname}.$${ext}") { - return($${LLVM_INSTALL_DIR}/$${suffix}/) - } - } - } - } -} - CLANGTOOLING_LIBS=-lclangTooling -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \ -lclangASTMatchers -lclangToolingCore -lclangAST -lclangLex -lclangBasic @@ -91,65 +88,87 @@ win32:CLANGTOOLING_LIBS += -lversion BIN_EXTENSION = win32: BIN_EXTENSION = .exe -llvm_config = $$system_quote($$LLVM_INSTALL_DIR/bin/llvm-config) -requires(exists($$llvm_config$$BIN_EXTENSION)) -#message("llvm-config found, querying it for paths and version") -LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines)) -LLVM_INCLUDEPATH = $$system($$llvm_config --includedir, lines) +isEmpty(LLVM_INSTALL_DIR) { + llvm_config = llvm-config +} else { + llvm_config = $$system_quote($$LLVM_INSTALL_DIR/bin/llvm-config) + requires(exists($$llvm_config$$BIN_EXTENSION)) +} + output = $$system($$llvm_config --version, lines) LLVM_VERSION = $$extractVersion($$output) -msvc { - LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --libnames, lines) +isEmpty(LLVM_VERSION) { + $$llvmWarningOrError(\ + "Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\ + "LLVM_INSTALL_DIR does not contain a valid llvm-config, candidate: $$llvm_config") +} else:!versionIsAtLeast($$LLVM_VERSION, 5, 0, 0): { + # CLANG-UPGRADE-CHECK: Adapt minimum version numbers. + $$llvmWarningOrError(\ + "LLVM/Clang version >= 5.0.0 required, version provided: $$LLVM_VERSION") + LLVM_VERSION = } else { - LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --libs, lines) -} -LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --system-libs, lines) - -LLVM_STATIC_LIBS = $$split(LLVM_STATIC_LIBS_STRING, " ") - -LIBCLANG_MAIN_HEADER = $$LLVM_INCLUDEPATH/clang-c/Index.h -!exists($$LIBCLANG_MAIN_HEADER): error("Cannot find libclang's main header file, candidate: $$LIBCLANG_MAIN_HEADER") -!exists($$LLVM_LIBDIR): error("Cannot detect lib dir for clang, candidate: $$LLVM_LIBDIR") -CLANG_LIB = $$findClangLibInLibDir($$LLVM_LIBDIR) -isEmpty(CLANG_LIB): error("Cannot find Clang shared library in $$LLVM_LIBDIR") - -!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBCLANG_LIBS = -L$${LLVM_LIBDIR} -LIBCLANG_LIBS += $${CLANG_LIB} - -QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) -isEmpty(QTC_NO_CLANG_LIBTOOLING) { - QTC_FORCE_CLANG_LIBTOOLING = $$(QTC_FORCE_CLANG_LIBTOOLING) - versionIsEqual($$LLVM_VERSION, 5, 0)|!isEmpty(QTC_FORCE_CLANG_LIBTOOLING) { - !contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR} - LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS - contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH = + LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines)) + LLVM_BINDIR = $$quote($$system($$llvm_config --bindir, lines)) + LLVM_INCLUDEPATH = $$system($$llvm_config --includedir, lines) + msvc { + LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --libnames, lines) } else { - warning("Clang LibTooling is disabled because only version 5.0 is supported.") + LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --libs, lines) } -} else { - warning("Clang LibTooling is disabled.") + LLVM_STATIC_LIBS_STRING += $$system($$llvm_config --system-libs, lines) + + LLVM_STATIC_LIBS = $$split(LLVM_STATIC_LIBS_STRING, " ") + + LIBCLANG_MAIN_HEADER = $$LLVM_INCLUDEPATH/clang-c/Index.h + !exists($$LIBCLANG_MAIN_HEADER) { + $$llvmWarningOrError(\ + "Cannot find libclang's main header file, candidate: $$LIBCLANG_MAIN_HEADER") + } + !exists($$LLVM_LIBDIR) { + $$llvmWarningOrError("Cannot detect lib dir for clang, candidate: $$LLVM_LIBDIR") + } + !exists($$LLVM_BINDIR) { + $$llvmWarningOrError("Cannot detect bin dir for clang, candidate: $$LLVM_BINDIR") + } + CLANG_LIB = $$findClangLibInLibDir($$LLVM_LIBDIR) + isEmpty(CLANG_LIB) { + $$llvmWarningOrError("Cannot find Clang shared library in $$LLVM_LIBDIR") + } + + !contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBCLANG_LIBS = -L$${LLVM_LIBDIR} + LIBCLANG_LIBS += $${CLANG_LIB} + + QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) + isEmpty(QTC_NO_CLANG_LIBTOOLING) { + QTC_FORCE_CLANG_LIBTOOLING = $$(QTC_FORCE_CLANG_LIBTOOLING) + versionIsEqual($$LLVM_VERSION, 5, 0)|!isEmpty(QTC_FORCE_CLANG_LIBTOOLING) { + !contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR} + LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS + contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH = + } else { + warning("Clang LibTooling is disabled because only version 5.0 is supported.") + } + } else { + warning("Clang LibTooling is disabled.") + } + + # Remove unwanted flags. It is a workaround for linking. + # It is not intended for cross compiler linking. + LLVM_CXXFLAGS = $$system($$llvm_config --cxxflags, lines) + LLVM_CXXFLAGS ~= s,-fno-exceptions, + LLVM_CXXFLAGS ~= s,-std=c++11, + LLVM_CXXFLAGS ~= s,-std=c++0x, + LLVM_CXXFLAGS ~= s,-O\S*, + LLVM_CXXFLAGS ~= s,/O\S*, + LLVM_CXXFLAGS ~= s,/W4, + LLVM_CXXFLAGS ~= s,/EH\S*, + LLVM_CXXFLAGS ~= s,-Werror=date-time, + LLVM_CXXFLAGS ~= s,-Wcovered-switch-default, + LLVM_CXXFLAGS ~= s,-fPIC, + LLVM_CXXFLAGS ~= s,-pedantic, + LLVM_CXXFLAGS ~= s,-Wstring-conversion, + # split-dwarf needs objcopy which does not work via icecc out-of-the-box + LLVM_CXXFLAGS ~= s,-gsplit-dwarf, + + LLVM_IS_COMPILED_WITH_RTTI = $$system($$llvm_config --has-rtti, lines) } - -isEmpty(LLVM_VERSION): error("Cannot determine clang version at $$LLVM_INSTALL_DIR") -!versionIsAtLeast($$LLVM_VERSION, 5, 0, 0): { # CLANG-UPGRADE-CHECK: Adapt minimum version numbers. - error("LLVM/Clang version >= 5.0.0 required, version provided: $$LLVM_VERSION") -} - -# Remove unwanted flags. It is a workaround for linking. It is not intended for cross compiler linking. -LLVM_CXXFLAGS = $$system($$llvm_config --cxxflags, lines) -LLVM_CXXFLAGS ~= s,-fno-exceptions, -LLVM_CXXFLAGS ~= s,-std=c++11, -LLVM_CXXFLAGS ~= s,-std=c++0x, -LLVM_CXXFLAGS ~= s,-O\S*, -LLVM_CXXFLAGS ~= s,/O\S*, -LLVM_CXXFLAGS ~= s,/W4, -LLVM_CXXFLAGS ~= s,/EH\S*, -LLVM_CXXFLAGS ~= s,-Werror=date-time, -LLVM_CXXFLAGS ~= s,-Wcovered-switch-default, -LLVM_CXXFLAGS ~= s,-fPIC, -LLVM_CXXFLAGS ~= s,-pedantic, -LLVM_CXXFLAGS ~= s,-Wstring-conversion, -# split-dwarf needs objcopy which does not work via icecc out-of-the-box -LLVM_CXXFLAGS ~= s,-gsplit-dwarf, - -LLVM_IS_COMPILED_WITH_RTTI = $$system($$llvm_config --has-rtti, lines) diff --git a/src/tools/clangbackend/clangbackend.pro b/src/tools/clangbackend/clangbackend.pro index 32ca5f08422..3b7c5de518c 100644 --- a/src/tools/clangbackend/clangbackend.pro +++ b/src/tools/clangbackend/clangbackend.pro @@ -6,6 +6,8 @@ include(../../qtcreatortool.pri) include(../../shared/clang/clang_installation.pri) include(source/clangbackendclangipc-source.pri) +requires(!isEmpty(LLVM_VERSION)) + QT += core network QT -= gui diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro index 8dab349dd34..b54db0be04a 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro @@ -33,4 +33,4 @@ unix { !disable_external_rpath: QMAKE_LFLAGS += -Wl,-rpath,$$shell_quote($${LLVM_LIBDIR}) } -DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\" +DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($${LLVM_BINDIR}/clang)xxx\\\"\" diff --git a/src/tools/tools.pro b/src/tools/tools.pro index 23268020b79..9cd8728ef32 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -20,17 +20,14 @@ mac { SUBDIRS += iostool } -isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) -exists($$LLVM_INSTALL_DIR) { - SUBDIRS += clangbackend +SUBDIRS += clangbackend - QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) - isEmpty(QTC_NO_CLANG_LIBTOOLING) { - SUBDIRS += clangrefactoringbackend - SUBDIRS += clangpchmanagerbackend - } else { - warning("Building the Clang refactoring back end and the pch manager plugins are disabled.") - } +QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING) +isEmpty(QTC_NO_CLANG_LIBTOOLING) { + SUBDIRS += clangrefactoringbackend + SUBDIRS += clangpchmanagerbackend +} else { + warning("Building the Clang refactoring back end and the pch manager plugins are disabled.") } isEmpty(BUILD_CPLUSPLUS_TOOLS):BUILD_CPLUSPLUS_TOOLS=$$(BUILD_CPLUSPLUS_TOOLS) diff --git a/tests/tests.pro b/tests/tests.pro index a7c5bc6bd23..08d0e9438d0 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1,4 +1,2 @@ TEMPLATE=subdirs -SUBDIRS += auto manual tools -isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) -exists($$LLVM_INSTALL_DIR):SUBDIRS += unit +SUBDIRS += auto manual tools unit diff --git a/tests/unit/unittest/clang_dependency.pri b/tests/unit/unittest/clang_dependency.pri index bbce04a527a..9c2a3c57a3c 100644 --- a/tests/unit/unittest/clang_dependency.pri +++ b/tests/unit/unittest/clang_dependency.pri @@ -1,27 +1,26 @@ -isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) -!isEmpty(LLVM_INSTALL_DIR) { include(../../../src/shared/clang/clang_installation.pri) -requires(!isEmpty(LIBCLANG_LIBS)) -equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!") -requires(equals(LLVM_IS_COMPILED_WITH_RTTI, "YES")) +!isEmpty(LLVM_VERSION) { + requires(!isEmpty(LIBCLANG_LIBS)) + equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!") + requires(equals(LLVM_IS_COMPILED_WITH_RTTI, "YES")) -DEFINES += CLANG_UNIT_TESTS -INCLUDEPATH += $$LLVM_INCLUDEPATH -win32 { - LIBS += -lVersion + DEFINES += CLANG_UNIT_TESTS + INCLUDEPATH += $$LLVM_INCLUDEPATH + win32 { + LIBS += -lVersion - # set run path for clang.dll dependency - bin_path = $$LLVM_INSTALL_DIR/bin - bin_path ~= s,/,\\,g - # the below gets added to later by testcase.prf - check.commands = cd . & set PATH=$$bin_path;%PATH%& cmd /c + # set run path for clang.dll dependency + bin_path = $$LLVM_BINDIR + bin_path ~= s,/,\\,g + # the below gets added to later by testcase.prf + check.commands = cd . & set PATH=$$bin_path;%PATH%& cmd /c + } + + LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS + QMAKE_RPATHDIR += $$LLVM_LIBDIR + + LLVM_CXXFLAGS ~= s,-g\d?, + QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS + + DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_BINDIR/clang)xxx\\\"\" } - -LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS -QMAKE_RPATHDIR += $$LLVM_LIBDIR - -LLVM_CXXFLAGS ~= s,-g\d?, -QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS -} - -DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\" diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index f86f9e9967e..ae82403f00e 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -14,7 +14,7 @@ include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri) include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri) include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) include(cplusplus.pri) -!isEmpty(LLVM_INSTALL_DIR) { +!isEmpty(LLVM_VERSION) { include($$PWD/../../../src/shared/clang/clang_defines.pri) include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri) include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)