summaryrefslogtreecommitdiffstats
path: root/mkspecs/features
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2016-03-03 13:12:47 +0100
committerMartin Smith <martin.smith@qt.io>2017-08-10 07:31:47 +0000
commitb032aee53c8fb6807485186f276ca25b86ac1251 (patch)
treea23ca6f0a1e2d13b2629299a49234035b1fb3863 /mkspecs/features
parent3c74e2594595f06b3e07f441b254ee7f57b2c770 (diff)
Use clang as a parser in qdoc
The file qt_find_clang.prf is inspired by qtcreator's clang_installation.pri. The code from the while loop in ClangVisitor::parseProperty contains code moved from CppCodeParser::matchProperty. The code in the for loop of ClangCodeParser::parseSourceFile (from the "Doc parses the comment"), is mostly moved from CppCodeParser::matchDocsAndStuff. In CppCodeParser, most of the code is removed since clang is used for parsing. We just need to leave enough to parse the declaration in the comments which still use the old parser (\fn, ...) Known issues: - When the parameter name is a comment, it is lost. (e.g. QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) - I can't compute default parameters when they are expanded from a macro. (e.g. QObject::tr) - Instances of #ifndef Q_QDOC need to be reviewed Change-Id: I92d4ca4fc52810d9d3de433147a9953eea3a1802 Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io>
Diffstat (limited to 'mkspecs/features')
-rw-r--r--mkspecs/features/qt_find_clang.prf100
1 files changed, 100 insertions, 0 deletions
diff --git a/mkspecs/features/qt_find_clang.prf b/mkspecs/features/qt_find_clang.prf
new file mode 100644
index 000000000..14a2e80bf
--- /dev/null
+++ b/mkspecs/features/qt_find_clang.prf
@@ -0,0 +1,100 @@
+config_clang_done: return()
+
+defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+)(svn)?$, \\1)) }
+defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+(svn)?$, \\1)) }
+defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+(svn)?$, \\1)) }
+defineReplace(extractPatchVersion) { return($$replace(1, ^\\d+\\.\\d+\\.(\\d+)(svn)?$, \\1)) }
+
+defineTest(versionIsAtLeast) {
+ actual_major_version = $$extractMajorVersion($$1)
+ actual_minor_version = $$extractMinorVersion($$1)
+ actual_patch_version = $$extractPatchVersion($$1)
+ required_min_major_version = $$extractMajorVersion($$2)
+ required_min_minor_version = $$extractMinorVersion($$2)
+ required_min_patch_version = $$extractPatchVersion($$2)
+
+ isEqual(actual_major_version, $$required_min_major_version) {
+ isEqual(actual_minor_version, $$required_min_minor_version) {
+ isEqual(actual_patch_version, $$required_min_patch_version): return(true)
+ greaterThan(actual_patch_version, $$required_min_patch_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/*)
+ for (version_dir, version_dirs) {
+ fileName = $$basename(version_dir)
+ version = $$find(fileName, ^(\\d+\\.\\d+\\.\\d+)$)
+ !isEmpty(version) {
+ isEmpty(candidateVersion): candidateVersion = $$version
+ else: versionIsAtLeast($$version, $$candidateVersion): candidateVersion = $$version
+ }
+ }
+ return($$candidateVersion)
+}
+
+for(_, $$list(_)) { # just a way to break easily
+ isEmpty(CLANG_INSTALL_DIR): CLANG_INSTALL_DIR = $$(CLANG_INSTALL_DIR)
+ CLANG_INSTALL_DIR = $$clean_path($$CLANG_INSTALL_DIR)
+ clangInstallDir = $$CLANG_INSTALL_DIR
+ isEmpty(CLANG_INSTALL_DIR) {
+ win32 {
+ log("Set the CLANG_INSTALL_DIR environment variable to configure clang location.$$escape_expand(\\n)")
+ break()
+ }
+ clangInstallDir = /usr
+ }
+
+ # note: llvm_config only exits on unix
+ llvm_config = $$clangInstallDir/bin/llvm-config
+ exists($$llvm_config) {
+ CLANG_LIBDIR = $$system("$$llvm_config --libdir 2>/dev/null")
+ CLANG_INCLUDEPATH = $$system("$$llvm_config --includedir 2>/dev/null")
+ output = $$system("$$llvm_config --version 2>/dev/null")
+ CLANG_VERSION = $$extractVersion($$output)
+ } else {
+ CLANG_LIBDIR = $$clangInstallDir/lib
+ CLANG_INCLUDEPATH = $$clangInstallDir/include
+ CLANG_VERSION = $$findLLVMVersionFromLibDir($$CLANG_LIBDIR)
+ }
+ isEmpty(CLANG_VERSION) {
+ !isEmpty(CLANG_INSTALL_DIR): \
+ error("Cannot determine clang version at $${CLANG_INSTALL_DIR}.")
+ log("Set the CLANG_INSTALL_DIR environment variable to configure clang location.$$escape_expand(\\n)")
+ break()
+ }
+
+ LIBCLANG_MAIN_HEADER = $$CLANG_INCLUDEPATH/clang-c/Index.h
+ !exists($$LIBCLANG_MAIN_HEADER) {
+ !isEmpty(CLANG_INSTALL_DIR): \
+ error("Cannot find libclang's main header file, candidate: $${LIBCLANG_MAIN_HEADER}.")
+ log("Set the CLANG_INSTALL_DIR environment variable to configure clang location.$$escape_expand(\\n)")
+ break()
+ }
+
+ !contains(QMAKE_DEFAULT_LIBDIRS, $$CLANG_LIBDIR): CLANG_LIBS = -L$${CLANG_LIBDIR}
+ win32: \
+ CLANG_LIBS += -llibclang -ladvapi32 -lshell32
+ else: \
+ CLANG_LIBS += -lclang
+
+ !versionIsAtLeast($$CLANG_VERSION, "3.6.2") {
+ log("LLVM/Clang version >= 3.6.2 required, version provided: $$CLANG_VERSION.$$escape_expand(\\n)")
+ log("Clang was found in $$CLANG_INSTALL_DIR. Set the CLANG_INSTALL_DIR environment variable to override.$$escape_expand(\\n)")
+ break()
+ }
+
+ cache(CLANG_LIBS)
+ cache(CLANG_INCLUDEPATH)
+ cache(CLANG_LIBDIR)
+ cache(CLANG_VERSION)
+ cache(CONFIG, add, $$list(config_clang))
+}
+
+cache(CONFIG, add, $$list(config_clang_done))