From c61c499970a25b2fc5d6e0fb7109afe9597b372b Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 18 Jun 2019 11:31:46 +0200 Subject: [PATCH] CMake: Add an option to override cmake reader type Add an option to override the cmake reader type that is going to be used. By default the reader type is "auto" for autodetection, but that can get changed in the cmaketools.xml settings file. Other supported options are "tealeaf", "servermode" or "fileapi" and that will force that reader. You can also set QTC_CMAKE_IGNORE_FILEAPI=1 in your environment to force creator to ignore the existence of fileapi support in all cmake tools. Change-Id: I2006616312090ce2909154dc1966f7a8eaa2949a Reviewed-by: Eike Ziller --- .../cmakeprojectmanager/builddirreader.cpp | 10 ++- src/plugins/cmakeprojectmanager/cmaketool.cpp | 70 +++++++++++++++++-- src/plugins/cmakeprojectmanager/cmaketool.h | 12 ++-- .../cmakeprojectmanager/fileapireader.cpp | 2 +- .../cmakeprojectmanager/servermodereader.cpp | 3 + .../cmakeprojectmanager/tealeafreader.cpp | 4 +- 6 files changed, 83 insertions(+), 18 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirreader.cpp b/src/plugins/cmakeprojectmanager/builddirreader.cpp index 6c71218ec7a..ca808d36fd0 100644 --- a/src/plugins/cmakeprojectmanager/builddirreader.cpp +++ b/src/plugins/cmakeprojectmanager/builddirreader.cpp @@ -44,11 +44,15 @@ std::unique_ptr BuildDirReader::createReader(const BuildDirParam { CMakeTool *cmake = p.cmakeTool(); QTC_ASSERT(p.isValid() && cmake, return {}); - if (cmake->hasFileApi()) + + switch (cmake->readerType()) { + case CMakeTool::FileApi: return std::make_unique(); - if (cmake->hasServerMode()) + case CMakeTool::ServerMode: return std::make_unique(); - return std::make_unique(); + default: + return std::make_unique(); + } } } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 47da660ab2b..d42bf9abf25 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -48,7 +48,7 @@ const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; - +const char CMAKE_INFORMATION_READERTYPE[] = "ReaderType"; bool CMakeTool::Generator::matches(const QString &n, const QString &ex) const { @@ -57,6 +57,40 @@ bool CMakeTool::Generator::matches(const QString &n, const QString &ex) const namespace Internal { +const char READER_TYPE_TEALEAF[] = "tealeaf"; +const char READER_TYPE_SERVERMODE[] = "servermode"; +const char READER_TYPE_FILEAPI[] = "fileapi"; + +static bool ignoreFileApi() +{ + static bool s_ignoreFileApi = qEnvironmentVariableIsSet("QTC_CMAKE_IGNORE_FILEAPI"); + return s_ignoreFileApi; +} + +static Utils::optional readerTypeFromString(const QString &input) +{ + if (input == READER_TYPE_TEALEAF) + return CMakeTool::TeaLeaf; + if (input == READER_TYPE_SERVERMODE) + return CMakeTool::ServerMode; + if (input == READER_TYPE_FILEAPI) + return ignoreFileApi() ? CMakeTool::ServerMode : CMakeTool::FileApi; + return {}; +} + +static QString readerTypeToString(const CMakeTool::ReaderType &type) +{ + switch (type) { + case CMakeTool::TeaLeaf: + return READER_TYPE_TEALEAF; + case CMakeTool::ServerMode: + return READER_TYPE_SERVERMODE; + case CMakeTool::FileApi: + return READER_TYPE_FILEAPI; + } + return QString(); +} + // -------------------------------------------------------------------- // CMakeIntrospectionData: // -------------------------------------------------------------------- @@ -104,6 +138,8 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString(); m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool(); m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool(); + m_readerType = Internal::readerTypeFromString( + map.value(CMAKE_INFORMATION_READERTYPE).toString()); //loading a CMakeTool from SDK is always autodetection if (!fromSdk) @@ -190,6 +226,9 @@ QVariantMap CMakeTool::toMap() const data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory); + if (m_readerType.has_value()) + data.insert(CMAKE_INFORMATION_READERTYPE, + Internal::readerTypeToString(m_readerType.value())); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); return data; } @@ -301,6 +340,22 @@ CMakeTool::PathMapper CMakeTool::pathMapper() const return [](const Utils::FilePath &fn) { return fn; }; } +CMakeTool::ReaderType CMakeTool::readerType() const +{ + if (!m_readerType.has_value()) { + // Find best possible reader type: + if (hasFileApi()) { + if (hasServerMode() && Internal::ignoreFileApi()) + return ServerMode; // We were asked to fall back to server mode + return FileApi; + } + if (hasServerMode()) + return ServerMode; + return TeaLeaf; + } + return m_readerType.value(); +} + void CMakeTool::readInformation(CMakeTool::QueryType type) const { if ((type == QueryType::GENERATORS && !m_introspection->m_generators.isEmpty()) @@ -343,10 +398,10 @@ static QStringList parseDefinition(const QString &definition) ignoreWord = true; } - if (c == ' ' || c == '[' || c == '<' || c == '(' - || c == ']' || c == '>' || c == ')') { + if (c == ' ' || c == '[' || c == '<' || c == '(' || c == ']' || c == '>' || c == ')') { if (!ignoreWord && !word.isEmpty()) { - if (result.isEmpty() || Utils::allOf(word, [](const QChar &c) { return c.isUpper() || c == '_'; })) + if (result.isEmpty() + || Utils::allOf(word, [](const QChar &c) { return c.isUpper() || c == '_'; })) result.append(word); } word.clear(); @@ -403,11 +458,12 @@ QStringList CMakeTool::parseVariableOutput(const QString &output) QStringList result; foreach (const QString &v, variableList) { if (v.startsWith("CMAKE_COMPILER_IS_GNU")) { // This key takes a compiler name :-/ - result << "CMAKE_COMPILER_IS_GNUCC" << "CMAKE_COMPILER_IS_GNUCXX"; + result << "CMAKE_COMPILER_IS_GNUCC" + << "CMAKE_COMPILER_IS_GNUCXX"; } else if (v.contains("")) { const QString tmp = QString(v).replace("", "%1"); - result << tmp.arg("DEBUG") << tmp.arg("RELEASE") - << tmp.arg("MINSIZEREL") << tmp.arg("RELWITHDEBINFO"); + result << tmp.arg("DEBUG") << tmp.arg("RELEASE") << tmp.arg("MINSIZEREL") + << tmp.arg("RELWITHDEBINFO"); } else if (v.contains("")) { const QString tmp = QString(v).replace("", "%1"); result << tmp.arg("C") << tmp.arg("CXX"); diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 73044d8ba40..c8c29665c2f 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -48,10 +49,9 @@ namespace Internal { class IntrospectionData; } class CMAKE_EXPORT CMakeTool { public: - enum Detection { - ManualDetection, - AutoDetection - }; + enum Detection { ManualDetection, AutoDetection }; + + enum ReaderType { TeaLeaf, ServerMode, FileApi }; struct Version { @@ -110,6 +110,8 @@ public: void setPathMapper(const PathMapper &includePathMapper); PathMapper pathMapper() const; + ReaderType readerType() const; + private: enum class QueryType { GENERATORS, @@ -137,6 +139,8 @@ private: bool m_isAutoDetected = false; bool m_autoCreateBuildDirectory = false; + Utils::optional m_readerType; + std::unique_ptr m_introspection; PathMapper m_pathMapper; diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp index 957ebaaea0a..e98f2c9c118 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.cpp +++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp @@ -107,7 +107,7 @@ void FileApiReader::setParameters(const BuildDirParameters &p) bool FileApiReader::isCompatible(const BuildDirParameters &p) { const CMakeTool *cmakeTool = p.cmakeTool(); - return cmakeTool && cmakeTool->hasFileApi(); + return cmakeTool && cmakeTool->readerType() == CMakeTool::FileApi; } void FileApiReader::resetData() diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index d4104dbe1df..77f2cd8cb4c 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -109,6 +109,9 @@ void ServerModeReader::setParameters(const BuildDirParameters &p) bool ServerModeReader::isCompatible(const BuildDirParameters &p) { CMakeTool *newCmake = p.cmakeTool(); + if (newCmake->readerType() != CMakeTool::FileApi) + return false; + CMakeTool *oldCmake = m_parameters.cmakeTool(); if (!newCmake || !oldCmake) return false; diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 4e355a003c9..264f97daceb 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -135,9 +135,7 @@ void TeaLeafReader::setParameters(const BuildDirParameters &p) bool TeaLeafReader::isCompatible(const BuildDirParameters &p) { - if (!p.cmakeTool()) - return false; - return !p.cmakeTool()->hasServerMode(); + return p.cmakeTool() && p.cmakeTool()->readerType() == CMakeTool::TeaLeaf; } void TeaLeafReader::resetData()