CMake
注释
用 #
已有宏
PROJECT_SOURCE_DIR
使用 cmake 命令后紧跟的目录,一般是工程的根目录
CMAKE_CURRENT_SOURCE_DIR
当前处理的 CMakeLists.txt 所在的路径
EXECUTABLE_OUTPUT_PATH
用来指定生成文件路径,如果不存在该路径则会创建
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output)
搜索
aux_source_directory
查找某个路径下的所有源文件
aux_source_directory(< dir > < variable >)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
dir:要搜索的目录variable:将从 dir 目录下搜索到的源文件列表存储到该变量中
file
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。(可选)
指定头文件路径
保证在编译过程中编译器能够找到这些头文件,并顺利通过编译。
include_directories(headpath)
include_directories(${PROJECT_SOURCE_DIR}/include)
生成可执行文件
cmake_minimum_required(VERSION 3.15)project(test) #cmake项目名
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output) #输出路径
include_directories(${PROJECT_SOURCE_DIR}/inc) #头文件
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) #源文件
add_executable(app ${SRC}) #前者为生成的可执行文件名
生成库文件
静态库和动态库
- 静态库在编译时将所有依赖的库代码直接链接到可执行文件中,使得程序独立性高但体积较大。
- 动态库在运行时加载,允许程序共享库代码,有助于减小程序体积和节省系统资源,但需要确保运行环境中存在正确的库版本。
更新与维护
静态库:
- 更新静态库后,所有使用该库的应用都需要重新编译和链接,以便包含新的库代码。
动态库:
- 动态库可以在不重新编译应用的情况下进行更新,只要库的接口没有改变。这对于发布补丁或性能优化非常有用。
生成步骤
首先把 main.c 剔除出 src 文件夹,不让其包含在库中
cmake_minimum_required(VERSION 3.15)
project(test)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #库文件存放路径(不存在则创建)
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
add_library(test SHARED ${SRC}) #生成动态库 库文件将被命名为libtest.so
#add_library(test STATIC ${SRC}) #生成静态库(默认)库文件将被命名为libtest.a
链接库文件
链接静态库
target_link_libraries 和 link_libraries 均可
前者更好
cmake_minimum_required(VERSION 3.15)
project(test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output)
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
#除库文件以外的源文件(包括mian.c)
#link_libraries(test)
#库的名字(可以只写中间部分,也可以全名)
link_directories(${PROJECT_SOURCE_DIR}/lib)
#自定义库的路径
add_executable(app ${SRC})
target_link_libraries(app test)#要放在最后
链接动态库
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output)
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
link_directories(${PROJECT_SOURCE_DIR}/lib) #要在add_...之前
add_executable(app ${SRC})
target_link_libraries(app test pthread)#要放在最后
链接多个库
如果多个库之间存在依赖关系,确保按照正确的顺序列出库名称。通常,被依赖的库应该放在后面
cmake_minimum_required(VERSION 3.15)
project(test)set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output)
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR} SRC)# 自定义库的路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
add_executable(app ${SRC})# 链接多个静态库
target_link_libraries(app
lib1 # 第一个库的名字
lib2 # 依赖lib3
lib3 # 被lib2依赖
)
静态库动态库混合
如果同时需要链接动态库和静态库,同样可以在 target_link_libraries 中一并列出。
有多个库路径
link_directories(
${PROJECT_SOURCE_DIR}/lib1
${PROJECT_SOURCE_DIR}/lib2
${PROJECT_SOURCE_DIR}/lib3
)
寻找加载库文件
find_library
第一个参数:找到的库文件的路径
第二个参数:库文件名
第三个参数:固定为 PATHS
第 4 - …个参数:查找的路径
find_library(TEST_LIB test PATHS
${PROJECT_SOURCE_DIR}/libs
/usr/local/lib)
add_executable(app main.c)
target_link_libraries(app ${TEST_LIB})
消息通知
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
message("test")
message(STATUS "check1")
message(FATAL_ERROR "error")
打印如下
test
-- check1
CMake Error at CMakeLists.txt:29 (message):
error
(无) :重要消息STATUS :非重要消息WARNING:CMake 警告, 会继续执行AUTHOR_WARNING:CMake 警告 (dev), 会继续执行SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤FATAL_ERROR:CMake 错误, 终止所有处理过程
添加宏
C/C++ 中未赋值的宏默认为 1
add_definitions(-D宏名称)
add_definitions(-DMY_MACRO=2)
add_definitions(-DDEBUG)
项目中 cmake
project_name/
├── src/ # 存放源代码文件
│ ├── CMakeLists.txt # 构建脚本
│ ├── main.c # 主程序入口
│ ├── module1.c # 模块1的实现
│ ├── module2.c # 模块2的实现
│ └── utils.c # 工具函数实现
├── include/ # 存放头文件(.h)
│ ├── module1.h # 模块1的声明
│ ├── module2.h # 模块2的声明
│ └── utils.h # 工具函数声明
├── lib/ # 存放第三方库或静态库文件
│ ├── libxyz.a # 静态库文件
│ └── xyz.h # 第三方库头文件
├── tests/ # 存放测试代码
│ ├── CMakeLists.txt # 构建脚本
│ ├── test_module1.c # 测试模块1
│ └── test_utils.c # 测试工具函数
├── docs/ # 存放文档(如设计文档、API文档等)
│ ├── design.md # 设计文档
│ └── api.md # API文档
├── build/ # 编译生成的中间文件和目标文件
├── bin/ # 存放最终生成的可执行文件
├── CMakeLists.txt # 构建脚本
├── README.md # 项目说明文档
└── LICENSE # 项目许可证
cmake 文件结构
每一个有源文件的地方都要有一个 cmake 文件
项目根目录中
cmake_minimum_required(VERSION 3.15)
project(test)
set(EXE_PATH ${PROJECT_SOURCE_DIR}/bin)
set(INC_PATH ${PROJECT_SOURCE_DIR}/inc)
set(LIB_PATH ${PROJECT_SOURCE_DIR}/lib)
# 设置名字
set(APPNAME app)
set(APPNAME1 test1)
set(APPNAME2 test2)
set(LIBAD ad)
set(LIBDI di)
#设置子目录
add_subdirectory(src)
add_subdirectory(ad)
add_subdirectory(di)
add_subdirectory(tests)
生成库文件
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
aux_source_directory(${PROJECT_SOURCE_DIR}/di SRC)
include_directories(${INC_PATH})
add_library(${LIBDI} SHARED ${SRC})
生成可执行文件
set(EXECUTABLE_OUTPUT_PATH ${EXE_PATH})
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
include_directories(${INC_PATH})
link_directories(${LIB_PATH})
add_executable(${APPNAME} ${SRC})
target_link_libraries(${APPNAME} ${LIBAD} ${LIBDI} pthread)
生成测试文件
set(EXECUTABLE_OUTPUT_PATH ${EXE_PATH})
#include_directories(${INC_PATH})
link_directories(${LIB_PATH})
add_executable(${APPNAME1} test1.c) #分别生成执行文件
add_executable(${APPNAME2} test2.c)
target_include_directories(${APPNAME1} PUBLIC ${INC_PATH})# 分别链接各自头
target_include_directories(${APPNAME2} PUBLIC ${INC_PATH})
target_link_libraries(${APPNAME1} ${LIBAD}) # 分别链接库
target_link_libraries(${APPNAME2} ${LIBDI} pthread)
交叉编译
- 项目文件下创建文件声明交叉编译链
arm.cmake
# 目标系统名称
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_STANDARD 99)
# 指定交叉编译器路径
set(TOOLCHAIN_DIR /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}g++)
查看交叉编译器路径方法:
which arm-linux-gnueabihf-gcc
- 在 build 目录下
cmake
cmake -DCMAKE_TOOLCHAIN_FILE=./../arm.cmake ..
- 正常
make
查看生成文件是什么架构:
file ../bin/app
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 宋振威的博客!
评论
