diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 817d02ed638..b6b0947dd59 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -1241,6 +1241,7 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume env, project->projectDirectory(), buildDirectory); + CMakePresets::Macros::updateInstallDir(configurePreset, env, project->projectDirectory()); // Merge the presets cache variables CMakeConfig cache; diff --git a/src/plugins/cmakeprojectmanager/presetsmacros.cpp b/src/plugins/cmakeprojectmanager/presetsmacros.cpp index 1a7b884ca9d..0e156ab4a47 100644 --- a/src/plugins/cmakeprojectmanager/presetsmacros.cpp +++ b/src/plugins/cmakeprojectmanager/presetsmacros.cpp @@ -253,6 +253,44 @@ void updateToolchainFile( configurePreset.cacheVariables = cache; } +void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset, + const Utils::Environment &env, + const Utils::FilePath &sourceDirectory) +{ + if (!configurePreset.installDir) + return; + + QString installDirString = configurePreset.installDir.value(); + CMakePresets::Macros::expand(configurePreset, env, sourceDirectory, installDirString); + + // Resolve the relative path first to source and afterwards to build directory + Utils::FilePath installDir = Utils::FilePath::fromString(installDirString); + if (installDir.isRelativePath()) { + Utils::FilePath probePath = sourceDirectory.resolvePath(installDir); + if (probePath != sourceDirectory) { + installDir = probePath; + } + } + installDirString = installDir.cleanPath().toString(); + + // installDir takes precedence to CMAKE_INSTALL_PREFIX + CMakeConfig cache = configurePreset.cacheVariables ? configurePreset.cacheVariables.value() + : CMakeConfig(); + + auto it = std::find_if(cache.begin(), cache.end(), [](const CMakeConfigItem &item) { + return item.key == "CMAKE_INSTALL_PREFIX"; + }); + if (it != cache.end()) + it->value = installDirString.toUtf8(); + else + cache << CMakeConfigItem("CMAKE_INSTALL_PREFIX", + CMakeConfigItem::PATH, + installDirString.toUtf8()); + + configurePreset.cacheVariables = cache; +} + + template void expandConditionValues(const PresetType &preset, const Utils::Environment &env, diff --git a/src/plugins/cmakeprojectmanager/presetsmacros.h b/src/plugins/cmakeprojectmanager/presetsmacros.h index 0acf4d37cb6..09083b11fa5 100644 --- a/src/plugins/cmakeprojectmanager/presetsmacros.h +++ b/src/plugins/cmakeprojectmanager/presetsmacros.h @@ -53,6 +53,13 @@ void updateToolchainFile(PresetsDetails::ConfigurePreset &configurePreset, const Utils::FilePath &sourceDirectory, const Utils::FilePath &buildDirectory); +/** + * Updates the cacheVariables parameter of the configurePreset with the expanded installDir parameter. + * Including macro expansion and relative paths resolving. + */ +void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset, + const Utils::Environment &env, + const Utils::FilePath &sourceDirectory); /** * Expands the condition values and then evaluates the condition object of the preset and returns * the boolean result. diff --git a/src/plugins/cmakeprojectmanager/presetsparser.cpp b/src/plugins/cmakeprojectmanager/presetsparser.cpp index 441709109db..bd0d17d8cb8 100644 --- a/src/plugins/cmakeprojectmanager/presetsparser.cpp +++ b/src/plugins/cmakeprojectmanager/presetsparser.cpp @@ -177,6 +177,8 @@ bool parseConfigurePresets(const QJsonValue &jsonValue, preset.generator = object.value("generator").toString(); if (object.contains("binaryDir")) preset.binaryDir = object.value("binaryDir").toString(); + if (object.contains("installDir")) + preset.installDir = object.value("installDir").toString(); if (object.contains("toolchainFile")) preset.toolchainFile = object.value("toolchainFile").toString(); if (object.contains("cmakeExecutable")) @@ -462,6 +464,9 @@ void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other) if (!binaryDir && other.binaryDir) binaryDir = other.binaryDir; + if (!installDir && other.installDir) + installDir = other.installDir; + if (!cmakeExecutable && other.cmakeExecutable) cmakeExecutable = other.cmakeExecutable; diff --git a/src/plugins/cmakeprojectmanager/presetsparser.h b/src/plugins/cmakeprojectmanager/presetsparser.h index 5577620d5d8..7717f19c666 100644 --- a/src/plugins/cmakeprojectmanager/presetsparser.h +++ b/src/plugins/cmakeprojectmanager/presetsparser.h @@ -100,6 +100,7 @@ public: std::optional toolset; std::optional toolchainFile; std::optional binaryDir; + std::optional installDir; std::optional cmakeExecutable; std::optional cacheVariables; std::optional> environment; diff --git a/tests/manual/cmakepresets/CMakePresets.json b/tests/manual/cmakepresets/CMakePresets.json index 8f0ef76f8fc..f4eb2283263 100644 --- a/tests/manual/cmakepresets/CMakePresets.json +++ b/tests/manual/cmakepresets/CMakePresets.json @@ -10,6 +10,7 @@ "name": "mingw", "displayName": "MinGW 11.2.0", "generator": "Ninja", + "installDir": "../inst-${presetName}", "cacheVariables": { "CMAKE_PREFIX_PATH": "c:/Qt/6.3.2/mingw_64" },