首页 > 其他分享 >CMake教程

CMake教程

时间:2024-07-01 11:46:27浏览次数:1  
标签:教程 cmake 变量 package VERSION build CMake

CMake 教程

1. 运行CMake

1.1 构建项目

在构建项目前建议创建一个build目录,以下是一个经典的Cmake构建过程:

~/package $ mkdir build
~/package $ cd build
~/package/build $ cmake ..
~/package/build $ make

make命令也可以使用cmake --build来代替

以下任何一条命令都可以执行安装:

# From the build directory (pick one)
~/package/build $ make install
~/package/build $ cmake --build . --target install
~/package/build $ cmake --install . # CMake 3.15+ only

# From the source directory (pick one)
~/package $ make -C build install
~/package $ cmake --build build --target install
~/package $ cmake --install build # CMake 3.15+ only

1.2 选择编译器

选择编译器必须在第一次运行时在空的目录中进行,以clang编译器为例:

~/package/build $ CC=clang CXX=clang++ cmake ..

1.3 指定生成器

可以选择的构建工具有很多,make工具通常是默认的。可以使用cmake --help来查看系统支持的生成器

也可以使用-G"My tool"选择构建工具,这同样需要在第一次运行Cmake之前就指定构建工具

可以使用环境变量CMAKE_GENERATOR来控制默认的生成器

1.4 标准选项

以下是一些常用的cmake选项:

  • -DCMAKE_BUILD_TYPE= 从Release、RelWithDebInfo、Debug等参数中选择
  • -DCMAKE_INSTALL_PREFIX= 安装位置,安装在UNIX系统中通常是/usr/local,用户目录通常是~/.local,或者也可以另选一个文件夹
  • -DBUILD_SHARED_LIBS= 可以设置该选项为onoff来控制共享库的默认值
  • -DBUILD_TESTING= 启用测试的常用名称

1.5 调试CMake文件

可以使用-trace选项来打印CMake运行的每一行,由于它过于冗长,CMake 3.7 添加了 --trace-source="filename" 选项,这可以打印出想看的特定文件运行时执行的每一行。

2. CMake基础知识

2.1 最低版本要求

这是每个 CMakeLists.txt 都必须包含的第一行:

cmake_minimum_required(VERSION 3.1)

从CMake 3.12开始,版本号可以声明为一个范围,如VERSION 3.1...3.15,这意味着这个工程最低可以支持3.1版本,最高可以支持3.15版本

当开始一个新的项目时,推荐这样写:

cmake_minimum_required(VERSION 3.7...3.21)

if(${CMAKE_VERSION} VERSION_LESS 3.12)
    cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()

当CMake的版本低于3.12时,则CMake将会被设置为当前的版本

2.2 设置一个项目

每个顶层CMakeLists文件都应当有类似下面这行:

project(MyProject VERSION 1.0
                  DESCRIPTION "Very nice project"
                  LANGUAGES CXX)

这行表面项目的名称为MyProject,项目版本号为1.0,项目描述是"Very nice project",项目的语言为CXX(可以是C、CXX、Fortran、ASM、CUDA、SWIFT)

2.3 生成一个可执行文件

add_executable(one two.cpp three.h)

one是生成的可执行文件的名称,也是想创建的CMake目标的名称;two.cpp是源文件的列表,可以添加多个;three.h是头文件,通常可以忽略

2.4 生成一个库

add_library(one STATIC two.cpp three.h)

生成一个库时,可以选择库的类型,可以是 STATIC, SHARED或者MODULE,如果不选择,CMake将会通过BUILD_SHARED_LIBS 的值来选择构建STATIC还是SHARED类型的库

2.5 指定目标信息

target_include_directories(one PUBLIC include)

为目标one包含一个目录include,PUBLIC对于二进制目标没有什么含义,但是对于库来说,它让CMake知道,任何链接到这个目标的目标也必须包含这个目录,其他选项还有PRIVATE以(只影响当前目标,不影响依赖)及INTERFACE(只影响依赖)

将目标链接起来:

add_library(another STATIC another.cpp another.h)
# 将one库链接到目标another
target_link_libraries(another PUBLIC one)
cmake_minimum_required(VERSION 3.8)

project(Calculator LANGUAGES CXX)

add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp)
target_include_directories(calclib PUBLIC include)
target_compile_features(calclib PUBLIC cxx_std_11)

add_executable(calc apps/calc.cpp)
target_link_libraries(calc PUBLIC calclib)

3. 变量与缓存

3.1 本地变量

声明本地变量的方式如下:

set(MY_VARIBALE "value")

变量名通常全部用大写,变量值跟在其后。可以通过 ${} 来解析一个变量,例如 ${MY_VARIABLE}

CMake有作用域的概念,在声明一个变量后,只可以在它的作用域内访问这个变量。

列表就是包含一系列变量:

set(MY_LIST "one;two")

需要注意的是,在 CMake 中如果一个值没有空格,那么加和不加引号的效果是一样的。

3.2 缓存变量

CMake 提供了一个缓存变量来允许从命令行中设置变量。CMake 中已经有一些预置的变量,像 CMAKE_BUILD_TYPE 。如果一个变量还没有被定义,可以这样声明并设置它:

set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")
# 定义声明缓存变量时可以不使用加上FORCE

修改缓存变量:

set(MY_CACHE_VARIABLE "MODIFIED" CACHE STRING "MODIFY VARIABLE")

3.3 环境变量

可以通过 set(ENV{variable_name} value)$ENV{variable_name} 来设置和获取环境变量

3.4 缓存

缓存实际上就是个文本文件CMakeCache.txt ,当运行 CMake 构建目录时会创建它。 CMake 可以通过它来记住设置的所有东西,因此可以不必在重新运行 CMake 的时候再次列出所有的选项。

3.5 属性

CMake 也可以通过属性来存储信息。这就像是一个变量,但它被附加到一些其他的物体 ( item ) 上,像是一个目录或者是一个目标。一个全局的属性可以是一个有用的非缓存的全局变量。许多目标属性都是被以 CMAKE_ 为前缀的变量来初始化的。

set_property(TARGET TargetName
             PROPERTY CXX_STANDARD 11)

set_target_properties(TargetName PROPERTIES
                      CXX_STANDARD 11)

4. 流程控制

CMake的if语句:

if(variable)
    # If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero number
else()
    # If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND`
endif()
# If variable does not expand to one of the above, CMake will expand it then try again

if语句中的条件既可以是变量名,也可以是使用${}进行解析

if("${variable}")  # 注意这里加了引号,防止多次解析
    # True if variable is not false-like
else()
    # Note that undefined variables would be `""` thus false
endif()

if条件还可以使用一些关键字,例如:

  • 一元的: NOT, TARGET, EXISTS (文件), DEFINED, 等。
  • 二元的: STREQUAL, AND, OR, MATCHES ( 正则表达式 ), VERSION_LESS, VERSION_LESS_EQUAL ( CMake 3.7+ ), 等。

5. 宏定义与函数

CMake可以定义自己的函数和宏 functionmacro 。函数和宏只有作用域上存在区别,宏没有作用域的限制。所以说,如果你想让函数中定义的变量对外部可见,你需要使用 PARENT_SCOPE 来改变其作用域。

一个简单函数示例:

function(SIMPLE REQUIRED_ARG)
    message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGN}")
    set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE)
endfunction()

simple(This Foo Bar)
message("Output: ${This}")

一个简单宏示例:

macro(macro1)
	message(STATUS "macro1 called!")
endmacro()

macro1()

函数和宏的所有参数都会被存储在ARGN这个变量中

注意:函数名和宏名并不区分大小写!

标签:教程,cmake,变量,package,VERSION,build,CMake
From: https://www.cnblogs.com/N1rv2na/p/18277723

相关文章

  • 前端vue/react通用工程化eslint prettier stylelint husky项目规范(新手入门详细教程)
    前言本文章内的项目基于vite+react+ts搭建,但通篇并未涉及react的东西,所以可以通用。适合新手入门的工程化项目规范,最小化的完成代码规范和git提交规范,开发工具使用vscode。为什么是最小化?本意是为了让大家都能看懂入手这些规范,很多文章中,都长篇进行自定义的配置,其......
  • Linux上的Vim编辑器教程
    当谈到Linux上的Vim编辑器时,以下是一个最全面的教程,涵盖了Vim的基本使用、模式、命令以及高级功能。一、Vim简介Vim(ViIMproved)是一个在Linux和其他类Unix系统上广泛使用的文本编辑器。它提供了一套强大的命令和快捷键,使用户能够高效地编辑文本。Vim有三种主要模式:正常模......
  • 全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装
    全网最适合入门的面向对象编程教程:06类和对象的Python实现-自定义类的数据封装摘要:本文我们主要介绍了数据封装的基本概念和特性,如何设置自定义类的私有属性和私有方法,protect属性的概念和特点。往期推荐:学嵌入式的你,还不会面向对象??!全网最适合入门的面向对象编程教程:00......
  • QQ机器人开发教程:智能群聊助手
    随着社交媒体的普及,QQ群已成为人们日常生活中重要的交流平台。本文将介绍如何开发一款智能的QQ机器人,作为群聊助手,提供便捷的服务和娱乐功能。一、开发环境搭建首先,需要搭建开发环境。安装Python解释器,并配置好相关的开发工具和库。同时,需要申请一个QQ号作为机器人的登录账......
  • 3分钟手把手教Parallels Desktop for Mac 19中文破解版安装激活图文教程
    ParallelsDesktopforMac 19专为最新的Apple硬件和最新版macOS14Ventura设计,改进了基于ARM运行的Windows11的兼容性并始终保持最新状态,让用户能够不间断地完成更多工作。据介绍,Parallels最新版本旨在优化最新Apple硬件的可用性,同时还支持性能和游戏更新,为用......
  • 【Effective Python教程】(90个有效方法)笔记——第3章:函数——24:用None和docstring来描
    文章目录第3章:函数第24条用None和docstring来描述默认值会变的参数函数默认值的坑(函数的默认参数值只在定义函数时计算)解决方法:将函数默认参数值设为None,然后再在函数体中判断并初始化函数默认参数值设置为None的其他应用示例“函数默认参数值设置为None”与“函数参数......
  • 超详细Python教程—— 进程
    进程Python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在Python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转......
  • Qt下载安装及配置教程
    文章目录1. QT简介2. 下载QT3.检查配置环境4.创建QT项目1. QT简介Qt是一个跨平台C++图形用户界面(GUI)工具包,它由Qt公司(前身为Trolltech)开发和维护。自1995年发布以来,Qt因其强大的功能和跨平台能力,成为了许多软件开发者的首选工具。无论是在桌面应用程序、移动应用......
  • 【ESP32】打造全网最强esp-idf基础教程——13.ESP32中的NVS
    ESP32中的NVS    这几天的天气只有钱包的余额能让我冷静,好好活着,每天都有新的打击,写写博客压压惊。一、什么是NVS?    NVS即Non-volatilestorage,意思是非易失存储,也就是掉电后能依然能持久化保存数据。在我们应用NVS时,一般用于存储一些配置数据、状态数据等,一......
  • 鸿蒙应用开发 && 打包与上架 [ 非常详细的保姆教程 ]
    1,准备阶段1.1 当我们鸿蒙项目开发之后就要开始,这个时候我们去AppGalleryConnect申请上架,华为审核通过后,用户即可在华为应用市场获取您的HarmonyOS应用/元服务。1.2  HarmonyOS会通过数字证书与Profile文件等签名信息来保证应用的完整性,需要上架的HarmonyOS应用/元服......