发布时间:2025-06-21
浏览次数:0
我对CMake的印象始终是作为一种项目构建工具,然而在接触到--build选项后,我才意识到CMake竟然还能统一不同平台的编译环节。若想深入理解CMake的构建与编译过程,首要任务是掌握生成器的相关知识。
一、生成器
CMake的生成器功能主要负责构建底层系统的输入文件编写。通过执行cmake --help命令,可以查看所有可用的生成器。以cmake 3.26.5版本为例,我的系统所支持的生成器有:
Generators
本平台提供以下发电机选项,其中*号表示默认配置:
Green Hills MULTI 等同于生成Green Hills MULTI文件
此项目目前处于实验阶段,尚在不断完善之中。
Unix Makefiles的功能是生成标准的UNIX构建文件。
忍者模块 = 生成构建的.ninja文件。
Ninja Multi-Config功能能够生成构建.ninja files.
Watcom WMake 工具能够生成 Watcom WMake 的构建文件。
CodeBlocks这款软件,与Ninja结合,能够生成CodeBlocks的项目文件。
CodeBlocks与Unix Makefiles相对应,能够生成CodeBlocks的项目文件。
CodeLite与Ninja结合,能够生成CodeLite的项目文件。
CodeLite针对Unix系统生成的Makefiles,能够创建CodeLite的项目文件。
Eclipse CDT4与Ninja结合,能够生成Eclipse CDT 4.0版本的项目文件。
Eclipse CDT4与Unix Makefiles相结合,能够生成Eclipse CDT 4.0版本的项目文件。
Kate,也被称为忍者,能够生成Kate项目文件。
Kate与Unix Makefiles相关联,能够生成Kate的项目文件。
Sublime Text 2 - Ninja 功能强大,能够生成Sublime Text 2的项目文件。
Sublime Text 2,适用于Unix系统的Makefiles
该工具能够生成令人赞叹的Sublime Text 2项目文件。
正如本文所阐述,CMake 包含了多种生成器,这些生成器涵盖了命令行生成器、集成开发环境(IDE)生成器以及其他类型的生成器。
1. 命令行生成器
这些生成器适用于命令行构建工具,例如Make和Ninja。在采用CMake构建系统生成之前,必须对所选择的具体工具链进行相应的配置。
支持的生成器包括:
2. IDE 生成器
这些生成器适用于集成开发环境,并且它们自带了编译器功能。比如,某些生成器自身就配备了编译器,例如Xcode,它本身就内置了一个编译器。
支持的生成器包括:
3. 其他生成器
这些生成器负责构建配置文件,并能与各类集成开发环境(IDE)协同运作,同时它们还需被整合进IDE内部的生成器或命令行工具之中。
支持的生成器包括:
要调用 CMake 生成器,可以使用 -G 命令行开关。
二、CMake构建及编译
在Linux操作系统中,当采用CMake进行项目的构建与编译过程时,一般会执行以下操作指令:
mkdir build
cd build
cmake ..
cmake --build .
cmake命令中的点号以及cmake --build点号,这两者均为构建与编译C/C++项目所频繁使用的指令。
【解析】
使用cmake命令进行项目构建,该命令主要负责生成必要的文件,包括cmake文件以及构建系统所需的其他相关文件。
使用cmake进行构建操作sublime text 3 编译c,当前目录下的项目将被编译并完成链接过程。
【拓展】
首先,通过命令行工具cmake,例如输入cmake ..,你可以在构建目录中(采用外部构建方式)创建项目文件,这些文件也被官方文档称为构建树或tree。在这些文件中,除了上述内容,还包括其他一些相关的文件、目录或子目录。
接下来,自然是在目录构建过程中,对已经生成的项目文件进行编译和链接操作,这一步骤需要用到您所提到的cmake --build .命令。
最终,在--build之后出现的那个点号,它所指的是构建项目文件时生成的构建树路径。通常情况下,当你确切了解系统中采用的是何种构建工具(Build)时,例如Unix系统,你便可以直接运用make命令来完成编译和链接操作。这种--build格式,常被应用于自动化脚本编写,亦或是在集成开发环境(IDE)中。
请注意,这里所说的“注意”是指源文件及其顶层目录的路径,而cmake命令则预设了该路径位于上一级目录。
当然,在CMake进行C/C++项目的构建与编译过程中,还存在另一种编写方法,具体如下所示:
注意:当前目录为 .txt 所在的顶层目录
构建项目
cmake . -Bbuild -G "Unix Makefiles"
编译项目
cmake --build build
该指令旨在对位于“build”文件夹内的项目进行编译和链接操作;在Linux操作系统中,通常采用“make”命令来完成项目的编译和链接工作。然而,在本例中,我们选择通过执行“cmake --build build”命令来完成这一过程。
之所以选择不直接采用“make”命令,而是采用“cmake --build”的命令格式,主要考虑了跨平台的兼容性。在CMake中,存在一个名为“CMake”的概念,它使得CMake能够适配多种底层系统,例如GCC系列、Ninja系列等。若需使用Ninja构建系统,请执行命令:cmake -G Ninja。若未找到“cmake --build build”这一指令,则需借助底层命令进行构建sublime text 3 编译c,例如make或ninja。目前,cmake已提供了一种统一的命令接口,采用该接口后,无论底层技术如何,只需执行--build命令即可顺利完成编译过程。
三、CMake构建及编译实战演示
以其中的多目录文件工程实例为示范,我们将向大家展示如何利用CMake进行跨平台的工程项目构建与编译。
工程项目结构如下:
# 工程文件目录结构
在本地主机的multi_dir目录下,执行tree命令,以展示层级为2的目录结构视图。
.
├── app
│ └── main.c
├── build
├── CMakeLists.txt
├── hello
│ ├── CMakeLists.txt
│ ├── include
│ └── src
└── world
├── CMakeLists.txt
├── include
└── src
8 directories, 4 files
顶级目录下的主 .txt 文件:.txt。
# CMake最低版本号要求
设置CMake最低需求版本为3.0。
# 项目信息,随便写
project(HelloWorld)
设定C/C++的开发环境版本(例如c99、c++11、c++17等),此处即表明选择了c99版本。
set(CMAKE_C_STANDARD 99)
将指定文件夹纳入编译器的头文件查找范围,该文件夹被视为相对于当前源码目录的相对位置。
当然,您还可以采用完整的路径或者设定特定的变量。在默认设置中,include_directories指令会自动添加指定的目录。
将内容置于列表尾部(选择“AFTER”选项)。然而,您可以通过执行特定命令来调整CMAKE的包含目录顺序。
通过设置变量为ON来调整其预设功能,使得目录得以置于列表的首位。此外,在每次执行include_directories指令时,均可实现此操作。
在指定位置,选择AFTER或BEFORE选项,以确定是将其添加至列表的开头还是结尾。
包含头文件目录(hello目录下的include子目录,world目录下的include子目录)
设定变量DIR_SRCS,将其赋值为位于app目录下的源代码文件main.c。
set(DIR_SRCS ./app/main.c)
创建子目录hello与world,同时确保hello和world目录中的CMakeLists.txt配置文件及相应源代码文件均纳入处理范围。
add_subdirectory(hello)
add_subdirectory(world)
在配置静态库的搜索路径时,需指定主CMakeLists.txt文件所在文件夹的路径,该路径通过变量${PROJECT_SOURCE_DIR}来表示。
# 即项目所在根目录文件路径
将项目源目录中的world文件夹链接至当前路径。
在生成子目录的链接库文件libworld.a时,通常的做法是在指定时去除文件名前缀“lib”以及后缀“.a”。
link_libraries(world)
# 指定生成目标
创建可执行文件HelloWorld,并将源文件目录中的所有源文件包含在内。
在生成子目录的链接动态库文件libhello.so时,通常我们会去掉文件名前缀“lib”以及后缀“.so”。
对HelloWorld项目进行链接,使用target_link_libraries命令。
文件源码如下:
hello 子目录头文件:hello//hello.h。
#ifndef HELLOWORLD_HELLO_H
#define HELLOWORLD_HELLO_H
extern void hello(void);
#endif //HELLOWORLD_HELLO_H
您好,请查阅子目录下的源文件,具体路径为hello/src/hello.c。
#include "hello.h"
#include
void hello()
{
printf("hello.\n");
}
hello 子目录.txt 文件:hello/.txt。
# 添加头文件路径
在编译过程中,需指定包含目录为当前目录下的include文件夹。
设定变量DIR_SRCS,赋予其hello/src目录中源文件hello的路径。c
set(DIR_SRCS ./src/hello.c)
# 生成动态链接库
add_library(hello SHARED ${DIR_SRCS})
world 子目录头文件:world//world.h。
#ifndef HELLOWORLD_WORLD_H
#define HELLOWORLD_WORLD_H
extern void world(void);
#endif //HELLOWORLD_WORLD_H
world子目录下的源文件位于:world/src目录中的world.c文件。
#include "world.h"
#include
void world()
{
printf("world.\n");
}
world 子目录.txt 文件:world/.txt。
# 添加头文件路径
include_directories(./include)
设定变量DIR_SRCS,赋予其值为位于world/src目录下的源文件world。c
set(DIR_SRCS ./src/world.c)
# 生成静态链接库
add_library(world STATIC ${DIR_SRCS})
app 子目录主源文件:app/main.c。
#include "hello.h"
#include "world.h"
int main()
{
hello();
world();
return 0;
}
接下来,我们将通过实际操作展示如何运用CMake,以实现调用多种底层跨平台构建和编译工具,进而对不同的工程项目进行构建。
1. Unix
本节将展示如何运用Unix生成器来创建适合Unix/Linux操作系统的文件。接着,通过执行命令“cmake --build build”,我们可以调用底层的make命令来编译并链接项目。具体操作步骤如下:
在本地主机的多目录下执行列出文件命令。
在项目构建过程中,CMake曾采用Unix Makefiles的方式进行操作。
在本地主机的多目录环境中,执行以下命令:使用cmake工具对当前目录下的项目进行配置,指定构建目录为"build",并选择生成适用于Unix系统的Makefiles。
编译器识别为GNU版本,具体为8.5.0。
编译器识别结果为GNU版本8.5.0,属于CXX编译器系列。
检测C编译器的应用程序二进制接口信息
检测C编译器的ABI信息——完成
检测是否安装了可用的C语言编译器:/usr/bin/cc —— 跳过此步骤
识别C语言编译器的特性
成功识别了C语言编译器的特性,任务已完成。
检测C++编译器的应用程序二进制接口信息
检测CXX编译器ABI信息——已完成,操作完成。
检查CXX编译器是否正常工作:/usr/bin/c++,已跳过。
检测CXX编译器的特性
成功检测了CXX编译特性,任务已完成。
-- Configuring done (0.4s)
-- Generating done (0.0s)
构建文件已成功生成,具体位置位于:/backup/cmake/multi_dir/build。
[root@localhost multi_dir]# ls
在本地主机的根目录下,位于multi_dir文件夹中,执行了列出build目录内容的命令。
CMakeCache.txt文件、CMakeFiles目录、cmake_install.cmake脚本、hello可执行文件、Makefile构建脚本以及world目标文件。
使用CMake进行项目构建,通过make命令执行编译过程,最终生成名为HelloWorld的可执行文件。
在本地主机的multi_dir目录下,执行了cmake命令,随后进行了构建操作,命令行输入为:cmake --build build。
[ 16%] 构建C对象世界/CMakeFiles/world.dir/src/world.c.o
[ 33%] 将C语言静态库命名为libworld.a
[ 33%] Built target world
构建C对象hello,在路径CMakeFiles/hello.dir/src下,生成文件hello.c.o。
将C语言共享库链接为libhello.so文件。
[ 66%] Built target hello
[ 83% ] 正在构建C语言模块C,生成CMakeFiles目录下的HelloWorld子目录,并编译main.c源文件生成的目标文件.o。
确保将C语言编写的HelloWorld程序正确链接。
成功构建了目标HelloWorld。
[root@localhost multi_dir]# ls
app build CMakeLists.txt hello world
[root@localhost multi_dir]#
[root@localhost multi_dir]# ls build/
CMakeCache.txt文件、CMakeFiles目录、cmake_install.cmake脚本、hello和HelloWorld文件、Makefile以及world文件。
在本地主机的根目录下,位于multi_dir文件夹中,执行了位于build目录下的HelloWorld程序。
hello.
world.
2. Ninja
本节将展示如何运用Ninja生成器来创建适用于Ninja构建系统的相关文件。接着,通过执行命令“cmake --build build”,我们将调用底层的ninja命令来编译并链接项目。
请注意,若要在cmake中使用Ninja生成器,必须确保您的计算机上已经正确安装了Ninja执行文件。该程序的安装途径包括通过命令行操作或源代码编译。关于具体的安装步骤,您可以自行通过网络搜索获取详细信息。
示例如下:
# cmake 使用过Ninja构建项目
在本地主机上,针对multi_dir目录执行了cmake命令,指定当前目录作为源码位置,并设置build目录作为构建目标,同时选择了Ninja作为生成器。
-- The C compiler identification is GNU 8.5.0
-- The CXX compiler identification is GNU 8.5.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 (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /backup/cmake/multi_dir/build
[root@localhost multi_dir]# ls
app build CMakeLists.txt hello world
[root@localhost multi_dir]#
[root@localhost multi_dir]# ls build/
构建脚本.ninja、构建缓存文件CMakeCache.txt、构建目录CMakeFiles、安装脚本cmake_install.cmake、程序名hello、输出文件world。
在CMake中,通过ninja编译器对项目进行构建,最终生成名为HelloWorld的可执行文件。
[root@localhost multi_dir]# cmake --build build
将C语言的可执行文件HelloWorld进行关联。
[root@localhost multi_dir]# ls
app build CMakeLists.txt hello world
[root@localhost multi_dir]#
[root@localhost multi_dir]# ls build/
构建脚本文件.ninja,CMake的缓存文件CMakeCache.txt,CMake生成的目录CMakeFiles,安装脚本cmake_install.cmake,主程序hello,主程序对应的源文件HelloWorld,以及输出信息world。
[root@localhost multi_dir]# ./build/HelloWorld
hello.
world.
如有侵权请联系删除!
Copyright © 2023 江苏优软数字科技有限公司 All Rights Reserved.正版sublime text、Codejock、IntelliJ IDEA、sketch、Mestrenova、DNAstar服务提供商
13262879759
微信二维码