I need to define some properties in a .json file, that must be used inside a CMakePresets.json
. This because the CMakePresets.json
that I use in my pc is different from the one that I use in the build machine, but some properties (like library versions) are the same and I want to avoid to duplicate those information because I'll forgot to update both files.
So I've created a CMakeCommon.json
file that contains:
{
"version": 5,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 1
},
"configurePresets": [
{
"cacheVariables": {
"MYLIB_VERSION": "1_0"
}
}
]
}
and my CMakePresets.json
is:
{
"version": 5,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 1
},
"include": [
"CMakeCommon.json"
],
"configurePresets": [
{
"name": "default",
"displayName": "Default Config",
"description": "Default config generator with ninja",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"hidden": true,
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "MyPath/vcpkg/scripts/buildsystems/vcpkg.cmake",
"VCPKG_DEFAULT_TRIPLET": "x64-windows",
"CMAKE_EXPORT_COMPILE_COMMANDS": "TRUE",
"MYLIB_PATH": "D:/MyLib/${MYLIB_VERSION}"
},
"environment": {
}
},
{
"inherits": "default",
"name": "debug",
"displayName": "Debug",
"description": "Debug build.",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"inherits": "default",
"name": "release",
"displayName": "Release",
"description": "Release build.",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "debug"
},
{
"name": "Release",
"configurePreset": "release"
}
],
"testPresets": [ ]
}
I cannot use MYLIB_VERSION
variable defined in CMakeCommon.json
inside the cache variable MYLIB_PATH
defined in CMakePresets.json
.
Is there a way to achieve this result?
There are two issues with your current implementation: You need to give the preset in the CMakeCommon.json
file a name, and then have the default
preset in CMakePresets.json
to inherit from it, otherwise how would the default
preset know to use the value of MYLIB_VERSION
from there.
The second issue is that ${MYLIB_VERSION}
in the default
preset in CMakePresets.json
is not a valid macro expansion. Currently, there is no way to access cache variables of presets you inherited from through macro expansion, only environment variables can be referenced. So you need to make MYLIB_VERSION
an environment variable in CMakeCommon.json
and then use $env{MYLIB_VERSION}
instead of ${MYLIB_VERSION}
All in all it would look something like this:
CMakeCommon.json
:
{
"version": 5,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 1
},
"configurePresets": [
{
"name": "common",
"hidden": true,
"environment": {
"MYLIB_VERSION": "1_0"
}
}
]
}
CMakePresets.json
:
{
"version": 5,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 1
},
"include": [
"CMakeCommon.json"
],
"configurePresets": [
{
"name": "default",
"inherits": "common",
"displayName": "Default Config",
"description": "Default config generator with ninja",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"hidden": true,
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "MyPath/vcpkg/scripts/buildsystems/vcpkg.cmake",
"VCPKG_DEFAULT_TRIPLET": "x64-windows",
"CMAKE_EXPORT_COMPILE_COMMANDS": "TRUE",
"MYLIB_PATH": "D:/MyLib/$env{MYLIB_VERSION}"
},
"environment": {
}
},
{
"inherits": "default",
"name": "debug",
"displayName": "Debug",
"description": "Debug build.",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"inherits": "default",
"name": "release",
"displayName": "Release",
"description": "Release build.",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "debug"
},
{
"name": "Release",
"configurePreset": "release"
}
],
"testPresets": [ ]
}
If you need MYLIB_VERSION
to be a cache variable you can also add it back to the cache variables pf the common
preset, but set the value to $env{MYLIB_VERSION}
so you don't have to duplicate the version number.
I'd also like to point out that CMake actually has a built-in mechanism for this exact issue of needing machine-specific presets. If you rename your current CMakePresets.json
file to CMakeUserPresets.json
and the CMakeCommon.json
file to CMakePresets.json
then you can remove the include
from the file that is now CMakeUserPresets.json
and get the same behavior, but with the standard names.