当前位置: 首页 > article >正文

cmake 常用方法自我总结

目录

1. 编译一个库依赖另一个库

2. 把某一个CMakeLists.txt中变量设为整个工程中任意CMakeLists.txt都可以访问

3. 枚举目录下所有匹配文件

4. 拷贝文件

5. 解决方案下分Header Files,Source Files目录

6. 依赖头文件(附加依赖项)

7. install

8. 生成库、执行文件

9. 生成debug/release版本判读

10. 编译工程命令

11. 设置默认 C++ 标准

12. 工程示例

13. 指定字符集

14. 注意

15. Cmake设置宏,VS中使用

16. 参考


1. 编译一个库依赖另一个库

最近在做C++项目时,当编译A库得时候,A依赖B库,所以要先生成B库,然后把

B库的lib设置到A库中,一旦工程新建,就要把前面操作过程都执行下,挺繁琐。

cmake里面可以通过 “target_link_libraries” 这个方法来设置,如下:

target_link_libraries(pcb debug ${OpenCV_LIBS} common)

pcb库依赖opencv,common库,当我们这样设置的时候,在pcb工程属性中就可以看到自动设置好了依赖,如下图所示:

最关键的是,当我点击生成pcb库的时候,其会先自动生成common.lib库,然后再生成pcb库,也就是说,cmake会自动判断依赖项,并根据依赖项依次生成,非常方便便捷。

生成的库,还依赖别的生成库,或者依赖别的已有库,这时使用 target_link_libraries 命令,这个命令target_link_libraries一定要放到 add_library 或 add_executable 后面,不然会有问题。

2. 把某一个CMakeLists.txt中变量设为整个工程中任意CMakeLists.txt都可以访问

set(NEED_Lib_Path /xxx/xxx/opencv.lib CACHE STRING INTERNAL)

set命令中的 CACHE STRING INTERNAL 这几个参数就是把变量 NEED_Lib_Path 设为全局都可以访问

3. 枚举目录下所有匹配文件

当想把一个文件夹下所有文件都放到一个变量时,可以通过 file 和 set 一起使用,如下:

file(GLOB  NEED_Lib_Dir  xxx/xxx/lib/Release/*.lib)
set(NEED_Lib_Path ${NEED_Lib_Dir } CACHE STRING INTERNAL)

file命令通过GLOB参数,把xxx/xxx/lib/Release目录下所有后缀为 .lib 的文件全部以绝对路径放到变量 NEED_Lib_Dir 中。

接着通过set命令中的 CACHE STRING INTERNAL 这几个参数,把 NEED_Lib_Path 设为了全局,在整个工程中的CMakeLists.txt都可以访问整个参数。

4. 拷贝文件

file(COPY ${Debug_OpenCV_Bin} DESTINATION Debug)

这个命令是把变量 Debug_OpenCV_Bin 拷贝到此工程的 Debug 目录下

5. 解决方案下分Header Files,Source Files目录

为了更好的显示文件,需要对.h和.cpp进行分目录,如下图所示:

通过如下命令:

file(GLOB HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CPP_H_CRYPTOPP_PATH}/*.h)
source_group("Header Files" FILES ${HEADERS})
aux_source_directory(src/ SOURCES)

1.先通过file的GLOB把所有文件放到变量HEADERS中

2.通过 source_group 把 HEADERS 变量中的内容放到 “Header Files” 目录中

3.那 aux_source_directory 这是 cmake 命令自动把 .cpp全部放到 “Source Files” 中,这个不需要我们再创建这个目录

6. 依赖头文件(附加依赖项)

通过如下命令,可以把好多不同路径下include都加到工程里,下面加了4个路径的include到工程中

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${DEBUG_NCNN_INCLUDE_PATH} ${DEBUG_CRYPTOPP_INCLUDE_PATH})

7. install

当我们点击install,会自动把需要提供给别人的库和头文件,lib都生成好,且自动输出一个目录下,效果如下图所示:

我当前是需要pcb这个库导出,所以 install 命令是写在 pcb 这个目录下的 CMakeLists.txt 中,命令如下:

set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "The path to use for make install" FORCE)
set(PCB_OUT_PUT_INCULDE ${CMAKE_CURRENT_SOURCE_DIR}/include/pcb.h)

install(FILES ${PCB_OUT_PUT_INCULDE} DESTINATION include)
install(TARGETS pcb LIBRARY DESTINATION CMAKE_INSTALL_PREFIX)

1.第一行的 set 以及里面内容是通用的,应该就默认这么写

2.第二行中是设置了PCB_OUT_PUT_INCULDE 为需要导出的 .h 文件

3.第三行通过 install 和 参数 FILES 把 .h 文件导出到 DESTINATION 路径下,这个 DESTINATION 参数也是默认的

4.通过 install 和 参数 TARGETS 把 pcb 的 lib 和 dll 导出到 DESTINATION 路径下。这里会把 pcb.lib 导出到 lib 目录,pcb.dll 导出到 bin 目录。pcb 后面跟的参数 “LIBRARY” 也是默认的

8. 生成库、执行文件

1.生成库

通过如下命令可以生成库,这里的 SHARED 是动态库,即 .dll,也可以改为 STATIC 生成 静态库,即 .lib。后面跟的  ${SOURCES}  ${HEADERS} 是生成pcb库对应的源文件和头文件

add_library(pcb SHARED ${SOURCES} ${HEADERS})

2.生成执行文件,即 .exe

add_executable命令第一个参数是生成的执行文件名,后面是 ${DIR_LIB_SRCS} 源文件,这里依赖的头文件通过命令 include_directories 设置

add_executable(test ${DIR_LIB_SRCS})

9. 生成debug/release版本判读

通过如下命令可以判断生成debug版本,还是release版本

if(CMAKE_CONFIGURATION_TYPES AND (CMAKE_CONFIGURATION_TYPES STREQUAL "Debug"))
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${DEBUG_NCNN_INCLUDE_PATH} ${DEBUG_CRYPTOPP_INCLUDE_PATH})
	target_link_libraries(pcb debug ${OpenCV_LIBS} ${DEBUG_NCNN_LIB_PATH} ${DEBUG_CRYPTOPP_LIB_PATH} common)
else()
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${RELEASE_NCNN_INCLUDE_PATH} ${RELEASE_CRYPTOPP_INCLUDE_PATH})
	target_link_libraries(pcb optimized ${OpenCV_LIBS} ${RELEASE_NCNN_LIB_PATH} ${RELEASE_CRYPTOPP_LIB_PATH} common)
endif()

在生成cmake的时候可以在命令行输入:-D CMAKE_CONFIGURATION_TYPES:STRING=Debug 这样CMakeLists.txt 中就会自动判断是debug,还是release

10. 编译工程命令

cmake ..  -A x64 -D CMAKE_CONFIGURATION_TYPES:STRING=Debug

11. 设置默认 C++ 标准

通过在顶级目录的CMakeLists.txt中设置,就可以达到下图效果

set(CMAKE_CXX_STANDARD 17)

12. 工程示例

1. 下图是我的工程示例,顶级必须设置的是下图右边红色框内容,顶级目录我基本设置一些路径,这样别人只需要修改这个 CMakeLists.txt 就可以了。这里我就把source加到工程中,因为代码都在source文件夹下

2. source目录下的内容如下:

3. 构建好的工程如下图所示:

4. 附一张 test 的 CMakeLists.txt 内容图以及命令

project(test)

set(OpenCV_DIR ${OpenCV_PATH})
#opencv
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

set(COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../common/include/)
# this is add C/C++ -> COMMON -> ADD INCLUDE
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_INCLUDE})
# 将当前目录下所有源码文件添加到变量DIR_LIB_SRCS
file(GLOB DIR_LIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 递归
# file(GLOB_RECURSE DIR_LIB_HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h )
file(GLOB DIR_LIB_HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
source_group("Header Files" FILES ${DIR_LIB_HEADERS})

message("Debug_OpenCV_Bin: ${Debug_OpenCV_Bin}")

file(COPY ${Debug_OpenCV_Bin} DESTINATION Debug)
file(COPY ${Release_OpenCV_Bin} DESTINATION Release)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../pcb/include/pcb.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/include)

link_directories(${JIANJU_OUT_PUT_INCULDE})

add_executable(test ${DIR_LIB_SRCS})

target_link_libraries(test ${OpenCV_LIBS} pcb)

13. 指定字符集

默认Visual Studio是使用 “使用多字节字符集”, 当某个工程需要使用 “使用 Unicode 字符集”,则在此CMakeLists.txt中加入如下,就可以指定设置 “使用 Unicode 字符集”,如下及下图所示:

add_definitions(-DUNICODE -D_UNICODE)

14. 注意

1. 有时候明明方法对,就是执行不对,比如message也显示不对变量,这个时候需要把之前生成的工程目录下所有文件全部删了,重新生成,这个时候就对了。

2. 生成的库,还依赖别的生成库,或者依赖别的已有库,这时使用 target_link_libraries 命令,这个命令target_link_libraries一定要放到 add_library 或 add_executable 后面,不然会有问题。

15. Cmake设置宏,VS中使用

有时需要通过宏定义来判断是否执行某个方法,这时候可以在cmake中传参数,然后在CMakeLists.txt中判断,并把参数设置到 visual studio 工程中

如下,我需要在 VS 代码中判断是否定义了宏 “SAVEXML”,顶层 CMakeLists.txt 中添加如下代码

if (SAVE STREQUAL XML)
    add_definitions(-DSAVEXML)
endif()

cmake在编译的时候,传入参数:

cmake ..  -A x64 -D CMAKE_CONFIGURATION_TYPES:STRING=Debug -DSAVE=XML

-DSAVE=XML 则为传入 CMakeLists.txt  的参数,接着在 VS 代码中添加如下判断:

#ifdef SAVEXML
	std::cout << "save xml" << std::endl;
#else
	std::cout << "not save xml" << std::endl;
#endif // SAVEXML

效果展示,如下是添加了-DSAVE=XML

如下是没有添加-DSAVE=XML,效果展示:

 

同时在项目属性中也可以看到,有 SAVEXML 宏定义,如下图所示:

 

仔细对比添加和没有添加对VS代码中影响,可以发现,添加了,则 #ifdef SAVEXML 代码高亮,没有添加的则灰色

16. 参考

1. cmake:在 CMake 生成的 VS2015 工程中保持源码文件的目录组织_cmake source_group_OceanStar的学习笔记的博客-CSDN博客

2.CMake定义宏的方式_cmake 宏定义_风闲1217的博客-CSDN博客

3.CMake通过外部传参执行不同逻辑的方案比如瑞芯微(1126)地平线(horizon)-CSDN博客


http://www.kler.cn/a/8217.html

相关文章:

  • [项目代码] YOLOv5 铁路工人安全帽安全背心识别 [目标检测]
  • XML Schema 字符串数据类型
  • [SWPUCTF 2022 新生赛]Power! 反序列化详细题解
  • Kettle——CSV文件转换成excel文件输出
  • TCP可靠连接的建立和释放,TCP报文段的格式,UDP简单介绍
  • 【大数据学习 | HBASE】hbase的读数据流程与hbase读取数据
  • 通过阿里云函数计算解决ChatGPT API的调用问题
  • 算法训练第四十九天 | 121.买卖股票的最佳时机、122.买卖股票的最佳时机II
  • python教程requests详解
  • entos7系统部署网站项目教程【超详细教程】
  • 实践分享:如何在自己的App 中引入AI 画图
  • Web前端如何防止被恶意调式?
  • JS 数组排序方法 - sortFun
  • Kotlin 面向对象(二)
  • Redis —缓存常见异常
  • 父子组件传值问题
  • Ludwig Otto Hölder
  • php企业公司员工考勤加班系统
  • 面试被问到:测试计划和测试方案有什么区别?
  • 派盘为您的个人数据安家
  • 一篇文章,弄懂蓝牙协议怎么看,进军物联网!
  • 【WCH】基于Keil环境CH32F203 GPIO点灯实验
  • 全国青少年电子信息智能创新大赛(复赛)python·模拟三卷,含答案解析
  • 1mm³大小,世界首个功率破KW的单芯片激光模组诞生
  • Unity入门开发资源链接
  • Flask项目运行报错解决:sqlalchemy.exc.OperationalError