4

I have a CMakePresets.json file which makes use of inheritance and macro expansion. Here is an excerpt, in reality I use multiple versions of "Foo":

{
 "configurePresets": [
        {
            "name": "default",
            "hidden": true,
            "generator": "Unix Makefiles",
            "binaryDir": "cmake-build-${presetName}",
            "environment": {
                "PATH":  "/opt/foo/$env{FOO_VERSION}/bin:$penv{PATH}",
                "LD_LIBRARY_PATH": "/opt/foo/$env{FOO_VERSION}.0/lib"
            },
            "cacheVariables": {
                "FOO_VERSION": "$env{FOO_VERSION}",
            }
        },
        {
            "name": "debug-foo1",
            "inherits": "default",
            "environment": { "FOO_VERSION": "1" }
        },
        {
            "name": "release-foo1",
            "inherits": "debug-foo1",
            "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
        }
    ],
    "buildPresets": [
        {
            "name": "debug-foo1",
            "configurePreset": "debug-foo1"
        },
        {
            "name": "release-foo1",
            "configurePreset": "release-foo1"
        }
    ]
}

Now assume I select the preset release-foo1. This would render the following variables, among others:

  • binaryDir = "cmake-build-release-foo1"
  • FOO_VERSION = "1"
  • LD_LIBRARY_PATH = "/opt/foo/1.0/lib"

Is there a way to query these results for a given preset? For example, given release-foo1, I want to know the resulting binaryDir.

Of course I could parse the JSON myself, but that seems tedious, especially because of the cross references and substitutions which are being made by CMake.

andreee
  • 4,459
  • 22
  • 42
  • https://stackoverflow.com/questions/66786315/how-to-recursively-merge-inherited-json-array-elements + just `jq` to extract the elements. – KamilCuk Aug 04 '21 at 14:57

2 Answers2

2

You can use the -N flag to print the computed presets info without running the configure or generate steps. After modifying the presets file in your question to work, I created an empty CMakeLists.txt next to it and ran this test (*** stands in for my PATH):

$ cmake --preset=release-foo1 -N
Preset CMake variables:

  CMAKE_BUILD_TYPE="Release"
  FOO_VERSION="1"

Preset environment variables:

  FOO_VERSION="1"
  LD_LIBRARY_PATH="/opt/foo/1.0/lib"
  PATH="/opt/foo/1/bin:***"

This is good enough for debugging your presets. If you need to go further, you could process the output using standard unix command line tools, like awk, grep, cut, etc.

I think this is the best you can do for now (CMake <=3.21) since there's nothing else in the command line documentation or the file API for IDEs that I could find.

Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
  • 2
    Hi Alex, thanks for your answer. I'm aware of `-N` but I would like to avoid parsing some human-readable output that may also change in the future. But even worse, only computed cache and environment seem to be printed, so I'm still unable to access `binaryDir`, for example. Anyway, +1 for pointing me to the CMake file API, I was completely unaware of it and it looks very helpful for my work. – andreee Aug 05 '21 at 06:52
0

Building on Alex Reinkings answer, you can get the binaryDir (and other parts) with the -N option if you tweek the preset a little bit. You need to add a environment variable and reference it for binaryDir:. See this tweeked example from CMake documentation:

{
    "version": 2,
    "cmakeMinimumRequired": {
      "major": 3,
      "minor": 20,
      "patch": 0
    },
    "configurePresets": [
      {
        "name": "default",
        "displayName": "Default Config",
        "description": "Default build using Ninja generator",
        "generator": "Ninja",
        "binaryDir": "$env{BUILD_DIR}",
        "cacheVariables": {
          "FIRST_CACHE_VARIABLE": {
            "type": "BOOL",
            "value": "OFF"
          },
          "SECOND_CACHE_VARIABLE": "ON"
        },
        "environment": {
          "BUILD_DIR": "${sourceDir}/build/default",
          "MY_ENVIRONMENT_VARIABLE": "Test",
          "PATH": "$env{HOME}/ninja/bin:$penv{PATH}"
        },
        "vendor": {
          "example.com/ExampleIDE/1.0": {
            "autoFormat": true
          }
        }
      },
      {
        "name": "ninja-multi",
        "inherits": "default",
        "displayName": "Ninja Multi-Config",
        "description": "Default build using Ninja Multi-Config generator",
        "generator": "Ninja Multi-Config"
      }
    ],
    "buildPresets": [
      {
        "name": "default",
        "configurePreset": "default"
      }
    ],
    "testPresets": [
      {
        "name": "default",
        "configurePreset": "default",
        "output": {"outputOnFailure": true},
        "execution": {"noTestsAction": "error", "stopOnFailure": true}
      }
    ],
    "vendor": {
      "example.com/ExampleIDE/1.0": {
        "autoFormat": false
      }
    }
  }

This will give you:

$ cmake --preset default -N
Preset CMake variables:

  FIRST_CACHE_VARIABLE:BOOL="OFF"
  SECOND_CACHE_VARIABLE="ON"

Preset environment variables:

=>BUILD_DIR="D:/tmp/presets/build/default"<=
  MY_ENVIRONMENT_VARIABLE="Test"
  PATH="..."
kuga
  • 1,483
  • 1
  • 17
  • 38