CMake 基础学习-认识 CMake 基本语法与应用

CMake 基础学习-认识 CMake

什么是 CMake

CMake 是一个跨平台、可扩展的开源脚本系统,它以独立于编译器的方式在操作系统中管理编译、工程文件的生成过程。

在 Linux 中 CMake 生成 Makefile(若是其他平台,则生成对应的编译管理文件) 文件,然后由 Makefile 文件管理 C、C++ 文件的编译组织。

与普通编程语言一样,CMake 也有承载用户定义的文件裁体:CmakeList.txt 文件。通常每个目录需要一个 CMakeLists.txt。

如何安装

# For Ubuntu

$ sudo apt-get install cmake

# For Redhat

$ yum install cmake

# For Mac OS X with Macports

$ sudo port install cmake

基础语法常识

指令(类似其他编程语言的函数)

CMake 命令类似于 C++/Java 方法或函数,它们将参数作为列表并相应地执行某些任务。

CMake 命令不区分大小写。有内置命令,可以从 cmake 文档中找到:https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html

一些常用的命令

  • message:打印给定的消息(类似print\printf)
  • cmake_minimum_required:设置要使用的最低 CMAKE 版本
  • add_executable:添加具有给定名称的可执行目标
  • add_library:添加要从列出的源文件构建的库目标
  • add_subdirectory:添加要参与构建的子目录

还有一些命令使开发人员能够写出条件语句、循环、迭代列表、赋值:

  • if, endif
  • elif, endif
  • while, endwhile
  • foreach, endforeach
  • list
  • return
  • set_property

CMake 中缩进不是强制性的,但在编写 CMake 脚本时建议使用。不同于 C/C++ 语言,CMake 不使用分号 ;来标识语句的结尾。

所有条件语句都应以其相应的结束命令(endifendwhileendforeach*)结尾。

一些开源软件框架有自己的 CMake 风格,如 KDE:

  • https://community.kde.org/Policies/CMake_Coding_Style

CMake 参数与变量

参数和变量是区分大小写的。

如:

set(files a.txt b.txt c.txt)

set 是赋值指令、files 是变量、a.txt 是参数。上面的语句类似 C 语句中的:

files = a.txt, b.txt, c.txt;

一些特别长的参数,如特别长的文件名,以双引号将处理不方便的文件名包含起来,如:

set(files “a1111.txt")

在变量的定义中,您只能使用字母、数字、字符、下划线破折号

可以在以下 URL 中找到有关 CMake 变量的更多详细信息

一些变量是系统根据根文件目录预定义的:

  • CMAKE_BINARY_DIR:构建库和二进制输出文件目录的完整路径,默认情况下定义为构建树的顶层。
  • CMAKE_HOME_DIRECTORY:源树顶部的路径
  • CMAKE_SOURCE_DIR:源代码的完整路径。
  • CMAKE_INCLUDE_PATH:用于查找文件的路径

可以使用 ${<variable_name>} 访问变量值。如下是赋值、打印语句的简单示例:

set(CMAKE_CXX_STANDARD 14)
message("CXX Standard: ${CMAKE_CXX_STANDARD}")

注意:在 if 语句中可以直接使用变量名,不使用 ${<variable_name>}:

if(files)
    message("defined files!!!!!!!!!!")
else()
    message("NOT defined files!!!!!!!!!")
endif()

if(open STREQUAL "ON")
	message("open = ON")
else()
	message("open = OFF")
endif()

CMake 环境变量

CMake 预定义了一些变量,它们是预定于的字符,有特殊含义。

环境变量用于为常规生成过程配置编译器标志链接器标志测试配置

可以从以下 URL 中看到环境变量的详细列表:

  • https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html

下面是一个示例,当您想在编译过程中启用所有警告时,可以通过上述 set 指令,对环境变量-Wall命令。

CMake 列表与注释

注释通过 #符号来标识。

CMake 中的所有值都存储为字符串,但在某些上下文中可以将多个字符串视为列表,每个字符串之间可以通过空格分隔。

表示为字符串的元素列表,最终会通过“;”符合来连接。

# sets files to "a.txt;b.txt;c.txt"
set(files a.txt b.txt c.txt)

使用 list(APPEND…) 命令追加列表:

list(APPEND requires "app_update" "esp_partition")

为了访问列表的值,您可以使用CMake 的 for 命令,如下所示,可以依次取出 files 中的每个元素存入 file:

foreach(file ${files})
    message("Filename: ${file}")
endforeach()

在 CMake 中使用宏定义

宏可定义可以帮助工程师有条件地构建代码,以根据正在运行的系统配置丢弃或包含某些方法。

您可以使用add_definitions命令在CMake中定义宏,在宏名称前使用-D标志。

让我们定义名为CMAKEMACROSAMPLE的宏,并将其打印在代码中。

# Darwin is Apple's system name
if(${CMAKE_SYSTEM_NAME} MATCHES Darwin)
    add_definitions(-DCMAKEMACROSAMPLE="Apple MacOS")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
    add_definitions(-DCMAKEMACROSAMPLE="Windows PC")
elseif(${CMAKE_SYSTEM_NAME} MATCHES ubuntu)
    add_definitions(-DCMAKEMACROSAMPLE="linux ubuntu")
endif()

下面是带有打印宏的.cpp 源文件:

#include <iostream>
#ifndef CMAKEMACROSAMPLE
    #define CMAKEMACROSAMPLE "NO SYSTEM NAME"
#endif
auto sum(int a, int b){
        return a + b;
}
int main() {
        std::cout<<"Hello CMake!"<<std::endl;
		std::cout<<CMAKEMACROSAMPLE<<std::endl;
        std::cout<<"Sum of 3 + 4 :"<<sum(3, 4)<<std::endl;
        return 0;
}

一些学习建议:

1)实践第一。如果工作中不是经常用到 cmake 就没有必要详细的学下去了,遇到问题查询一下就可以了。

2)大型项目下,如果你不是负责系统级别的工作,你可以考虑学习些 cmake 的基本语法,入门即可。小型项目其实不太会用 cmake,直接使用 Makefile 多一些。

3)在C/C++ 领域的大型项目中,如果你负责大型项目的维护工作,可以考虑研究下 cmake 的更多用法。学习 QT 开放的同学你可能向使用 qmake 更多一些。

使用 CMake 进行构建的流行的开源项目:

  • OpenCV: https://github.com/opencv/opencv
  • Caffe2:: https://github.com/caffe2/caffe2
  • Caffe2::https://github.com/mysql/mysql-server

可阅维基百科以获取更多的开源项目 https://en.wikipedia.org/wiki/CMake#Applications_that_use_CMake

示例与解析

获取示例代码:samples1

简单 cmake 示例的解析:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 2.8)

# Project's name
project(HELLO)

# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}")

其中有一些 CMake 的全局变量

  • CMAKE_BINARY_DIR:如果您在源代码中构建,则与 CMAKE_SOURCE_DIR 相同,否则这是构建树的顶级目录。

  • CMAKE_SOURCE_DIR: 这是启动 cmake 的目录,即顶级源目录。

  • EXECUTABLE_OUTPUT_PATH: 设置此变量以指定 CMake 应放置所有可执行文件的公共位置(而不是CMAKE_CURRENT_BINARY_DIR

  • LIBRARY_OUTPUT_PATH: 设置此变量以指定 CMake 应放置所有库的公共位置(而不是CMAKE_CURRENT_BINARY_DIR

  • PROJECT_NAME: 命令设置的项目名称PROJECT()。更完整的项目名称如下,后面的几个选项都可以缺省:

    project(myApp
        VERSION 1.0
        DESCRIPTION "A brief CMake experiment"
        LANGUAGES CXX)
    
  • PROJECT_SOURCE_DIR: 包含项目源目录根目录的完整路径,即 CMakeLists.txt 包含 PROJECT() 命令的最近目录.

现在要编译示例的 test.cpp,你需要在 cmake 中添加:

# hello 是要生成的可执行文件(目标),后面可以跟多个源文件、头文件。
add_executable(hello ${PROJECT_SOURCE_DIR}/test.cpp)

然后在 c1 目录查看并编译源文件:

$ ls
test.cpp   CMakeLists.txt
$ cmake -H. -Bbuild  // 在 build 目录创建 cmake 构建文件的临时文件,该命令会自动生成一个 bin 目录(H indicates source directory,B indicates build directory
$ ls
bin  build  CMakeLists.txt test.cpp
$ cmake --build build -- -j3 // 生成可执行文件./bin/hello,编译时的代码优化级别为 j3
$ ./bin/hello // 运行可执行文件./bin/hello
Hello World
$ cd build // 切换到 build 目录
$ make clean // 清理工程

注意:工程名HELLO,和可执行程序的名字 hello,他们是不同的。

注意:本示例演示的是 cmake 的外部构建流程,其实内部构建生成的临时文件很多,导致大部分情况下使用起来有些麻烦,因此这里仅介绍外部构建,内部构建的方式不过多叙述。

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网老王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值