forked from qt-creator/qt-creator
CMakePM: Add supprot for CMakePresets version 3
This includes Condition and toolchainFile https://cmake.org/cmake/help/v3.21/manual/cmake-presets.7.html Task-number: QTCREATORBUG-24555 Change-Id: I1026390af67b2be1aa0c3b02b654fc19442d3c89 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -1168,7 +1168,8 @@ static CommandLine defaultInitialCMakeCommand(const Kit *k, const QString buildT
|
|||||||
static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArguments,
|
static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArguments,
|
||||||
const CMakeProject *project,
|
const CMakeProject *project,
|
||||||
const Kit *k,
|
const Kit *k,
|
||||||
const Utils::Environment &env)
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &buildDirectory)
|
||||||
|
|
||||||
{
|
{
|
||||||
const CMakeConfigItem presetItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
|
const CMakeConfigItem presetItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
|
||||||
@@ -1230,6 +1231,11 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
|||||||
initialArguments.append("--debug-output");
|
initialArguments.append("--debug-output");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMakePresets::Macros::updateToolchainFile(configurePreset,
|
||||||
|
env,
|
||||||
|
project->projectDirectory(),
|
||||||
|
buildDirectory);
|
||||||
|
|
||||||
// Merge the presets cache variables
|
// Merge the presets cache variables
|
||||||
CMakeConfig cache;
|
CMakeConfig cache;
|
||||||
if (configurePreset.cacheVariables)
|
if (configurePreset.cacheVariables)
|
||||||
@@ -1547,15 +1553,16 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
|
|||||||
|
|
||||||
CMakeProject *cmakeProject = static_cast<CMakeProject *>(target->project());
|
CMakeProject *cmakeProject = static_cast<CMakeProject *>(target->project());
|
||||||
setUserConfigureEnvironmentChanges(getEnvironmentItemsFromCMakeConfigurePreset(cmakeProject, k));
|
setUserConfigureEnvironmentChanges(getEnvironmentItemsFromCMakeConfigurePreset(cmakeProject, k));
|
||||||
|
updateAndEmitConfigureEnvironmentChanged();
|
||||||
|
|
||||||
QStringList initialCMakeArguments = cmd.splitArguments();
|
QStringList initialCMakeArguments = cmd.splitArguments();
|
||||||
addCMakeConfigurePresetToInitialArguments(initialCMakeArguments,
|
addCMakeConfigurePresetToInitialArguments(initialCMakeArguments,
|
||||||
cmakeProject,
|
cmakeProject,
|
||||||
k,
|
k,
|
||||||
configureEnvironment());
|
configureEnvironment(),
|
||||||
|
info.buildDirectory);
|
||||||
m_buildSystem->setInitialCMakeArguments(initialCMakeArguments);
|
m_buildSystem->setInitialCMakeArguments(initialCMakeArguments);
|
||||||
m_buildSystem->setCMakeBuildType(buildType);
|
m_buildSystem->setCMakeBuildType(buildType);
|
||||||
updateAndEmitConfigureEnvironmentChanged();
|
|
||||||
|
|
||||||
setBuildPresetToBuildSteps(target);
|
setBuildPresetToBuildSteps(target);
|
||||||
});
|
});
|
||||||
@@ -1825,24 +1832,31 @@ void CMakeBuildConfiguration::setInitialBuildAndCleanSteps(const ProjectExplorer
|
|||||||
const CMakeConfigItem presetItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(
|
const CMakeConfigItem presetItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(
|
||||||
target->kit());
|
target->kit());
|
||||||
|
|
||||||
|
int buildSteps = 1;
|
||||||
if (!presetItem.isNull()) {
|
if (!presetItem.isNull()) {
|
||||||
const QString presetName = presetItem.expandedValue(target->kit());
|
const QString presetName = presetItem.expandedValue(target->kit());
|
||||||
const CMakeProject *project = static_cast<const CMakeProject *>(target->project());
|
const CMakeProject *project = static_cast<const CMakeProject *>(target->project());
|
||||||
|
|
||||||
const auto buildPresets = project->presetsData().buildPresets;
|
const auto buildPresets = project->presetsData().buildPresets;
|
||||||
const int count = std::count_if(buildPresets.begin(),
|
const int count
|
||||||
|
= std::count_if(buildPresets.begin(),
|
||||||
buildPresets.end(),
|
buildPresets.end(),
|
||||||
[presetName](const PresetsDetails::BuildPreset &preset) {
|
[presetName, project](const PresetsDetails::BuildPreset &preset) {
|
||||||
|
bool enabled = true;
|
||||||
|
if (preset.condition)
|
||||||
|
enabled = CMakePresets::Macros::evaluatePresetCondition(
|
||||||
|
preset, project->projectDirectory());
|
||||||
|
|
||||||
return preset.configurePreset == presetName
|
return preset.configurePreset == presetName
|
||||||
&& !preset.hidden.value();
|
&& !preset.hidden.value() && enabled;
|
||||||
});
|
});
|
||||||
|
if (count != 0)
|
||||||
for (int i = 0; i < count; ++i)
|
buildSteps = count;
|
||||||
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < buildSteps; ++i)
|
||||||
|
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
|
||||||
|
|
||||||
appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID);
|
appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1858,9 +1872,14 @@ void CMakeBuildConfiguration::setBuildPresetToBuildSteps(const ProjectExplorer::
|
|||||||
const CMakeProject *project = static_cast<const CMakeProject *>(target->project());
|
const CMakeProject *project = static_cast<const CMakeProject *>(target->project());
|
||||||
|
|
||||||
const auto allBuildPresets = project->presetsData().buildPresets;
|
const auto allBuildPresets = project->presetsData().buildPresets;
|
||||||
const auto buildPresets
|
const auto buildPresets = Utils::filtered(
|
||||||
= Utils::filtered(allBuildPresets, [presetName](const PresetsDetails::BuildPreset &preset) {
|
allBuildPresets, [presetName, project](const PresetsDetails::BuildPreset &preset) {
|
||||||
return preset.configurePreset == presetName && !preset.hidden.value();
|
bool enabled = true;
|
||||||
|
if (preset.condition)
|
||||||
|
enabled = CMakePresets::Macros::evaluatePresetCondition(preset,
|
||||||
|
project->projectDirectory());
|
||||||
|
|
||||||
|
return preset.configurePreset == presetName && !preset.hidden.value() && enabled;
|
||||||
});
|
});
|
||||||
|
|
||||||
const QList<BuildStep *> buildStepList
|
const QList<BuildStep *> buildStepList
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ FilePaths CMakeProjectImporter::importCandidates()
|
|||||||
if (configPreset.hidden.value())
|
if (configPreset.hidden.value())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (configPreset.condition) {
|
||||||
|
if (!CMakePresets::Macros::evaluatePresetCondition(configPreset, projectFilePath()))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const FilePath configPresetDir = m_presetsTempDir.filePath(configPreset.name);
|
const FilePath configPresetDir = m_presetsTempDir.filePath(configPreset.name);
|
||||||
configPresetDir.createDir();
|
configPresetDir.createDir();
|
||||||
candidates << configPresetDir;
|
candidates << configPresetDir;
|
||||||
@@ -403,13 +408,15 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
auto data = std::make_unique<DirectoryData>();
|
auto data = std::make_unique<DirectoryData>();
|
||||||
|
|
||||||
const QString presetName = importPath.fileName();
|
const QString presetName = importPath.fileName();
|
||||||
|
|
||||||
PresetsDetails::ConfigurePreset configurePreset
|
PresetsDetails::ConfigurePreset configurePreset
|
||||||
= Utils::findOrDefault(m_presetsData.configurePresets,
|
= Utils::findOrDefault(m_presetsData.configurePresets,
|
||||||
[presetName](const PresetsDetails::ConfigurePreset &preset) {
|
[presetName](const PresetsDetails::ConfigurePreset &preset) {
|
||||||
return preset.name == presetName;
|
return preset.name == presetName;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Environment env = Environment::systemEnvironment();
|
||||||
|
CMakePresets::Macros::expand(configurePreset, env, projectDirectory());
|
||||||
|
|
||||||
if (configurePreset.displayName)
|
if (configurePreset.displayName)
|
||||||
data->cmakePresetDisplayname = configurePreset.displayName.value();
|
data->cmakePresetDisplayname = configurePreset.displayName.value();
|
||||||
else
|
else
|
||||||
@@ -435,14 +442,16 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
QString binaryDir = importPath.toString();
|
QString binaryDir = importPath.toString();
|
||||||
if (configurePreset.binaryDir) {
|
if (configurePreset.binaryDir) {
|
||||||
binaryDir = configurePreset.binaryDir.value();
|
binaryDir = configurePreset.binaryDir.value();
|
||||||
CMakePresets::Macros::expand(configurePreset,
|
CMakePresets::Macros::expand(configurePreset, env, projectDirectory(), binaryDir);
|
||||||
Environment::systemEnvironment(),
|
|
||||||
projectDirectory(),
|
|
||||||
binaryDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data->buildDirectory = Utils::FilePath::fromString(binaryDir);
|
data->buildDirectory = Utils::FilePath::fromString(binaryDir);
|
||||||
|
|
||||||
|
CMakePresets::Macros::updateToolchainFile(configurePreset,
|
||||||
|
env,
|
||||||
|
projectDirectory(),
|
||||||
|
data->buildDirectory);
|
||||||
|
|
||||||
const CMakeConfig cache = configurePreset.cacheVariables
|
const CMakeConfig cache = configurePreset.cacheVariables
|
||||||
? configurePreset.cacheVariables.value()
|
? configurePreset.cacheVariables.value()
|
||||||
: CMakeConfig();
|
: CMakeConfig();
|
||||||
|
|||||||
@@ -12,6 +12,25 @@
|
|||||||
|
|
||||||
namespace CMakeProjectManager::Internal::CMakePresets::Macros {
|
namespace CMakeProjectManager::Internal::CMakePresets::Macros {
|
||||||
|
|
||||||
|
QString getHostSystemName()
|
||||||
|
{
|
||||||
|
Utils::OsType osType = Utils::HostOsInfo::hostOs();
|
||||||
|
|
||||||
|
switch (osType) {
|
||||||
|
case Utils::OsTypeWindows:
|
||||||
|
return "Windows";
|
||||||
|
case Utils::OsTypeLinux:
|
||||||
|
return "Linux";
|
||||||
|
case Utils::OsTypeMac:
|
||||||
|
return "Darwin";
|
||||||
|
case Utils::OsTypeOtherUnix:
|
||||||
|
return "Unix";
|
||||||
|
case Utils::OsTypeOther:
|
||||||
|
return "Other";
|
||||||
|
}
|
||||||
|
return "Other";
|
||||||
|
}
|
||||||
|
|
||||||
void expandAllButEnv(const PresetsDetails::ConfigurePreset &preset,
|
void expandAllButEnv(const PresetsDetails::ConfigurePreset &preset,
|
||||||
const Utils::FilePath &sourceDirectory,
|
const Utils::FilePath &sourceDirectory,
|
||||||
QString &value)
|
QString &value)
|
||||||
@@ -25,6 +44,8 @@ void expandAllButEnv(const PresetsDetails::ConfigurePreset &preset,
|
|||||||
value.replace("${presetName}", preset.name);
|
value.replace("${presetName}", preset.name);
|
||||||
if (preset.generator)
|
if (preset.generator)
|
||||||
value.replace("${generator}", preset.generator.value());
|
value.replace("${generator}", preset.generator.value());
|
||||||
|
|
||||||
|
value.replace("${hostSystemName}", getHostSystemName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void expandAllButEnv(const PresetsDetails::BuildPreset &preset,
|
void expandAllButEnv(const PresetsDetails::BuildPreset &preset,
|
||||||
@@ -141,6 +162,106 @@ void expand(const PresetType &preset,
|
|||||||
value.replace(match.captured(1), env.value(match.captured(2)));
|
value.replace(match.captured(1), env.value(match.captured(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateToolchainFile(
|
||||||
|
CMakeProjectManager::Internal::PresetsDetails::ConfigurePreset &configurePreset,
|
||||||
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &sourceDirectory,
|
||||||
|
const Utils::FilePath &buildDirectory)
|
||||||
|
{
|
||||||
|
if (!configurePreset.toolchainFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString toolchainFileName = configurePreset.toolchainFile.value();
|
||||||
|
CMakePresets::Macros::expand(configurePreset, env, sourceDirectory, toolchainFileName);
|
||||||
|
|
||||||
|
// Resolve the relative path first to source and afterwards to build directory
|
||||||
|
Utils::FilePath toolchainFile = Utils::FilePath::fromString(toolchainFileName);
|
||||||
|
if (toolchainFile.isRelativePath()) {
|
||||||
|
for (const auto &path : {sourceDirectory, buildDirectory}) {
|
||||||
|
Utils::FilePath probePath = toolchainFile.resolvePath(path);
|
||||||
|
if (probePath.exists() && probePath != path) {
|
||||||
|
toolchainFile = probePath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!toolchainFile.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// toolchainFile takes precedence to CMAKE_TOOLCHAIN_FILE
|
||||||
|
CMakeConfig cache = configurePreset.cacheVariables ? configurePreset.cacheVariables.value()
|
||||||
|
: CMakeConfig();
|
||||||
|
|
||||||
|
auto it = std::find_if(cache.begin(), cache.end(), [](const CMakeConfigItem &item) {
|
||||||
|
return item.key == "CMAKE_TOOLCHAIN_FILE";
|
||||||
|
});
|
||||||
|
if (it != cache.end())
|
||||||
|
it->value = toolchainFile.toString().toUtf8();
|
||||||
|
else
|
||||||
|
cache << CMakeConfigItem("CMAKE_TOOLCHAIN_FILE",
|
||||||
|
CMakeConfigItem::FILEPATH,
|
||||||
|
toolchainFile.toString().toUtf8());
|
||||||
|
|
||||||
|
configurePreset.cacheVariables = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class PresetType>
|
||||||
|
void expandConditionValues(const PresetType &preset,
|
||||||
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &sourceDirectory,
|
||||||
|
PresetsDetails::Condition &condition)
|
||||||
|
{
|
||||||
|
if (condition.isEquals() || condition.isNotEquals()) {
|
||||||
|
if (condition.lhs)
|
||||||
|
expand(preset, env, sourceDirectory, condition.lhs.value());
|
||||||
|
if (condition.rhs)
|
||||||
|
expand(preset, env, sourceDirectory, condition.rhs.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition.isInList() || condition.isNotInList()) {
|
||||||
|
if (condition.string)
|
||||||
|
expand(preset, env, sourceDirectory, condition.string.value());
|
||||||
|
if (condition.list)
|
||||||
|
for (QString &listValue : condition.list.value())
|
||||||
|
expand(preset, env, sourceDirectory, listValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition.isMatches() || condition.isNotMatches()) {
|
||||||
|
if (condition.string)
|
||||||
|
expand(preset, env, sourceDirectory, condition.string.value());
|
||||||
|
if (condition.regex)
|
||||||
|
expand(preset, env, sourceDirectory, condition.regex.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition.isAnyOf() || condition.isAllOf()) {
|
||||||
|
if (condition.conditions)
|
||||||
|
for (PresetsDetails::Condition::ConditionPtr &c : condition.conditions.value())
|
||||||
|
expandConditionValues(preset, env, sourceDirectory, *c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition.isNot()) {
|
||||||
|
if (condition.condition)
|
||||||
|
expandConditionValues(preset, env, sourceDirectory, *condition.condition.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class PresetType>
|
||||||
|
bool evaluatePresetCondition(const PresetType &preset, const Utils::FilePath &sourceDirectory)
|
||||||
|
{
|
||||||
|
if (!preset.condition)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||||
|
expand(preset, env, sourceDirectory);
|
||||||
|
|
||||||
|
PresetsDetails::Condition condition = preset.condition.value();
|
||||||
|
expandConditionValues(preset, env, sourceDirectory, condition);
|
||||||
|
|
||||||
|
return condition.evaluate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Expand for PresetsDetails::ConfigurePreset
|
// Expand for PresetsDetails::ConfigurePreset
|
||||||
template void expand<PresetsDetails::ConfigurePreset>(const PresetsDetails::ConfigurePreset &preset,
|
template void expand<PresetsDetails::ConfigurePreset>(const PresetsDetails::ConfigurePreset &preset,
|
||||||
Utils::Environment &env,
|
Utils::Environment &env,
|
||||||
@@ -155,6 +276,9 @@ template void expand<PresetsDetails::ConfigurePreset>(const PresetsDetails::Conf
|
|||||||
const Utils::FilePath &sourceDirectory,
|
const Utils::FilePath &sourceDirectory,
|
||||||
QString &value);
|
QString &value);
|
||||||
|
|
||||||
|
template bool evaluatePresetCondition<PresetsDetails::ConfigurePreset>(
|
||||||
|
const PresetsDetails::ConfigurePreset &preset, const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
// Expand for PresetsDetails::BuildPreset
|
// Expand for PresetsDetails::BuildPreset
|
||||||
template void expand<PresetsDetails::BuildPreset>(const PresetsDetails::BuildPreset &preset,
|
template void expand<PresetsDetails::BuildPreset>(const PresetsDetails::BuildPreset &preset,
|
||||||
Utils::Environment &env,
|
Utils::Environment &env,
|
||||||
@@ -169,4 +293,7 @@ template void expand<PresetsDetails::BuildPreset>(const PresetsDetails::BuildPre
|
|||||||
const Utils::FilePath &sourceDirectory,
|
const Utils::FilePath &sourceDirectory,
|
||||||
QString &value);
|
QString &value);
|
||||||
|
|
||||||
|
template bool evaluatePresetCondition<PresetsDetails::BuildPreset>(
|
||||||
|
const PresetsDetails::BuildPreset &preset, const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
} // namespace CMakeProjectManager::Internal::CMakePresets::Macros
|
} // namespace CMakeProjectManager::Internal::CMakePresets::Macros
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ class FilePath;
|
|||||||
|
|
||||||
namespace CMakeProjectManager::Internal {
|
namespace CMakeProjectManager::Internal {
|
||||||
|
|
||||||
|
namespace PresetsDetails {
|
||||||
|
class ConfigurePreset;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CMakePresets::Macros {
|
namespace CMakePresets::Macros {
|
||||||
/**
|
/**
|
||||||
* Expands the CMakePresets Macros using Utils::Environment as target and source for parent environment values.
|
* Expands the CMakePresets Macros using Utils::Environment as target and source for parent environment values.
|
||||||
@@ -40,6 +44,22 @@ void expand(const PresetType &preset,
|
|||||||
const Utils::FilePath &sourceDirectory,
|
const Utils::FilePath &sourceDirectory,
|
||||||
QString &value);
|
QString &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the cacheVariables parameter of the configurePreset with the expandned toolchainFile parameter.
|
||||||
|
* Including macro expansion and relative paths resolving.
|
||||||
|
*/
|
||||||
|
void updateToolchainFile(PresetsDetails::ConfigurePreset &configurePreset,
|
||||||
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &sourceDirectory,
|
||||||
|
const Utils::FilePath &buildDirectory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands the condition values and then evaluates the condition object of the preset and returns
|
||||||
|
* the boolean result.
|
||||||
|
*/
|
||||||
|
template<class PresetType>
|
||||||
|
bool evaluatePresetCondition(const PresetType &preset, const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
} // namespace CMakePresets::Macros
|
} // namespace CMakePresets::Macros
|
||||||
|
|
||||||
} // namespace CMakeProjectManager::Internal
|
} // namespace CMakeProjectManager::Internal
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "presetsparser.h"
|
#include "presetsparser.h"
|
||||||
|
#include "utils/algorithm.h"
|
||||||
|
|
||||||
#include "cmakeprojectmanagertr.h"
|
#include "cmakeprojectmanagertr.h"
|
||||||
|
|
||||||
@@ -34,6 +35,102 @@ bool parseCMakeMinimumRequired(const QJsonValue &jsonValue, QVersionNumber &vers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<PresetsDetails::Condition> parseCondition(const QJsonValue &jsonValue)
|
||||||
|
{
|
||||||
|
std::optional<PresetsDetails::Condition> condition;
|
||||||
|
|
||||||
|
if (jsonValue.isUndefined())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
condition = PresetsDetails::Condition();
|
||||||
|
|
||||||
|
if (jsonValue.isNull()) {
|
||||||
|
condition->type = "null";
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonValue.isBool()) {
|
||||||
|
condition->type = "const";
|
||||||
|
condition->constValue = jsonValue.toBool();
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jsonValue.isObject())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
QJsonObject object = jsonValue.toObject();
|
||||||
|
QString type = object.value("type").toString();
|
||||||
|
if (type.isEmpty())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
if (type == "const") {
|
||||||
|
condition->type = type;
|
||||||
|
condition->constValue = object.value("const").toBool();
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &equals : {QString("equals"), QString("notEquals")}) {
|
||||||
|
if (type == equals) {
|
||||||
|
condition->type = equals;
|
||||||
|
condition->lhs = object.value("lhs").toString();
|
||||||
|
condition->rhs = object.value("rhs").toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!condition->type.isEmpty())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
for (const auto &inList : {QString("inList"), QString("notInList")}) {
|
||||||
|
if (type == inList) {
|
||||||
|
condition->type = inList;
|
||||||
|
condition->string = object.value("string").toString();
|
||||||
|
if (object.value("list").isArray()) {
|
||||||
|
condition->list = QStringList();
|
||||||
|
const QJsonArray listArray = object.value("list").toArray();
|
||||||
|
for (const QJsonValue &listValue : listArray)
|
||||||
|
condition->list.value() << listValue.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!condition->type.isEmpty())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
for (const auto &matches : {QString("matches"), QString("notMatches")}) {
|
||||||
|
if (type == matches) {
|
||||||
|
condition->type = matches;
|
||||||
|
condition->string = object.value("string").toString();
|
||||||
|
condition->regex = object.value("regex").toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!condition->type.isEmpty())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
for (const auto &anyOf : {QString("anyOf"), QString("allOf")}) {
|
||||||
|
if (type == anyOf) {
|
||||||
|
condition->type = anyOf;
|
||||||
|
if (object.value("conditions").isArray()) {
|
||||||
|
condition->conditions = std::vector<PresetsDetails::Condition::ConditionPtr>();
|
||||||
|
const QJsonArray conditionsArray = object.value("conditions").toArray();
|
||||||
|
for (const QJsonValue &conditionsValue : conditionsArray) {
|
||||||
|
condition->conditions.value().emplace_back(
|
||||||
|
std::make_shared<PresetsDetails::Condition>(
|
||||||
|
parseCondition(conditionsValue).value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!condition->type.isEmpty())
|
||||||
|
return condition;
|
||||||
|
|
||||||
|
if (type == "not") {
|
||||||
|
condition->type = type;
|
||||||
|
condition->condition = std::make_shared<PresetsDetails::Condition>(
|
||||||
|
parseCondition(object.value("condition")).value());
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
bool parseConfigurePresets(const QJsonValue &jsonValue,
|
bool parseConfigurePresets(const QJsonValue &jsonValue,
|
||||||
QList<PresetsDetails::ConfigurePreset> &configurePresets)
|
QList<PresetsDetails::ConfigurePreset> &configurePresets)
|
||||||
{
|
{
|
||||||
@@ -68,6 +165,10 @@ bool parseConfigurePresets(const QJsonValue &jsonValue,
|
|||||||
preset.inherits.value() << inheritsValue;
|
preset.inherits.value() << inheritsValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object.contains("condition"))
|
||||||
|
preset.condition = parseCondition(object.value("condition"));
|
||||||
|
|
||||||
if (object.contains("displayName"))
|
if (object.contains("displayName"))
|
||||||
preset.displayName = object.value("displayName").toString();
|
preset.displayName = object.value("displayName").toString();
|
||||||
if (object.contains("description"))
|
if (object.contains("description"))
|
||||||
@@ -76,6 +177,8 @@ bool parseConfigurePresets(const QJsonValue &jsonValue,
|
|||||||
preset.generator = object.value("generator").toString();
|
preset.generator = object.value("generator").toString();
|
||||||
if (object.contains("binaryDir"))
|
if (object.contains("binaryDir"))
|
||||||
preset.binaryDir = object.value("binaryDir").toString();
|
preset.binaryDir = object.value("binaryDir").toString();
|
||||||
|
if (object.contains("toolchainFile"))
|
||||||
|
preset.toolchainFile = object.value("toolchainFile").toString();
|
||||||
if (object.contains("cmakeExecutable"))
|
if (object.contains("cmakeExecutable"))
|
||||||
preset.cmakeExecutable = object.value("cmakeExecutable").toString();
|
preset.cmakeExecutable = object.value("cmakeExecutable").toString();
|
||||||
|
|
||||||
@@ -218,6 +321,10 @@ bool parseBuildPresets(const QJsonValue &jsonValue,
|
|||||||
preset.inherits.value() << inheritsValue;
|
preset.inherits.value() << inheritsValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object.contains("condition"))
|
||||||
|
preset.condition = parseCondition(object.value("condition"));
|
||||||
|
|
||||||
if (object.contains("displayName"))
|
if (object.contains("displayName"))
|
||||||
preset.displayName = object.value("displayName").toString();
|
preset.displayName = object.value("displayName").toString();
|
||||||
if (object.contains("description"))
|
if (object.contains("description"))
|
||||||
@@ -334,6 +441,9 @@ bool PresetsParser::parse(const Utils::FilePath &jsonFile, QString &errorMessage
|
|||||||
|
|
||||||
void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
|
void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
|
||||||
{
|
{
|
||||||
|
if (!condition && other.condition && !other.condition.value().isNull())
|
||||||
|
condition = other.condition;
|
||||||
|
|
||||||
if (!vendor && other.vendor)
|
if (!vendor && other.vendor)
|
||||||
vendor = other.vendor;
|
vendor = other.vendor;
|
||||||
|
|
||||||
@@ -346,6 +456,9 @@ void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
|
|||||||
if (!toolset && other.toolset)
|
if (!toolset && other.toolset)
|
||||||
toolset = other.toolset;
|
toolset = other.toolset;
|
||||||
|
|
||||||
|
if (!toolchainFile && other.toolchainFile)
|
||||||
|
toolchainFile = other.toolchainFile;
|
||||||
|
|
||||||
if (!binaryDir && other.binaryDir)
|
if (!binaryDir && other.binaryDir)
|
||||||
binaryDir = other.binaryDir;
|
binaryDir = other.binaryDir;
|
||||||
|
|
||||||
@@ -370,6 +483,9 @@ void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
|
|||||||
|
|
||||||
void PresetsDetails::BuildPreset::inheritFrom(const BuildPreset &other)
|
void PresetsDetails::BuildPreset::inheritFrom(const BuildPreset &other)
|
||||||
{
|
{
|
||||||
|
if (!condition && other.condition && !other.condition.value().isNull())
|
||||||
|
condition = other.condition;
|
||||||
|
|
||||||
if (!vendor && other.vendor)
|
if (!vendor && other.vendor)
|
||||||
vendor = other.vendor;
|
vendor = other.vendor;
|
||||||
|
|
||||||
@@ -401,4 +517,46 @@ void PresetsDetails::BuildPreset::inheritFrom(const BuildPreset &other)
|
|||||||
nativeToolOptions = other.nativeToolOptions;
|
nativeToolOptions = other.nativeToolOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PresetsDetails::Condition::evaluate() const
|
||||||
|
{
|
||||||
|
if (isNull())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (isConst() && constValue)
|
||||||
|
return constValue.value();
|
||||||
|
|
||||||
|
if (isEquals() && lhs && rhs)
|
||||||
|
return lhs.value() == rhs.value();
|
||||||
|
|
||||||
|
if (isNotEquals() && lhs && rhs)
|
||||||
|
return lhs.value() != rhs.value();
|
||||||
|
|
||||||
|
if (isInList() && string && list)
|
||||||
|
return list.value().contains(string.value());
|
||||||
|
|
||||||
|
if (isNotInList() && string && list)
|
||||||
|
return !list.value().contains(string.value());
|
||||||
|
|
||||||
|
if (isMatches() && string && regex) {
|
||||||
|
QRegularExpression qRegex(regex.value());
|
||||||
|
return qRegex.match(string.value()).hasMatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotMatches() && string && regex) {
|
||||||
|
QRegularExpression qRegex(regex.value());
|
||||||
|
return !qRegex.match(string.value()).hasMatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAnyOf() && conditions)
|
||||||
|
return Utils::anyOf(conditions.value(), [](const ConditionPtr &c) { return c->evaluate(); });
|
||||||
|
|
||||||
|
if (isAllOf() && conditions)
|
||||||
|
return Utils::allOf(conditions.value(), [](const ConditionPtr &c) { return c->evaluate(); });
|
||||||
|
|
||||||
|
if (isNot() && condition)
|
||||||
|
return !condition.value()->evaluate();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // CMakeProjectManager::Internal
|
} // CMakeProjectManager::Internal
|
||||||
|
|||||||
@@ -43,6 +43,47 @@ public:
|
|||||||
std::optional<bool> find = false;
|
std::optional<bool> find = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Condition {
|
||||||
|
public:
|
||||||
|
QString type;
|
||||||
|
|
||||||
|
bool isNull() const { return type == "null"; }
|
||||||
|
bool isConst() const { return type == "const"; }
|
||||||
|
bool isEquals() const { return type == "equals"; }
|
||||||
|
bool isNotEquals() const { return type == "notEquals"; }
|
||||||
|
bool isInList() const { return type == "inList"; }
|
||||||
|
bool isNotInList() const { return type == "notInList"; }
|
||||||
|
bool isMatches() const { return type == "matches"; }
|
||||||
|
bool isNotMatches() const { return type == "notMatches"; }
|
||||||
|
bool isAnyOf() const { return type == "anyOf"; }
|
||||||
|
bool isAllOf() const { return type == "allOf"; }
|
||||||
|
bool isNot() const { return type == "not"; }
|
||||||
|
|
||||||
|
bool evaluate() const;
|
||||||
|
|
||||||
|
// const
|
||||||
|
std::optional<bool> constValue;
|
||||||
|
|
||||||
|
// equals, notEquals
|
||||||
|
std::optional<QString> lhs;
|
||||||
|
std::optional<QString> rhs;
|
||||||
|
|
||||||
|
// inList, notInList
|
||||||
|
std::optional<QString> string;
|
||||||
|
std::optional<QStringList> list;
|
||||||
|
|
||||||
|
// matches, notMatches
|
||||||
|
std::optional<QString> regex;
|
||||||
|
|
||||||
|
using ConditionPtr = std::shared_ptr<Condition>;
|
||||||
|
|
||||||
|
// anyOf, allOf
|
||||||
|
std::optional<std::vector<ConditionPtr>> conditions;
|
||||||
|
|
||||||
|
// not
|
||||||
|
std::optional<ConditionPtr> condition;
|
||||||
|
};
|
||||||
|
|
||||||
class ConfigurePreset {
|
class ConfigurePreset {
|
||||||
public:
|
public:
|
||||||
void inheritFrom(const ConfigurePreset &other);
|
void inheritFrom(const ConfigurePreset &other);
|
||||||
@@ -50,12 +91,14 @@ public:
|
|||||||
QString name;
|
QString name;
|
||||||
std::optional<bool> hidden = false;
|
std::optional<bool> hidden = false;
|
||||||
std::optional<QStringList> inherits;
|
std::optional<QStringList> inherits;
|
||||||
|
std::optional<Condition> condition;
|
||||||
std::optional<QHash<QString, QString>> vendor;
|
std::optional<QHash<QString, QString>> vendor;
|
||||||
std::optional<QString> displayName;
|
std::optional<QString> displayName;
|
||||||
std::optional<QString> description;
|
std::optional<QString> description;
|
||||||
std::optional<QString> generator;
|
std::optional<QString> generator;
|
||||||
std::optional<ValueStrategyPair> architecture;
|
std::optional<ValueStrategyPair> architecture;
|
||||||
std::optional<ValueStrategyPair> toolset;
|
std::optional<ValueStrategyPair> toolset;
|
||||||
|
std::optional<QString> toolchainFile;
|
||||||
std::optional<QString> binaryDir;
|
std::optional<QString> binaryDir;
|
||||||
std::optional<QString> cmakeExecutable;
|
std::optional<QString> cmakeExecutable;
|
||||||
std::optional<CMakeConfig> cacheVariables;
|
std::optional<CMakeConfig> cacheVariables;
|
||||||
@@ -72,6 +115,7 @@ public:
|
|||||||
QString name;
|
QString name;
|
||||||
std::optional<bool> hidden = false;
|
std::optional<bool> hidden = false;
|
||||||
std::optional<QStringList> inherits;
|
std::optional<QStringList> inherits;
|
||||||
|
std::optional<Condition> condition;
|
||||||
std::optional<QHash<QString, QString>> vendor;
|
std::optional<QHash<QString, QString>> vendor;
|
||||||
std::optional<QString> displayName;
|
std::optional<QString> displayName;
|
||||||
std::optional<QString> description;
|
std::optional<QString> description;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"version": 2,
|
"version": 3,
|
||||||
"cmakeMinimumRequired": {
|
"cmakeMinimumRequired": {
|
||||||
"major": 3,
|
"major": 3,
|
||||||
"minor": 20,
|
"minor": 21,
|
||||||
"patch": 0
|
"patch": 0
|
||||||
},
|
},
|
||||||
"configurePresets": [
|
"configurePresets": [
|
||||||
@@ -15,6 +15,11 @@
|
|||||||
"CMAKE_BUILD_TYPE": "Release",
|
"CMAKE_BUILD_TYPE": "Release",
|
||||||
"CMAKE_PREFIX_PATH": "c:/Qt/6.3.2/mingw_64"
|
"CMAKE_PREFIX_PATH": "c:/Qt/6.3.2/mingw_64"
|
||||||
},
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
"PATH": "c:/Qt/Tools/mingw1120_64/bin;$penv{PATH}"
|
"PATH": "c:/Qt/Tools/mingw1120_64/bin;$penv{PATH}"
|
||||||
},
|
},
|
||||||
@@ -36,8 +41,29 @@
|
|||||||
"architecture" : {
|
"architecture" : {
|
||||||
"value": "x64"
|
"value": "x64"
|
||||||
},
|
},
|
||||||
"cacheVariables": {
|
"toolchainFile" : "c:/Qt/6.3.2/msvc2019_64/lib/cmake/Qt6/qt.toolchain.cmake",
|
||||||
"CMAKE_PREFIX_PATH": "c:/Qt/6.3.2/msvc2019_64"
|
"condition" : {
|
||||||
|
"type": "not",
|
||||||
|
"condition": {
|
||||||
|
"type": "notEquals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "$env{HOST_SYSTEM_NAME}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"environment" : {
|
||||||
|
"HOST_SYSTEM_NAME": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-gcc",
|
||||||
|
"displayName": "Linux GCC",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/build-${presetName}",
|
||||||
|
"toolchainFile" : "$penv{HOME}/Qt/6.3.2/gcc_64/lib/cmake/Qt6/qt.toolchain.cmake",
|
||||||
|
"condition" : {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Linux"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user