博客地址:http://home.cnblogs.com/u/zengjianrong/

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仅仅是头文件依赖,编译时不需要链接到被依赖的对象。

 

posted @ 2021-03-04 16:05  black_man  阅读(391)  评论(0编辑  收藏  举报