CMakeList.txt编写踩坑记录

2023-05-16

target_link_libraries中PRIVATE/PUBLIC/INTERFACE的理解

cmake-target-include-directories-meaning-of-scope

specification-and-usage-requirements

Generally, a dependency should be specified in a use of target_link_libraries() with the PRIVATE keyword if it is used by only the implementation of a library, and not in the header files. If a dependency is additionally used in the header files of a library (e.g. for class inheritance), then it should be specified as a PUBLIC dependency. A dependency which is not used by the implementation of a library, but only by its headers should be specified as an INTERFACE dependency.


add_dependencies的基本作用

假设我们需要生成一个可执行文件,该文件生成需要链接a.so b.so c.so d.so四个动态库
正常来讲,我们一把只需要以下两条指令即可:

ADD_EXECUTABLE(main main.cpp)
TARGET_LINK_LIBRARIES(main a.so b.so c.so d.so)

但是编译的时候报错,一些符号的定义找不到,而这些符号恰恰就在这几个库中,假设在a.so 和 b.so中,在上述两条指令之间加上一条指令即可编译通过:

ADD_DEPENDENCIES(main a.so b.so)

原因比较简单,生成main需要依赖a.so和b.so中的符号定义,然而a.so和b.so库的生成是在main编译生产之后的,添加这条语句就是提醒编译器需要先生成main的依赖(a.so,b.so),然后再去生成main.


include_directories与target_include_directories的区别

what-is-the-difference-between-include-directories-and-target-include-directorie
可以认为一个是全局的,一个是针对于指定target的


cmake find_package的理解

对于找不到包的情况,如果用的是CMAKE-GUI,则会提示设置对应的DIR,或者手动在CMakeLists.txt中添加。可以参考这个链接和这个cmake find_package找不到opencv

当执行find_package()这条命令后,Cmake 就会从某些路径中找这Findxxx.cmake文件或者xxxConfig.cmake文件,Cmake找到任意一个之后就会执行这个文件,然后这个文件执行后就会设置好一些Cmake变量。比如下面的变量(NAME表示库的名字 比如可以用Opencv 代表Opencv库)

<NAME>_FOUND
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES
<NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS
<NAME>_DEFINITIONS

“轻松搞定CMake”系列之find_package用法详解

这里面能看到怎么在cmake中输出变量的值
https://blog.csdn.net/zhanghm1995/article/details/105466372


常用变量和常用环境变量的引用

一、变量的引用方式是使用“ ” , 在 I F 中 , 不 需 要 使 用 这 种 方 式 , 直 接 使 用 变 量 名 即 可 二 、 自 定 义 变 量 使 用 S E T ( O B J N A M E x x x x ) , 使 用 时 {}”,在IF中,不需要使用这种方式,直接使用变量名即可 二、自定义变量使用SET(OBJ_NAME xxxx),使用时 IF使使使SET(OBJNAMExxxx)使{OBJ_NAME}
三、cmake的常用变量:
CMAKE_BINARY_DIR, PROJECT_BINARY_DIR :这两个变量内容一致,如果是内部编译,就指的是工程的顶级目录,如果是外部编译,指的就是工程编译发生的目录。
CMAKE_SOURCE_DIR, PROJECT_SOURCE_DIR:这两个变量内容一致,都指的是工程的顶级目录。
CMAKE_CURRENT_BINARY_DIR:外部编译时,指的是target目录,内部编译时,指的是顶级目录
CMAKE_CURRENT_SOURCE_DIR:CMakeList.txt所在的目录
CMAKE_CURRENT_LIST_DIR:CMakeList.txt的完整路径
CMAKE_CURRENT_LIST_LINE:当前所在的行
CMAKE_MODULE_PATH:如果工程复杂,可能需要编写一些cmake模块,这里通过SET指定这个变量
LIBRARY_OUTPUT_DIR, BINARY_OUTPUT_DIR:库和可执行的最终存放目录
PROJECT_NAME, CMAKE_PROJECT_NAME:前者是当前CMakeList.txt里设置的project_name,后者是整个项目配置的project_name

cmake中调用环境变量
Using $ENV{NAME} : 调用系统环境变量,我们也可以使用 "SET(ENV{NAME} value)".  需要注意的是这里"ENV"没有"$".

CMAKE_INCLUDE_CURRENT_DIR 等同于 INCLUDE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
其他的内置变量
  • BUILD_SHARED_LIBS: set the default value when using ADD_LIBRARY()
  • CMAKE_C_FLAGS: set compiler for c language
  • CMAKE_CXX_FLAGS: set compiler for c++ language
区分debug和release

在工程build目录下执行 cmake .. -DCMAKE_BUILD_TYPE=DEBUG|RELEASE,再执行make, 或者在顶级CMakeList.txt里加入: set(CMAKE_BUILD_TYPE Debug|Release|MinSizeRel|RelWithDebInfo)

指定编译32bit或64bit程序

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")

通过cmake打印能获取到的所有系统环境变量
# 在CMakeList.txt中使用
execute_process(
  COMMAND ${CMAKE_COMMAND} -E environment
)
# 在终端中使用
cmake -E environment
设置install路径
// 命令行里设置
cmake -DCMAKE_INSTALL_PREFIX=<install_path>

// 或者在根cmake里设置
SET(CMAKE_INSTALL_PREFIX <install_path>)

默认安装路径是/usr/local

获取绝对路径和父目录
# 获取文件绝对路径
get_filename_component(FULL_NAME "${FILE}" ABSOLUTE)

# 获取文件父路径
get_filename_component(PARENT_DIR "${FULL_NAME}" PATH)
判断操作系统平台及Win是否为32位
if(CMAKE_SYSTEM_NAME MATCHES "Linux")  // 注意区分大写
  message(STATUS "Linux platorm!")
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
if(CMAKE_CL_64)
  message(STATUS "Windows Win64 platform!")
  else()
    message(STATUS "Windows Win32 platform!")
  endif(CMAKE_CL_64)
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
  message(STATUS "FreeBSD platform!")
else()
  message(STATUS "other platform!")
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")

生成器表达式(generator expressions)

在写CMakeList.txt时,如何打印生成器表达式的值?
生成器表达式的值是在编译时确定的。如果一定要这么做,可以参考编写以下命令:

add_custom_command(TARGET yourtarget POST_BUILD 
COMMAND ${CMAKE_COMMAND} -E echo "value = $<TARGET_FILE_DIR:yourtarget>")

cmake的add_custom_command和add_custom_target指令

链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMakeList.txt编写踩坑记录 的相关文章

随机推荐