(2021/4/23)更新模板项目供参考[helywin/cmake-modular-template]

按照如下目录结构建立好

├─assets    #图片
├─build        #构建目录
├─debug        #debug构建后的二进制文件
├─doc        #文档
├─lib        #第三方库
├─release    #release构建后的二进制文件
├─res        #Qt的qrc文件和rc文件
└─src        #源码目录

工程目录下的CMakeLists.txt文件如下:

1cmake_minimum_required(VERSION 3.12)
2project(xxxx)
3
4add_subdirectory(src)

src目录下CMakeLists.txt文件如下:

 1set(CMAKE_INCLUDE_CURRENT_DIR ON)
 2set(CMAKE_AUTOMOC ON)
 3set(CMAKE_AUTOUIC ON)
 4set(CMAKE_AUTORCC ON)
 5
 6find_package(Qt5Core CONFIG REQUIRED)
 7find_package(Qt5Widgets CONFIG REQUIRED)
 8find_package(Qt5Gui CONFIG REQUIRED)
 9find_package(Qt5OpenGL CONFIG REQUIRED)
10#find_package(Qt5PrintSupport CONFIG REQUIRED)
11#find_package(Qt5TextToSpeech CONFIG REQUIRED)
12set(CMAKE_CXX_COMPILER g++)
13set(CMAKE_C_COMPILER gcc)
14set(DEFINES "-DUNICODE -D_UNICODE -DWIN32 -DQT_DEPRECATED_WARNINGS")
15set(CMAKE_C_FLAGS "-fno-keep-inline-dllexport -fopenmp -march=i686 -mtune=core2 -Wa,-mbig-obj -O2 -Wall -W -Wextra ${DEFINES}")
16set(CMAKE_CXX_FLAGS "-fno-keep-inline-dllexport -fopenmp -O2 -g -Wall -W -Wextra -fexceptions -mthreads ${DEFINES}")
17
18if (CMAKE_BUILD_TYPE MATCHES Release)
19    message("release compile!!")
20    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-Wl,-s -Wl,-subsystem,windows -mthreads")
21    add_definitions(-DQT_NO_DEBUG)
22    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/release)
23endif (CMAKE_BUILD_TYPE MATCHES Release)
24
25if (CMAKE_BUILD_TYPE MATCHES Debug)
26    message("debug compile!!")
27    set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-mthreads")
28    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/debug)
29endif (CMAKE_BUILD_TYPE MATCHES Debug)
30
31aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
32include_directories(${PROJECT_SOURCE_DIR}/src)
33
34#set(UI ${PROJECT_SOURCE_DIR}/res/ui.qrc)
35
36add_executable(${PROJECT_NAME} ${SRC})
37
38target_link_libraries(${PROJECT_NAME}
39        Qt5Core
40        Qt5Widgets
41        Qt5Gui
42        Qt5OpenGL)

具体作用不解释,可以参考CMake手册和Qt手册关于CMake的部分

2019/4/21 补充:

  1. 可以通过CMAKE_OS_NAME来判断用来编译的是什么环境

  2. 从Qt官网下载的安装包CMake会找不到库的路径,可以添加以下一句解决

    1set(CMAKE_PREFIX_PATH qt-path/gcc_64)

    其中qt-path为qt库的路径

  3. 链接时把库名改为如下方式可以减少include目录的复杂程度

    1target_link_libraries(${PROJECT_NAME}
    2        Qt5::Core
    3        Qt5::Widgets
    4        Qt5::Gui
    5        Qt5::OpenGL)

2019/4/28 补充

  1. CMake可以 执行shell命令并且获取输出和返回值
 1find_program(GIT git)
 2
 3if ("${GIT}" STREQUAL "GIT-NOTFOUND")
 4    message(WARNING "找不到git程序,无法更新git提交记录")
 5    set(VERSION_REVISION "找不到提交号")
 6    set(VERSION_BRANCH "找不到提交分支")
 7else ()
 8    unset(GIT_VERSION_NUM CACHE)
 9    unset(GIT_BRANCH CACHE)
10    message("找到git,读取分支信息")
11    execute_process(
12            COMMAND git log -1 --format=%H
13            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
14            OUTPUT_VARIABLE GIT_COMMIT
15            OUTPUT_STRIP_TRAILING_WHITESPACE
16            RESULT_VARIABLE GIT_COMMIT_RESULT
17    )
18    if (NOT GIT_COMMIT_RESULT EQUAL 0)
19        message(FATAL_ERROR "找不到git提交的id号")
20    else ()
21        message("提交号 ${GIT_COMMIT}")
22    endif ()
23
24    execute_process(
25            COMMAND git symbolic-ref --short HEAD
26            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
27            OUTPUT_VARIABLE GIT_BRANCH
28            OUTPUT_STRIP_TRAILING_WHITESPACE
29            RESULT_VARIABLE GIT_BRANCH_RESULT
30    )
31    if (NOT GIT_BRANCH_RESULT EQUAL 0)
32        message(FATAL_ERROR "找不到git当前分支名称")
33    else ()
34        message("分支名称 ${GIT_BRANCH}")
35    endif ()
36
37    execute_process(
38            #            COMMAND env LC_ALL=C date "+%Y-%m-%d %H:%M:%S %Z"
39            COMMAND env LC_ALL=C date "+%m %b %Y %H:%M:%S %Z"
40            OUTPUT_VARIABLE DATE
41            OUTPUT_STRIP_TRAILING_WHITESPACE
42            RESULT_VARIABLE DATE_RESULT
43    )
44    if (NOT DATE_RESULT EQUAL 0)
45        message(FATAL_ERROR "无法读取当前时间")
46    else ()
47        message("编译时间 ${DATE}")
48    endif ()
49
50    set(VERSION_COMMIT ${GIT_COMMIT})
51    set(VERSION_BRANCH ${GIT_BRANCH})
52    set(VERSION_BUILD_DATE ${DATE})
53endif ()
  1. CMake可以替换模板文件生成源码

模板文件如下

 1#ifndef VERSION_HPP
 2#define VERSION_HPP
 3
 4// 编译版本信息
 5#define VERSION_MAJOR @VERSION_MAJOR@
 6#define VERSION_MINOR @VERSION_MINOR@
 7#define VERSION_MICRO @VERSION_MICRO@
 8#define VERSION_COMMIT "@VERSION_COMMIT@"
 9#define VERSION_BRANCH "@VERSION_BRANCH@"
10#define VERSION_BUILD_DATE "@VERSION_BUILD_DATE@"
11#define VERSION_QT "@VERSION_QT@"
12#define VERSION_QT_PLATFORM "@VERSION_QT_PLATFORM@"
13
14#endif //VERSION_HPP

在CMake里面相应设置值

1set(VERSION_QT ${QT_VERSION})
2set(VERSION_QT_PLATFORM ${QT_PLATFORM})

左边是文件里面的 @@中间的名称,右边是CMake变量,然后编写替换的文件名称就可以 了

1configure_file(src/Version.hpp.in src/Version.hpp @ONLY)

下次执行CMake会自动在编译目录下生成.hpp文件,所以还要加上include目录才能包含头文件

1include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)

2019/9/9 补充

  1. CMake获取时间跨平台方法

原来的方式获取时间Windows上就会有问题,如下命令代替即可

1string(TIMESTAMP DATE "%m %b %Y %H:%M:%S")

时间信息就存储在DATE里面了

参考连接:https://cmake.org/cmake/help/v3.5/command/string.html#timestamp

  1. CMake调用pkg-config

由于有些库不能通过CMake的find_package查找,但是可以通过pkg-config定位,比如breakpad

包的名称可以通过pkg-config --list-all查找

1include(FindPkgConfig)
2pkg_check_modules(BREAKPAD_CLIENT REQUIRED breakpad-client)
3if (${BREAKPAD_CLIENT_FOUND})
4    MESSAGE(STATUS "找到breakpad-client库: ${BREAKPAD_CLIENT_INCLUDE_DIRS}")
5endif()
6include_directories(${BREAKPAD_CLIENT_INCLUDE_DIRS})
7target_link_libraries(${PROJECT_NAME} ${BREAKPAD_CLIENT_LIBRARIES})

2020/2/19 补充

  1. 增加msvc编译参数,增加release模式生成pdb文件
 1if (CMAKE_BUILD_TYPE MATCHES Debug)
 2    message("Debug编译")
 3    set(PROJECT_BINARY_DIR ${PROJECT_SOURCE_DIR}/debug)
 4    add_definitions(-DDEBUG) # 加此宏是为了激活代码里面有的#ifdef DEBUG宏
 5else () #CMAKE_BUILD_TYPE MATCHES Release
 6    message("Release编译")
 7    set(PROJECT_BINARY_DIR ${PROJECT_SOURCE_DIR}/release)
 8    # 屏蔽Qt警告和调试
 9    add_definitions(-DQT_NO_DEBUG)
10    add_definitions(-DQT_NO_DEBUG_OUTPUT)
11    add_definitions(-DQT_DEPRECATED_WARNINGS)
12    set(SUBSYSTEM_TYPE "WIN32")
13endif ()
14
15set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
16
17# 设置编译参数
18if (UNIX)
19    set(DEFINES "-Wunused-parameter")
20    set(CMAKE_CXX_FLAGS_DEBUG "-pipe -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC ${DEFINES}")
21    set(CMAKE_C_FLAGS_DEBUG "-pipe -O2 -Wall -W -D_REENTRANT -fPIC ${DEFINES}")
22    set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-fno-pie")
23
24    set(CMAKE_CXX_FLAGS_RELEASE "-pipe -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC ${DEFINES}")
25    set(CMAKE_C_FLAGS_RELEASE "-pipe -O2 -Wall -W -D_REENTRANT -fPIC ${DEFINES}")
26    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-fno-pie")
27elseif (WIN32)
28    if (MSVC)
29        set(DEFINES_DEBUG "-D_WINDOWS -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 /wd4100")
30        set(CMAKE_CXX_FLAGS_DEBUG "/utf-8 /sdl /EHsc -nologo -Zc:wchar_t -FS -Zc:strictStrings -Zi -MDd -W3 -w44456 -w44457 -w44458 ${DEFINES_DEBUG}")
31        set(CMAKE_C_FLAGS_DEBUG "/utf-8 /sdl -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus /FS -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc ${DEFINES_DEBUG}")
32        set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /DEBUG")
33        # set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
34
35        # release模式下生成pdb用于调试
36        set(DEFINES_RELEASE "-D_WINDOWS -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG")
37        set(CMAKE_C_FLAGS_RELEASE "/utf-8 /sdl -nologo -Zc:wchar_t -FS -Zi -Zc:strictStrings -O2 -MD -W3 -w44456 -w44457 -w44458 ${DEFINES_RELEASE}")
38        set(CMAKE_CXX_FLAGS_RELEASE "/utf-8 /sdl -nologo -Zc:wchar_t -FS -Zi -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc ${DEFINES_RELEASE}")
39        set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF")# /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBC
40    else ()
41        message(FATAL_ERROR 不支持其他平台)
42    endif ()
43endif ()

其中CMAKE_CXX_FLAGS_RELEASE-ZiCMAKE_EXE_LINKER_FLAGS_RELEASE/DEBUG /OPT:REF /OPT:ICF是生成pdb添加的

参考链接:

https://stackoverflow.com/questions/28178978/how-to-generate-pdb-files-for-release-build-with-cmake-flags

参考链接:https://cmake.org/cmake/help/v3.5/module/FindPkgConfig.html?#module:FindPkgConfig

总参考链接:

CMake

Qt CMake