文章目录
0.前言
- 如果你有如下烦恼:
- 跨平台编译,改这改那,文件移来移去
- 只会VS手动创建项目,代码结构乱,配库烦
- 等等
- !!!强烈建议学一点cmake
- 这篇文章记录一点使用cmake的心得吧,虽然可能都是一些简单的东西,希望也能帮到你。
1. 常规设置
设置版本号
设置工程名称
设置可执行文件输出目录、库输出目录
设置工程包含当前目录
设置子目录
#设置cmake版本号
cmake_minimum_required(VERSION 3.18)
#设置工程名称
project(SortMultiCameraArch)
#设置可执行文件输出目录、库输出目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#设置工程包含当前目录,非必须
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#设置子目录
add_subdirectory(Your_path)
2.设置生成目标(编译可执行文件或库文件)
添加源文件
以添加src/A_moudle src/B_module src/utils.cpp为例
# aux_source_directory 是将目录下所有源文件追加到变量中
# aux_source_directory 不会覆盖变量
aux_source_directory("${CMAKE_SOURCE_DIR}/src/A_moudle" src_files)
aux_source_directory("${CMAKE_SOURCE_DIR}/src/B_moudle" src_files)
# set是设置变量,会覆盖,建议用set(A ${A} xxxx)这种写法
set(src_files ${src_files} "${CMAKE_SOURCE_DIR}/utils.cpp")
添加要生成的目标
注:cmake可以添加很多个目标
#添加exe
add_executable(test ${src_files})
#添加动态库
add_library(lib_shared SHARED ${src_files})
#添加静态库
add_library(lib_static STATIC ${src_files})
增加依赖项
后面会介绍怎么添加库
target_link_libraries(test xxx1 xxx2 xxx3)
3.添加依赖项(库文件)
当库提供了cmake引导文件,以opencv为例
#可以通过set(OpenCV_DIR xxxxxx)更改寻找目录
find_package(OpenCV PATHS)
#也可以通过find_package(OpenCV YOUR_DIR/cmake)指定cmake目录
include_directories(${OpenCV_INCLUDE_DIRS})
#一般寻找到的库包含目录变量名为 xxxx_INCLUDE_DIRS
#库目录为 xxxx_INCLUDE_LIBS
当没有cmake引导文件时,以添加Matlab库为例
set(Matlab_DIR "C:/Program Files/MATLAB/R2016b/extern")
set(Matlab_LIBS ${Matlab_LIBS} "${Matlab_DIR}/lib/win64/microsoft/mclmcrrt.lib")
include_directories(${Matlab_DIR}/include)
4.生成的库的一些设置
去除循环依赖
#在你自己要编写cmake install文件的时候,这句话很有用,不然别人加你的库还会要导入你的库的依赖包
set_target_properties(calib PROPERTIES INTERFACE_LINK_LIBRARIES "")
设置库文件名
set_target_properties(calib PROPERTIES OUTPUT_NAME "myname")
设置库版本号
这里放上一个链接,亲测可行:
windows库版本号设置
5.添加宏
全局添加,所有目标都会加上
add_definitions("-D宏1 -D宏2")
局部添加,只给指定目标加(墙裂建议)
#你可以用一个definitions变量保存要添加的宏,举个例子
#set(definitions ${definitions} "-D宏1")
#set(definitions ${definitions} "-D宏2")
#这样的好处是可以根据某些条件精准添加宏
target_compile_definitions(your_target PUBLIC ${definitions})
宏指定为某个值
指定宏其实可以用字符串的形式,也可以用非字符串的形式。
#添加一个宏:ABC 值为2
add_definitions("-DABC=2")
add_definitions(-DABC=2)
#添加一个宏:ABC 值为字符串 “2”
add_definitions("-DABC=\"2\"")
add_definitions(-DABC="2")
#精准添加3个宏:A=1 B=“2” C
set(definitions ${definitions} "-DA=1 -DB=\"2\" -DC" )
target_compile_definitions(your_target PUBLIC ${definitions})
6.添加Option选项
有时需要用户勾选一些选项,然后根据这些选项编译
option(WITH_ABC "help" OFF)
7.if控制
if(xxx)
xxxx
elseif(xxx)
xxxx
else()
xxxx
endif()
8.windows下 MD/MT报错
之前添加ncnn静态库的时候,报了MD/MT不匹配的问题,用如下方案解决
if (WIN32)
message(STATUS ${CMAKE_BUILD_TYPE})
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
TARGET_COMPILE_OPTIONS(calib PRIVATE "/MTd$<$<CONFIG:Debug>:>")
TARGET_COMPILE_OPTIONS(test_calib PRIVATE "/MTd$<$<CONFIG:Debug>:>")
else()
TARGET_COMPILE_OPTIONS(calib PRIVATE "/MT$<$<CONFIG:Release>:>")
TARGET_COMPILE_OPTIONS(test_calib PRIVATE "/MT$<$<CONFIG:Release>:>")
endif()
endif()