====== CMake ======
* Official Site:[[https://cmake.org/|cmake.org]]
* c++跨平台构建工具,开源[BSD]免费。
* CMake [[https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html|变量列表]]:
* CMake 变量的作用域:[[https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#cmake-language-variables|cmake-language-variables]]
* 父目录里的绑定变量默认会传到子目录的CMakefile作为初始值
* find_package 默认支持的列表:''cmake --help-module-list | grep -E ^Find''
===== Tips =====
* MSVC中, cmake 默认生成的 release 工程不生成 pdb 文件,可如下添加
if (MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
# if build .exe
set(CMAKE_EXE_LINKER_FLAGS_RELEASE"${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF" CACHE STRING "" FORCE)
# if build .dll
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF" CACHE STRING "" FORCE)
# if build static .lib
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF" CACHE STRING "" FORCE)
endif (MSVC)
参考 [[https://stackoverflow.com/questions/28178978/how-to-generate-pdb-files-for-release-build-with-cmake-flags/31264946|how to generate pdb files...]], 或者使用 [[https://cmake.org/cmake/help/v3.18/manual/cmake-generator-expressions.7.html|cmake generator expressions]]来设置:
target_compile_options(${YourProjName}
PRIVATE "$<$,$>:/Zi>"
)
target_link_options(${YourProjName}
PRIVATE "$<$,$>:/DEBUG>"
PRIVATE "$<$,$>:/OPT:REF>"
PRIVATE "$<$,$>:/OPT:ICF>"
)
* 给dll右键属性的详细信息里添加git version, 参考[[https://zhuanlan.zhihu.com/p/97512450|zhihu 97512450]]
add_definitions(-DMAIN_PROJECT_NAME=\"${YourProjName}\")
find_package(Git QUIET)
if(GIT_FOUND)
set(COMMIT_HASH "")
set(BRANCH_NAME "")
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%H
OUTPUT_VARIABLE COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
execute_process(
COMMAND ${GIT_EXECUTABLE} symbolic-ref --short -q HEAD
OUTPUT_VARIABLE BRANCH_NAME
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
message(STATUS "Git version is ${BRANCH_NAME}:${COMMIT_HASH}")
add_definitions(-DGIT_COMMIT_HASH=\"${COMMIT_HASH}\")
add_definitions(-DGIT_BRANCH_NAME=\"${BRANCH_NAME}\")
endif()
然后添加VersionInfo.rc
#if (defined GIT_COMMIT_HASH && defined GIT_BRANCH_NAME)
#define PRODUCT_VERSION GIT_BRANCH_NAME ":" GIT_COMMIT_HASH
#else
#define PRODUCT_VERSION "1.0.2"
#endif // GIT_COMMIT_HASH && GIT_BRANCH_NAME
#ifndef MAIN_PROJECT_NAME
#define MAIN_PROJECT_NAME "MyLib"
#endif
1 VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x0L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", MAIN_PROJECT_NAME " Binary"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", MAIN_PROJECT_NAME
VALUE "LegalCopyright", "Copyright (C) 2020 "
VALUE "OriginalFilename", MAIN_PROJECT_NAME ".dll"
VALUE "ProductName", MAIN_PROJECT_NAME
VALUE "ProductVersion", PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
* 循环子文件夹来包含子工程,参考 [[https://stackoverflow.com/questions/7787823/cmake-how-to-get-the-name-of-all-subdirectories-of-a-directory|stackoverflow 7787823]]:
MACRO(SUBDIRLIST result curdir)
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
SET(dirlist "")
FOREACH(child ${children})
IF(IS_DIRECTORY ${curdir}/${child} AND EXISTS ${curdir}/${child}/CMakeLists.txt)
LIST(APPEND dirlist ${child})
ENDIF()
ENDFOREACH()
SET(${result} ${dirlist})
ENDMACRO()
SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR})
message(STATUS "valid subdirs: ${SUBDIRS}")
FOREACH(subdir ${SUBDIRS})
ADD_SUBDIRECTORY(${subdir})
ENDFOREACH()
* 在 bat 批处理里面,如果cmake命令行报错,参考[[https://stackoverflow.com/questions/46709956/how-do-i-handle-cmake-exe-errors|这里]],可加以下一行来进行退出处理
cmake .
if errorlevel 1 exit /B
* 屏蔽VC编译 release 时的具体某个 warning,比如c4566, 可用如下,
add_compile_options("$<$,$>:/wd4566>")
注意 ''add_compile_options'' 可影响之后所有target与子项目target, 所以适合在ci(持续集成)时使用。如果只是想具体设置某target, 使用 ''target_compile_options''。另外,不建议开发时屏蔽warning。
* cmake 不支持静态库的 dependence, 本质上,静态库只有二进制的合并,没有 link, 只有MSVC可以加 静态库的dependence然后生成合并后的lib, 但这个其它编译器不一定支持,所以cmake也没有这个选项,如果生成的 a.lib 依赖b.lib, 而 c.exe 依赖 a.lib, 一种不用在 c 的配置中显式增加 b.lib 依赖的写法是利用 ''add_library( INTERFACE)'':
add_library(a STATIC ${STRMBASE_FILES})
# target_link_libraries(a b) # 这是不起作用的,因为 a 是静态库,没有link
add_library(ab INTERFACE) # 增加一个 ab, INTERFACE
target_link_libraries(ab INTERFACE a b)
add_executable(c ...)
target_link_libraries(c ab) # 此时 c 工程就包含了a.lib, b.lib
* [[https://stackoverflow.com/questions/26037954/cmake-target-link-libraries-interface-dependencies|target_link_libraries PUBLIC/PRIVATE/INTERFACE 的区别]]:当创建**动态库**时,
* 如果源文件包含该第三方头文件,但头文件中不包含该第三方头文件,采用 PRIVATE;
* 如果源文件和头文件中都包含该第三方头文件,采用 PUBLIC;
* 如果头文件中包含该第三方头文件,但源文件中不包含,采用 INTERFACE。