chapter12 - full project
总体结构
一些文件的分析
chapter12/01-full-project/src/calc/CMakeLists.txt
add_library(calc_obj OBJECT calc.cpp)
target_include_directories(calc_obj INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
set_target_properties(calc_obj PROPERTIES
PUBLIC_HEADER src/calc/include/calc/calc.h
POSITION_INDEPENDENT_CODE 1
)
add_library(calc_shared SHARED)
target_link_libraries(calc_shared calc_obj)
add_library(calc_static STATIC)
target_link_libraries(calc_static calc_obj)
一些要点:
- target_include_directories 使用生成器表达式为 build 和 install 之后指定了不同的包含路径。导出 target export file 的话这个细节非常重要。
- 然后是设置对象的属性。因为我们的库不是 SHARED 类型而是 OBJECT 类型,所以不是默认 PIC 的。需要正确设置 POSITION_INDEPENDENT_CODE 属性(我们实验室项目是在全局编译选项中加入
-fPIC
保证这一点的)。
chapter12/01-full-project/cmake/GetFTXUI.cmake
include(FetchContent)
FetchContent_Declare(
FTXTUI
GIT_REPOSITORY https://github.com/ArthurSonzogni/FTXUI.git
GIT_TAG v0.11
)
option(FTXUI_ENABLE_INSTALL "" OFF)
option(FTXUI_BUILD_EXAMPLES "" OFF)
option(FTXUI_BUILD_DOCS "" OFF)
FetchContent_MakeAvailable(FTXTUI)
要点:FetchContent 模块将 FetchContent_Declare
和 FetchContent_MakeAvailable
分成了两步,这样能够在导入之前设置一些属性。
chapter-12/01-full-project/cmake/BuildInfo.cmake
# ...
set(BUILDINFO_TEMPLATE_DIR ${CMAKE_CURRENT_LIST_DIR})
set(DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/buildinfo")
string(TIMESTAMP TIMESTAMP)
find_program(GIT_PATH git REQUIRED)
execute_process(COMMAND
${GIT_PATH} log --pretty=format:'%h' -n 1
OUTPUT_VARIABLE COMMIT_SHA)
configure_file(
"${BUILDINFO_TEMPLATE_DIR}/buildinfo.h.in"
"${DESTINATION}/buildinfo.h" @ONLY
)
# ...
configure_file
函数可以将 CMake 中的变量用 @VAR@
的方式传入到模板中,然后生成源码文件(这里被用来生成头文件了,但是实际上也可以用来生成其他文件):
struct BuildInfo {
static inline const std::string CommitSHA =
"@COMMIT_SHA@";
static inline const std::string Timestamp =
"@TIMESTAMP@";
static inline const
std::string Version = "@PROJECT_VERSION@";
};
这样就能动态嵌入 commit 和时间、版本等信息,不会出现更新内容后忘记更新源码各处散落的版本的情况。
configure_file
允许的替换有:@VAR@
, ${VAR}
, $CACHE{VAR}
和 $ENV{VAR}
这四种。使用 @ONLY
参数将只启用第一种。使用 COPYONLY
参数将不会进行任何替换。
此外 #cmakedefine VAR ...
会被替换成 #define VAR ...
或者 /* #undef VAR */
,而 #cmakedefine01 VAR
将会被替换成 #define VAR 0
或者 #define VAR 1
。