(六) CMake基本语法

1、编写的CMakeLists.txt需要符合一定的语法规则,它主要由CMake命令组成。

(1)注释的语法:在CMake中注释使用#字符开始到此行结束。

(2) CMake命令:命令不区分大小写(参数会区分大小写),命令由命令、参数列表组成,参数之间使用空格进行分隔。使用一对双引号包括的字符串认为是一个参数。命令可以是一个内置命令(例如:project,add_executable等),也可以是一个用户定义的宏(macro)或者函数(function)

(3) 数据类型:CMake的基本数据类型是字符串,一组字符串在一起称为列表,例如:

#通过set命令构建一个listVAR

set(VAR a b c)

使用语法${VariableName}来访问名字为VariableName的变量的值(变量名区分大小写)

#输出VAR=a;b;c

message(“VAR=${VAR}”)

使用语法$ENV{VariableName}来访问环境变量的值(ENV{VariableName}则表示环境变量本身)

message($ENV{PATH})

2、CMake常用命令

(1) project命令

命令语法:project(<projectname> [languageName1 languageName2 ...])
命令简述:用于指定项目的名称
使用范例:project(Main)

(2) cmake_minimum_required命令

命令语法:cmake_minimum_requried(VERSION major[.minor[.patch)
命令简述:用于指定需要的CMake的最低版本
使用范例:cmake_minimum_requried(VERSION 2.8)

(3) aux_source_directory命令

命令语法:aux_source_directory(<dir> <variable>)
命令简述:用于将dir目录下的所有源文件的名字保存在变量variable中
使用范例:aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src  DIR_SRCS)

(4) add_executable命令

命令语法:add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN)
命令简述:用于指定从一组源文件source1 source2 ... sourceN 编译出一个可执行文件且命名为name
使用范例:add_executable(Main $(DIR_SRCS))

(5) add_library命令

命令语法:add_library([STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1source2 … sourceN)
命令简述:用于指定从一组源文件 source1 source2 ... sourceN编译出一个库文件且命名为name
使用范例:add_library(Lib $(DIR_SRCS))

(6) add_dependencies命令

命令语法:add_dependencies(target-name depend-target1 depend-target2 …)
命令简述:用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的目标必须是add_executable、add_library、add_custom_target命令创建的目标

(7) add_subdirectory命令

命令语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
命令简述:用于添加一个需要进行构建的子目录
使用范例:add_subdirectory(Lib)

(8) target_link_libraries命令

命令语法:target_link_libraries(<target> [item1 [item2 […]]][[debug|optimized|general] ] …)
命令简述:用于指定target需要链接item1 item2 ...。这里target必须已经被创建,链接的item可以是已经存在的target(依赖关系会自动添加)
使用范例:target_link_libraries(Main Lib)

(9) set命令

命令简述:用于设定变量 variable 的值为 value。如果指定了 CACHE 变量将被放入 Cache(缓存)中。
命令语法:set(<variable> <value> [[CACHE <type><docstring> [FORCE]] | PARENT_SCOPE])
使用范例:set(ProjectName Main)

(10) unset命令

命令语法:unset(<variable> [CACHE])
命令简述:用于移除变量 variable。如果指定了 CACHE 变量将被从 Cache 中移除。
使用范例:unset(VAR CACHE)

(11) message命令

命令语法:message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] “message todisplay”…)
命令简述:用于输出信息
使用范例:message(“Hello World”)

(12) include_directories命令

命令语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
命令简述:用于设定目录,这些设定的目录将被编译器用来查找 include 文件
使用范例:include_directories(${PROJECT_SOURCE_DIR}/lib)

(13) find_path命令

命令语法:find_path(<VAR> name1 [path1 path2 …])
命令简述:用于查找包含文件name1的路径,如果找到则将路径保存在VAR中(此路径为一个绝对路径),如果没有找到则结果为<VAR>-NOTFOUND.默认情况下,VAR会被保存在Cache中,这时候我们需要清除VAR才可以进行下一次查询(使用unset命令)
find_path(LUA_INCLUDE_PATH lua.h ${LUA_INCLUDE_FIND_PATH})
if(NOT LUA_INCLUDE_PATH)
     message(SEND_ERROR "Header file lua.h not found")
endif()

(14) find_library命令

命令语法:find_library(<VAR> name1 [path1 path2 …])
命令简述:用于查找库文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。一个类似的命令 link_directories 已经不太建议使用了

(15) add_definitions命令

命令语法:add_definitions(-DFOO -DBAR …)
命令简述:用于添加编译器命令行标志(选项),通常的情况下我们使用其来添加预处理器定义
使用范例:add_definitions(-D_UNICODE -DUNICODE)

(16) file命令

命令简述:此命令提供了丰富的文件和目录的相关操作(这里仅说一下比较常用的)
使用范例:
# 目录的遍历
# GLOB 用于产生一个文件(目录)路径列表并保存在variable 中
# 文件路径列表中的每个文件的文件名都能匹配globbing expressions(非正则表达式,但是类似)
# 如果指定了 RELATIVE 路径,那么返回的文件路径列表中的路径为相对于 RELATIVE 的路径
file(GLOB variable [RELATIVE path][globbing expressions]...)
 
# 获取当前目录下的所有的文件(目录)的路径并保存到 ALL_FILE_PATH 变量中
file(GLOB ALL_FILE_PATH ./*)
# 获取当前目录下的 .h 文件的文件名并保存到ALL_H_FILE 变量中
# 这里的变量CMAKE_CURRENT_LIST_DIR 表示正在处理的 CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)
file(GLOB ALL_H_FILE RELATIVE${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/*.h)

3、CMake常用变量

UNIX如果为真,表示为UNIX-like的系统,包括AppleOSX和CygWin
WIN32 如果为真,表示为 Windows 系统,包括 CygWin
APPLE 如果为真,表示为 Apple 系统
CMAKE_SIZEOF_VOID_P表示void*的大小(例如为4或者8),可以使用其来判断当前构建为32位还是64位
CMAKE_CURRENT_LIST_DIR表示正在处理的CMakeLists.txt文件的所在的目录的绝对路径(2.8.3以及以后版本才支持)
CMAKE_ARCHIVE_OUTPUT_DIRECTORY用于设置ARCHIVE目标的输出路径
CMAKE_LIBRARY_OUTPUT_DIRECTORY用于设置LIBRARY目标的输出路径
CMAKE_RUNTIME_OUTPUT_DIRECTORY用于设置RUNTIME目标的输出路径

4、构建类型

CMake提供四种构建类型

Debug

Release

5、编译和链接标志

1)C编译标志相关变量
CMAKE_C_FLAGS
CMAKE_C_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

2)C++编译标志相关变量
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

CMAKE_C_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]或 CMAKE_CXX_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO] 则指定特定构建类型的编译标志,这些编译标志将被加入到 CMAKE_C_FLAGS 或 CMAKE_CXX_FLAGS 中去,例如,如果构建类型为 DEBUG,那么 CMAKE_CXX_FLAGS_DEBUG 将被加入到 CMAKE_CXX_FLAGS中去


3)链接标志相关变量
CMAKE_EXE_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]
CMAKE_MODULE_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]
CMAKE_SHARED_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]
它们类似于编译标志相关变量

6、生成Debug和Release版本

debug版的项目生成的可执行文件需要有调试信息并且不需要进行优化,而release版的不需要调试信息但需要优化。这些特性在gcc/g++中是通过编译时的参数决定的,如果将优化程度调到最高需要设置-O3,最低-O0即不做优化;添加调试信息的参数是-g -ggdb,如果不添加这个参数,调试信息就不会被包含在生成的二进制文件中。

CMake中有一个变量CMAKE_BUILD_TYPE,可以的取值是Debug、Release、RelWithDebInfo和MinSizeRel。当这个变量值为Debug的时候,CMake会使用变量CMAKE_CXX_FLAGS_DEBUG和 CMAKE_C_FLAGS_DEBUG中的字符串作为编译选项生成Makefile ,当这个变量值为 Release 的时候,工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和CMAKE_C_FLAGS_RELEASE 选项生成 Makefile。

project(main)
cmake_minimum_required(version 2.6)
set(CMAKE_SOURCE_DIR .)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
ADD_EXECUTABLE(main ${DIR_SRCS})
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和CMAKE_CXX_FLAGS_RELEASE, 这两个变量是分别用于 debug 和 release 的编译选项。

7、多源文件目录的处理方式

我们在每一个源码目录中都会放置一个CMakeLists.txt文件。我们现在假定有这么一个工程:

HelloWorld

+-------Main.cpp

+-------CMakeLists.txt

+-------Lib

        +------Lib.cpp

        +------Lib.h

        +------CMakeLists.txt

这里Lib目录下的文件将被编译为一个库。首先,Lib目录下的CMakeLists.txt文件

aux_source_directory(. DIR_SRCS)

add_library(Lib ${DIR_SRCS})

看一下HelloWorld目录下的CMakeLists.txt文件:

project(Main)
cmake_minimum_required(VERSION 2.8)
add_subdirectory(Lib)
aux_source_directory(. DIR_SRCS)
add_executable(Main ${DIR_SRCS})
target_link_libraries(Main Lib)

使用add_subdirectory指定需要进行构建的子目录,并且使用了target_link_libraries命令,表示Main可执行文件需要链接Lib库。执行CMake .命令,首先会执行HelloWorld目录下的CMakeLists.txt中的命令,当执行到add_subdirectory(Lib)命令的时候会进入Lib子目录并执行其中的CMakeLists.txt文件。

8、外部构建(out of source builds)

在CMakeLists.txt所在目录下执行CMake . 会生成大量的文件,这些文件和源文件混在一起不好管理,采用外部构建的方式来解决这个问题。以上面的Hello World工程来做解释:
在HelloWorld目录下建立一个build目录
进入build目录并进行外部构建CMake ..(语法为CMake <CMakeLists.txt的路径>,这里使用CMake ..表明了CMakeLists.txt在Build目录的父目录中)。这样CMake将在Build目录下生产文件。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值