CMake使用记录
使用CMake写工程管理真的很方便,配合make或者ninja工具,用起来确实爽。
这里记录一个简单的使用示例,实现代码的分层管理。这里有CMake的教程Introduction · Modern CMake (modern-cmake-cn.github.io)。
cmake文件的标准步骤就是下面几个步骤:
- 确定cmake的最低版本要求;
- 确定project的名字;
- 确定需要加入编译的源文件列表;
- 确定需要加入编译的头文件路径清单;
- 确定最终输出的可执行文件/库文件;
- 确定project/target需要加入链接的库。
我这里实现一个主cmake文件以及3个子模块。
先确定目录分层
- main目录,存放可执行文件的输出;
- sub1目录,编译成sub1库,供main链接使用;
- sub2目录,编译成sub2库,供sub1和main链接使用。
# tree -a . ├── CMakeLists.txt ├── build-target.txt ├── main │ ├── CMakeLists.txt │ └── main.c ├── sub1 │ ├── CMakeLists.txt │ ├── sub1.c │ └── sub1.h └── sub2 ├── CMakeLists.txt ├── sub2.c └── sub2.h
根CMakeLists.txt文件
1 cmake_minimum_required(VERSION 3.22 FATAL_ERROR) 2 3 set(CMAKE_C_STANDARD 99) 4 set(CMAKE_CXX_STANDARD 17) 5 6 project(hello 7 VERSION 1.0 8 LANGUAGES C CXX ASM) 9 10 set(CMAKE_EXPORT_COMPILE_COMMANDS OFF) 11 set(CMAKE_VERBOSE_MAKEFILE OFF) 12 13 14 add_subdirectory(main) 15 add_subdirectory(sub1) 16 add_subdirectory(sub2)
主目录下的文件详情
1 #include <stdio.h> 2 #include "sub1.h" 3 #include "sub2.h" 4 5 6 void function_defined_in_main(void) { 7 printf("function_defined_in_main() invoked.\n"); 8 } 9 10 int main(void) { 11 printf("enter main function.\n"); 12 13 printf("invoke sub1() in main.\n"); 14 sub1(); 15 16 printf("invoke sub2() in main.\n"); 17 sub2(); 18 19 printf("exit main function.\n"); 20 21 printf("press Enter key to exit.\n"); 22 getchar(); 23 return 0; 24 }
1 cmake_minimum_required(VERSION 3.22) 2 3 set(TARGET "main") 4 project(${TARGET} C CXX ASM) 5 6 7 # 可执行输出 8 add_executable(${TARGET} ${CMAKE_CURRENT_LIST_DIR}/main.c) 9 10 # 目标依赖的头文件路径 11 target_include_directories(${TARGET} PUBLIC 12 ${CMAKE_CURRENT_LIST_DIR}/../sub1 13 ${CMAKE_CURRENT_LIST_DIR}/../sub2 14 ${CMAKE_CURRENT_LIST_DIR}) 15 16 # 目标链接需要的库 17 target_link_libraries(${TARGET} PRIVATE sub1 sub2) 18 19 # 指明优先在当前路径下查找库 20 target_link_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
目录sub1下的文件详情
1 cmake_minimum_required(VERSION 3.22) 2 3 set(TARGET "sub1") 4 project(${TARGET} C CXX ASM) 5 6 7 add_library(${TARGET} STATIC ${CMAKE_CURRENT_LIST_DIR}/sub1.c) 8 9 # 目标依赖的头文件路径 10 target_include_directories(${TARGET} PUBLIC 11 ${CMAKE_CURRENT_LIST_DIR} 12 ${CMAKE_CURRENT_LIST_DIR}/../sub2)
1 #include <stdio.h> 2 #include "sub2.h" 3 4 void function_defined_in_sub1(void) { 5 printf("function_defined_in_sub1() invoked.\n"); 6 } 7 8 void sub1(void) { 9 printf("enter sub1 function.\n"); 10 printf("invoke sub2() in library \"sub1\"\n"); 11 sub2(); 12 printf("exit sub1 function.\n"); 13 }
1 #ifndef __SUB1_H__ 2 #define __SUB1_H__ 3 4 5 void sub1(void); 6 7 #endif/*__SUB2_H__*/
目录sub2下的文件详情
1 cmake_minimum_required(VERSION 3.22) 2 3 set(TARGET "sub2") 4 project(${TARGET} C CXX ASM) 5 6 7 add_library(${TARGET} STATIC ${CMAKE_CURRENT_LIST_DIR}/sub2.c) 8 9 10 # 目标依赖的头文件路径 11 target_include_directories(${TARGET} PUBLIC 12 ${CMAKE_CURRENT_LIST_DIR})
1 #include <stdio.h> 2 3 extern void function_defined_in_main(void); 4 extern void function_defined_in_sub1(void); 5 6 void sub2(void) { 7 printf("enter sub2 function.\n"); 8 printf("invoke function_defined_in_main in library \"sub2\".\n"); 9 function_defined_in_main(); 10 printf("invoke function_defined_in_sub1 in library \"sub2\".\n"); 11 function_defined_in_sub1(); 12 13 printf("exit sub2 function.\n"); 14 }
1 #ifndef __SUB2_H__ 2 #define __SUB2_H__ 3 4 5 void sub2(void); 6 7 #endif/*__SUB2_H__*/
编译命令
在根目录下执行cmake编译,将输出全部指定在 build 目录下。
- “cmake -B build”表示将所有输出放到 build 目录下。
- “./build/main/mian”是启动可执行文件。
# cmake -B build . && cd ./build && make && cd .. && ./build/main/main
上面的命令行有些繁杂,我们可以做的更加精简:
# cmake -B build . && cmake --build build
输出结果
1 root@lxxx:/mnt/d/workspace/hello# ls 2 CMakeLists.txt build-target.txt main sub1 sub2 3 root@lxxx:/mnt/d/workspace/hello# cmake -B build . && cd ./build && make && cd .. && ./build/main/main 4 -- The C compiler identification is GNU 11.4.0 5 -- The CXX compiler identification is GNU 11.4.0 6 -- The ASM compiler identification is GNU 7 -- Found assembler: /usr/bin/cc 8 -- Detecting C compiler ABI info 9 -- Detecting C compiler ABI info - done 10 -- Check for working C compiler: /usr/bin/cc - skipped 11 -- Detecting C compile features 12 -- Detecting C compile features - done 13 -- Detecting CXX compiler ABI info 14 -- Detecting CXX compiler ABI info - done 15 -- Check for working CXX compiler: /usr/bin/c++ - skipped 16 -- Detecting CXX compile features 17 -- Detecting CXX compile features - done 18 -- Configuring done 19 -- Generating done 20 -- Build files have been written to: /mnt/d/workspace/hello/build 21 [ 16%] Building C object sub2/CMakeFiles/sub2.dir/sub2.c.o 22 [ 33%] Linking C static library libsub2.a 23 [ 33%] Built target sub2 24 [ 50%] Building C object sub1/CMakeFiles/sub1.dir/sub1.c.o 25 [ 66%] Linking C static library libsub1.a 26 [ 66%] Built target sub1 27 [ 83%] Building C object main/CMakeFiles/main.dir/main.c.o 28 [100%] Linking C executable main 29 [100%] Built target main 30 enter main function. 31 invoke sub1() in main. 32 enter sub1 function. 33 invoke sub2() in library "sub1" 34 enter sub2 function. 35 invoke function_defined_in_main in library "sub2". 36 function_defined_in_main() invoked. 37 invoke function_defined_in_sub1 in library "sub2". 38 function_defined_in_sub1() invoked. 39 exit sub2 function. 40 exit sub1 function. 41 invoke sub2() in main. 42 enter sub2 function. 43 invoke function_defined_in_main in library "sub2". 44 function_defined_in_main() invoked. 45 invoke function_defined_in_sub1 in library "sub2". 46 function_defined_in_sub1() invoked. 47 exit sub2 function. 48 exit main function. 49 press Enter key to exit. 50 51 root@lxxx:/mnt/d/workspace/hello#
特此记录。
如果转载,请注明出处。https://www.cnblogs.com/ssdq/