You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CMake Presets实现环境变量或缓存变量二选一约束?

如何在CMakePresets.json中实现「VCPKG_DIR环境变量或CMAKE_TOOLCHAIN_FILE缓存变量二选一」的约束?

问题背景

我们可以通过CMakePresets.json基于父环境变量VCPKG_DIR指定vcpkg工具链文件,示例配置如下:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "demo",
      "displayName": "demo",
      "description": "demo",
      "generator": "Unix Makefiles",
      "binaryDir": "${sourceDir}/build",
      "toolchainFile": "$penv{VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake"
    }
  ]
}

执行时设置VCPKG_DIR即可自动加载工具链:

$ VCPKG_DIR=/home/user/dev/vcpkg/ cmake --preset demo
Preset CMake variables:

  CMAKE_TOOLCHAIN_FILE:FILEPATH="/home/user/dev/vcpkg//scripts/buildsystems/vcpkg.cmake"

-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_env_or_cachevar_for_toolchain/build
$

同时,用户也可以直接通过-DCMAKE_TOOLCHAIN_FILE参数指定工具链,无需设置VCPKG_DIR:

$ cmake --preset demo -DCMAKE_TOOLCHAIN_FILE=/home/user/dev/vcpkg/scripts/buildsystems/vcpkg.cmake
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/dev/cmake_learn/preset_env_or_cachevar_for_toolchain/build
$

我们希望实现的逻辑是:当用户未指定CMAKE_TOOLCHAIN_FILE时,必须设置VCPKG_DIR环境变量;若用户已指定CMAKE_TOOLCHAIN_FILE,则无需设置VCPKG_DIR。

最初尝试添加condition约束VCPKG_DIR非空,但这样会导致即使指定了CMAKE_TOOLCHAIN_FILE,仍要求必须设置VCPKG_DIR,不符合需求:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "demo",
      "displayName": "demo",
      "description": "demo",
      "generator": "Unix Makefiles",
      "binaryDir": "${sourceDir}/build",
      "toolchainFile": "$penv{VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake",
      "condition": {
        "type": "allOf",
        "conditions": [
          {
            "type": "notEquals",
            "lhs": "$penv{VCPKG_DIR}",
            "rhs": ""
          }
        ]
      }
    }
  ]
}

执行时的问题示例:

$ cmake --preset demo -DCMAKE_TOOLCHAIN_FILE=/home/user/dev/vcpkg/scripts/buildsystems/vcpkg.cmake # 不符合预期:因未定义VCPKG_DIR而失败
CMake Error: Could not use disabled preset "demo"
$

解决方案

要实现二选一约束,需要在condition中使用anyOf组合两个判断条件:

  1. VCPKG_DIR环境变量非空
  2. CMAKE_TOOLCHAIN_FILE缓存变量已被指定(非空)

修改后的CMakePresets.json配置如下:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20
  },
  "configurePresets": [
    {
      "name": "demo",
      "displayName": "demo",
      "description": "demo",
      "generator": "Unix Makefiles",
      "binaryDir": "${sourceDir}/build",
      "toolchainFile": "$penv{VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake",
      "condition": {
        "type": "anyOf",
        "conditions": [
          {
            "type": "notEquals",
            "lhs": "$penv{VCPKG_DIR}",
            "rhs": ""
          },
          {
            "type": "notEquals",
            "lhs": "$cache{CMAKE_TOOLCHAIN_FILE}",
            "rhs": ""
          }
        ]
      }
    }
  ]
}

验证效果

  1. 仅设置VCPKG_DIR:正常执行,自动加载工具链
$ VCPKG_DIR=/home/user/dev/vcpkg/ cmake --preset demo
# 执行输出与之前一致,配置成功
  1. 仅指定CMAKE_TOOLCHAIN_FILE:无需设置VCPKG_DIR,正常执行
$ cmake --preset demo -DCMAKE_TOOLCHAIN_FILE=/home/user/dev/vcpkg/scripts/buildsystems/vcpkg.cmake
# 执行输出与之前一致,配置成功
  1. 两者都未设置:预设被禁用,执行失败(符合预期)
$ cmake --preset demo
CMake Error: Could not use disabled preset "demo"
$

内容的提问来源于stack exchange,提问作者StoneThrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:35:04