Cmake 初探 电脑版发表于:2024/5/26 17:04 ![](https://img.tnblog.net/arcimg/hb/e32ff5dc048e49299a2be42d5d75fdff.png) >#Cmake 初探 [TOC] CMake简介 ------------ tn2>CMake 是一个开源的、跨平台的构建系统(编译工具),它主要用于管理项目的构建过程。 它通过使用简明的脚本语言来生成适用于不同平台和编译器的构建文件。(可跨平台) 安装CMake ------------ tn2>通过执行如下命令的进行安装CMake。 ```bash sudo apt install cmake -y # 查看版本 cmake --version ``` ![](https://img.tnblog.net/arcimg/hb/58fe67e13a5045e39e6750fec9e78309.png) 简单示例 ------------ tn2>首先创建一个`main.c`文件的c程序,编写一点简单的代码输出hello word。 ```c #include <stdio.h> int main(void) { printf("Hello World\n"); return 0; } ``` tn2>`CMakeLists.txt` 是 CMake(Cross-Platform Make)构建系统中的一个核心文件,它用于定义一个项目的构建过程。 接下来我们在同一目录下创建一个`CMakeLists.txt`文件,并写入如下内容。 ```c # cmake的最低版本要求是2.8 cmake_minimum_required (VERSION 2.8) # 工程名 project (demo) # 由源文件main.c 生成执行文件main add_executable(main main.c) ``` tn2>然后我们在当前目录中执行如下命令进行编译。 ```c # 自动生成文件有 CMakeCache.txt CMakeFiles cmake_install.cmake Makefile cmake . # 编译文件(用已自动生成的Makefile文件) make ls ``` ![](https://img.tnblog.net/arcimg/hb/fc02cc3f19bd4a658aee9d8c9fa3bef3.png) tn2>其中`main`绿色的就是我们的可执行程序 ```c ./main ``` ![](https://img.tnblog.net/arcimg/hb/3f3704fc214b4e3686bbd248b513f333.png) tn2>接下了我们执行清理编译之后的相关程序 ```c # 清楚编译中的生成文件(如 main.o main) make clean ``` ![](https://img.tnblog.net/arcimg/hb/cd168b1ff052488c8b0825e1786fec7e.png) 多文件 ------------ tn2>重新写`main.c`代码。 ```c #include <stdio.h> #include "fun.h" int main(void) { show(10); return 0; } ``` tn2>定义`fun.h` ```c #ifndef _FUN_H_ #define _FUN_H_ void show(int data); #endif ``` tn2>定义`fun.c` ```c #include <stdio.h> #include "fun.h" void show(int data) { printf("data is %d\n", data); } ``` tn2>修改`CMakeLists.txt`的第一种方式,在`add_executable`方法中添加相关文件名 ```c # cmake的最低版本要求是2.8 cmake_minimum_required (VERSION 2.8) # 工程名 project (demo) # 由源文件main.c 生成执行文件main add_executable(main main.c fun.c) ``` ![](https://img.tnblog.net/arcimg/hb/2072d79f228546368663ecded33decdf.png) tn2>第二种,用变量存放编译需要的源文件。 ```c cmake_minimum_required (VERSION 2.8) # 工程名 project (demo) # 用变量,存放的文件列表 set( SRC_LIST ./main.c ./fun.c ) # 根据SRC_LIST中的源文件 生成执行文件main add_executable(main ${SRC_LIST}) ``` ![](https://img.tnblog.net/arcimg/hb/13d1f97414424d2a836d3360bb94fdd7.png) tn2>源文件很多时,通过指定当前目录的位置进行编译。 ```c cmake_minimum_required (VERSION 2.8) project (demo) # 把当前目录下的源文件列表,存放到变量SRC_LIST里 aux_source_directory(. SRC_LIST) # 根据SRC_LIST中的源文件 生成执行文件main add_executable(main ${SRC_LIST}) ``` ![](https://img.tnblog.net/arcimg/hb/9220e86f3a534d57ae90afa173160a06.png) 多目录 ------------ tn2>多目录,还有相同的接口情况下如何解决? ```c //main.c #include <stdio.h> #include "fun.h" #include "look.h" int main(void) { show(10); look(); return 0; } ``` tn2>定义两个目录`fun`和`look`目录。 ![](https://img.tnblog.net/arcimg/hb/b688537b12e24876b4efb00c6696b65e.png) ```c // fun.h #ifndef _FUN_H_ #define _FUN_H_ void show(int data); #endif // fun.c #include <stdio.h> #include "fun.h" void show(int data) { printf("data is %d\n", data); } ``` ```c // look.h #ifndef _FUN_H_ #define _FUN_H_ void look(); #endif // look.c #include <stdio.h> #include "look.h" void look() { printf("look go\n"); } ``` tn2>修改`CMakeLists.txt`。 通过`include_directories`的方法指定一个或多个包含目录。 通过`aux_source_directory`方法用于自动添加一个目录中的所有源文件到一个变量中。 ```bash cmake_minimum_required (VERSION 2.8) project (demo) # 指定头文件的搜索路径(先fun目录,再look目录) include_directories (fun look) # 把fun目录下的源文件列表,存放到变量SRC_LIST_FUN里 aux_source_directory (fun SRC_LIST_FUN) # 把look目录下的源文件列表,存放到变量SRC_LIST_LOOK里 aux_source_directory (look SRC_LIST_LOOK) add_executable (main main.c ${SRC_LIST_FUN} ${SRC_LIST_LOOK}) ``` ![](https://img.tnblog.net/arcimg/hb/dae20c1d2f1f4b1892ad55437feeb082.png) 库生成 ------------ tn2>好处就是源代码我们一般不希望对方看到。 目录结构如下: ![](https://img.tnblog.net/arcimg/hb/4248fda1a7664dc49934b5633cec5ac8.png) tn2>其中的`fun.c`和`fun.h`的内容不变。 添加一个`CMakeLists.txt`文件,内容如下: ```bash aux_source_directory (. SRC_LIST) # 根据SRC_LIST的源文件,生成动态库fun_shared add_library (fun_shared SHARED ${SRC_LIST}) # 根据SRC_LIST的源文件,生成静态库fun_static add_library (fun_static STATIC ${SRC_LIST}) # 设置库的属性(如输出库名 版本号等) set_target_properties (fun_shared PROPERTIES OUTPUT_NAME "fun") set_target_properties (fun_static PROPERTIES OUTPUT_NAME "fun") #//指定生成的库文件,存放在工程根目录下的lib目录 set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) ``` tn2>修改在`learning`根目录下的`CMakeLists.txt`。 ```bash cmake_minimum_required (VERSION 2.8) project (demo) add_subdirectory (fun) ``` ![](https://img.tnblog.net/arcimg/hb/255ce43356a148ec8e7b36793c17d8fd.png) tn2>可以看见在`lib`目录下已经生成了相关的文件 库使用 ------------ tn2>创建`include`文件夹将`fun/fun.h`复制到该目录下。 让`include`成为接口目录。 ![](https://img.tnblog.net/arcimg/hb/935ac58a6413419f803a13b3e4ecfb17.png) tn2>创建一个新的目录`src`,并在下面定义`main.c`文件以及`CMakeLists.txt`文件。 ![](https://img.tnblog.net/arcimg/hb/0cdc0c22069345ea88cab8ced2569c20.png) ```c #include <stdio.h> #include "fun.h" int main(void) { show(10); return 0; } ``` ```bash aux_source_directory (. SRC_LIST) include_directories (../include) # 添加非标准的共享库搜索路径 link_directories (${PROJECT_SOURCE_DIR}/lib) add_executable (main ${SRC_LIST}) # 连接库(默认链接动态库,无则链接静态库,也可指明链接fun.a) target_link_libraries (main fun) set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ``` tn2>修改在根目录下的`CMakeLists.txt`文件。 ```bash cmake_minimum_required (VERSION 2.8) project (demo) add_subdirectory (fun) add_subdirectory (src) ``` ![](https://img.tnblog.net/arcimg/hb/5b0f8f7acbad4a8b8beecd276f7bee68.png) 标准结构 ------------ ```bash //bin 输出的执行文件 //build 存放构建中的中间文件 //lib 库 libfun.a libfun.so //CMakeLists.txt cmake的总配置文件 cmake_minimum_required (VERSION 2.8) #// cmake的最低版本要求是2.8,我们安装的是3.10.2 project (demo) #//工程名 add_subdirectory (src) #//添加子目录(自动构建时,会进入src中找 子CMakeLists.txt) //include/fun.h #ifndef _FUN_H_ #define _FUN_H_ void show(int data); #endif //include/look.h #ifndef _LOOK_H_ #define _LOOK_H_ void look(); #endif //src/main.c #include <stdio.h> #include "fun.h" #include "look.h" int main(void) { show(10); look(); return 0; } //src/look.c #include <stdio.h> #include "look.h" void look(void) { printf("look go\n"); } //src/CMakeLists.txt cmake的子配置文件 aux_source_directory (. SRC_LIST) #//把当前目录下的源文件列表,存放到变量SRC_LIST里 include_directories (../include) #//指定 上级目录下的include 为头文件的搜索路径 link_directories (${PROJECT_SOURCE_DIR}/lib) #//添加库搜索路径 add_executable (main ${SRC_LIST}) #//根据SRC_LIST中的源文件 生成执行文件main target_link_libraries (main fun) #//连接库(默认链接动态库,无则链接静态库,也可指明链接fun.a) #//设定 执行文件的输出位置 为工程根目录下的bin目录 set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) //构建运行 $ cd build $ cmake .. //进到build 目录后再cmake构建,避免生成中间文件,污染了工程 $ make $ cd ../bin //执行文件是输出到 bin下 $ ./main ```