public:it:cmake

CMake

  • Official Site:cmake.org
  • c++跨平台构建工具,开源[BSD]免费。
  • CMake 变量列表:
  • CMake 变量的作用域:cmake-language-variables
    • 父目录里的绑定变量默认会传到子目录的CMakefile作为初始值
  • find_package 默认支持的列表:cmake –help-module-list | grep -E ^Find
  • 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)

    参考 how to generate pdb files..., 或者使用 cmake generator expressions来设置:

    target_compile_options(${YourProjName} 
        PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/Zi>"
    )
    target_link_options(${YourProjName}
        PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/DEBUG>"
        PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/OPT:REF>"
        PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/OPT:ICF>"
    )
  • 给dll右键属性的详细信息里添加git version, 参考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
  • 循环子文件夹来包含子工程,参考 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命令行报错,参考这里,可加以下一行来进行退出处理
    cmake .
    if errorlevel 1 exit /B
  • 屏蔽VC编译 release 时的具体某个 warning,比如c4566, 可用如下,
    add_compile_options("$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/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(<name> 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
    • 如果源文件包含该第三方头文件,但头文件中不包含该第三方头文件,采用 PRIVATE;
    • 如果源文件和头文件中都包含该第三方头文件,采用 PUBLIC;
    • 如果头文件中包含该第三方头文件,但源文件中不包含,采用 INTERFACE。
  • public/it/cmake.txt
  • 最后更改: 2024/09/03 14:06
  • oakfire