CMakeToolchain

CMakeToolchain 是 CMake 的工具链生成器。它生成工具链文件,该文件可以通过在 CMake 命令行调用中使用 -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake 来使用。此生成器将当前包配置、设置和选项转换为 CMake 工具链语法。

它可以声明为

from conan import ConanFile

class Pkg(ConanFile):
    generators = "CMakeToolchain"

或者在 generate() 方法中完全实例化

from conan import ConanFile
from conan.tools.cmake import CMakeToolchain

class App(ConanFile):
    settings = "os", "arch", "compiler", "build_type"
    requires = "hello/0.1"
    generators = "CMakeDeps"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": False, "fPIC": True}

    def generate(self):
        tc = CMakeToolchain(self)
        tc.variables["MYVAR"] = "MYVAR_VALUE"
        tc.preprocessor_definitions["MYDEFINE"] = "MYDEF_VALUE"
        tc.generate()

注意

CMakeToolchain 旨在与 CMakeDeps 依赖项生成器一起运行。请勿将其他 CMake 传统生成器(如 cmakecmake_paths)与其一起使用。

生成的文件

conan install(或在缓存中构建包)之后,这将生成以下文件,其中包含 generate() 方法中提供的信息以及从当前 settings 翻译而来的信息

  • conan_toolchain.cmake:包含将 Conan 设置转换为 CMake 变量的内容。此文件中将定义的一些事项:

    • CMake 生成器平台和生成器工具集的定义

    • 基于 fPIC 选项定义 CMAKE_POSITION_INDEPENDENT_CODE

    • 根据需要定义 C++ 标准

    • 定义 C++ 使用的标准库

    • 在 OSX 中禁用 rpaths

    • 在 Windows 上使用 Visual Studio 时定义 CMAKE_VS_DEBUGGER_ENVIRONMENT。这会设置 PATH 环境变量指向包含 DLL 的目录,以便直接从 Visual Studio IDE 调试而无需复制 DLL(需要 CMake 3.27)。

    • 定义 CONAN_RUNTIME_LIB_DIRS 以允许收集运行时依赖项(共享库),详情请参见下文。

  • conanvcvars.bat:在某些情况下,为了构建,需要正确定义 Visual Studio 环境,例如使用 Ninja 或 NMake 生成器时。如果需要,CMakeToolchain 将生成此脚本,从而更容易定义正确的 Visual Studio 提示符。

  • CMakePresets.json:此工具链生成标准的 CMakePresets.json 文件。有关更多信息,请参阅此处的文档。它当前使用 JSON 模式的“3”版本。Conan 将 configurebuildtest 预设条目添加到 JSON 文件中

    • configurePresets 存储以下信息
      • 要使用的 generator

      • conan_toolchain.cmake 的路径。

      • 对应于指定设置的缓存变量,如果在工具链中指定则无法工作。

      • 单配置生成器的 CMAKE_BUILD_TYPE 变量。

      • 当配置 tools.build:skip_test 为 true 时,BUILD_TESTING 变量设置为 OFF

      • 一个环境部分,设置所有与 VirtualBuildEnv 相关的环境信息(如果适用)。此环境可以在配方的 generate() 方法中通过 CMakeToolchain.presets_build_environment 属性传递一个环境来修改。可以使用 tools.cmake.cmaketoolchain:presets_environment 配置跳过此部分的生成。

      • 默认情况下,预设名称将是 conan-xxxx,但可以使用 CMakeToolchain.presets_prefix = “conan” 属性自定义“conan-”前缀。

      • 预设名称由 layout() self.folders.build_folder_vars 定义控制,该定义可以包含设置、选项、self.nameself.version 以及常量 const.xxx 的列表,例如 [“settings.compiler”, “settings.arch”, “options.shared”, “const.myname”]

      • 如果 CMake 作为直接的 tool_requires 依赖项被发现,或者 tools.cmake:cmake_program 被设置,则配置预设将包含一个 cmakeExecutable 字段。此字段表示用于此预设的 CMake 可执行文件路径。如 CMake 文档所述,此字段保留供 IDE 使用,CMake 本身不使用。

    • buildPresets 存储以下信息
      • 与此构建预设关联的 configurePreset

    • testPresets 存储以下信息
      • 与此构建预设关联的 configurePreset

      • 一个环境部分,设置所有与 VirtualRunEnv 相关的环境信息(如果适用)。此环境可以在配方的 generate() 方法中通过 CMakeToolchain.presets_run_environment 属性传递一个环境来修改。请注意,由于此预设继承自 configurePreset,它也将继承其环境。可以使用tools.cmake.cmaketoolchain:presets_environment 配置跳过此部分的生成。

  • CMakeUserPresets.json:如果您在配方中声明 layout() 并且您的 CMakeLists.txt 文件位于 conanfile.source_folder 文件夹中,则将自动生成(如果尚不存在)一个 CMakeUserPresets.json 文件,其中包含 CMakePresets.json(位于 conanfile.generators_folder),以允许您的 IDE(Visual Studio、Visual Studio Code、CLion 等)或 cmake 工具找到 CMakePresets.json。生成的 CMakeUserPresets.json 的位置可以通过 user_presets_path 属性进一步调整,如下所述。生成的 CMakeUserPresets.json 的版本架构是“4”,需要 CMake >= 3.23。此文件的文件名可以使用 CMakeToolchain.user_presets_path = "CMakeUserPresets.json" 属性进行配置,因此如果您想生成一个“ConanPresets.json”而不是从您自己的文件中包含,您可以在 generate() 方法中定义 tc.user_presets_path = "ConanPresets.json"。有关完整示例,请参见 扩展您自己的 CMake 预设

    注意:如果 CMakeUserPresets.json 已存在且不是由 Conan 生成的,Conan 将跳过其生成。

    注意:要列出所有可用的预设,请使用 cmake --list-presets 命令

注意

生成的 CMakeUserPresets.json 的版本架构是 4(兼容 CMake>=3.23),而 CMakePresets.json 的架构是 3(兼容 CMake>=3.21)。

CONAN_RUNTIME_LIB_DIRS

生成的 conan_toolchain.cmake 文件中的此变量包含一个目录列表,这些目录包含主机上下文中所有依赖项的运行时库(如 DLL)。这旨在用于依赖 CMake 功能收集共享库以创建可重定位包,如下例所示。

只需将 CONAN_RUNTIME_LIB_DIRS 变量传递给 install(RUNTIME_DEPENDENCY_SET ...) 调用中的 DIRECTORIES 参数即可。

install(RUNTIME_DEPENDENCY_SET my_app_deps
    PRE_EXCLUDE_REGEXES
        [[api-ms-win-.*]]
        [[ext-ms-.*]]
        [[kernel32\.dll]]
        [[libc\.so\..*]] [[libgcc_s\.so\..*]] [[libm\.so\..*]] [[libstdc\+\+\.so\..*]]
    POST_EXCLUDE_REGEXES
        [[.*/system32/.*\.dll]]
        [[^/lib.*]]
        [[^/usr/lib.*]]
    DIRECTORIES ${CONAN_RUNTIME_LIB_DIRS}
)

自定义

preprocessor_definitions

此属性允许定义编译器预处理器定义,用于多种配置(Debug、Release 等)。

def generate(self):
    tc = CMakeToolchain(self)
    tc.preprocessor_definitions["MYDEF"] = "MyValue"
    tc.preprocessor_definitions.debug["MYCONFIGDEF"] = "MyDebugValue"
    tc.preprocessor_definitions.release["MYCONFIGDEF"] = "MyReleaseValue"
    # Setting to None will add the definition with no value
    tc.preprocessor_definitions["NOVALUE_DEF"] = None
    tc.generate()

这将转换为

  • conan_toolchain.cmake 文件中为 MYDEF 定义一个 add_compile_definitions()

  • 一个 add_compile_definitions() 定义,在 conan_toolchain.cmake 文件中使用 cmake 生成器表达式,为不同的配置使用不同的值。

cache_variables

此属性允许定义 CMake 缓存变量。这些变量与 variables 不同,是单配置的。它们将存储在 CMakePresets.json 文件中(在 configurePreset 中的 cacheVariables 处),并在使用 CMake() 构建助手调用 cmake.configure 时,通过 -D 参数应用。

def generate(self):
    tc = CMakeToolchain(self)
    tc.cache_variables["foo"] = True
    tc.cache_variables["foo2"] = False
    tc.cache_variables["var"] = "23"

赋给 cache_variable 的布尔值将转换为 CMake 中的 ONOFF 符号。

variables

此属性允许定义 CMake 变量,用于多种配置(Debug、Release 等)。这些变量应G用于定义与工具链相关的事项,在大多数情况下,您可能希望使用cache_variables。此外,请注意,由于这些变量是在 conan_toolchain.cmake 文件中定义的,并且工具链会多次被 CMake 加载,因此这些变量的定义也会在这些点进行。

def generate(self):
    tc = CMakeToolchain(self)
    tc.variables["MYVAR"] = "MyValue"
    tc.variables.debug["MYCONFIGVAR"] = "MyDebugValue"
    tc.variables.release["MYCONFIGVAR"] = "MyReleaseValue"
    tc.generate()

这将转换为

  • conan_toolchain.cmake 文件中为 MYVAR 定义一个 set()

  • 一个 set() 定义,在 conan_toolchain.cmake 文件中使用 cmake 生成器表达式,为不同的配置使用不同的值。

赋给变量的布尔值将转换为 CMake 中的 ONOFF 符号

def generate(self):
    tc = CMakeToolchain(self)
    tc.variables["FOO"] = True
    tc.variables["VAR"] = False
    tc.generate()

将生成语句:set(FOO ON ...)set(VAR OFF ...)

user_presets_path

此属性允许指定生成的 CMakeUserPresets.json 文件的位置。接受的值:

  • 绝对路径

  • 相对于 self.source_folder 的路径

  • 布尔值 False,用于完全抑制文件的生成。

例如,我们可以通过以下方式阻止生成器创建 CMakeUserPresets.json

def generate(self):
    tc = CMakeToolchain(self)
    tc.user_presets_path = False
    tc.generate()

也可以使用 tools.cmake.cmaketoolchain:user_presets 实验性配置来更改 CMakeUserPresets.json 文件的名称和位置。将其分配为空字符串将完全禁用文件的生成。请查看conf 部分获取更多信息。

presets_build_environment, presets_run_environment

这些属性分别通过分配一个 Environment 来修改与预设关联的构建和运行环境。这可以在 generate() 方法中完成。

例如,您可以覆盖构建环境中已设置的环境变量的值

def generate(self):
    buildenv = VirtualBuildEnv(self)
    buildenv.environment().define("MY_BUILD_VAR", "MY_BUILDVAR_VALUE_OVERRIDDEN")
    buildenv.generate()

    tc = CMakeToolchain(self)
    tc.presets_build_environment = buildenv.environment()
    tc.generate()

或者生成一个新的环境并将其与现有环境组合

def generate(self):
    runenv = VirtualRunEnv(self)
    runenv.environment().define("MY_RUN_VAR", "MY_RUNVAR_SET_IN_GENERATE")
    runenv.generate()

    env = Environment()
    env.define("MY_ENV_VAR", "MY_ENV_VAR_VALUE")
    env = env.vars(self, scope="run")
    env.save_script("other_env")

    tc = CMakeToolchain(self)
    tc.presets_run_environment = runenv.environment().compose_env(env)
    tc.generate()

额外编译标志

您可以使用以下属性将额外的编译标志附加到工具链

  • extra_cxxflags (默认为 []) 用于附加的 cxxflags

  • extra_cflags (默认为 []) 用于附加的 cflags

  • extra_sharedlinkflags (默认为 []) 用于附加的共享链接标志

  • extra_exelinkflags (默认为 []) 用于附加的可执行文件链接标志

注意

标志优先级顺序:在 tools.build 配置中指定的标志,例如 cxxflagscflagssharedlinkflagsexelinkflags,将始终优先于 CMakeToolchain 属性设置的标志。

presets_prefix

默认情况下,它是 "conan",它将生成名为“conan-xxxx”的 CMake 预设。这样做是为了避免与用户自己的预设潜在的名称冲突。

absolute_paths

默认情况下,CMakeToolchain 将生成相对路径。例如,CMakeUserPresets.json 将包含一个指向所包含的 CMakePresets.json(这两个文件都由 CMakeToolchain 生成)的相对路径,而 CMakePresets.json 文件将包含一个指向在其 toolchainFile 字段中定义的 conan_toolchain.cmake 文件的相对路径,该路径将相对于构建文件夹,如 CMake 预设文档所指定。

如果出于某种原因需要使用绝对路径,可以通过以下方式实现:

def generate(self):
    tc = CMakeToolchain(self)
    tc.absolute_paths = True
    tc.generate()

使用自定义工具链文件

提供自定义 CMake 工具链文件有两种方式

  • conan_toolchain.cmake 文件可以完全跳过并替换为用户提供的文件,通过定义 tools.cmake.cmaketoolchain:toolchain_file=<filepath> 配置值。请注意,这种方法将把所有工具链责任转移到用户提供的工具链,但如果没有一些帮助,定位依赖项中必要的 xxx-config.cmake 文件可能会很困难。因此,在大多数情况下,建议使用以下 tools.cmake.cmaketoolchain:user_toolchain,如果需要,可以使用 tools.cmake.cmaketoolchain:enabled_blocks

  • 自定义用户工具链文件可以通过使用下面描述的 user_toolchain 块,并定义 tools.cmake.cmaketoolchain:user_toolchain=["<filepath>"] 配置值,添加到(从)conan_toolchain.cmake 文件中。

    配置 tools.cmake.cmaketoolchain:user_toolchain=["<filepath>"] 可以在 global.conf 中定义。也可以为您的工具链创建一个 Conan 包,并使用 self.conf_info 来声明工具链文件

    import os
    from conan import ConanFile
    class MyToolchainPackage(ConanFile):
        ...
        def package_info(self):
            f = os.path.join(self.package_folder, "mytoolchain.cmake")
            self.conf_info.define("tools.cmake.cmaketoolchain:user_toolchain", [f])
    

    如果您将上一个包声明为 tool_require,则工具链将自动应用。

  • 如果您定义了多个 tool_requires,则可以通过在每个 tool_requires 中使用 append 方法,轻松地将所有用户工具链值附加在一起,例如:

    import os
    from conan import ConanFile
    class MyToolRequire(ConanFile):
        ...
        def package_info(self):
            f = os.path.join(self.package_folder, "mytoolchain.cmake")
            # Appending the value to any existing one
            self.conf_info.append("tools.cmake.cmaketoolchain:user_toolchain", f)
    

    因此,它们将由您的 CMakeToolchain 生成器自动应用,而无需编写任何额外代码。

    from conan import ConanFile
    from conan.tools.cmake import CMake
    class Pkg(ConanFile):
        settings = "os", "compiler", "arch", "build_type"
        exports_sources = "CMakeLists.txt"
        tool_requires = "toolchain1/0.1", "toolchain2/0.1"
        generators = "CMakeToolchain"
    
        def build(self):
            cmake = CMake(self)
            cmake.configure()
    

注意

重要说明

  • 在大多数情况下,tools.cmake.cmaketoolchain:user_toolchain 将优先于 tools.cmake.cmaketoolchain:toolchain_file

  • user_toolchain 文件可以定义用于交叉构建的变量,例如 CMAKE_SYSTEM_NAMECMAKE_SYSTEM_VERSIONCMAKE_SYSTEM_PROCESSOR。如果在用户工具链文件中定义了这些变量,它们将受到尊重,并且 conan_toolchain.cmake 推导出的变量不会覆盖用户定义的变量。如果这些变量未在用户工具链文件中定义,则将使用 Conan 自动推导出的变量。在 user_toolchain 文件中定义的这些变量也将比 tools.cmake.cmaketoolchain:system_name 等配置定义的变量具有更高的优先级。

  • tools.cmake.cmaketoolchain:enabled_blocks 的使用可以与 tools.cmake.cmaketoolchain:user_toolchain 一起使用,以仅启用某些块,但避免 CMakeToolchain 覆盖用户工具链文件中定义的 CMake 值。

扩展和高级自定义

CMakeToolchain 实现了扩展和自定义生成的工具链文件的强大功能。

内容按可自定义的 组织。以下预定义块可用,并按此顺序添加:

  • user_toolchain:允许从 conan_toolchain.cmake 文件中包含用户工具链。如果定义了配置 tools.cmake.cmaketoolchain:user_toolchain=["xxxx", "yyyy"],其值将作为 conan_toolchain.cmake 中的第一行,即 include(xxx)\ninclude(yyyy)

  • generic_system:定义 CMAKE_SYSTEM_NAMECMAKE_SYSTEM_VERSIONCMAKE_SYSTEM_PROCESSORCMAKE_GENERATOR_PLATFORMCMAKE_GENERATOR_TOOLSET

  • compilers:为不同语言定义 CMAKE_<LANG>_COMPILER,如 tools.build:compiler_executables 配置所定义。

  • android_system:定义 ANDROID_PLATFORMANDROID_STLANDROID_ABI 并包含 ANDROID_NDK_PATH/build/cmake/android.toolchain.cmake,其中 ANDROID_NDK_PATHtools.android:ndk_path 配置值中定义。

  • apple_system:为 Apple 系统定义 CMAKE_OSX_ARCHITECTURES(参见通用二进制文件部分)、CMAKE_OSX_SYSROOT

  • fpic:当存在 options.fPIC 时,定义 CMAKE_POSITION_INDEPENDENT_CODE

  • arch_flags:在必要时定义 C/C++ 标志,例如 -m32, -m64

  • linker_scripts:定义任何提供的链接器脚本的标志。

  • libcxx:在必要时定义 -stdlib=libc++ 标志以及 _GLIBCXX_USE_CXX11_ABI

  • vs_runtime:定义 CMAKE_MSVC_RUNTIME_LIBRARY 变量,作为多配置的生成器表达式。

  • vs_debugger_environment:从依赖项的“bindirs”文件夹定义 CMAKE_VS_DEBUGGER_ENVIRONMENT,仅适用于 Visual Studio。

  • cppstd:定义 CMAKE_CXX_STANDARDCMAKE_CXX_EXTENSIONS

  • parallel:为 Visual 定义 /MP 并行构建标志。

  • extra_flags:添加来自 tools.build:cxxflagstools.build:cflagstools.build:definestools.build:sharedlinkflags 等的额外定义、编译和链接标志。

  • cmake_flags_init:基于先前定义的 Conan 变量定义 CMAKE_XXX_FLAGS 变量。上面的块只定义 CONAN_XXX 变量,而这个块将定义 CMake 变量,例如 set(CMAKE_CXX_FLAGS_INIT "${CONAN_CXX_FLAGS}" CACHE STRING "" FORCE)

  • extra_variables:来自 tools.cmake.cmaketoolchain:extra_variables 的额外 CMake 变量定义。

  • try_compile:如果定义了 IN_TRY_COMPILE CMake 属性,则停止处理工具链,跳过此块下面的块。

  • find_paths:定义 CMAKE_FIND_PACKAGE_PREFER_CONFIGCMAKE_MODULE_PATHCMAKE_PREFIX_PATH,以便找到从 CMakeDeps 生成的文件。

  • pkg_config:基于 tools.gnu:pkg_config 定义 PKG_CONFIG_EXECUTABLE,并将 CMAKE_CURRENT_LIST_DIR 添加到 ENV{PKG_CONFIG_PATH},以便 pkg-config 找到生成的 .pc 文件。

  • rpath:定义 CMAKE_SKIP_RPATH。默认情况下,它是禁用的,如果您想激活 CMAKE_SKIP_RPATH,则需要定义 self.blocks["rpath"].skip_rpath=True

  • shared:定义 BUILD_SHARED_LIBS

  • output_dirs:定义 CMAKE_INSTALL_XXX 变量。

    • CMAKE_INSTALL_PREFIX:使用 package_folder 设置,因此如果运行“cmake install”操作,生成物将转到该位置。

    • CMAKE_INSTALL_BINDIRCMAKE_INSTALL_SBINDIRCMAKE_INSTALL_LIBEXECDIR:默认设置为 bin

    • CMAKE_INSTALL_LIBDIR:默认设置为 lib

    • CMAKE_INSTALL_INCLUDEDIRCMAKE_INSTALL_OLDINCLUDEDIR:默认设置为 include

    • CMAKE_INSTALL_DATAROOTDIR:默认设置为 res

    如果要更改默认值,请在 layout() 方法中调整 cpp.package 对象。

    def layout(self):
        ...
        # For CMAKE_INSTALL_BINDIR, CMAKE_INSTALL_SBINDIR and CMAKE_INSTALL_LIBEXECDIR, takes the first value:
        self.cpp.package.bindirs = ["mybin"]
        # For CMAKE_INSTALL_LIBDIR, takes the first value:
        self.cpp.package.libdirs = ["mylib"]
        # For CMAKE_INSTALL_INCLUDEDIR, CMAKE_INSTALL_OLDINCLUDEDIR, takes the first value:
        self.cpp.package.includedirs = ["myinclude"]
        # For CMAKE_INSTALL_DATAROOTDIR, takes the first value:
        self.cpp.package.resdirs = ["myres"]
    

    注意

    package_info() 方法中更改 self.cpp_info 是无效的,需要改为定义 self.cpp.package

  • variables:从 CMakeToolchain.variables 属性定义 CMake 变量。

  • preprocessor:从 CMakeToolchain.preprocessor_definitions 属性定义预处理器指令。

自定义内容块

每个块都可以通过不同方式进行自定义(请记住在自定义后调用 tc.generate())。

# tc.generate() should be called at the end of every one

# remove an existing block, the generated conan_toolchain.cmake
# will not contain code for that block at all
def generate(self):
    tc = CMakeToolchain(self)
    tc.blocks.remove("generic_system")

# remove several blocks
def generate(self):
    tc = CMakeToolchain(self)
    tc.blocks.remove("generic_system", "cmake_flags_init")

# LEGACY: keep one block, remove all the others
# If you want to generate conan_toolchain.cmake with only that
# block. Use "tc.blocks.enabled()" instead
def generate(self):
    tc = CMakeToolchain(self)
    # this still leaves blocks "variables" and "preprocessor"
    # use "tc.blocks.enabled()"" instead
    tc.blocks.select("generic_system")

# LEGACY: keep several blocks, remove the other blocks
# Use "tc.blocks.enabled()" instead
def generate(self):
    tc = CMakeToolchain(self)
    # this still leaves blocks "variables" and "preprocessor"
    # use "tc.blocks.enabled()" instead
    tc.blocks.select("generic_system", "cmake_flags_init")

# keep several blocks, remove the other blocks
# This can be done from configuration with
# tools.cmake.cmaketoolchain:enabled_blocs
def generate(self):
    tc = CMakeToolchain(self)
    # Discard all the other blocks except ``generic_system``
    tc.blocks.enabled("generic_system")

# iterate blocks
def generate(self):
    tc = CMakeToolchain(self)
    for block_name in tc.blocks.keys():
        # do something with block_name
    for block_name, block in tc.blocks.items():
        # do something with block_name and block

# modify the template of an existing block
def generate(self):
    tc = CMakeToolchain(self)
    tmp = tc.blocks["generic_system"].template
    new_tmp = tmp.replace(...)  # replace, fully replace, append...
    tc.blocks["generic_system"].template = new_tmp

# modify one or more variables of the context
def generate(self):
    tc = CMakeToolchain(conanfile)
    # block.values is the context dictionary
    toolset = tc.blocks["generic_system"].values["toolset"]
    tc.blocks["generic_system"].values["toolset"] = "other_toolset"

# modify the whole context values
def generate(self):
    tc = CMakeToolchain(conanfile)
    tc.blocks["generic_system"].values = {"toolset": "other_toolset"}

# modify the context method of an existing block
import types

def generate(self):
    tc = CMakeToolchain(self)
    generic_block = toolchain.blocks["generic_system"]

    def context(self):
        assert self  # Your own custom logic here
        return {"toolset": "other_toolset"}
    generic_block.context = types.MethodType(context, generic_block)

# completely replace existing block
from conan.tools.cmake import CMakeToolchain

def generate(self):
    tc = CMakeToolchain(self)
    # this could go to a python_requires
    class MyGenericBlock:
        template = "HelloWorld"

        def context(self):
            return {}

    tc.blocks["generic_system"] = MyGenericBlock

# add a completely new block
from conan.tools.cmake import CMakeToolchain
def generate(self):
    tc = CMakeToolchain(self)
    # this could go to a python_requires
    class MyBlock:
        template = "Hello {{myvar}}!!!"

        def context(self):
            return {"myvar": "World"}

    tc.blocks["mynewblock"] = MyBlock

可以通过配置文件中的配置选择哪些块是活动的,使用 tools.cmake.cmaketoolchain:enabled_blocks 配置。这是一个块列表,因此这样做:

[conf]
tools.cmake.cmaketoolchain:enabled_blocks=["generic_system"]

将只保留 generic_system 块,并丢弃所有其他块。此功能可用于例如当用户提供自己的工具链文件时,并且他们不需要 Conan CMakeToolchain 定义任何标志或 CMake 变量,除了必要的路径以便找到依赖项。对于这种情况,应该可以这样做:

[conf]
tools.cmake.cmaketoolchain:user_toolchain+=my_user_toolchain.cmake
tools.cmake.cmaketoolchain:enabled_blocks=["find_paths"]

有关这些块的更多信息,请查阅源代码。

查找依赖项路径

生成的 conan_toolchain.cmake 在其 find_paths 块中包含变量信息,例如 CMAKE_PROGRAM_PATHCMAKE_LIBRARY_PATHCMAKE_INCLUDE_PATH 等,这些变量允许 CMake 运行 find_program()find_file() 和其他特殊的“查找器”例程,这些例程在没有通过整体推荐的 find_package() 显式包和目标定义的情况下查找工件。

借助新的孵化中 CMakeConfigDepsconan_toolchain.cmake 中的 find_paths 块不再自行定义信息,而是加载由 CMakeConfigDeps 生成器生成的新文件,即 conan_cmakedeps_paths.cmake 文件。通过这种方式,创建依赖项信息的责任由 CMakeConfigDeps 生成器承担,并且该新文件可以在某些无法传递工具链的场景中使用。

交叉构建

generic_system 块包含一些基本的交叉构建功能。在一般情况下,用户可能希望提供自己的用户工具链来定义所有细节,这可以通过配置 tools.cmake.cmaketoolchain:user_toolchain 来完成。如果定义了此 conf 值,generic_system 块将包含提供的一个或多个文件,但不再为交叉构建定义任何 CMake 变量。

如果 user_toolchain 未定义,并且 Conan 检测到正在进行交叉构建(因为构建和主机配置文件包含不同的操作系统或架构),它将尝试定义以下变量:

  • CMAKE_SYSTEM_NAME:如果定义了 tools.cmake.cmaketoolchain:system_name 配置,则使用该值,否则将尝试自动检测。如果目标是 Android 系统(由其他块管理),且不是 x86_64、sparc 和 ppc 系统中的 64 位到 32 位构建,则此块将考虑交叉构建。

  • CMAKE_SYSTEM_VERSION:如果定义了 tools.cmake.cmaketoolchain:system_version 配置,则使用该值,否则使用 os.version 子设置(主机)的值(如果定义)。在 Apple 系统上,此 os.version 会转换为相应的 Darwin 版本。

  • CMAKE_SYSTEM_PROCESSOR:如果定义了 tools.cmake.cmaketoolchain:system_processor 配置,则使用该值,否则使用 arch 设置(主机)的值(如果定义)。

macOS 中通用二进制文件的支持

警告

此功能是实验性的,可能会有重大更改。有关更多信息,请参见Conan 稳定性部分。

从 Conan 2.2.0 开始,初步支持使用 CMakeToolchain 在 macOS 上构建通用二进制文件。要在 Conan 中为通用二进制文件指定多种架构,请在设置中定义架构时使用 | 分隔符。这种方法允许传递架构列表。例如,运行:

conan create . --name=mylibrary --version=1.0 -s="arch=armv8|x86_64"

将为 mylibrary 创建一个通用二进制文件,其中包含 armv8x86_64 架构,方法是在 conan_toolchain.cmake 文件中将 CMAKE_OSX_ARCHITECTURES 的值设置为 arm64;x86_64

警告

重要的是要注意,此方法不适用于 CMake 之外的构建系统。

请注意,此功能主要有利于为发布目的构建最终的通用二进制文件。Conan 默认的按架构管理一个二进制文件的行为通常能提供更可靠、无故障的体验。用户应谨慎,不要过度依赖此功能以用于更广泛的用例。

参考

class CMakeToolchain(conanfile, generator=None)
generate()

此方法会将生成的文件保存到 conanfile.generators_folder。

conf

CMakeToolchain 受以下 [conf] 变量影响:

  • tools.cmake.cmaketoolchain:toolchain_file:用户工具链文件,用于替换 conan_toolchain.cmake

  • tools.cmake.cmaketoolchain:user_toolchain:要从 conan_toolchain.cmake 文件中包含的用户工具链列表。

  • tools.android:ndk_pathANDROID_NDK_PATH 的值。

  • tools.android:cmake_legacy_toolchainANDROID_USE_LEGACY_TOOLCHAIN_FILE 的布尔值。只有在给定值时才会在 conan_toolchain.cmake 中定义。Android NDK 中指定的 CMake 工具链(在 tools.android:ndk_path 配置中)会考虑这一点,适用于 r23c 及更高版本。如果通过 tools.build:cflagstools.build:cxxflags 定义了编译器标志,则将此设置为 False 可能很有用,以防止 Android 的旧版 CMake 工具链覆盖这些值。如果将此设置为 False,请确保您使用 CMake 3.21 或更高版本。

  • tools.cmake.cmaketoolchain:system_name:在大多数情况下不是必需的,仅用于强制定义 CMAKE_SYSTEM_NAME

  • tools.cmake.cmaketoolchain:system_version:在大多数情况下不是必需的,仅用于强制定义 CMAKE_SYSTEM_VERSION

  • tools.cmake.cmaketoolchain:system_processor:在大多数情况下不是必需的,仅用于强制定义 CMAKE_SYSTEM_PROCESSOR

  • tools.cmake.cmaketoolchain:enabled_blocks:定义哪些块被启用并丢弃其他块。

  • tools.cmake.cmaketoolchain:extra_variables:类似于字典的 Python 对象,指定 CMake 变量名称和值。该值可以是普通字符串、数字或类似于字典的 Python 对象,必须指定 value(字符串/数字)、cache(布尔值)、type(CMake 缓存类型),以及可选的 docstring(字符串:默认为变量名称)和 force(布尔值)键。它可以覆盖 CMakeToolchain 定义的变量,用户自行承担风险。例如:

[conf]
tools.cmake.cmaketoolchain:extra_variables={'MY_CMAKE_VAR': 'MyValue'}

结果为

set(MY_CMAKE_VAR "MyValue")

这将在稍后注入,因此它可以覆盖默认的 Conan 变量。

另一种高级用法

tools.cmake.cmaketoolchain:extra_variables={'MyIntegerVariable': 42, 'CMAKE_GENERATOR_INSTANCE': '${ENV}/buildTools/'}
tools.cmake.cmaketoolchain:extra_variables*={'CACHED_VAR': {'value': '/var/run', 'cache': True, 'type': 'PATH', 'docstring': 'test cache var', 'force': True}}

结果为

set(MyIntegerVariable 42)
set(CMAKE_GENERATOR_INSTANCE "${ENV}/buildTools/")
set(CACHED_VAR "/var/run" CACHE BOOL "test cache var" FORCE)

此块注入 $,该字符将在稍后展开。它还定义了一个类型为 PATH 的缓存变量。

提示

使用 配置数据运算符 *=更新(而不是重新定义)配置文件或全局配置中已设置的 conf 变量。

  • tools.cmake.cmaketoolchain:toolset_arch:将在 conan_toolchain.cmake 文件的 CMAKE_GENERATOR_TOOLSET 变量中添加 ,host=xxx 指定符。

  • tools.cmake.cmaketoolchain:toolset_cuda:(实验性)将在 conan_toolchain.cmake 文件的 CMAKE_GENERATOR_TOOLSET 变量中添加 ,cuda=xxx 指定符。

  • tools.cmake.cmake_layout:build_folder_vars:设置、选项、self.nameself.version 以及常量 const.uservalue,它们将生成不同的构建文件夹和不同的 CMake 预设名称。

  • tools.cmake.cmaketoolchain:presets_environment:设置为 'disabled' 以阻止将环境部分添加到生成的 CMake 预设中。

  • tools.cmake.cmaketoolchain:user_presets:(实验性)允许为 CMakeUserPresets.json 文件设置自定义名称或子文件夹。空字符串完全禁用文件生成。

  • tools.build:cxxflags:将被附加到 CMAKE_CXX_FLAGS_INIT 的额外 C++ 标志列表。

  • tools.build:cflags:将被附加到 CMAKE_C_FLAGS_INIT 的额外纯 C 标志列表。

  • tools.build:sharedlinkflags:将被附加到 CMAKE_SHARED_LINKER_FLAGS_INIT 的额外链接器标志列表。

  • tools.build:exelinkflags:将被附加到 CMAKE_EXE_LINKER_FLAGS_INIT 的额外链接器标志列表。

  • tools.build:defines:将被 add_definitions() 使用的预处理器定义列表。

  • tools.apple:sdk_pathCMAKE_OSX_SYSROOT 的值。一般情况下不需要,将通过设置值传递给 CMake。

  • tools.apple:enable_bitcode:布尔值,用于启用/禁用 Bitcode Apple Clang 标志,例如 CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE

  • tools.apple:enable_arc:布尔值,用于启用/禁用 ARC Apple Clang 标志,例如 CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC

  • tools.apple:enable_visibility:布尔值,用于启用/禁用 Visibility Apple Clang 标志,例如 CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN

  • tools.build:sysroot:定义 CMAKE_SYSROOT 的值。

  • tools.microsoft:winsdk_version:根据 CMake 策略 CMP0149 定义 CMAKE_SYSTEM_VERSIONCMAKE_GENERATOR_PLATFORM

  • tools.build:compiler_executables:类似于字典的 Python 对象,指定编译器作为键,编译器可执行文件路径作为值。这些键将按如下方式映射:

    • c:将在 conan_toolchain.cmake 中设置 CMAKE_C_COMPILER

    • cpp:将在 conan_toolchain.cmake 中设置 CMAKE_CXX_COMPILER

    • RC:将在 conan_toolchain.cmake 中设置 CMAKE_RC_COMPILER

    • objc:将在 conan_toolchain.cmake 中设置 CMAKE_OBJC_COMPILER

    • objcpp:将在 conan_toolchain.cmake 中设置 CMAKE_OBJCXX_COMPILER

    • cuda:将在 conan_toolchain.cmake 中设置 CMAKE_CUDA_COMPILER

    • fortran:将在 conan_toolchain.cmake 中设置 CMAKE_Fortran_COMPILER

    • asm:将在 conan_toolchain.cmake 中设置 CMAKE_ASM_COMPILER

    • hip:将在 conan_toolchain.cmake 中设置 CMAKE_HIP_COMPILER

    • ispc:将在 conan_toolchain.cmake 中设置 CMAKE_ISPC_COMPILER