Cmake

简介

Cmake维基百科

Cmake官网

Cmake3.19Documentation

*Cmake用户接口

Cmake进阶指初识Cmake

Cmake使用方法详解博客园

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake, 只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows [Visual C++](https://baike.baidu.com/item/Visual C%2B%2B/1811800) 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件.

使用

CMake的所有的语句都写在一个叫:CMakeLists.txt的文件中。当CMakeLists.txt文件确定后,可以用ccmake命令对相关 的变量值进行配置。这个命令必须指向CMakeLists.txt所在的目录。配置完成之后,应用cmake命令生成相应的makefile(在Unix like系统下)或者 project文件(指定用window下的相应编程工具编译时)。

具体的操作流程:

  1. $> ccmake directory
  2. $> cmake directory
  3. $> make

其中directory为CMakeList.txt所在目录;

  • 第一条语句用于配置编译选项,如VTK_DIR目录 ,一般这一步不需要配置,直接执行第二条语句即可,但当出现错误时,这里就需要认为配置了,这一步才真正派上用场;
  • 第二条命令用于根据CMakeLists.txt生成Makefile文件;
  • 第三条命令用于执行Makefile文件,编译程序,生成可执行文件;

生成Buildsytem

Cmake是一个生成 生成项目文件的工具, Cmakelists就是生成 生成项目文件的文件, 这个生成项目文件就是Build System.

不同的系统的build tool是不一样的, Cmake会根据平台的不同选择默认的build tool,也可以自己设置,

命令行为

$ cmake .. -G Ninja

GUI设置过程为官网上说

The “Configure” button triggers a new dialog to select the CMake generator to use

但是我试了一下有点奇怪, 直接生成了, 没有弹出对话框.

设置Build Variables

常见内部变量

Variable Meaning
CMAKE_PREFIX_PATH Path to search for [dependent packages](https://cmake.org/cmake/help/v3.22/guide/using-dependencies/index.html#guide:Using Dependencies Guide)
CMAKE_MODULE_PATH Path to search for additional CMake modules
CMAKE_BUILD_TYPE Build configuration, such as Debug or Release, determining debug/optimization flags. This is only relevant for single-configuration buildsystems such as Makefile and Ninja. Multi-configuration buildsystems such as those for Visual Studio and Xcode ignore this setting.
CMAKE_INSTALL_PREFIX Location to install the software to with the install build target
CMAKE_TOOLCHAIN_FILE File containing cross-compiling data such as toolchains and sysroots.
BUILD_SHARED_LIBS Whether to build shared instead of static libraries for add_library() commands used without a type
CMAKE_EXPORT_COMPILE_COMMANDS Generate a compile_commands.json file for use with clang-based tools

其它的特殊变量也许是用于构建系统, 通常禁止或者允许项目的组件.

CMAKE_开头的是 Cmake 自己提供的变量, 其它人应该使用自己的前缀, cmake-gui 可以识别出这些变量,比如 biogears:

image-20211112222025541

内置变量的使用

  1. 在CMakeLists.txt中指定,使用set
  2. cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF

命令行参数

-G可以重写 Cmake 默认的 generater , 使用cmake --help可以本机支持的 generator:

$ cmake .. -G Ninja

-A是可以选择目标平台的体系结构,比如:

cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64

-T可以选择Visual Studio的工具集:

$ # Build with the clang-cl toolset
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T ClangCL
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp

-D可以设置变量值

$ mkdir build
$ cd build
$ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug

-U重置变量的值,比如

$ cd build
$ cmake . -UMyPackage_DIR

Cmake Cache

当首次执行时,CMake在包含键值对的构建目录中生成CMAKECACHE.TXT文件。可以通过运行cmake-gui(1) or ccmake(1) 工具来查看或编辑缓存文件。该工具提供了一个交互式界面,用于重新配置提供的软件并重新生成构建系统,如在编辑缓存值后所需的那样。每个缓存条目都可以具有关联的简短帮助文本,该文本显示在用户界面工具中。

Presets(预设参数)

Cmake识别CMakePresets.json和用户自定义的CMakeUserPresets.json来定义预定义参数,预定义参数列表, 这些都可以被用户自定义的参数覆盖,比如一个CMakePresets.json样例:

{
  "version": 1,
  "configurePresets": [
    {
      "name": "ninja-release",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "generator": "Ninja",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ]
}

然后运行

cmake -S /path/to/source --preset=ninja-release

就可以在/path/to/source/build/ninja-releaseNinja生成一个build目录。

用下面这条语句可以列出所有的可用presets:

cmake -S /path/to/source --list-presets

这条语句会列出可以哦那个prests在/path/to/source/CMakePresets.json and /path/to/source/CMakeUsersPresets.json without generating a build tree.

Invoking the Buildsystem

在生成buildsystem后,软件可以通过调用特殊的build tool的方法被构建。在IDE生成器的情况下,这可能涉及将生成的项目文件加载到IDE中以调用构建。

而cmake也知道用命令行构建是常用的, 下面的命令可以在build目录调用用于生成buildsystem或者project.

$ cmake --build .

--build打开一个cmake tool的特殊模式, 它调用了generatorCMAKE_MAKE_PROGRAM命令.或者是用户自定义配置指定的build tool.

--build也接收--target参数来指定特殊的目标来构建, 例如一个库, 执行文件或者自定义的目标就像install:

$ cmake --build . --target myexe

--build也接收--config参数用来在multi-config generators中指定某个配置来build:

$ cmake --build . --target myexe --config Release

--config参数在cmake时使用CMAKE_BUILD_TYPE时没有任何作用.

--verbose可以忽略提示信息:

$ cmake --build . --target myexe --verbose

--build还可以通过--提供更多的参数比如让cmake在失败时继续运行.

对于所有生成器,可以在调用CMake后运行底层构建工具。例如,可以在使用unix makefiles生成器生成之后执行,以在使用ninja生成器等生成后调用构建或ninja等。IDE构建系统通常提供用于构建也可以调用的项目的命令行工具。

Selecting a Target

每一个可执行文件库文件在Cmake files都是一个 build taget, buildsystem也可以描述根据用户需求自定义的目标,比如生成一个文档.

Cmake提供了一些内置的build targets:

  • all

    The default target used by Makefile and Ninja generators. Builds all targets in the buildsystem, except those which are excluded by their EXCLUDE_FROM_ALL target property or EXCLUDE_FROM_ALL directory property. The name ALL_BUILD is used for this purpose for the Xcode and Visual Studio generators.

  • help

    Lists the targets available for build. This target is available when using the [Unix Makefiles](https://cmake.org/cmake/help/v3.22/generator/Unix Makefiles.html#generator:Unix Makefiles) or Ninja generator, and the exact output is tool-specific.

  • clean

    Delete built object files and other output files. The Makefile based generators create a clean target per directory, so that an individual directory can be cleaned. The Ninja tool provides its own granular -t clean system.

  • test

    Runs tests. This target is only automatically available if the CMake files provide CTest-based tests. See also Running Tests.

  • install

    Installs the software. This target is only automatically available if the software defines install rules with the install() command. See also Software Installation.

  • package

    Creates a binary package. This target is only automatically available if the CMake files provide CPack-based packages.

  • package_source

    Creates a source package. This target is only automatically available if the CMake files provide CPack-based packages.

基于Makefile的系统也同样提供了build-targets来预处理, 汇编, 编译文件:

$ make foo.cpp.i
$ make foo.cpp.s
$ make foo.cpp.o

也提供了这种

$ make foo.i
$ make foo.s
$ make foo.o

Specifying a Build Program

CMAKE_MAKE_PROGRAM设置的模式可以用--build来被调用, 对于更多的generator, 特殊的程序不需要被配置,一些常见的Generator对应的make program:

Generator Default make program Alternatives
XCode xcodebuild
Unix Makefiles make
NMake Makefiles nmake jom
NMake Makefiles JOM jom nmake
MinGW Makefiles mingw32-make
MSYS Makefiles make
Ninja ninja
Visual Studio msbuild
Watcom WMake wmake

Software Installation

CMAKE_INSTALL_PREFIX可以在Cmake cache中设置为在哪里安装软件,如果软件有特殊的安装目录需求, 用install()命令可以用上面那个参数的安装路径, Windows默认的安装路径是ProgramFiles, Unix是/usr/local.

The CMAKE_INSTALL_PREFIX变量永远指向target filesystem 的installation prefix.

下面的命令:

$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DCMAKE_SYSROOT=$HOME/root \
  -DCMAKE_STAGING_PREFIX=/tmp/package
$ cmake --build .
$ cmake --build . --target install

会在目标机器安装 /tmp/package/lib/libfoo.so,目标机器的/usr/local不会被影响.

一些软件会提供uninstall规则, 但是Cmake默认不提供.

Running Tests

Cmake自带的ctest(1)工具可以提供测试和报告结果,虽然test的build-target可以运行所有可用的tests,但是ctest允许granular控制哪个tests可以运行, 如何运行, 如何报告结果.执行ctest命令在build directory里面是这样的:

$ ctest

使用正则表达式可以用来告诉运行哪些tests, 比如运行Qt的 tests 就可以这样:

$ctest -R Qt

也可以指定名字:

$ ctest -E Qt

也可以用-j参数指定并行线程数

$ ctest -R Qt -j8

环境变量中的CTEST_PARALLEL_LEVEL就可以用-j来代替.

默认的ctest不打印tests的输出, -v或者--verbose打印所有输出,--output-on-failure打印只报错的信息.设置CTEST_OUTPUT_ON_FAILURE1可以用来代替--output-on-failure这个参数.


欢迎在评论区中进行批评指正,转载请注明来源,如涉及侵权,请联系作者删除。

×

喜欢就点赞,疼爱就打赏