cmake 构建工具 一 hello world

本文介绍了CMake在大型项目中的优势,从创建基本项目、配置编译选项到生成可执行文件的流程,包括CMakeLists.txt的设置和关键命令的解析。通过实例展示了如何利用CMake进行跨平台编译,并提到了其与Makefile的关系及分布式编译的配合方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

对于C/C++代码来说,不使用任何构建工具来辅助编译C/C++代码的话,就需要自己手动指定使用的编译器(clang、gcc/g++或者其他编译器),一般来说需要在编译命令下指定这些:

  • 指定需要编译的源文件
  • 指定头文件的搜索目录
  • 指定库文件的搜索目录
  • 需要链接的动态库和静态库
  • 指定需要额外定义的宏或者取消定义的宏来控制编译
  • 指定编译优化选项
  • 指定语言标准
  • 等等

直接使用gcc/g++命令在使用代码文件不多,库直接的依赖关系不复杂的情况下是可以接受的。但是在一些大型项目中,源文件上千上万,各个文件和库直接的依赖关系复杂,如果还手动输入编译命令的话,复杂度就会变得很大。

什么是构建工具

简单来讲,代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),编译过程中调用哪些库和文件,叫做构建(build)。

CMake

CMake是一个跨平台的自动化构建工具,支持多种编译平台(Makefile、XCode、Visual Studio等),其输出标准构建档(比如,可以输出Visual Studio的“.sln”项目文件,然后再用Visual Studio打开编译即可),不直接输出二进制文件。具有一定的依赖自动分析能力。

CMake 支持语言: CCXX (i.e. C++), CUDAOBJC (i.e. Objective-C), OBJCXXFortranHIPISPC, and ASMproject — CMake 3.24.0-rc3 Documentation);对Java有部分支持,但是并不完善。

分布式编译:CMake只输出构建档,所以它本身是不支持分布式编译的。一般需要配合分布式编译工具,例如distcc等,来实现分布式编译。

hello world

以hello world为例,演示一个cmake的简单项目。首先创建如下的目录结构

目录

cpp_test
|---src
    |---hello_world.cc

hello_world.cc代码如下:

#include <iostream>
int main() {
    std::cout << "hello world" << std::endl;
    return 0;
}

我们代码就构建完成了

然后再根目录下创建CmakeLists.txt文件,代码如下:

# cmake 最低版本需求
cmake_minimum_required(VERSION 3.13)

# 工程名称
project(cmake_study)

# 设置
set(CMAKE_CXX_STANDARD 11)

# 编译源码生成目标
add_executable(cmake_study src/main.cc)

 具体意义后面再讲,先跟着做一遍。然后在根目录下创建一个空文件夹build,添加完CmakeLists.txt后目录结构如下:

cpp_test
|--src
|  |--hello_world.cc
|
|--build
|
|--CmakeLists.txt

然后一次执行以下命令:

cd build
cmake ..
make

 可以看到build文件夹中会生成如下的文件

 其中cmake_study 是我们最终生成的可执行文件,输入

./cmake_study

即可运行该文件。

下面来解释做的这些事情是为什么。

CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库

CMakeLists.txt中记录了编译所需要的所有信息,我们来看一下我们都设置了什么信息:

cmake_minimum_required(VERSION 3.13)

# cmake 最低版本需求,这个要求和你的cmake版本对应

project(cmake_study)

# 给你的工程设置一个名称,这个名字一般用于编译中的目录搜索,对我们用户是透明的,所以随便起就行

set(CMAKE_CXX_STANDARD 11)

# 指定编译器版本

add_executable(cmake_study src/main.cc)

# 编译源码生成目标,这个比较重要,用于指定我们编译的文件和生成的可执行文件文件名。我们的main函数最终生成一个cmake_study 就是因为这个设置。

我们刚刚编译过程中,一共用到了三个命令

cd build
cmake ..
make

除了第一个切换到build路径下不谈,我们来看执行cmake会发生什么?

 

可以看到,cmake运行之后,生成了3个文件一个文件夹, 其中CMakeFiles文件夹是一个多层嵌套的文件夹。这也是为什么要切换到build文件夹的原因,如果在根目录下,会生成大量的编译中间文件,使目录结构看起来混乱无比。

在生成的文件中,makefile是最重要的文件,其中记录了编译的文件,其中依赖等等。在cmake之前与一个构建工具叫make,make就是通过编写makefiles来编译项目。cmake把编写makefiles的过程也进行了简化,通过设置CMakeLists.txt文件,就可以自动生成makefiles。然后调用make 就实现编译。

这里需要注意的是cmake处理对象是文件夹,所以cmake后面一定要跟着一个文件夹的路径,且这个路径下要有CMakeLists.txt文件

那么执行make以后会发生什么呢?我们注意cpp_test/build/CMakeFiles/cmake_study.dir/src 这个路径

 在执行完cmake以后还是空的

执行完make以后出现了main.cc.o和 main.cc.o同时再build文件夹下也出现了cmake_study文件。 这说明 make命令才是真正执行了编译和链接。而cmake只是提供了makefiles而已。

这也说明了,如果我们没有修改代码的引用和依赖,就不用重新cmake。

当然,cmake工具自己也可以打印hello world。不过是在在生成makefile文件的时候,而不是编译的时候。

# cmake 最低版本需求
cmake_minimum_required(VERSION 3.13)

# 工程名称
project(cmake_study1)

# 设置
set(CMAKE_CXX_STANDARD 11)

message("hello world .....  ")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值