CMake

资源: 

  https://github.com/xiaoweiChen/CMake-Cookbook

  生成器表达式章节:参考

  find_package和pkg_check_modules

  qt的国际化:ts文件的更新   参考wiki

1. 一些命令

cmake -S . -B build       # 自动创建 build 文件夹
cmake -S . -B build && cmake --build build --target all -- -j$(nproc)
cmake --help-command ADD_SUBDIRECTORY
apt rdepends qtbase5-dev-tools # 查找哪些软件依赖于这个 from: dpkg -S qdbusxml2cpp

  cmake 的 clean 方式:参考

  优雅的构建CMake项目:参考

  集成GTest:参考,相关命令:enable_testing()    add_test()   详细参考

  在cmake中优雅的使用pkgconfig参考

  cmake的函数以及参数传递参考

alex@alex-PC:~/Desktop/Test/translator/example1$ dpkg -S Qt5LinguistTools
qttools5-dev:amd64: /usr/lib/x86_64-linux-gnu/cmake/Qt5LinguistTools/Qt5LinguistToolsMacros.cmake
qttools5-dev:amd64: /usr/lib/x86_64-linux-gnu/cmake/Qt5LinguistTools/Qt5LinguistToolsConfig.cmake
qttools5-dev:amd64: /usr/lib/x86_64-linux-gnu/cmake/Qt5LinguistTools/Qt5LinguistToolsConfigVersion.cmake
qttools5-dev:amd64: /usr/lib/x86_64-linux-gnu/cmake/Qt5LinguistTools
函数参数

  安装路径的指定:知乎 

  安装权限的指定:参考

  现代cmake技巧:参考

  cmake生成器表达式参考    生成器表达式的简单示例:参考    参考   参考   参考   官方参考    详参

  include_directories 和 link_directories参考(LINK_DIRECTORIES放在ADD_EXECUTABLE之前)

  GNU开发工具——CMake构建Qt工程实践

  编译 Debug 或 Release 版本的坑:参考

  aux_source_directory

  get_filename_component

  strip --strip-unneeded

  install -m 644 -p 

  在编译时下载:参考

  对于龙芯的支持:参考

  添加单元测试: 参考

  CMakePrintHelpers

  打印所有可见变量:参考

cmake_minimum_required(VERSION 3.7)

打印可见变量及其值
message("内置变量 -----------------------------------------------------------------------------------") get_cmake_property(_variableNames VARIABLES) foreach (_variableName ${_variableNames}) message(STATUS "${_variableName}=${${_variableName}}") endforeach()
message("环境变量 -----------------------------------------------------------------------------------") 打印环境变量及其值 execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "environment")

  使用Qt的私有库,重要参考

The package qt5-base:x86-windows provides CMake targets:

    find_package(Qt5AccessibilitySupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::AccessibilitySupport Qt5::AccessibilitySupport Qt::AccessibilitySupportPrivate Qt5::AccessibilitySupportPrivate)

    find_package(Qt5Bootstrap CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::Bootstrap Qt5::Bootstrap Qt::BootstrapPrivate Qt5::BootstrapPrivate)

    find_package(Qt5Concurrent CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::Concurrent Qt5::Concurrent Qt::ConcurrentPrivate Qt5::ConcurrentPrivate)

    find_package(Qt5Core CONFIG REQUIRED)
    # Note: 2 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::Core Qt5::Core Qt::WinMain Qt5::WinMain)

    find_package(Qt5DBus CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::DBus Qt5::DBus Qt::DBusPrivate Qt5::DBusPrivate)

    find_package(Qt5DeviceDiscoverySupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::DeviceDiscoverySupport Qt5::DeviceDiscoverySupport Qt::DeviceDiscoverySupportPrivate Qt5::DeviceDiscoverySupportPrivate)

    find_package(Qt5EdidSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::EdidSupport Qt5::EdidSupport Qt::EdidSupportPrivate Qt5::EdidSupportPrivate)

    find_package(Qt5EventDispatcherSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::EventDispatcherSupport Qt5::EventDispatcherSupport Qt::EventDispatcherSupportPrivate Qt5::EventDispatcherSupportPrivate)

    find_package(Qt5FbSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::FbSupport Qt5::FbSupport Qt::FbSupportPrivate Qt5::FbSupportPrivate)

    find_package(Qt5FontDatabaseSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::FontDatabaseSupport Qt5::FontDatabaseSupport Qt::FontDatabaseSupportPrivate Qt5::FontDatabaseSupportPrivate)

    find_package(Qt5Gui CONFIG REQUIRED)
    # Note: 9 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::Gui Qt5::Gui Qt::GuiPrivate Qt5::GuiPrivate)

    find_package(Qt5Network CONFIG REQUIRED)
    # Note: 1 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::Network Qt5::Network Qt::NetworkPrivate Qt5::NetworkPrivate)

    find_package(Qt5OpenGL CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::OpenGL Qt5::OpenGL Qt::OpenGLPrivate Qt5::OpenGLPrivate)

    find_package(Qt5OpenGLExtensions CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::OpenGLExtensions Qt5::OpenGLExtensions Qt::OpenGLExtensionsPrivate Qt5::OpenGLExtensionsPrivate)

    find_package(Qt5PlatformCompositorSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::PlatformCompositorSupport Qt5::PlatformCompositorSupport Qt::PlatformCompositorSupportPrivate Qt5::PlatformCompositorSupportPrivate)

    find_package(Qt5PrintSupport CONFIG REQUIRED)
    # Note: 1 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::PrintSupport Qt5::PrintSupport Qt::PrintSupportPrivate Qt5::PrintSupportPrivate)

    find_package(Qt5Sql CONFIG REQUIRED)
    # Note: 3 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::Sql Qt5::Sql Qt::SqlPrivate Qt5::SqlPrivate)

    find_package(Qt5Test CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::Test Qt5::Test Qt::TestPrivate Qt5::TestPrivate)

    find_package(Qt5ThemeSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::ThemeSupport Qt5::ThemeSupport Qt::ThemeSupportPrivate Qt5::ThemeSupportPrivate)

    find_package(Qt5Widgets CONFIG REQUIRED)
    # Note: 1 target(s) were omitted.
    target_link_libraries(main PRIVATE Qt::Widgets Qt5::Widgets Qt::WidgetsPrivate Qt5::WidgetsPrivate)

    find_package(Qt5WindowsUIAutomationSupport CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::WindowsUIAutomationSupport Qt5::WindowsUIAutomationSupport Qt::WindowsUIAutomationSupportPrivate Qt5::WindowsUIAutomationSupportPrivate)

    find_package(Qt5Xml CONFIG REQUIRED)
    target_link_libraries(main PRIVATE Qt::Xml Qt5::Xml Qt::XmlPrivate Qt5::XmlPrivate)
View Code

  cmake 中 ts 转 qm 文件: 参考   参考   参考   官方翻译)   git-example   qt国际化   参考

  添加 ui 文件、资源文件等:参考

  使用OpenGL:参考   参考

  关于 moc_predefs.h

2. 内置变量

  cmake 中使用 Qt 的 private module:参考   官方   参考   参考   这有个不错的示例

# qtbase 中搜索 CorePrivate 这个:
set_target_properties(QtLibraryInfo PROPERTIES COMPILE_OPTIONS $
<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_OPTIONS> COMPILE_DEFINITIONS $<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_DEFINITIONS> INCLUDE_DIRECTORIES $<TARGET_PROPERTY:Qt::Core,INTERFACE_INCLUDE_DIRECTORIES> INCLUDE_DIRECTORIES $<TARGET_PROPERTY:Qt::CorePrivate,INTERFACE_INCLUDE_DIRECTORIES> )

  参考(不错的文章)

  add_subdirectory(添加一个子目录并构建该子目录):参考

  include_directories() 用于添加 Headers 搜索路径( -I 标志), add_subdirectory() 在这种情况下没有区别 .

  include_directories 和 target_include_directories 区别: 参考   和生成器使用

find_package( Threads REQUIRED )
target_link_libraries(demo ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
set_and_check 代替普通的
target_include_directories(t x y) # 添加 x y 到目标的包含路径 t
# 这种方法的优点是你可以控制选项传播到依赖于这个PUBLIC和PRIVATE的其他目标. same as CMAKE_EXE_LINKER_FLAGS :
target_compile_options(first-test PRIVATE -fexceptions)

  target_compile_options add_compile_options  reference

  自动处理版本号:参考

cmake_minimum_required(VERSION 3.10)

if(NOT DTK_CORE_VERSION)
    set(DTK_CORE_VERSION 5.4.3)
endif()

project(dtkcore VERSION ${DTK_CORE_VERSION} LANGUAGES CXX)

message("CMAKE_PROJECT_NAME = ${CMAKE_PROJECT_NAME}")
message("PROJECT_VERSION = ${PROJECT_VERSION}")
message("PROJECT_VERSION_MAJOR = ${PROJECT_VERSION_MAJOR}")
message("PROJECT_VERSION_MINOR = ${PROJECT_VERSION_MINOR}")
message("PROJECT_VERSION_PATCH = ${PROJECT_VERSION_PATCH}")
message("PROJECT_VERSION_TWEAK = ${PROJECT_VERSION_TWEAK}")

# cmake -DDTK_CORE_VERSION=10.2.1.3 CMakeLists.txt
# cmake -S . -B build
View Code

  外部传入字符串:参考

  同时编译动态、静态库的方法

  参考

  cmake的RPATH:

SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 
SET(CMAKE_INSTALL_RPATH "\${ORIGIN}/lib") #指定运行时动态库的加载路径,ORIGIN指运行文件所在目录

3. 常用

  cmake gui:参考

  参考

if (UNIX) 
     set(CMAKE_CXX_FLAGS "-pthread")
     set(CMAKE_CXX_FLAGS "-dl")
endif (UNIX)
ADD_DEFINITIONS(-DXXX -DXXX)

4. 安装

  参考   

  cmake -DCMAKE_INSTALL_PREFIX=<你想要安装的路径>

  set(CMAKE_INSTALL_PREFIX /usr/local)
  install(TARGETS test DESTINATION bin) #将test安装到/usr/local/bin目录下

  关于 EXPORT 和 configuration :参考,结合这个一起看

5. 动态、静态的生成

  BUILD_SHARED_LIBS这个开关用来控制默认的库编译方式,如果不进行设置,

  使用ADD_LIBRARY 并没有指定库类型的情况下,默认编译生成的库都是静态库。

  如果 SET(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库。

6. 其它

  CMake 的查找规则:参考

  GLOB的陷阱

  PUBLIC_HEADER 主要是用于mac系统安装的:参考

  CMake 里面使用sed命令

execute_process(COMMAND
      sh -c "sed -i 's#\\;#\\\n#g'  ${CMAKE_CURRENT_LIST_DIR}/dtkcore_config.h"
)

对于关键字的解释:

依赖关系 描述
PRIVATE 我需要,但是依赖者不需要
PUBLIC 我和依赖者都需要
INTERFACE 我不需要,但是依赖者需要

生成器表达式中使用C++11:

  

实例代码:

  编译时执行命令从ts文件生成qm文件:

cmake_minimum_required(VERSION 3.10)
# git clean -dfx . && cmake CMakeLists.txt && make && find . -name "*.qm"
project(generate_qm)

if (NOT TARGET Qt5::release)
    add_executable(Qt5::lrelease IMPORTED)
    set(imported_location "/usr/bin/lrelease")
    if (NOT EXISTS "${imported_location}")
        message(FATAL_ERROR "/usr/bin/lrelease does not exist. please install dependences qttools5-dev-tools.")
    endif()

    set_target_properties(Qt5::lrelease PROPERTIES
        IMPORTED_LOCATION ${imported_location}
    )
endif()

set(Qt5_LRELEASE_EXECUTABLE Qt5::lrelease)


function(DTK_CREATE_QM_FROM_TS QM_FILE_LIST)
    set(options)
    set(oneValueArgs)
    set(multiValueArgs OPTIONS)
    cmake_parse_arguments(_LRELEASE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    set(LRELEASE_FILES ${_LRELEASE_UNPARSED_ARGUMENTS})


    set(QM_FILES_OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/qm_files)
    # foreach(TS_FILE_PATH ${LRELEASE_FILES})
    #     message(STATUS ${TS_FILE_PATH})
    #     get_filename_component(FILE_NAME_NO_SUFFIX ${TS_FILE_PATH} NAME_WE) 
    #     set(QM_FILE_LOCATION ${QM_FILES_OUTPUT_PATH}/${FILE_NAME_NO_SUFFIX}.qm)
    #     # message("${Qt5_LRELEASE_EXECUTABLE} ARGS ${TS_FILE_PATH} -qm ${QM_FILE_LOCATION} ????")
    #     # add_custom_command(OUTPUT ${QM_FILE_LOCATION}
    #     #     COMMAND ${Qt5_LRELEASE_EXECUTABLE} ARGS ${TS_FILE_PATH} -qm ${QM_FILE_LOCATION}
    #     #     DEPENDS ${QM_FILE_LOCATION} VERBATIM
    #     # )
    #     list(APPEND ${QM_FILE_LIST} ${QM_FILE_LOCATION})
    # endforeach()
    dtk_add_translation(${QM_FILE_LIST} ${LRELEASE_FILES})
    set(${QM_FILE_LIST} ${${QM_FILE_LIST}} PARENT_SCOPE)
    file(MAKE_DIRECTORY "${QM_FILES_OUTPUT_PATH}")
endfunction()

function(DTK_ADD_TRANSLATION _qm_files)
    set(options)
    set(oneValueArgs)
    set(multiValueArgs OPTIONS)

    cmake_parse_arguments(_LRELEASE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    set(_lrelease_files ${_LRELEASE_UNPARSED_ARGUMENTS})

    foreach(_current_FILE ${_lrelease_files})
        get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE)
        get_filename_component(qm ${_abs_FILE} NAME)
        # everything before the last dot has to be considered the file name (including other dots)
        string(REGEX REPLACE "\\.[^.]*$" "" FILE_NAME ${qm})
        get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION)
        if(output_location)
            file(MAKE_DIRECTORY "${output_location}")
            set(qm "${output_location}/${FILE_NAME}.qm")
        else()
            set(qm "${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.qm")
        endif()

        add_custom_command(OUTPUT ${qm}
            COMMAND ${Qt5_LRELEASE_EXECUTABLE}
            ARGS ${_LRELEASE_OPTIONS} ${_abs_FILE} -qm ${qm}
            DEPENDS ${_abs_FILE} VERBATIM
        )
        list(APPEND ${_qm_files} ${qm})
    endforeach()
    set(${_qm_files} ${${_qm_files}} PARENT_SCOPE)
endfunction()

file(GLOB LANGUAGE_TS_FILES "*.ts")
dtk_create_qm_from_ts(QM_FILES
    ${LANGUAGE_TS_FILES}
)

add_custom_target(${PROJECT_NAME} ALL DEPENDS ${QM_FILES})
View Code

  原来使用这个函数,只要把Translate加到target中或者depends中就能生成:

file(GLOB_RECURSE LANGUAGE_TS_FILES "*.ts")
qt5_create_translation(Translate
    # main.cpp                # 扫描源文件,如果有 tr 的也会被替换
    # dialog.ui
    # en.ts
    ${LANGUAGE_TS_FILES}
)
View Code

遇到的重要问题记录:

   rpmlint -c BinariesCheck

  使用 link_directories 链接本地库可以比 add_directories 提供更好的编译并行性能。

技巧,同一个目录生成多个可执行文件:

cmake_minimum_required(VERSION 3.14)
# https://stackoverflow.com/questions/35696103/cmake-wildcard-for-target-objects
project(myTestDemo)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

add_library(Client OBJECT main1.cpp)
add_library(Server OBJECT main2.cpp)

function(DTK_ADD_EXECUTABLE _target)
    foreach(_source IN ITEMS ${ARGN})
        if (NOT TARGET "${_source}")
            list(APPEND _source_list "${_source}")
        else()
            get_target_property(_type "${_source}" TYPE)
            if (_type STREQUAL "OBJECT_LIBRARY")
                list(APPEND _source_list "$<TARGET_OBJECTS:${_source}>")
            else()
                message(SEND_ERROR "my_add_executable: '${_source}' given as parameter is not a object-library target.")
            endif()
        endif()
    endforeach()
    add_executable(${_target} ${_source_list})
endfunction()

dtk_add_executable(target1 main1.cpp )  # 非main的对象写在后面 Client、Server
dtk_add_executable(target2 main2.cpp )  

add_custom_target(target3)
add_dependencies(target3 target1 target2)
multi executable

生成代码测试覆盖率:

  参考 

CMAKE_EXE_LINKER_FLAGS 的坑:参考 

添加子文件夹:

   gerrit链接

# https://stackoverflow.com/questions/8934295/add-source-in-a-subdirectory-to-a-cmake-project
# https://crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources/
# 正规写法: https://www.jianshu.com/p/cbee27847638

cmake_minimum_required(VERSION 3.10)
project(dtkcore VERSION 5.5)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)


set(REQUIRED_QT_VERSION 5.11.3)

find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core DBus Xml Concurrent)

include_directories(base filesystem log settings util)

find_library(QGSETTINGS_LIB gsettings-qt)

set(Qt_LIBS
    Qt5::Core
    Qt5::DBus
    Qt5::Xml
    Qt5::Concurrent
)

add_library(${PROJECT_NAME} STATIC SHARED ${HEADERS} ${SOURCES} ${RESOURCES} ${QMLS} ${QGSETTINGS_LIB})

add_subdirectory("log")
add_subdirectory("base")
add_subdirectory("util")
add_subdirectory("settings")
add_subdirectory("filesystem")

set(HEADERS
    dtkcore_global.h
    dsysinfo.h
    dsecurestring.h
    ddesktopentry.h
)

set(SOURCES
    dsysinfo.cpp
    dsecurestring.cpp
    ddesktopentry.cpp
    dtkcore_global.cpp
)

set(RESOURCES
    util/util.qrc
)

target_link_libraries(${PROJECT_NAME} PRIVATE ${Qt_LIBS} pthread)
main cmake
set(HEADERS ${HEADERS}
        ${CMAKE_CURRENT_SOURCE_DIR}/dbasefilewatcher.h
        ${CMAKE_CURRENT_SOURCE_DIR}/dfilesystemwatcher.h
        ${CMAKE_CURRENT_SOURCE_DIR}/dfilewatcher.h          
        ${CMAKE_CURRENT_SOURCE_DIR}/dfilewatchermanager.h
        ${CMAKE_CURRENT_SOURCE_DIR}/dpathbuf.h
        ${CMAKE_CURRENT_SOURCE_DIR}/dstandardpaths.h
        ${CMAKE_CURRENT_SOURCE_DIR}/dtrashmanager.h


        ${CMAKE_CURRENT_SOURCE_DIR}/private/dbasefilewatcher_p.h
        ${CMAKE_CURRENT_SOURCE_DIR}/private/dfilesystemwatcher_linux_p.h

        # DFileWatcher
        # DBaseFileWatcher
        # DFileSystemWatcher
        # DFileWatcherManager
        # DPathBuf
        # DStandardPaths
        # DTrashManager
)

set(SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/dbasefilewatcher.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/dfilewatcher.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/dfilewatchermanager.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/dstandardpaths.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/dpathbuf.cpp

        ${CMAKE_CURRENT_SOURCE_DIR}/dfilesystemwatcher_linux.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/dtrashmanager_linux.cpp
)

target_sources(${PROJECT_NAME} PRIVATE ${HEADERS} ${SOURCES})
sub cmake
原文地址:https://www.cnblogs.com/abnk/p/15095325.html