Advertisement

项目开发 - CMake教程+实战

阅读量:

文章目录

  • 1、 cmake 介绍
  • 2、cmake 语法介绍
    • 2.1、环境搭建

    • 2.2 简单的CMakeLists.txt

      • 2.2.1 基础起点
      • 2.2.2 添加库
      • 2.2.3 使用库的优化
      • 2.2.4 安装
    • 2.3 demo

通过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 ############

全部评论 (0)

还没有任何评论哟~