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)

一些要点:

  1. target_include_directories 使用生成器表达式为 build 和 install 之后指定了不同的包含路径。导出 target export file 的话这个细节非常重要。
  2. 然后是设置对象的属性。因为我们的库不是 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_DeclareFetchContent_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