CMake: Parse Generators out of new cmake -E capabilities output

Makes for way more robust (and featureful) generator discovery.

Change-Id: I7df837500e1c3a200960e9d157b5c105dacd4068
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Tobias Hunger
2016-09-28 15:18:29 +02:00
parent b3b6cfb5ef
commit 3ef11019e2
2 changed files with 43 additions and 14 deletions

View File

@@ -31,6 +31,8 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QFileInfo> #include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QProcess> #include <QProcess>
#include <QSet> #include <QSet>
#include <QTextDocument> #include <QTextDocument>
@@ -110,7 +112,7 @@ bool CMakeTool::isValid() const
return m_didRun; return m_didRun;
} }
Utils::SynchronousProcessResponse CMakeTool::run(const QString &arg) const Utils::SynchronousProcessResponse CMakeTool::run(const QStringList &args, bool mayFail) const
{ {
if (m_didAttemptToRun && !m_didRun) { if (m_didAttemptToRun && !m_didRun) {
Utils::SynchronousProcessResponse response; Utils::SynchronousProcessResponse response;
@@ -126,9 +128,9 @@ Utils::SynchronousProcessResponse CMakeTool::run(const QString &arg) const
cmake.setProcessEnvironment(env.toProcessEnvironment()); cmake.setProcessEnvironment(env.toProcessEnvironment());
cmake.setTimeOutMessageBoxEnabled(false); cmake.setTimeOutMessageBoxEnabled(false);
Utils::SynchronousProcessResponse response = cmake.runBlocking(m_executable.toString(), QStringList() << arg); Utils::SynchronousProcessResponse response = cmake.runBlocking(m_executable.toString(), args);
m_didAttemptToRun = true; m_didAttemptToRun = true;
m_didRun = (response.result == Utils::SynchronousProcessResponse::Finished); m_didRun = mayFail ? true : (response.result == Utils::SynchronousProcessResponse::Finished);
return response; return response;
} }
@@ -161,9 +163,12 @@ bool CMakeTool::isAutoRun() const
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
{ {
if (m_generators.isEmpty())
fetchGeneratorsFromCapabilities();
if (m_generators.isEmpty()) { if (m_generators.isEmpty()) {
fetchGeneratorsFromHelp(); fetchGeneratorsFromHelp();
} }
return m_generators; return m_generators;
} }
@@ -171,19 +176,19 @@ TextEditor::Keywords CMakeTool::keywords()
{ {
if (m_functions.isEmpty()) { if (m_functions.isEmpty()) {
Utils::SynchronousProcessResponse response; Utils::SynchronousProcessResponse response;
response = run("--help-command-list"); response = run({ "--help-command-list" });
if (response.result == Utils::SynchronousProcessResponse::Finished) if (response.result == Utils::SynchronousProcessResponse::Finished)
m_functions = response.stdOut().split('\n'); m_functions = response.stdOut().split('\n');
response = run("--help-commands"); response = run({ "--help-commands" });
if (response.result == Utils::SynchronousProcessResponse::Finished) if (response.result == Utils::SynchronousProcessResponse::Finished)
parseFunctionDetailsOutput(response.stdOut()); parseFunctionDetailsOutput(response.stdOut());
response = run("--help-property-list"); response = run({ "--help-property-list" });
if (response.result == Utils::SynchronousProcessResponse::Finished) if (response.result == Utils::SynchronousProcessResponse::Finished)
m_variables = parseVariableOutput(response.stdOut()); m_variables = parseVariableOutput(response.stdOut());
response = run("--help-variable-list"); response = run({ "--help-variable-list" });
if (response.result == Utils::SynchronousProcessResponse::Finished) { if (response.result == Utils::SynchronousProcessResponse::Finished) {
m_variables.append(parseVariableOutput(response.stdOut())); m_variables.append(parseVariableOutput(response.stdOut()));
m_variables = Utils::filteredUnique(m_variables); m_variables = Utils::filteredUnique(m_variables);
@@ -315,7 +320,7 @@ QStringList CMakeTool::parseVariableOutput(const QString &output)
void CMakeTool::fetchGeneratorsFromHelp() const void CMakeTool::fetchGeneratorsFromHelp() const
{ {
Utils::SynchronousProcessResponse response = run("--help"); Utils::SynchronousProcessResponse response = run({ "--help" });
if (response.result != Utils::SynchronousProcessResponse::Finished) if (response.result != Utils::SynchronousProcessResponse::Finished)
return; return;
@@ -361,11 +366,29 @@ void CMakeTool::fetchGeneratorsFromHelp() const
} }
// Populate genertor list: // Populate genertor list:
for (auto it = generatorInfo.constBegin(); it != generatorInfo.constEnd(); ++it) { for (auto it = generatorInfo.constBegin(); it != generatorInfo.constEnd(); ++it)
Generator info; m_generators.append(Generator(it.key(), it.value()));
info.name = it.key(); }
info.extraGenerators = it.value();
m_generators.append(info); void CMakeTool::fetchGeneratorsFromCapabilities() const
{
Utils::SynchronousProcessResponse response = run({ "-E", "capabilities" }, true);
if (response.result != Utils::SynchronousProcessResponse::Finished)
return;
auto doc = QJsonDocument::fromJson(response.stdOut().toUtf8());
if (!doc.isObject())
return;
const QVariantMap data = doc.object().toVariantMap();
m_hasServerMode = data.value("serverMode").toBool();
const QVariantList generatorList = data.value("generators").toList();
for (const QVariant &v : generatorList) {
const QVariantMap gen = v.toMap();
m_generators.append(Generator(gen.value("name").toString(),
gen.value("extraGenerators").toStringList(),
gen.value("platformSupport").toBool(),
gen.value("toolsetSupport").toBool()));
} }
} }

View File

@@ -55,6 +55,10 @@ public:
class Generator class Generator
{ {
public: public:
Generator(const QString &n, const QStringList &eg, bool pl = true, bool ts = true) :
name(n), extraGenerators(eg), supportsPlatform(pl), supportsToolset(ts)
{ }
QString name; QString name;
QStringList extraGenerators; QStringList extraGenerators;
bool supportsPlatform = true; bool supportsPlatform = true;
@@ -92,11 +96,12 @@ public:
QString mapAllPaths(const ProjectExplorer::Kit *kit, const QString &in) const; QString mapAllPaths(const ProjectExplorer::Kit *kit, const QString &in) const;
private: private:
Utils::SynchronousProcessResponse run(const QString &arg) const; Utils::SynchronousProcessResponse run(const QStringList &args, bool mayFail = false) const;
void parseFunctionDetailsOutput(const QString &output); void parseFunctionDetailsOutput(const QString &output);
QStringList parseVariableOutput(const QString &output); QStringList parseVariableOutput(const QString &output);
void fetchGeneratorsFromHelp() const; void fetchGeneratorsFromHelp() const;
void fetchGeneratorsFromCapabilities() const;
Core::Id m_id; Core::Id m_id;
QString m_displayName; QString m_displayName;
@@ -107,6 +112,7 @@ private:
mutable bool m_didAttemptToRun = false; mutable bool m_didAttemptToRun = false;
mutable bool m_didRun = false; mutable bool m_didRun = false;
mutable bool m_hasServerMode = false;
mutable QList<Generator> m_generators; mutable QList<Generator> m_generators;
mutable QMap<QString, QStringList> m_functionArgs; mutable QMap<QString, QStringList> m_functionArgs;