You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if(variable)
# If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero numberelse()
# If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND`endif()
if("${variable}")
# True if variable is not false-likeelse()
# Note that undefined variables would be `""` thus falseendif()
宏和函数
function(SIMPLE REQUIRED_ARG)
message(STATUS"Simple arguments: ${REQUIRED_ARG}, followed by ${ARGV}")
set(${REQUIRED_ARG}"From SIMPLE" PARENT_SCOPE)
endfunction()
simple(This)
message("Output: ${This}")
# Assuming the canonical version is listed in a single line# This would be in several parts if picking up from MAJOR, MINOR, etc.set(VERSION_REGEX "#define MY_VERSION[ \t]+\"(.+)\"")
# Read in the line containing the versionfile(STRINGS"${CMAKE_CURRENT_SOURCE_DIR}/include/My/Version.hpp"
VERSION_STRING REGEX${VERSION_REGEX})
# Pick out just the versionstring(REGEX REPLACE ${VERSION_REGEX}"\\1" VERSION_STRING "${VERSION_STRING}")
# Automatically getting PROJECT_VERSION_MAJOR, My_VERSION_MAJOR, etc.project(My LANGUAGES CXX VERSION${VERSION_STRING})
title: CMake简明教程
date: 2018-08-12 17:39:00
tags:
前言
主要最近的换工作,完全在Linux下开发,虽然以前都接触过CMake,不过体系也是零散的,遂做了一个简短的CMake教程,以供后续快速入门。
另外,好久也没有写文章了,这份工作还是有一定的技术性,之前的那家公司是开发/维护,大部分工作都是维护,没有什么写文章的激情。
所以,今天是硬凑一篇文章。
正文
CMake
CMake是跨平台的元构建系统,也就是说,它不实际产生构建行为,它只是生成给其他构建系统使用的文件,比如Makefile,MSBuild的solution file。
CMake根据读取名为CMakeLists.txt的文件,然后生成平台特定的构建文件,但是一个很大的问题是,CMake官方提供的教程特别复杂,对于新手的个坑,很难快速入门。
这个教程会通过例子来学习怎么用CMake。以下我们提供几个C++源代码供例子使用:
那么描述构建的CMakeLists.txt内容会是以下:
以上代码很简单,但是第一个问题是,它是不可移植的,因为它没有任何逻辑判断就设置了GCC/Clang的特定编译参数。
第二个问题是,它全局改变了include的搜索路径。
CMake也要有好的书写习惯,采用更加现代的方式来写CMake文件:
注意了,以上代码有几点改变了:
然后在构建过程中,你会发现没有警告,因为CMake不会设定编译器的警告级别,需要你根据不同平台来指定相应的编译器警告参数:
如果就采用上述的CMake文件,那么它生成的工程文件并不好,没有预期,你会发现如果生成VS的solution,你打开工程,你会发现没有包含头文件(vector.h array.h)。因为CMake不理解C++语言,它只是构建工具。
所以CMake文件中要改变下:
当然,也可以通过CMake的source_group命令给文件归类:
这样VS工程下就可以看到对C++源文件分类的文件夹图标了。
Tests
CMake是一堆工具的集合,所以它有一个test runner,叫CTest。
要使用它,你需要显式指定它:
测试返回0表示成功,返回其他值表示失败。
还可以自定义,通过set_tests_properties来设置其相关属性。
对于我们的例子工程,我们仅仅是运行bin文件,并不做额外检查:
COMMAND后面的表达式是generator-expression。
最后,我们的CMakeLists.txt的内容会是:
libraries
之前的教程都是很简单的例子,但是现实中的项目往往要拆分模块,链接外部的第三方库或者链接工程内的库。
如果不想阅读此章节,可以参考JetBrain的CLion提供的一个简明的CMake教程。
里面记录如何包含链接外部的library。
构建生成一个library的cmake指令如下:
下面我们来写一个计算器程序的cmake,bin文件依赖了lib文件,这样看起来就像一个小工程了:
变量和缓存变量
为什么要说这个?因为如果cmake维护一个很大的工程,会有各种编译策略参数,这个就需要逻辑判断,变量这些就随之诞生了。
给一个局部变量设置一个值:
当然,cmake也有list类型的变量,有2种表达方式:
以上变量如果离开作用域就无效了。
下面来说下缓存变量,如果你要从命令行来设置cmake的变量,那么就需要声明缓存变量。类似于CMAKE_BUILD_TYPE这样的变量都是缓存变量:
但是以上不会替换已经存在的值,需要按照以下这样:
环境变量
cmake可以访问环境变量:
属性
cmake也会在属性中保存一些信息,这些属性有点像变量,但是这些属性的作用一般是针对一个target或者目录什么的。cmake的属性变量是以CMAKE_打头的,类似CMAKE_BUILD_TYPE,CMAKE_CXX_STANDARD这些。
比如使用CXX标准可以用设置属性的方式办到,有两种表达:
当然既然有set,当然有get:
Cmake编程
控制流
宏和函数
与源码文件“通信”
Cmake允许源代码访问cmake的变量,这个指令就是configure_file。
这样的功能在版本管理上经常使用:
Version.h.in
可以从上面的配置看出来,本质上cmake只是把后缀in的文件,进行变量标记替换,然后再拷贝到指定目录的文件名。没有什么神奇的。
当然,cmake也可以反过来,cmake代码访问源码文件的内容:
怎样规划你的工程结构
基本如下:
运行其他的程序
编译的时候要做很多事情,比如你构建完毕要用nsis进行打包等等,有些时候不得不调用其他命令行。
配置时运行一个命令
编译时运行一个命令
Cmake其他的一些特性
CMAKE_BUILD_TYPE变量默认既不是Debug也不是Release。必须指定。
关于C++ 11等一些新标准,有以下配置:
查找库
The text was updated successfully, but these errors were encountered: