forked from qt-creator/qt-creator
CMake: Move code to read CMakeCache.txt into CMakeItem class
Change-Id: Ie5d76a2b50007c80d68b2e97d3339a582afce469 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include <projectexplorer/kit.h>
|
#include <projectexplorer/kit.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
#include <utils/macroexpander.h>
|
#include <utils/macroexpander.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -219,6 +221,91 @@ CMakeConfigItem CMakeConfigItem::fromString(const QString &s)
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QByteArray trimCMakeCacheLine(const QByteArray &in) {
|
||||||
|
int start = 0;
|
||||||
|
while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t'))
|
||||||
|
++start;
|
||||||
|
|
||||||
|
return in.mid(start, in.count() - start - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArrayList splitCMakeCacheLine(const QByteArray &line) {
|
||||||
|
const int colonPos = line.indexOf(':');
|
||||||
|
if (colonPos < 0)
|
||||||
|
return QByteArrayList();
|
||||||
|
|
||||||
|
const int equalPos = line.indexOf('=', colonPos + 1);
|
||||||
|
if (equalPos < colonPos)
|
||||||
|
return QByteArrayList();
|
||||||
|
|
||||||
|
return QByteArrayList() << line.mid(0, colonPos)
|
||||||
|
<< line.mid(colonPos + 1, equalPos - colonPos - 1)
|
||||||
|
<< line.mid(equalPos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FileName &cacheFile, QString *errorMessage)
|
||||||
|
{
|
||||||
|
CMakeConfig result;
|
||||||
|
QFile cache(cacheFile.toString());
|
||||||
|
if (!cache.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
if (errorMessage)
|
||||||
|
*errorMessage = QCoreApplication::translate("CMakeProjectManager::CMakeConfigItem", "Failed to open %1 for reading.")
|
||||||
|
.arg(cacheFile.toUserOutput());
|
||||||
|
return CMakeConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QByteArray> advancedSet;
|
||||||
|
QMap<QByteArray, QByteArray> valuesMap;
|
||||||
|
QByteArray documentation;
|
||||||
|
while (!cache.atEnd()) {
|
||||||
|
const QByteArray line = trimCMakeCacheLine(cache.readLine());
|
||||||
|
|
||||||
|
if (line.isEmpty() || line.startsWith('#'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line.startsWith("//")) {
|
||||||
|
documentation = line.mid(2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArrayList pieces = splitCMakeCacheLine(line);
|
||||||
|
if (pieces.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QTC_ASSERT(pieces.count() == 3, continue);
|
||||||
|
const QByteArray key = pieces.at(0);
|
||||||
|
const QByteArray type = pieces.at(1);
|
||||||
|
const QByteArray value = pieces.at(2);
|
||||||
|
|
||||||
|
if (key.endsWith("-ADVANCED") && value == "1") {
|
||||||
|
advancedSet.insert(key.left(key.count() - 9 /* "-ADVANCED" */));
|
||||||
|
} else if (key.endsWith("-STRINGS") && CMakeConfigItem::typeStringToType(type) == CMakeConfigItem::INTERNAL) {
|
||||||
|
valuesMap[key.left(key.count() - 8) /* "-STRINGS" */] = value;
|
||||||
|
} else {
|
||||||
|
CMakeConfigItem::Type t = CMakeConfigItem::typeStringToType(type);
|
||||||
|
result << CMakeConfigItem(key, t, documentation, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set advanced flags:
|
||||||
|
for (int i = 0; i < result.count(); ++i) {
|
||||||
|
CMakeConfigItem &item = result[i];
|
||||||
|
item.isAdvanced = advancedSet.contains(item.key);
|
||||||
|
|
||||||
|
if (valuesMap.contains(item.key)) {
|
||||||
|
item.values = CMakeConfigItem::cmakeSplitValue(QString::fromUtf8(valuesMap[item.key]));
|
||||||
|
} else if (item.key == "CMAKE_BUILD_TYPE") {
|
||||||
|
// WA for known options
|
||||||
|
item.values << "" << "Debug" << "Release" << "MinSizeRel" << "RelWithDebInfo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::sort(result, CMakeConfigItem::sortOperator());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QString CMakeConfigItem::toString(const Utils::MacroExpander *expander) const
|
QString CMakeConfigItem::toString(const Utils::MacroExpander *expander) const
|
||||||
{
|
{
|
||||||
if (key.isEmpty() || type == CMakeProjectManager::CMakeConfigItem::STATIC)
|
if (key.isEmpty() || type == CMakeProjectManager::CMakeConfigItem::STATIC)
|
||||||
|
@@ -31,7 +31,10 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace ProjectExplorer { class Kit; }
|
namespace ProjectExplorer { class Kit; }
|
||||||
namespace Utils { class MacroExpander; }
|
namespace Utils {
|
||||||
|
class FileName;
|
||||||
|
class MacroExpander;
|
||||||
|
} // namespace Utils
|
||||||
|
|
||||||
namespace CMakeProjectManager {
|
namespace CMakeProjectManager {
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ public:
|
|||||||
|
|
||||||
static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator();
|
static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator();
|
||||||
static CMakeConfigItem fromString(const QString &s);
|
static CMakeConfigItem fromString(const QString &s);
|
||||||
|
static QList<CMakeConfigItem> itemsFromFile(const Utils::FileName &input, QString *errorMessage);
|
||||||
QString toString(const Utils::MacroExpander *expander = nullptr) const;
|
QString toString(const Utils::MacroExpander *expander = nullptr) const;
|
||||||
QString toArgument(const Utils::MacroExpander *expander = nullptr) const;
|
QString toArgument(const Utils::MacroExpander *expander = nullptr) const;
|
||||||
|
|
||||||
|
@@ -123,28 +123,6 @@ static QStringList toArguments(const CMakeConfig &config, const MacroExpander *e
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray trimCMakeCacheLine(const QByteArray &in) {
|
|
||||||
int start = 0;
|
|
||||||
while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t'))
|
|
||||||
++start;
|
|
||||||
|
|
||||||
return in.mid(start, in.count() - start - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QByteArrayList splitCMakeCacheLine(const QByteArray &line) {
|
|
||||||
const int colonPos = line.indexOf(':');
|
|
||||||
if (colonPos < 0)
|
|
||||||
return QByteArrayList();
|
|
||||||
|
|
||||||
const int equalPos = line.indexOf('=', colonPos + 1);
|
|
||||||
if (equalPos < colonPos)
|
|
||||||
return QByteArrayList();
|
|
||||||
|
|
||||||
return QByteArrayList() << line.mid(0, colonPos)
|
|
||||||
<< line.mid(colonPos + 1, equalPos - colonPos - 1)
|
|
||||||
<< line.mid(equalPos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// TeaLeafReader:
|
// TeaLeafReader:
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -242,7 +220,7 @@ CMakeConfig TeaLeafReader::parsedConfiguration() const
|
|||||||
if (!cacheFile.exists())
|
if (!cacheFile.exists())
|
||||||
return result;
|
return result;
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
m_cmakeCache = parseConfiguration(cacheFile, &errorMessage);
|
m_cmakeCache = CMakeConfigItem::itemsFromFile(cacheFile, &errorMessage);
|
||||||
if (!errorMessage.isEmpty())
|
if (!errorMessage.isEmpty())
|
||||||
emit errorOccured(errorMessage);
|
emit errorOccured(errorMessage);
|
||||||
const FileName sourceOfBuildDir
|
const FileName sourceOfBuildDir
|
||||||
@@ -257,67 +235,6 @@ CMakeConfig TeaLeafReader::parsedConfiguration() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeConfig TeaLeafReader::parseConfiguration(const FileName &cacheFile, QString *errorMessage) const
|
|
||||||
{
|
|
||||||
CMakeConfig result;
|
|
||||||
QFile cache(cacheFile.toString());
|
|
||||||
if (!cache.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
if (errorMessage)
|
|
||||||
*errorMessage = tr("Failed to open %1 for reading.").arg(cacheFile.toUserOutput());
|
|
||||||
return CMakeConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QByteArray> advancedSet;
|
|
||||||
QMap<QByteArray, QByteArray> valuesMap;
|
|
||||||
QByteArray documentation;
|
|
||||||
while (!cache.atEnd()) {
|
|
||||||
const QByteArray line = trimCMakeCacheLine(cache.readLine());
|
|
||||||
|
|
||||||
if (line.isEmpty() || line.startsWith('#'))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (line.startsWith("//")) {
|
|
||||||
documentation = line.mid(2);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArrayList pieces = splitCMakeCacheLine(line);
|
|
||||||
if (pieces.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QTC_ASSERT(pieces.count() == 3, continue);
|
|
||||||
const QByteArray key = pieces.at(0);
|
|
||||||
const QByteArray type = pieces.at(1);
|
|
||||||
const QByteArray value = pieces.at(2);
|
|
||||||
|
|
||||||
if (key.endsWith("-ADVANCED") && value == "1") {
|
|
||||||
advancedSet.insert(key.left(key.count() - 9 /* "-ADVANCED" */));
|
|
||||||
} else if (key.endsWith("-STRINGS") && CMakeConfigItem::typeStringToType(type) == CMakeConfigItem::INTERNAL) {
|
|
||||||
valuesMap[key.left(key.count() - 8) /* "-STRINGS" */] = value;
|
|
||||||
} else {
|
|
||||||
CMakeConfigItem::Type t = CMakeConfigItem::typeStringToType(type);
|
|
||||||
result << CMakeConfigItem(key, t, documentation, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set advanced flags:
|
|
||||||
for (int i = 0; i < result.count(); ++i) {
|
|
||||||
CMakeConfigItem &item = result[i];
|
|
||||||
item.isAdvanced = advancedSet.contains(item.key);
|
|
||||||
|
|
||||||
if (valuesMap.contains(item.key)) {
|
|
||||||
item.values = CMakeConfigItem::cmakeSplitValue(QString::fromUtf8(valuesMap[item.key]));
|
|
||||||
} else if (item.key == "CMAKE_BUILD_TYPE") {
|
|
||||||
// WA for known options
|
|
||||||
item.values << "" << "Debug" << "Release" << "MinSizeRel" << "RelWithDebInfo";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(result, CMakeConfigItem::sortOperator());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
|
void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
|
||||||
{
|
{
|
||||||
root->setDisplayName(m_projectName);
|
root->setDisplayName(m_projectName);
|
||||||
|
@@ -70,8 +70,6 @@ private:
|
|||||||
bool extractCXXFlagsFromMake(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
|
bool extractCXXFlagsFromMake(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
|
||||||
bool extractCXXFlagsFromNinja(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
|
bool extractCXXFlagsFromNinja(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
|
||||||
|
|
||||||
CMakeConfig parseConfiguration(const Utils::FileName &cacheFile, QString *errorMessage) const;
|
|
||||||
|
|
||||||
Utils::QtcProcess *m_cmakeProcess = nullptr;
|
Utils::QtcProcess *m_cmakeProcess = nullptr;
|
||||||
|
|
||||||
// For error reporting:
|
// For error reporting:
|
||||||
|
Reference in New Issue
Block a user