Search code examples
cmakecmake-presets

Can CMakePresets.json configurePreset enforce both its condition and an inherited condition?


The following CMakePresets.json demonstrates enforcing that an environment variable is set using configurePresets conditions:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "fail_if_no_foo",
      "displayName": "Fail if no FOO",
      "description": "Demo failing if environment variable FOO is unset",
      "binaryDir": "${sourceDir}/build",
      "generator": "Unix Makefiles",
      "condition": {
        "type": "notEquals",
        "lhs": "$penv{FOO}",
        "rhs": ""
      }
    }
  ]
}
$ cmake --preset fail_if_no_foo
CMake Error: Could not use disabled preset "fail_if_no_foo"
$
$ FOO=bar cmake --preset fail_if_no_foo
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_condition/build
$

The following modification shows that the condition can be inherited:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "fail_if_no_foo",
      "displayName": "Fail if no FOO",
      "description": "Demo failing if environment variable FOO is unset",
      "binaryDir": "${sourceDir}/build",
      "generator": "Unix Makefiles",
      "condition": {
        "type": "notEquals",
        "lhs": "$penv{FOO}",
        "rhs": ""
      }
    },
    {
      "name": "inherited_preset",
      "inherits": "fail_if_no_foo",
      "displayName": "Inherited fail if no FOO",
      "description": "Demo inherited condition to fail if environment variable FOO is unset"
    }
  ]
}
$ cmake --preset inherited_preset
CMake Error: Could not use disabled preset "inherited_preset"
$
$ FOO=bar cmake --preset inherited_preset
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_condition/build
$

But inheritance of the parent's condition seems to go away if the inheriting conditionPresets introduces its own condition:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "fail_if_no_foo",
      "displayName": "Fail if no FOO",
      "description": "Demo failing if environment variable FOO is unset",
      "binaryDir": "${sourceDir}/build",
      "generator": "Unix Makefiles",
      "condition": {
        "type": "notEquals",
        "lhs": "$penv{FOO}",
        "rhs": ""
      }
    },
    {
      "name": "inherited_preset",
      "inherits": "fail_if_no_foo",
      "displayName": "Inherited fail if no FOO",
      "description": "Demo inherited condition to fail if environment variable FOO is unset",
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Linux"
      }
    }
  ]
}
$ uname -s
Linux
$
$ cmake --preset inherited_preset
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_condition/build
$

Is there a way to implement an "and" relationship between conditions implemented in the current configurePreset and condition(s) from an inherited configurePreset?
I want inherited_preset to enforce the condition that ${hostSystemName} is "Linux" and that the parent environment defines FOO.
The CMake Presets documentation notes an allOf keyword, but doesn't give an example of how to use it, and I haven't figured out how to use it to implement my need.


Below is my implementation using allOf, which parses correctly (an earlier version of this question used allOf with incorrect syntax), but still fails to implement the desired behavior of enforcing both the child's and parent's conditions:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "fail_if_no_foo",
      "displayName": "Fail if no FOO",
      "description": "Demo failing if environment variable FOO is unset",
      "binaryDir": "${sourceDir}/build",
      "generator": "Unix Makefiles",
      "condition": {
        "type": "allOf",
        "conditions": [
          {
            "type": "notEquals",
            "lhs": "$penv{FOO}",
            "rhs": ""
          }
        ]
      }
    },
    {
      "name": "inherited_preset",
      "inherits": "fail_if_no_foo",
      "displayName": "Inherited fail if no FOO",
      "description": "Demo inherited condition to fail if environment variable FOO is unset",
      "condition": {
        "type": "allOf",
        "conditions": [
          {
            "type": "equals",
            "lhs": "${hostSystemName}",
            "rhs": "Linux"
          }
        ]
      }
    }
  ]
}
$ uname -s
Linux
$
$ cmake --preset fail_if_no_foo
CMake Error: Could not use disabled preset "fail_if_no_foo"
$
$ FOO=bar cmake --preset fail_if_no_foo
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_condition/build
$
$ cmake --preset inherited_preset
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_condition/build
$

Solution

  • It sounds to me like what you want is what's requested in the open feature-request presets: Inheritance of conditional presets, which requests that instead of conditions only being evaluated for effect after all of inheritance has been completed, it be evaluated for effect on each preset in the inheritance tree before inheritance takes place. I suggest that you give that issue ticket a thumbs up to show support for it. You can also subscribe to it to get notified about discussion and progress. Please avoid making noisy comments there like ones that just consist of "+1" / "bump".