Presets - conditional config

Is there a way for a single preset to apply different settings based on a condition?

For example, I would like cmake --preset default to choose the appropriate vcpkg triplet for the current OS.

"configurePresets": [
    {
      "name": "windows",
      "hidden": true,
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-windows"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    },
    {
      "name": "macos",
      "hidden": true,
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-macos"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Darwin"
      }
    },
    {
      "name": "default",
      "binaryDir": "${sourceDir}/build/default",
      "generator": "Ninja",
      "inherits": [
        "windows",
        "macos"
      ]
    }
]

This does not work as ā€˜defaultā€™ winds up with conflicting condition objects and just picks the first (I think)

 {
      "name": "default",
      "binaryDir": "${sourceDir}/build/default",
      "generator": "Ninja",
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-windows"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    },
    {
      "name": "default",
      "binaryDir": "${sourceDir}/build/default",
      "generator": "Ninja",
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-macos"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Darwin"
      }
    }

This does not work as you may not have two presets with the same name, even if one is disabled.

Is this something that is currently possible, or planned for the future?

3 Likes

Cc: @kyle.edwards

I have also noticed this limitation, and it would be nice to be able to have a conditional preset of the same name.

1 Like

Ah. I was about to make a topic but the search found this. Indeed, I have need for something like this myself. I would like to set a cache variable differently on different OSs (say, ON for Linux, but OFF for Darwin`).

This is neither an answer nor a question, but a report of way to achieve a similar goal in a different way. It also failed, but perhaps it helps to find the right way.

Tried to inherit from multiple platform specific presets, which are enabled/disabled according to the platform. According to the 3.21 documentation a condition can have a value of ā€œnullā€, so that (as I understood, but I might be wrong) the according preset is enabled (i.e. does not cause a inherited presets to fail), but the inheriting presets do not inherit from the preset (cache variables/environment/ā€¦). But this also failed, cause if the condition is ā€œfalseā€ the inherited configurations can not be used.

What I would need, is a object, so that the value of the condition field becomes null (not false).

"configurePresets": [

        {
            "name": "windows-only",
            "hidden": true,
            "condition": {
                "type": "equals",
                "lhs": "${hostSystemName}",
                "rhs": "Windows"
            },
            "environment": {
                "PLATFORM": "WINDOWS64",
            }
        },
        {
            "name": "linux-only",
            "hidden": true,
            "condition": {
                "type": "equals",
                "lhs": "${hostSystemName}",
                "rhs": "Windows"
            },
            "environment": {
                "PLATFORM": "LINUX64",
            }
        },
        {
            "name": "default",
            "inherits": [
                "linux-only",
                "windows-only"
            ],
...

In the big picture, I tried to have the platform to be a property (different build/install folders, environments, cache settings, ā€¦) but not, that I need to double/tripple/ā€¦ (for 2/3/ā€¦ platforms) each preset (for e.g. Debug/Release/NightlyBuild/DeploymentBuild/CI/ā€¦

Any news on this topics ? I would like to set a cache variable differently on different OSs

IMHO: It would be time to get a response ?

Zombie thread reactivate! Iā€™m hoping gurus like @scivision or @ben.boeckel might have a fix for me as I try to do this.

Namely, I want to build with presets differently on one machine versus others (due to how disks are set up, etc.). I have:

  "configurePresets": [
    {
      "name": "base-configure-nccs",
      "hidden": true,
      "displayName": "Base Configure Settings",
      "description": "Sets build and install directories",
      "binaryDir": "$penv{CMAKE_BUILD_LOCATIONS}/${sourceDirName}/build-${presetName}",
      "installDir": "$penv{CMAKE_INSTALL_LOCATIONS}/${sourceDirName}/install-${presetName}",
      "condition": { "lhs": "$penv{CMAKE_SITE_NAME}", "type": "equals", "rhs": "NCCS" }
    },
    {
      "name": "base-configure-default",
      "hidden": true,
      "displayName": "Base Configure Settings",
      "description": "Sets build and install directories",
      "binaryDir": "${sourceDir}/build-${presetName}",
      "installDir": "${sourceDir}/install-${presetName}",
      "condition": { "lhs": "$penv{CMAKE_SITE_NAME}", "type": "notEquals", "rhs": "NCCS" } },
    {
      "name": "base-configure",
      "hidden": true,
      "inherits": [
         "base-configure-nccs",
         "base-configure-default"
         ],
      "displayName": "Base Configure Settings",
      "description": "Sets build and install directories"
    },

So if I have CMAKE_SITE_NAME=NCCS in my environment, we build and install to directories external to the sourceDir. But otherwise, Iā€™ll just keep the build and install dirs in sourceDir.

Good news is that it works on the NCCS machine. But anywhere else:

āÆ cmake --preset Debug
CMake Error: Could not use disabled preset "Debug"

Is there an obvious mistake I made here?

Alas, my knowledge of presets is about the same as it was back then. The new issue you have filed is probably the most useful next step.

I did figure outā€¦something for my case that seems to work, though Iā€™m still testing. Iā€™m trying:

  "include": [
    "presets/CMake$penv{CMAKE_PRESET_NAME}Presets.json"
  ],

where Iā€™m using an environment variable to control which file has my ā€œbaseā€ configure class. Thanks to v7 this is doable. Iā€™m still trying to figure out how little I need to include in my include.

with cmake v3.30 this works now:

{
    "version": 9,
    "include": [
        "CMake${hostSystemName}Presets.json"
    ],
    "buildPresets": [
        {
            "name": "default",
            "configurePreset": "default"
        }
    ],
    "testPresets": [
        {
            "name": "default",
            "configurePreset": "default",
            "output": {
                "outputOnFailure": true
            },
            "execution": {
                "noTestsAction": "error",
                "stopOnFailure": true
            }
        }
    ],
    "packagePresets": [
        {
            "name": "default",
            "configurePreset": "default",
            "generators": [
                "TGZ"
            ]
        }
    ],
    "workflowPresets": [
        {
            "name": "default",
            "steps": [
                {
                    "type": "configure",
                    "name": "default"
                },
                {
                    "type": "build",
                    "name": "default"
                },
                {
                    "type": "test",
                    "name": "default"
                },
                {
                    "type": "package",
                    "name": "default"
                }
            ]
        }
    ]
}

Hmm. What was added in version 9 of presets? (I usually donā€™t look for the changes in presets until my current setup breaks. :slight_smile: )

  • cmake-presets(7) files now support schema version 9. include fields now expand all macros except $env{}and preset-specific macros, i.e., those derived from the fields inside a presetā€™s definition.

Ohhhhhh! You have:

        "CMake${hostSystemName}Presets.json"

where there is no $penv{}!

I kept staring at your code trying to figure out what was different in there. :slight_smile: