Ubuntu 22.04 CMake 安装与命令参数详解

Ubuntu 22.04 平台 CMake 3.22.1 在线与离线安装及全部核心命令参数(-S/-B/-D/-G/-U/-L/-LA/-LH/--build/--target/--install/--trace/-E)的真实回显详解。

Linux开发与编译工具链cmake2026/10/06

Ubuntu 22.04 CMake 安装与命令参数详解

目标:完成 CMake 在 Ubuntu 22.04 x86_64 环境下的在线安装与离线安装,并对 --version、-S、-B、-D、-G、-U、-L/-LA/-LH、--build、--target、--install、--trace、-E 子命令、--help-command 等核心参数逐条实测,配合一个静态库/共享库可切换的真实工程走通「配置 → 构建 → 运行 → 安装」全流程。所有命令与回显均在本机 Ubuntu 22.04 x86_64 环境实测采集。

一、环境信息

项目值
操作系统Ubuntu 22.04.5 LTS(Jammy Jellyfish)
内核版本6.8.0-138-generic
系统架构x86_64
包管理器apt
默认 C 编译器GCC 11.4.0(gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0)
GNU Make4.3
CMake 版本3.22.1(软件包版本 3.22.1-1ubuntu1.22.04.2)
软件源archive.ubuntu.com(jammy / jammy-updates / jammy-backports、security.ubuntu.com jammy-security)
操作用户root(非 root 用户执行安装类命令时请加 sudo 前缀)

系统与工具链版本实测:

$ head -4 /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"

$ uname -r
6.8.0-138-generic

$ uname -m
x86_64

$ gcc --version | head -1
gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

$ make --version | head -1
GNU Make 4.3

$ cmake --version
cmake version 3.22.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

二、工具概述

CMake 是一个跨平台、开源的构建系统生成工具(Cross-platform, open-source make system),由 Kitware 公司主导开发。它不直接参与编译,而是读取工程根目录下的 CMakeLists.txt 脚本,通过配置(Configure)阶段探测编译器、库、头文件等环境信息,再生成平台原生的构建文件(在 Linux 下默认生成 Makefile,也可生成 Ninja 工程),最后由 GNU Make 或 Ninja 完成实际的编译与链接。

核心要点:

  • 一次编写、多平台生成:同一份 CMakeLists.txt 在 Linux/Windows/macOS 上分别生成 Makefile、Visual Studio 工程、Xcode 工程,无需为每个平台单独维护构建脚本。
  • 与 GCC、Make 的分工:GCC 负责把 C/C++ 源文件编译成目标文件、链接成可执行文件或库;Make 负责按依赖关系调度编译;CMake 负责把「构建什么、怎么构建」的描述翻译成 Make/Ninja 能识别的规则。三者通常搭配使用:cmake -S . -B build 生成 Makefile,cmake --build build 或 make -C build 执行构建。
  • 与 build-essential 的关系:Ubuntu 官方 build-essential 元包提供 gcc/g++/make 等基础编译工具,CMake 安装后依赖系统已有的编译器工作,二者互补。
  • 典型使用场景:大型 C/C++ 工程(如 LLVM、OpenCV)、跨平台项目、需要控制编译选项(优化级别、宏定义、构建类型 Release/Debug)的项目、依赖第三方库(通过 find_package)的项目、需要统一「配置 → 构建 → 测试 → 安装」流程的项目。

三、在线安装方案

3.1 基础环境准备

Ubuntu 22.04 的 apt 软件源默认已配置好(/etc/apt/sources.list 指向 archive.ubuntu.com 与 security.ubuntu.com)。首次使用前先刷新软件包索引:

$ apt update
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Hit:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
Hit:3 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
Hit:4 http://security.ubuntu.com/ubuntu jammy-security InRelease
Reading package lists...
Building dependency tree...
Reading state information...
8 packages can be upgraded. Run 'apt list --upgradable' to see them.

💡 说明:非 root 用户请使用 sudo apt update。Hit: 表示对应源已在本地缓存命中,无需重新下载索引。

3.2 安装 cmake 软件包

$ apt install -y cmake
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  cmake-data
Suggested packages:
  cmake-doc ninja-build cmake-format
The following NEW packages will be installed:
  cmake cmake-data
0 upgraded, 2 newly installed, 0 to remove and 8 not upgraded.
Need to get 6923 kB of archives.
After this operation, 31.3 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cmake-data all 3.22.1-1ubuntu1.22.04.2 [1913 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cmake amd64 3.22.1-1ubuntu1.22.04.2 [5010 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 6923 kB in 5s (1470 kB/s)
Selecting previously unselected package cmake-data.
(Reading database ... 21583 files and directories currently installed.)
Preparing to unpack .../cmake-data_3.22.1-1ubuntu1.22.04.2_all.deb ...
Unpacking cmake-data (3.22.1-1ubuntu1.22.04.2) ...
Selecting previously unselected package cmake.
Preparing to unpack .../cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb ...
Unpacking cmake (3.22.1-1ubuntu1.22.04.2) ...
Setting up cmake-data (3.22.1-1ubuntu1.22.04.2) ...
Setting up cmake (3.22.1-1ubuntu1.22.04.2) ...

💡 说明:cmake-data 是 cmake 的架构无关数据包(包含模块文件与文档数据),由 apt 自动一并安装。安装过程中出现 debconf: delaying package configuration, since apt-utils is not installed 仅为提示,不影响安装结果。

3.3 验证安装与软件源候选版本

$ cmake --version
cmake version 3.22.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

$ apt-cache policy cmake
cmake:
  Installed: 3.22.1-1ubuntu1.22.04.2
  Candidate: 3.22.1-1ubuntu1.22.04.2
  Version table:
 *** 3.22.1-1ubuntu1.22.04.2 500
        500 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        100 /var/lib/dpkg/status
     3.22.1-1ubuntu1.22.04.2 500
        500 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages

💡 说明:apt-cache policy cmake 显示已安装版本(Installed)与候选版本(Candidate)均为 3.22.1-1ubuntu1.22.04.2,说明当前已是最新可安装版本。3.22.1-1ubuntu1 是 jammy 主仓库版本,3.22.1-1ubuntu1.22.04.2 是 jammy-updates 更新仓库版本(包含安全修复)。

四、离线安装方案

在内网或无法访问公网软件源的环境中,可先在联网机器上下载 .deb 安装包,再拷贝到目标机器用 dpkg -i 离线安装。

4.1 仅下载安装包(不安装)

apt install --download-only 只把软件包下载到本地缓存 /var/cache/apt/archives/,不执行安装:

$ apt install --download-only --no-install-recommends -y cmake
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  cmake-data
Suggested packages:
  cmake-doc ninja-build cmake-format
The following NEW packages will be installed:
  cmake cmake-data
0 upgraded, 2 newly installed, 0 to remove and 8 not upgraded.
Need to get 6923 kB of archives.
After this operation, 31.3 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cmake-data all 3.22.1-1ubuntu1.22.04.2 [1913 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cmake amd64 3.22.1-1ubuntu1.22.04.2 [5010 kB]
Fetched 6923 kB in 3s (2576 kB/s)
Download complete and in download only mode

💡 说明:--no-install-recommends 可避免拉取 Recommends 建议包(如 gcc、make 的重复依赖),让离线包最小化。命令执行后系统里并没有安装 cmake,只是下载了 .deb。

4.2 查看下载的安装包

$ ls -lh /var/cache/apt/archives/*.deb
-rw-r--r-- 1 root root 1.9M Feb 14  2024 /var/cache/apt/archives/cmake-data_3.22.1-1ubuntu1.22.04.2_all.deb
-rw-r--r-- 1 root root 4.8M Feb 14  2024 /var/cache/apt/archives/cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb

4.3 拷贝到离线目录

$ mkdir -p /opt/devchain-demo/cmake-ubuntu-test/offline
$ cp /var/cache/apt/archives/*.deb /opt/devchain-demo/cmake-ubuntu-test/offline/
$ ls -lh /opt/devchain-demo/cmake-ubuntu-test/offline/
total 6.7M
-rw-r--r-- 1 root root 1.9M Oct  6 06:22 cmake-data_3.22.1-1ubuntu1.22.04.2_all.deb
-rw-r--r-- 1 root root 4.8M Oct  6 06:22 cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb

⚠️ 注意:拷贝目标机器后,两个 .deb 都要保留。cmake-data 与 cmake 相互依赖,漏掉任何一个都会导致 dpkg -i 报依赖错误。

4.4 查看 deb 包控制信息

dpkg-deb -I(info)查看 deb 包元数据,包括包名、版本、架构、依赖关系与描述:

$ dpkg-deb -I /opt/devchain-demo/cmake-ubuntu-test/offline/cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb
 new Debian package, version 2.0.
 size 5010038 bytes: control archive=1378 bytes.
    1438 bytes,    27 lines      control
     915 bytes,    14 lines      md5sums
 Package: cmake
 Version: 3.22.1-1ubuntu1.22.04.2
 Architecture: amd64
 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
 Installed-Size: 20742
 Depends: libarchive13 (>= 3.3.3), libc6 (>= 2.34), libcurl4 (>= 7.16.2), libexpat1 (>= 2.0.1), libgcc-s1 (>= 3.3.1), libjsoncpp25 (>= 1.9.5), librhash0 (>= 1.2.6), libstdc++6 (>= 12), libuv1 (>= 1.38.0), zlib1g (>= 1:1.1.4), cmake-data (= 3.22.1-1ubuntu1.22.04.2), procps
 Recommends: gcc, make
 Suggests: cmake-doc, ninja-build, cmake-format
 Section: devel
 Priority: optional
 Multi-Arch: foreign
 Homepage: https://cmake.org/
 Description: cross-platform, open-source make system
  CMake is used to control the software compilation process using
  simple platform and compiler independent configuration files. CMake
  generates native makefiles and workspaces that can be used in the
  compiler environment of your choice. CMake is quite sophisticated: it
  is possible to support complex environments requiring system
  configuration, pre-processor generation, code generation, and template
  instantiation.

💡 说明:Depends 列出运行 cmake 所需的全部动态库与依赖包。标准 Ubuntu 22.04 服务器通常已具备 libc6、libstdc++6、zlib1g 等基础库;若离线机器缺少其中某些库,需一并下载对应 deb 包。

4.5 离线安装并验证

$ dpkg -i /opt/devchain-demo/cmake-ubuntu-test/offline/*.deb
Selecting previously unselected package cmake-data.
(Reading database ... 21614 files and directories currently installed.)
Preparing to unpack .../cmake-data_3.22.1-1ubuntu1.22.04.2_all.deb ...
Unpacking cmake-data (3.22.1-1ubuntu1.22.04.2) ...
Selecting previously unselected package cmake.
Preparing to unpack .../cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb ...
Unpacking cmake (3.22.1-1ubuntu1.22.04.2) ...
Setting up cmake-data (3.22.1-1ubuntu1.22.04.2) ...
Setting up cmake (3.22.1-1ubuntu1.22.04.2) ...

$ cmake --version
cmake version 3.22.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

⚠️ 注意:dpkg -i 若因缺少依赖失败,会提示 dependency problems,此时可用 apt install -f 修复依赖,或补充下载缺失的依赖 deb 包后重新执行 dpkg -i。本环境依赖库齐备,直接安装成功。

五、命令与参数详解

本章节所有命令与回显均在本机实测。演示工程位于 /opt/devchain-demo/cmake-ubuntu-test(工程内容见「六、配置说明」),包含一个静态/共享库可切换的库目标 foo 与一个可执行目标 demo。

5.1 版本与帮助参数

5.1.1 --version:查看版本

$ cmake --version
cmake version 3.22.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

5.1.2 --help:查看用法与全部参数

$ cmake --help
Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
  cmake [options] -S <path-to-source> -B <path-to-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Options
  -S <path-to-source>          = Explicitly specify a source directory.
  -B <path-to-build>           = Explicitly specify a build directory.
  -C <initial-cache>           = Pre-load a script to populate the cache.
  -D <var>[:<type>]=<value>    = Create or update a cmake cache entry.
  -U <globbing_expr>           = Remove matching entries from CMake cache.
  -G <generator-name>          = Specify a build system generator.
  -T <toolset-name>            = Specify toolset name if supported by
                                 generator.
  -A <platform-name>           = Specify platform name if supported by
                                 generator.
  --toolchain <file>           = Specify toolchain file
                                 [CMAKE_TOOLCHAIN_FILE].
  --install-prefix <directory> = Specify install directory
                                 [CMAKE_INSTALL_PREFIX].
  -E                           = CMake command mode.
  -L[A][H]                     = List non-advanced cached variables.
  --build <dir>                = Build a CMake-generated project binary tree.
  --install <dir>              = Install a CMake-generated project binary
                                 tree.
  --trace                      = Put cmake in trace mode.
  --warn-uninitialized         = Warn about uninitialized values.
  --help,-help,-usage,-h,-H,/? = Print usage information and exit.
  --version,-version,/V [<f>]  = Print version number and exit.
  --help-command <cmd> [<f>]   = Print help for one command and exit.
  --help-command-list [<f>]    = List commands with help available and exit.
  ...

Generators 段落(当前平台可用生成器,* 为默认):

Generators

The following generators are available on this platform (* marks default):
  Green Hills MULTI            = Generates Green Hills MULTI files
                                 (experimental, work-in-progress).
* Unix Makefiles               = Generates standard UNIX makefiles.
  Ninja                        = Generates build.ninja files.
  Ninja Multi-Config           = Generates build-<Config>.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.

💡 说明:未加 -G 时默认使用 Unix Makefiles 生成器,即生成 Makefile 交给 make 执行。

5.1.3 --help-command <命令>:查看单个 CMake 命令的帮助

add_executable 帮助(片段):

$ cmake --help-command add_executable
add_executable
--------------

Add an executable to the project using the specified source files.

Normal Executables
^^^^^^^^^^^^^^^^^^

 add_executable(<name> [WIN32] [MACOSX_BUNDLE]
                [EXCLUDE_FROM_ALL]
                [source1] [source2 ...])

Adds an executable target called ``<name>`` to be built from the source
files listed in the command invocation.  The
``<name>`` corresponds to the logical target name and must be globally
unique within a project.  The actual file name of the executable built is
constructed based on conventions of the native platform (such as
``<name>.exe`` or just ``<name>``).

.. versionadded:: 3.1
  Source arguments to ``add_executable`` may use "generator expressions" with
  the syntax ``$<...>``.  See the ``cmake-generator-expressions(7)``
  manual for available expressions.

.. versionadded:: 3.11
  The source files can be omitted if they are added later using
  ``target_sources()``.

By default the executable file will be created in the build tree
directory corresponding to the source tree directory in which the
command was invoked.  See documentation of the
``RUNTIME_OUTPUT_DIRECTORY`` target property to change this
location.  See documentation of the ``OUTPUT_NAME`` target property
to change the ``<name>`` part of the final file name.

If ``WIN32`` is given the property ``WIN32_EXECUTABLE`` will be
set on the target created.  See documentation of that target property for
details.

add_library 帮助(片段):

$ cmake --help-command add_library
add_library
-----------

Add a library to the project using the specified source files.

Normal Libraries
^^^^^^^^^^^^^^^^

 add_library(<name> [STATIC | SHARED | MODULE]
             [EXCLUDE_FROM_ALL]
             [<source>...])

Adds a library target called ``<name>`` to be built from the source files
listed in the command invocation.  The ``<name>``
corresponds to the logical target name and must be globally unique within
a project.  The actual file name of the library built is constructed based
on conventions of the native platform (such as ``lib<name>.a`` or
``<name>.lib``).

.. versionadded:: 3.1
  Source arguments to ``add_library`` may use "generator expressions" with
  the syntax ``$<...>``.  See the ``cmake-generator-expressions(7)``
  manual for available expressions.

.. versionadded:: 3.11
  The source files can be omitted if they are added later using
  ``target_sources()``.

``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of
library to be created.  ``STATIC`` libraries are archives of object files

💡 说明:--help-command 输出的反引号(`)与 reStructuredText 标记是 CMake 帮助文档的原样排版,直接照抄即可。

5.2 配置阶段参数:-S、-B、-D、-G、-U、-L/-LA/-LH

5.2.1 -S <源目录> 与 -B <构建目录>:指定源目录与构建目录

-S 指定工程源目录(含 CMakeLists.txt),-B 指定构建目录(生成 Makefile、CMakeCache.txt 等构建文件的目录)。二者配对使用是现代 CMake 推荐写法,避免在源目录里生成构建产物:

$ cmake -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build
-- The C 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
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build

💡 说明:配置阶段探测了编译器(GNU 11.4.0,即 gcc 11.4)、编译器 ABI 信息与 C 语言特性(C standard features);Configuring done 表示解析 CMakeLists.txt 完成,Generating done 表示构建文件已生成。

⚠️ 注意:对同一构建目录重复执行 cmake -S ... -B ... 会复用已有 CMakeCache.txt 增量重新配置,不会重复打印编译器探测信息;若 CMakeLists.txt 或缓存条目发生变化会重新生成对应规则。

5.2.2 -D <变量>=<值>:创建或修改缓存条目

-D 可向 CMakeCache.txt 写入或覆盖缓存变量,常用于指定构建类型(CMAKE_BUILD_TYPE)、开关宏(BUILD_SHARED_LIBS)等。本例以 Release 构建类型 + 共享库模式配置第二个构建目录:

$ cmake -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build_d -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
-- 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
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build_d

验证写入缓存的条目:

$ grep -E "CMAKE_BUILD_TYPE|BUILD_SHARED_LIBS" /opt/devchain-demo/cmake-ubuntu-test/build_d/CMakeCache.txt
BUILD_SHARED_LIBS:BOOL=ON
CMAKE_BUILD_TYPE:STRING=Release

💡 说明:CMAKE_BUILD_TYPE=Release 使编译器使用 -O3 -DNDEBUG 优化(见 5.2.5 中 CMAKE_C_FLAGS_RELEASE);BUILD_SHARED_LIBS=ON 使工程按 if(BUILD_SHARED_LIBS) 分支生成共享库 libfoo.so(默认 OFF 时生成静态库 libfoo.a,见「六、配置说明」的 CMakeLists.txt)。

5.2.3 -G <生成器>:指定构建系统生成器

显式指定 Unix Makefiles 生成器(与默认一致,此处演示显式指定写法):

$ cmake -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build_mk -G "Unix Makefiles"
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build_mk

生成的 Makefile 头部(-G 生效的直接证据):

$ head -3 /opt/devchain-demo/cmake-ubuntu-test/build_mk/Makefile
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.22

💡 说明:若机器装有 Ninja,可改用 -G Ninja 生成 build.ninja(构建更快);-G 必须与首次配置同一并指定,否则切换生成器前需清空构建目录。

5.2.4 -U <匹配表达式>:删除缓存条目

-U 按 glob 匹配删除 CMakeCache.txt 中的条目。演示:先从缓存中删除 CMAKE_BUILD_TYPE(此前为 Release),再重新配置:

$ grep -n "CMAKE_BUILD_TYPE" /opt/devchain-demo/cmake-ubuntu-test/build_d/CMakeCache.txt
28:CMAKE_BUILD_TYPE:STRING=Release

$ cmake -U CMAKE_BUILD_TYPE -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build_d
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build_d

$ grep -n "CMAKE_BUILD_TYPE" /opt/devchain-demo/cmake-ubuntu-test/build_d/CMakeCache.txt
28:CMAKE_BUILD_TYPE:STRING=

💡 说明:-U 支持通配符,例如 cmake -U CMAKE_* 可删除所有 CMAKE_ 开头的缓存条目。删除后该条目按默认值重建(如上例变为空值),即回到「未指定构建类型」的默认状态。

5.2.5 -L / -LA / -LH:列出缓存变量

  • -L:列出非高级(non-advanced)缓存变量;
  • -LA:列出全部缓存变量(含高级变量);
  • -LH:列出非高级缓存变量并附帮助文本。

⚠️ 注意:-L 系列会执行一次配置(以当前工作目录为构建目录),为不污染工程目录,以下实测在临时目录 /tmp/lsx 中执行。

cmake -L -S <源目录>:

$ cd /tmp/lsx
$ cmake -L -S /opt/devchain-demo/cmake-ubuntu-test
-- The C 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
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/lsx
-- Cache values
BUILD_SHARED_LIBS:BOOL=OFF
CMAKE_BUILD_TYPE:STRING=
CMAKE_INSTALL_PREFIX:PATH=/usr/local

cmake -LA -S <源目录>(开头片段):

$ cmake -LA -S /opt/devchain-demo/cmake-ubuntu-test
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/lsx
-- Cache values
BUILD_SHARED_LIBS:BOOL=OFF
CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
CMAKE_AR:FILEPATH=/usr/bin/ar
CMAKE_BUILD_TYPE:STRING=
CMAKE_COLOR_MAKEFILE:BOOL=ON
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-11
CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-11
CMAKE_C_FLAGS:STRING=
CMAKE_C_FLAGS_DEBUG:STRING=-g
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
...

cmake -LA 结尾片段(编译器工具链相关):

$ cmake -LA -S /opt/devchain-demo/cmake-ubuntu-test
...
CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
CMAKE_EXE_LINKER_FLAGS:STRING=
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
CMAKE_INSTALL_PREFIX:PATH=/usr/local
CMAKE_LINKER:FILEPATH=/usr/bin/ld
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake
CMAKE_MODULE_LINKER_FLAGS:STRING=
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_NM:FILEPATH=/usr/bin/nm
CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
CMAKE_READELF:FILEPATH=/usr/bin/readelf
CMAKE_SHARED_LINKER_FLAGS:STRING=
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
CMAKE_SKIP_RPATH:BOOL=NO
CMAKE_STATIC_LINKER_FLAGS:STRING=
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_STRIP:FILEPATH=/usr/bin/strip
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE

cmake -LH -S <源目录>(带帮助文本):

$ cmake -LH -S /opt/devchain-demo/cmake-ubuntu-test
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/lsx
-- Cache values
// Build shared libraries
BUILD_SHARED_LIBS:BOOL=OFF

// Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ...
CMAKE_BUILD_TYPE:STRING=

// Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local

💡 说明:// 开头 的行是缓存变量的帮助文本(来自 CMakeLists.txt 中 option 或 set(... CACHE ...) 的注释参数)。CMAKE_C_FLAGS_RELEASE=-O3 -DNDEBUG 印证了 5.2.2 中 -DCMAKE_BUILD_TYPE=Release 的实际编译参数来源。

5.3 构建阶段参数:--build、--target

5.3.1 --build <构建目录>:执行构建

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build
[ 25%] Building C object CMakeFiles/foo.dir/lib/foo.c.o
[ 50%] Linking C static library libfoo.a
[ 50%] Built target foo
[ 75%] Building C object CMakeFiles/demo.dir/main.c.o
[100%] Linking C executable demo
[100%] Built target demo

运行生成的可执行文件:

$ /opt/devchain-demo/cmake-ubuntu-test/build/demo
hello cmake, foo(2, 3) = 5

构建目录内容:

$ ls -l /opt/devchain-demo/cmake-ubuntu-test/build/
total 52
-rw-r--r-- 1 root root 12547 Oct  6 06:23 CMakeCache.txt
drwxr-xr-x 6 root root  4096 Oct  6 06:23 CMakeFiles
-rw-r--r-- 1 root root  8175 Oct  6 06:23 Makefile
-rw-r--r-- 1 root root  2643 Oct  6 06:23 cmake_install.cmake
-rwxr-xr-x 1 root root 16024 Oct  6 06:23 demo
-rw-r--r-- 1 root root  1376 Oct  6 06:23 libfoo.a

💡 说明:--build 等价于在构建目录内执行 make,但省去了切换目录,且不依赖具体生成器(对 Ninja 同样生效)。demo 是可执行文件(16024 字节),libfoo.a 是静态库(1376 字节)。

增量构建(第二次 --build,只重做发生变化的步骤):

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build
[ 50%] Built target foo
Consolidate compiler generated dependencies of target demo
[100%] Built target demo

💡 说明:增量构建时 foo 与 demo 均显示 Built target 而不再重新编译,这正是 Makefile 依赖机制的效果。

5.3.2 --target <目标名>:只构建指定目标

只构建库目标 foo:

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build --target foo
Consolidate compiler generated dependencies of target foo
[100%] Built target foo

只构建可执行目标 demo(会自动补齐依赖的 foo):

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build --target demo
[ 50%] Built target foo
[100%] Built target demo

清理目标 clean(删除已生成的目标文件与产物,无输出、退出码为 0):

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build --target clean
$ ls /opt/devchain-demo/cmake-ubuntu-test/build/
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake

⚠️ 注意:--target clean 后 demo 与 libfoo.a 已被删除,构建目录仅剩构建系统文件;需要重新构建时再次执行 cmake --build <build> 即可。

5.4 安装阶段参数:--install

--install <构建目录> 按 CMakeLists.txt 中 install(TARGETS ...) 的规则安装产物;--prefix 可覆盖默认安装前缀(默认 /usr/local):

$ cmake --install /opt/devchain-demo/cmake-ubuntu-test/build_d --prefix /opt/devchain-demo/cmake-ubuntu-test/inst
-- Install configuration: ""
-- Installing: /opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo
-- Set runtime path of "/opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo" to ""
-- Installing: /opt/devchain-demo/cmake-ubuntu-test/inst/lib/libfoo.so

查看安装结果:

$ find /opt/devchain-demo/cmake-ubuntu-test/inst -type f
/opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo
/opt/devchain-demo/cmake-ubuntu-test/inst/lib/libfoo.so

💡 说明:本例对 build_d(共享库版本)执行安装:可执行文件 demo 安装到 bin/,共享库 libfoo.so 安装到 lib/,与 CMakeLists.txt 中 RUNTIME DESTINATION bin、LIBRARY DESTINATION lib、ARCHIVE DESTINATION lib 对应。若安装静态库版本(build),则 libfoo.a 会按 ARCHIVE DESTINATION 装到 lib/。

5.5 调试跟踪参数:--trace

--trace 打印配置过程中执行的每一条 CMake 命令及其来源文件与行号,用于排查 CMakeLists.txt 逻辑:

$ cmake --trace -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build_trace 2>&1 | head -20
/opt/devchain-demo/cmake-ubuntu-test/CMakeLists.txt(1):  cmake_minimum_required(VERSION 3.10 )Running with trace output on.

/opt/devchain-demo/cmake-ubuntu-test/CMakeLists.txt(3):  project(CmakeDemo VERSION 1.0.0 LANGUAGES C )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(35):  if(CMAKE_HOST_UNIX )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(36):  find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(37):  if(CMAKE_UNAME )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(38):  if(CMAKE_HOST_SYSTEM_NAME STREQUAL AIX )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(44):  else()
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(45):  exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(47):  if(CMAKE_HOST_SYSTEM_NAME MATCHES Linux|CYGWIN.*|MSYS.*|^GNU$|Android )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(48):  exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(97):  if(${val} GREATER 0 )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(100):  set(CMAKE_UNAME ${CMAKE_UNAME} CACHE INTERNAL uname command )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(102):  string(REPLACE \"  CMAKE_HOST_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR} )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(103):  string(REPLACE / _ CMAKE_HOST_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR} )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(119):  if(CMAKE_TOOLCHAIN_FILE )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(139):  if(CMAKE_SYSTEM_NAME )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(144):  elseif(CMAKE_VS_WINCE_VERSION )
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(150):  else()
/usr/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake(151):  set(CMAKE_SYSTEM_NAME ${CMAKE_HOST_SYSTEM_NAME} )

💡 说明:2>&1 | head -20 用于截取前 20 行(trace 输出默认走 stderr)。可见 trace 不仅跟踪工程 CMakeLists.txt,也跟踪 cmake 内置模块(/usr/share/cmake-3.22/Modules/)的执行过程。相关变体:--trace-expand(展开变量后的命令)、--trace-redirect=<文件>(输出重定向到文件)。

5.6 命令模式 -E 子命令

cmake -E <子命令> 以命令行工具方式调用 CMake 内置的跨平台小工具,不依赖工程文件。

5.6.1 -E echo:打印文本

$ cmake -E echo "hello cmake"
hello cmake

5.6.2 -E make_directory:创建目录

$ cmake -E make_directory /opt/devchain-demo/cmake-ubuntu-test/x

💡 说明:命令无输出即成功(退出码 0),并会自动创建父目录。

5.6.3 -E touch 与 -E echo 配合写入文件

$ cmake -E touch /opt/devchain-demo/cmake-ubuntu-test/x/t.txt
$ cmake -E echo "hello from cmake -E" > /opt/devchain-demo/cmake-ubuntu-test/x/t.txt
$ cmake -E cat /opt/devchain-demo/cmake-ubuntu-test/x/t.txt
hello from cmake -E

💡 说明:touch 创建空文件(已存在则更新时间戳);echo 默认输出到标准输出,配合 > 重定向即可向文件写入内容;cat 打印文件内容。

5.6.4 -E ls:实测结论——cmake 3.22.1 无此子命令

执行 cmake -E ls 会直接报错并打印全部可用子命令(真实回显):

$ cmake -E ls /opt/devchain-demo/cmake-ubuntu-test/x
CMake Error: cmake version 3.22.1
Usage: cmake -E <command> [arguments...]
Available commands:
  capabilities              - Report capabilities built into cmake in JSON format
  cat <files>...            - concat the files and print them to the standard output
  chdir dir cmd [args...]   - run command in a given directory
  compare_files [--ignore-eol] file1 file2
                              - check if file1 is same as file2
  copy <file>... destination  - copy files to destination (either file or directory)
  copy_directory <dir>... destination   - copy content of <dir>... directories to 'destination' directory
  copy_if_different <file>... destination  - copy files if it has changed
  echo [<string>...]        - displays arguments as text
  echo_append [<string>...] - displays arguments as text but no new line
  env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...
                            - run command in a modified environment
  environment               - display the current environment
  make_directory <dir>...   - create parent and <dir> directories
  md5sum <file>...          - create MD5 checksum of files
  sha1sum <file>...         - create SHA1 checksum of files
  sha224sum <file>...       - create SHA224 checksum of files
  sha256sum <file>...       - create SHA256 checksum of files
  sha384sum <file>...       - create SHA384 checksum of files
  sha512sum <file>...       - create SHA512 checksum of files
  remove [-f] <file>...     - remove the file(s), use -f to force it (deprecated: use rm instead)
  remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)
  rename oldname newname    - rename a file or directory (on one volume)
  rm [-rRf] <file/dir>...    - remove files or directories, use -f to force it, r or R to remove directories and their contents recursively
  sleep <number>...         - sleep for given number of seconds
  tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]
                            - create or extract a tar or zip archive
  time command [args...]    - run command and display elapsed time
  touch <file>...           - touch a <file>.
  touch_nocreate <file>...  - touch a <file> but do not create it.
  create_symlink old new    - create a symbolic link new -> old
  create_hardlink old new   - create a hard link new -> old
  true                      - do nothing with an exit code of 0
  false                      - do nothing with an exit code of 1

⚠️ 注意:cmake 3.22.1 的 -E 模式没有 ls 子命令(上表为完整可用列表),需要列出目录内容时请用系统命令(如 ls、find)或 cmake -E cat 查看文件内容。

5.6.5 -E rm:删除文件或目录

$ cmake -E rm -rf /opt/devchain-demo/cmake-ubuntu-test/x

💡 说明:rm 用法与系统 rm 一致,-r 递归删除目录、-f 强制删除;无输出即成功(退出码 0)。

5.6.6 -E copy:复制文件

$ cmake -E copy /opt/devchain-demo/cmake-ubuntu-test/main.c /opt/devchain-demo/cmake-ubuntu-test/main_copy.c
$ ls -l /opt/devchain-demo/cmake-ubuntu-test/main_copy.c
-rw-r--r-- 1 root root 130 Oct  6 06:25 /opt/devchain-demo/cmake-ubuntu-test/main_copy.c

5.6.7 -E md5sum:计算 MD5 校验值

$ cmake -E md5sum /opt/devchain-demo/cmake-ubuntu-test/main.c
67e1eba70ec653814f073a95aff6f09f  /opt/devchain-demo/cmake-ubuntu-test/main.c

💡 说明:md5sum 输出格式与系统 md5sum 一致(哈希值 + 两空格 + 文件名),另有 sha1sum/sha256sum 等对应子命令。

5.6.8 -E tar:打包与列出归档

$ cmake -E tar czf demo_src.tar.gz main.c lib
$ ls -lh demo_src.tar.gz
-rw-r--r-- 1 root root 328 Oct  6 06:25 demo_src.tar.gz

$ cmake -E tar tzf demo_src.tar.gz
main.c
lib/
lib/foo.c
lib/foo.h

💡 说明:czf 中的 c 表示创建、z 表示 gzip 压缩、f 指定归档文件名;tzf 表示列出(t)压缩归档内容。-E tar 是跨平台一致的打包方式,不依赖系统 tar 版本差异。

5.6.9 -E time:运行命令并计时

$ cmake -E time ./build/demo
hello cmake, foo(2, 3) = 5
Elapsed time: 0 s. (time), 0.000804 s. (clock)

💡 说明:输出第一行是被执行命令自身的输出(demo 运行结果),第二行是耗时统计:0 s. (time) 为 wall time(墙钟时间),0.000804 s. (clock) 为 CPU 时间。

5.6.10 -E capabilities:输出 CMake 能力清单

$ cmake -E capabilities
{"fileApi":{"requests":[{"kind":"codemodel","version":[{"major":2,"minor":3}]},{"kind":"cache","version":[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":[{"major":1,"minor":0}]},{"kind":"toolchains","version":[{"major":1,"minor":0}]}]},"generators":[{"extraGenerators":[],"name":"Watcom WMake","platformSupport":false,"toolsetSupport":false},{"extraGenerators":[],"name":"Ninja Multi-Config","platformSupport":false,"toolsetSupport":false},{"extraGenerators":["CodeBlocks","CodeLite","Eclipse CDT4","Kate","Sublime Text 2"],"name":"Ninja","platformSupport":false,"toolsetSupport":false},{"extraGenerators":["CodeBlocks","CodeLite","Eclipse CDT4","Kate","Sublime Text 2"],"name":"Unix Makefiles","platformSupport":false,"toolsetSupport":false},{"extraGenerators":[],"name":"Green Hills MULTI","platformSupport":true,"toolsetSupport":true}],"serverMode":false,"version":{"isDirty":false,"major":3,"minor":22,"patch":1,"string":"3.22.1","suffix":""}}

5.7 add_executable 与 add_library 完整示例:配置 → 构建 → 运行 → 安装

以演示工程(CMakeLists.txt 全文见「六、配置说明」)为例走通全流程。工程包含:add_library(foo STATIC/SHARED ...) 库目标、add_executable(demo ...) 可执行目标、target_include_directories 与 target_link_libraries 依赖关系、install(TARGETS ...) 安装规则。

步骤一:配置(-S -B)

$ cmake -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build
-- The C 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
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build

步骤二:构建(--build)

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build
[ 25%] Building C object CMakeFiles/foo.dir/lib/foo.c.o
[ 50%] Linking C static library libfoo.a
[ 50%] Built target foo
[ 75%] Building C object CMakeFiles/demo.dir/main.c.o
[100%] Linking C executable demo
[100%] Built target demo

💡 说明:默认 BUILD_SHARED_LIBS=OFF,走 add_library(foo STATIC ...) 分支,生成静态库 libfoo.a。

步骤三:运行

$ /opt/devchain-demo/cmake-ubuntu-test/build/demo
hello cmake, foo(2, 3) = 5

步骤四:切换到共享库再走一遍(-D)

$ cmake -S /opt/devchain-demo/cmake-ubuntu-test -B /opt/devchain-demo/cmake-ubuntu-test/build_d -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
-- 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
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/devchain-demo/cmake-ubuntu-test/build_d

$ cmake --build /opt/devchain-demo/cmake-ubuntu-test/build_d
[ 25%] Building C object CMakeFiles/foo.dir/lib/foo.c.o
[ 50%] Linking C shared library libfoo.so
[ 50%] Built target foo
[ 75%] Building C object CMakeFiles/demo.dir/main.c.o
[100%] Linking C executable demo
[100%] Built target demo

$ /opt/devchain-demo/cmake-ubuntu-test/build_d/demo
hello cmake, foo(2, 3) = 5

$ ls -l /opt/devchain-demo/cmake-ubuntu-test/build_d/ | grep -E "libfoo|demo"
-rwxr-xr-x 1 root root 16000 Oct  6 06:24 demo
-rwxr-xr-x 1 root root 15136 Oct  6 06:24 libfoo.so

💡 说明:-DBUILD_SHARED_LIBS=ON 使 add_library(foo SHARED ...) 分支生效,生成共享库 libfoo.so(15136 字节);demo 通过 build tree 内的 rpath 找到该共享库,因此可直接运行。

步骤五:安装(--install)

$ cmake --install /opt/devchain-demo/cmake-ubuntu-test/build_d --prefix /opt/devchain-demo/cmake-ubuntu-test/inst
-- Install configuration: ""
-- Installing: /opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo
-- Set runtime path of "/opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo" to ""
-- Installing: /opt/devchain-demo/cmake-ubuntu-test/inst/lib/libfoo.so

$ find /opt/devchain-demo/cmake-ubuntu-test/inst -type f
/opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo
/opt/devchain-demo/cmake-ubuntu-test/inst/lib/libfoo.so

💡 说明:install(TARGETS demo foo ...) 中 RUNTIME DESTINATION bin(可执行文件 demo)、LIBRARY DESTINATION lib(共享库 libfoo.so)、ARCHIVE DESTINATION lib(静态库 libfoo.a)三条规则分别对应三类产物。

六、配置说明

6.1 工程目录结构

/opt/devchain-demo/cmake-ubuntu-test/
├── CMakeLists.txt
├── main.c
├── lib/
│   ├── foo.c
│   └── foo.h
├── build/       (cmake -S ... -B build 生成的构建目录)
├── build_d/     (-D 参数生成的 Release 共享库构建目录)
├── build_mk/    (-G "Unix Makefiles" 生成)
└── offline/     (离线安装包目录)

6.2 CMakeLists.txt(完整内容,原样录入)

cmake_minimum_required(VERSION 3.10)

project(CmakeDemo VERSION 1.0.0 LANGUAGES C)

option(BUILD_SHARED_LIBS "Build shared libraries" OFF)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

if(BUILD_SHARED_LIBS)
    add_library(foo SHARED lib/foo.c)
else()
    add_library(foo STATIC lib/foo.c)
endif()

target_include_directories(foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lib)

add_executable(demo main.c)
target_link_libraries(demo PRIVATE foo)

install(TARGETS demo foo
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)

指令说明:

  • cmake_minimum_required(VERSION 3.10):声明所需 CMake 最低版本,低于 3.10 会报错退出。
  • project(CmakeDemo VERSION 1.0.0 LANGUAGES C):声明工程名、版本号与语言(C)。LANGUAGES C 只启用 C 编译器探测。
  • option(BUILD_SHARED_LIBS "Build shared libraries" OFF):声明布尔型缓存开关 BUILD_SHARED_LIBS,默认 OFF;可用 -DBUILD_SHARED_LIBS=ON 从命令行覆盖(见 5.2.2、5.7)。
  • set(CMAKE_C_STANDARD 11) 与 set(CMAKE_C_STANDARD_REQUIRED ON):要求按 C11 标准编译,编译器不支持时视为错误。
  • add_library(foo SHARED/STATIC lib/foo.c):创建库目标 foo,源文件为 lib/foo.c;SHARED 生成 libfoo.so,STATIC 生成 libfoo.a。
  • target_include_directories(foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lib):为 foo 及其使用者(PUBLIC 传递)添加头文件搜索路径 lib/。
  • add_executable(demo main.c):创建可执行目标 demo,源文件为 main.c。
  • target_link_libraries(demo PRIVATE foo):demo 链接库目标 foo(PRIVATE 表示仅 demo 自身需要)。
  • install(TARGETS demo foo ...):定义安装规则:可执行文件装到 bin/,共享库装到 lib/,静态库装到 lib/。

6.3 源文件内容

main.c:

#include <stdio.h>
#include "foo.h"

int main(void)
{
    printf("hello cmake, foo(2, 3) = %d\n", foo_add(2, 3));
    return 0;
}

lib/foo.h:

#ifndef FOO_H
#define FOO_H

int foo_add(int a, int b);

#endif

lib/foo.c:

#include "foo.h"

int foo_add(int a, int b)
{
    return a + b;
}

💡 说明:main.c 通过 #include "foo.h" 使用库接口 foo_add;头文件搜索路径正是由 6.2 的 target_include_directories(foo PUBLIC ...) 提供的。

6.4 CMakeCache.txt 关键条目

构建目录下的 CMakeCache.txt 保存配置阶段的缓存变量(文本格式,可读可改):

$ grep -E "CMAKE_BUILD_TYPE|BUILD_SHARED_LIBS|CMAKE_C_COMPILER:" /opt/devchain-demo/cmake-ubuntu-test/build/CMakeCache.txt
BUILD_SHARED_LIBS:BOOL=OFF
CMAKE_BUILD_TYPE:STRING=
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc

💡 说明:缓存条目格式为 变量名:变量类型=值;BOOL 布尔型(OFF/ON)、STRING 字符串型、FILEPATH 文件路径型。修改缓存的推荐方式是用 -D 参数重新配置,直接编辑该文件虽可行但易出错。

6.5 生成文件说明

-S/-B 配置后构建目录生成的关键文件:

$ ls /opt/devchain-demo/cmake-ubuntu-test/build/
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
  • Makefile:由 Unix Makefiles 生成器生成的顶层构建脚本,make 读取它执行构建;
  • CMakeCache.txt:配置缓存(见 6.4);
  • CMakeFiles/:内部目录,存放编译依赖信息、目标文件目录等;
  • cmake_install.cmake:安装脚本,--install 调用它执行安装。

Makefile 头部(真实内容):

$ head -10 /opt/devchain-demo/cmake-ubuntu-test/build/Makefile
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.22

# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target

# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:

⚠️ 注意:Makefile 头部明确标注「CMAKE generated file: DO NOT EDIT!」——构建文件由 cmake 生成,手工修改会在下次重新配置时被覆盖。要改变构建行为,请改 CMakeLists.txt 后重新配置。

七、常见问题(FAQ)

Q1:执行 cmake 提示 cmake: command not found?

A:说明 cmake 未安装。执行 apt install -y cmake(在线)或按第四章离线安装。

Q2:cmake -E ls 为什么报 Usage 错误?

A:cmake 3.22.1 的 -E 命令模式没有 ls 子命令(完整可用列表见 5.6.4)。列目录请用系统 ls/find,查看文件内容用 cmake -E cat。

Q3:配置时报错找不到编译器(如 CMAKE_C_COMPILER NOTFOUND)?

A:需要先安装编译器与构建工具,例如 apt install -y build-essential(提供 gcc/g++/make)。cmake 默认使用 /usr/bin/cc,该符号链接由 gcc 包提供。

Q4:CMAKE_BUILD_TYPE 在 CMakeCache.txt 里为什么是空值?

A:未用 -DCMAKE_BUILD_TYPE=... 指定时,缓存中该项为空,编译器不带优化参数。可选值有 Debug、Release、RelWithDebInfo、MinSizeRel(对应编译选项见 5.2.5 的 CMAKE_C_FLAGS_*)。

Q5:切换了 -DBUILD_SHARED_LIBS=ON,重新构建还是静态库?

A:-D 写入了 build_d 构建目录的缓存;若仍在旧构建目录(如 build)执行构建,需重新用 -D 配置该目录,或按 5.7 为不同配置使用独立构建目录。缓存值由 option() 首次创建后不再被默认值覆盖。

Q6:安装共享库版本后,运行 inst/bin/demo 报找不到 libfoo.so?

A:安装时 -- Set runtime path ... to "" 说明安装版 demo 的 rpath 被清空,需要设置共享库搜索路径后再运行:LD_LIBRARY_PATH=/opt/devchain-demo/cmake-ubuntu-test/inst/lib /opt/devchain-demo/cmake-ubuntu-test/inst/bin/demo。构建目录内运行不受影响(build tree 自带 rpath)。

Q7:cmake --help 输出的内容是什么?

A:--help 打印全部命令行选项与可用生成器(见 5.1.2)。更细的帮助包括:--help-command <cmd>(单个命令)、--help-commands(全部命令手册)、--help-variables(变量手册)等。

Q8:如何查看配置时实际传给编译器的参数?

A:构建时加 VERBOSE=1(make 方式):cmake --build <build> -- VERBOSE=1;或查看 CMakeCache.txt 中的 CMAKE_C_FLAGS_*(见 5.2.5),以及 --trace(见 5.5)跟踪配置过程。

Q9:apt install --download-only 下载的包在哪个目录?

A:默认在 /var/cache/apt/archives/,文件名形如 cmake_3.22.1-1ubuntu1.22.04.2_amd64.deb(见 4.2),可拷贝到离线机器用 dpkg -i 安装(见 4.5)。

Q10:卸载后重装,apt install -y cmake 提示 already the newest version?

A:说明系统已安装 cmake(dpkg -l cmake 状态为 ii)。需要重装时先卸载(见第八章)或使用 apt install --reinstall -y cmake。

八、卸载与清理

8.1 查看安装状态

$ dpkg -l cmake
+++-==============-=======================-============-=======================================
ii  cmake          3.22.1-1ubuntu1.22.04.2 amd64        cross-platform, open-source make system

💡 说明:dpkg -l 第一列状态为 ii 表示已安装且配置完成(i 期望安装、i 实际安装)。

8.2 卸载 cmake 及数据包

$ apt-get remove --purge -y cmake cmake-data
Removing cmake (3.22.1-1ubuntu1.22.04.2) ...
Removing cmake-data (3.22.1-1ubuntu1.22.04.2) ...
(Reading database ... 21583 files and directories currently installed.)
Purging configuration files for cmake-data (3.22.1-1ubuntu1.22.04.2) ...

💡 说明:remove --purge 在移除软件包的同时清除配置文件;cmake 与 cmake-data 需一并卸载。若只想卸载 cmake 而保留数据包会残留依赖。

8.3 清理 apt 缓存与离线包

$ apt-get clean

apt-get clean 清空 /var/cache/apt/archives/ 下的 deb 包。测试目录中自行拷贝的离线包与构建产物可一并删除:

$ rm -rf /opt/devchain-demo/cmake-ubuntu-test/offline
$ rm -rf /opt/devchain-demo/cmake-ubuntu-test/build /opt/devchain-demo/cmake-ubuntu-test/build_d /opt/devchain-demo/cmake-ubuntu-test/build_mk /opt/devchain-demo/cmake-ubuntu-test/build_trace /opt/devchain-demo/cmake-ubuntu-test/inst

8.4 卸载后验证

$ cmake --version
bash: cmake: command not found

⚠️ 注意:如需继续使用 cmake,卸载后按第三章重新安装即可。

九、参考链接