Is there a way to extract rendered preset information from CMake?
Asked Answered
K

2

6

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.

Kennet answered 4/8, 2021 at 13:35 Comment(1)
#66786815 + just jq to extract the elements.Elrod
R
3

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.

Rilke answered 4/8, 2021 at 20:30 Comment(1)
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.Kennet
D
1

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="..."
Demur answered 30/9, 2022 at 6:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.