cmake技巧
https://www.cnblogs.com/zengjianrong/p/17010429.html
1. 变量传递,同makefile,变量可由上至下传递,包括路径声明,不带target的link_libraries等;
顶层cmakelist
INCLUDE_DEREATORIES(${CMAKE_CURRENT_SOURCE_DIR}/inc)
ADD_SUBDIREATORY(xx)
底层xx目录的cmakelist已自动将上层的inc目录添加到了头文件路径;
2. 遍历:https://cmake.org/cmake/help/latest/command/foreach.html
SET(SRC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/aa ${CMAKE_CURRENT_SOURCE_DIR}/bb ${CMAKE_CURRENT_SOURCE_DIR}/cc ) FOREACH(dir ${SRC_DIRS}) INCLUDE_DIREACTORIES(${dir}/inc) AUX_SOURCE_DIREACTORY(${dir} SRCS) ENDFOREACH()
3. [多个]静态库转成动态库
99. 其他常用宏
ADD_DEFINATIONS(-DXXXX)
#libxxx.so PROJECT(xxx) TARGET_LINK_LIBRARIES(${PROJECT_NAME}, PRIVATE "-Wl,--whole-archive" ${STATIC_LIBS} "-Wl,--no-whole-archive" INTERFACE -lpthread -ldl -lrt)
CMAKE_INSTALL_RPATH 用于指定make install生成的lib and exec files的runtime path(LD链接路经,多个rpath使用“:”分隔),同时INCLUDE_DIRECTORIES 声明的路径也会被添加到rpath(同gcc/ld -rpath,可通过:readelf -d file 查看rpath) https://cmake.org/cmake/help/v3.14/variable/CMAKE_INSTALL_RPATH.html?highlight=rpath#variable:CMAKE_INSTALL_RPATH CMAKE_BUILD_RPATH 同上,仅仅影响make生成的lib and exec files CMAKE_SKIP_BUILD_RPATH 默认去除了make生成的lib and exec files的rpath
4. 区分编译器来源
https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") message("LLVM Clang"); elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") message("GNU Compiler Collection"); endif ()
5. 目录宏
PROJECT_SOURCE_DIR 最近一个定义了PROJECT()的CMakeLists.txt 所在路径;
PROJECT_BINARY_DIR = ${PROJECT_SOURCE_DIR}/build
CMAKE_SOURCE_DIR 顶层的CMakeLists.txt所在路径;
CMAKE_BINARY_DIR 当前运行cmake的根路径;例如我们通常会在代码根目录建立一个build目录,进入到build目录再做"cmake ..",此时CMAKE_BINARY_DIR 即为build目录;
CMAKE_CURRENT_SOURCE_DIR 当前CMakeLists.txt所在路径;
CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_SOURCE_DIR}/build
6. PUBLIC、PRIVATE、INTERFACE
用在 target_* 等指令中,指定此target依赖属性:
PRIVATE:私有依赖,常见于executable类型的target,表示这个依赖不需要向外传递;
PUBLIC:公开依赖,常见于library类型的target,表示这个依赖需要向外传递;
PRIVATE vs PUBLIC 举例说明如下:
# case 1: add_library(libtest SHARED xxx.cpp)
add_library(test::lib ALIAS libtest) # 重命名
target_include_directories(libtest PUBLIC xxx/include) target_link_libraries(libtest PUBLIC libtest_base) add_executable(test xxx.cpp) # 由于libtest声明的依赖是PUBLIC,故test的依赖声明仅仅需要指明依赖libtest即可; # libtest_base和xxx/include 会自动依赖进来; target_link_libraries(test PRIVATE test::lib) # 对于executable,通常都不需要将依赖关系传递出去 # case 2: add_library(libtest SHARED xxx.cpp) target_include_directories(libtest PRIVATE xxx/include) target_link_libraries(libtest PRIVATE libtest_base) add_executable(test xxx.cpp) # 由于libtest声明的依赖是PRIVATE,故test的依赖声明需要指明嵌套依赖libtest_base以及xxx/include; target_link_libraries(test PRIVATE libtest libtest_base) target_include_directories(test PRIVATE xxx/include)
除此之外,INTERFACE,类似PRIVATE,区别是:此target仅仅是头文件依赖,编译时不需要链接到被依赖的对象。