CMakeToolchain: 向依赖项注入任意 CMake 变量

您可以在 GitHub 的 examples2 仓库中找到重现此项目的源代码

$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/examples/tools/cmake/cmake_toolchain/user_toolchain_profile

通常情况下,Conan 包 recipes 通过 settings、confs 和 options 提供必要的抽象来控制构建的不同方面。许多 recipes 定义了 options 来激活或禁用特性、可选依赖项或二进制特性。像 tools.build:cxxflags 这样的配置可用于注入任意 C++ 编译标志。

在某些特殊情况下,可能需要直接将 CMake 变量注入进行 CMake 构建的依赖项。当这些依赖项使用 CMakeToolchain 集成时,这是可能的。让我们在这个简单的示例中进行检查。

如果我们有以下包 recipe,其中包含一个简单的 conanfile.py 和一个打印变量的 CMakeLists.txt

conanfile.py
from conan import ConanFile
from conan.tools.cmake import CMake

class AppConan(ConanFile):
    name = "foo"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    exports_sources = "CMakeLists.txt"

    generators = "CMakeToolchain"

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(foo LANGUAGES NONE)
message(STATUS "MYVAR1 ${MY_USER_VAR1}!!")

我们可以定义一个 profile 文件和一个 myvars.cmake 文件(都在同一个文件夹中),如下所示

myprofile
include(default)
[conf]
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/myvars.cmake

请注意 {{profile_dir}} 是一个 jinja 模板表达式,它评估为当前 profile 文件夹,允许计算 myvars.cmake 文件的必要路径。tools.cmake.cmaketoolchain:user_toolchain 是一个要注入到生成的 conan_toolchain.cmake 中的文件列表,因此使用 += 运算符将其附加到列表中。

myvars.cmake 可以定义任意数量的变量

myvars.cmake
set(MY_USER_VAR1 "MYVALUE1")

应用此 profile 后,我们可以看到包的 CMake 构建有效地使用了外部 myvars.cmake 文件中提供的变量

$ conan create . -pr=myprofile
...
-- MY_USER_VAR1 MYVALUE1

请注意,在使用 user_toolchain 的同时定义像 tools.cmake.cmaketoolchain:system_name 这样的 conf 值是受支持的。

此外,user_toolchain 文件可以定义用于交叉构建的变量,例如 CMAKE_SYSTEM_NAMECMAKE_SYSTEM_VERSIONCMAKE_SYSTEM_PROCESSOR。如果在用户 toolchain 文件中定义了这些变量,它们将受到尊重,并且 conan_toolchain.cmake 推导出的变量不会覆盖用户定义的变量。如果这些变量未在用户 toolchain 文件中定义,则将使用 Conan 自动推导出的变量。

tools.cmake.cmaketoolchain:user_toolchain 的 conf 值也可以在命令行 -c 参数中传递,但 myvars.cmake 的位置需要是绝对路径才能找到,因为 jinja 替换不会发生在命令行中。