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 <eike.ziller@qt.io>
This commit is contained in:
Tobias Hunger
2019-06-18 11:31:46 +02:00
parent a95eb53d3b
commit c61c499970
6 changed files with 83 additions and 18 deletions

View File

@@ -44,11 +44,15 @@ std::unique_ptr<BuildDirReader> 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<FileApiReader>();
if (cmake->hasServerMode())
case CMakeTool::ServerMode:
return std::make_unique<ServerModeReader>();
default:
return std::make_unique<TeaLeafReader>();
}
}
} // namespace Internal

View File

@@ -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<CMakeTool::ReaderType> 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<LANG>")) { // 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("<CONFIG>")) {
const QString tmp = QString(v).replace("<CONFIG>", "%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("<LANG>")) {
const QString tmp = QString(v).replace("<LANG>", "%1");
result << tmp.arg("C") << tmp.arg("CXX");

View File

@@ -31,6 +31,7 @@
#include <texteditor/codeassist/keywordscompletionassist.h>
#include <utils/fileutils.h>
#include <utils/optional.h>
#include <utils/synchronousprocess.h>
#include <QObject>
@@ -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<ReaderType> m_readerType;
std::unique_ptr<Internal::IntrospectionData> m_introspection;
PathMapper m_pathMapper;

View File

@@ -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()

View File

@@ -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;

View File

@@ -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()