文章目录
通过Cmake 搭建一个demo,已熟悉cmake 的相关命令。
本文需要达到的目标
- 构建多个文件的demo vs 工程,生成exe
- 界面采用Qt
- 依赖三方库
- 自定义配置一些宏
1、 cmake 介绍
CMake 是一个开源、跨平台的工具系列,旨在构建、测试和打包软件
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装。也就是项目或者工程对的搭建,例如:windows 的vs , linux 下 makefile 。要知道这些工程的搭建是非常麻烦的。
CMake 功能强大。
- CMake 支持同一个项目中的多个开发环境和编译器(例如,Visual Studio IDE、QtCreator、JetBrains、vim、emacs、gcc、MSVC、clang、Intel)
- CMake 支持多种语言,包括 C/C++/CUDA/Fortran/Python,还支持在构建过程中运行任意自定义命令
- CMake 通过 CTest 支持与 Jenkins、Travis、CircleCI、GitlabCI 以及几乎任何 CI 系统协同工作的持续集成 (CI) 测试。测试结果使用 CDash (www.cdash.org) 显示。
- CMake 支持将 3rd 方库集成到您的项目中。
2、cmake 语法介绍
2.1、环境搭建
首先需要安装CMake.exe, 大家可以自行安装。
cmake 的运行依赖还有什么,最重要的输入就是CMakeLists.txt ,cmake 根据你编写的CMakeLists.txt 来进行生成工程。在项目根目录下创建一个CMakeLists.txt。例如:开源项目 obs
2.2 简单的CMakeLists.txt
2.2.1 基础起点
下面的是最简单的一个CMakeLists.txt,就可以生成文件
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cxx)
此示例在CMakeLists.txt文件中使用小写命令。CMake 支持大写、小写和大小写混合命令。目录中tutorial.cxx提供了 的源代码
将cmake 配置设置到源文件中,可以在配置中TutorialConfig.h.in 配置一些宏定义,可以将cmake 的值生成到TutorialConfig.h,例如,在cmake中设置版本号
# set the project name and version
project(Tutorial VERSION 1.0)
configure_file(TutorialConfig.h.in TutorialConfig.h)
例如:
TutorialConfig.h.in
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
生成 TutorialConfig.h
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 0
2.2.2 添加库
现在我们将向我们的项目添加一个库。这个库将包含我们自己的计算数字平方根的实现。然后可执行文件可以使用这个库代替编译器提供的标准平方根函数。
1、创建一个依赖库
在本教程中,我们将把库放到一个名为MathFunctions. 此目录已包含头文件 MathFunctions.h和源文件mysqrt.cxx。源文件有一个被调用的函数mysqrt,它提供与编译器sqrt函数类似的功能。
将以下一行CMakeLists.txt文件添加到MathFunctions 目录中:
## MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
2、在Tutorial 中使用库
为了使用新库,我们将
- 添加一个 add_subdirectory() 在 顶层CMakeLists.txt文件,以便构建库
- 将新库添加到可执行文件中
- 添加MathFunctions为包含目录,以便mysqrt.h可以找到头文件。
顶层 CMakeLists.txt文件的最后几行现在应该如下所示:
## CMakeLists.txt
# add the MathFunctions library , 引用子目录的cameklists
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
# 添加链接库
target_link_libraries(Tutorial PUBLIC MathFunctions)
# 添加 库目录 和 include 目录
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
3. 设置库为可选
在大型项目中,会进行设置成可选
## CMakeLists.txt
option(USE_MYMATH "Use tutorial provided math implementation" ON)
此选项将显示在 cmake-gui 和 ccmakeON用户可以更改 默认值。此设置将存储在缓存中,以便用户每次在构建目录上运行 CMake 时无需设置该值。
下一个更改是使MathFunctions库的构建和链接有条件。为此,我们将创建一个if检查选项值的语句。在if块内,将 add_subdirectory()上面的命令和一些额外的列表命令来存储链接到库所需的信息,并将子目录添加为Tutorial目标中的包含目录。顶级CMakeLists.txt文件的结尾现在将如下所示:
## CMakeLists.txt
# 判断是否使用mymath , 使用EXTRA_LIBS 来收集所有的 lib名称
# 使用EXTRA_INCLUDES 收集所有include 的目录
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
对源代码的相应更改相当简单。首先,在 中tutorial.cxx,MathFunctions.h如果需要,请包含标题:
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
由于源代码现在需要USE_MYMATH我们可以TutorialConfig.h.in使用以下行添加它
#cmakedefine USE_MYMATH
2.2.3 使用库的优化
使用 INTERFACE 来优化,我们使用INTERFACE 向外暴露路径。这样对应使用方就非常简单,例如:include 路径
MathFunctions/CMakeLists.txt , 添加一下命令,向外暴露的路径
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
在使用方的cmakeLists 就可以简化,不需要依赖他的include 目录,因为在第一句,引用子目录的使用,子目录的cmakelists 提供给了使用方。
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
2.2.4 安装
安装规则相当简单:因为MathFunctions我们要安装库和头文件,而对于应用程序,我们要安装可执行文件和配置的头文件。
MathFunctions/CMakeLists.txt
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
在顶层的末尾,CMakeLists.txt我们添加:
CMakeLists.txt
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
2.3 demo
本文需要达到的目标
- 构建多个文件的demo vs 工程,生成exe
- 界面采用Qt
- 依赖三方库
- 自定义配置一些宏
############# 0.基础信息 - begin #############
## 设置依赖camke 的版本号
cmake_minimum_required(VERSION 2.8)
## 打印版本号,输出信息
message(STATUS "CMake version: ${CMAKE_VERSION}")
############# 0.基础信息 - end #############
############# 1.工程名字 - begin #############
## 设置工程的名字
project(d3ddemo)
############# 1.工程名字 - end #############
############# 2.工程配置 - begin ############
## 使用c++11 编译
set(CMAKE_CXX_STANDARD 11)
## 添加编译参数, 打开告警
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall")
## 编译的类型
# set(CMAKE_BUILD_TYPE REALSE) # 单生成器
SET(CMAKE_CONFIGURATION_TYPES Debug Release) #指定多配置生成器
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) # 设置文件输出路径
############# 2.工程配置 - end ############
############# 3.源文件& 生成可执行文件 - begin ############
## 查找依赖QT 包
set(CMAKE_PREFIX_PATH "C:/Qt/Qt5.12.2/5.12.2/msvc2017/lib/cmake")
find_package(Qt5Widgets ${FIND_MODE})
if(NOT Qt5Widgets_FOUND)
message(STATUS "Qt5 not found - UI disabled")
return()
endif()
# qt相关的配置,自动打开moc uic rcc
set(CMAKE_AUTOMOC ON) #生成moc文件
set(CMAKE_AUTOUIC ON) #生成_ui.h
set(CMAKE_AUTORCC ON) #.qrc
## 源文件
#该GLOB_RECURSE模式将遍历匹配目录的所有子目录并匹配文件
file(GLOB_RECURSE SOURCE *.cpp)
file(GLOB_RECURSE HEADER *.h)
file(GLOB_RECURSE demo_UI *.ui)
file(GLOB_RECURSE demo_QRC *.qrc)
qt5_wrap_ui(demo_UI_HEADERS ${demo_UI})
qt5_add_resources(demo_QRC_SOURCES ${demo_QRC})
# 生成exe
add_executable(d3ddemo ${SOURCE} ${HEADER})
# 链接库
target_link_libraries(d3ddemo Qt5::Widgets d3d11)
############# 3.源文件& 生成可执行文件 - end ############