美文网首页
CMake搭建项目工程(2)-CMake控制命令、函数与宏、安装

CMake搭建项目工程(2)-CMake控制命令、函数与宏、安装

作者: WalkeR_ZG | 来源:发表于2019-04-13 23:57 被阅读0次

CMake+GoogleTest搭建项目工程(1)-C/C++编译及CMake那些事
本篇主要阐述CMake的其他常用命令,并给出一个示例代码。

CMake控制命令

if else endif指令
if(expression)
    command(……)
else(expression)
    command(……)
endif(expression)
if elseif endif指令
if(expression_1)
   command(……)
elseif(expression_2)
   command(……)
elseif(expression_3)
   command(……)
endif(expression_1)

if的判断条件:
如果expression是变量,则当expression为:空、0、N、 NO、 OFF、 FALSE、 NOTFOUND 、expression_NOTFOUND 时,表达式为假,其余为真。
同时支持与(and)、或(or)、非(not)的语义,与常规语言的与或非含义一致。

while指令
while(expression)
    command(……)
endwhile(expression)       

与常规编程语言的while一致。

foreach
//var依次取列表arg中的值
foreach(var arg1 arg2……)
    command(……)
endforeach(var)
//var从0到total以1为步长增加
foreach(var range total)
    command(……)
endforeach(var)
//var从start到end, 以step为步长增加
foreach(var range start end step)
    command(……)
endforeach(var)

CMake宏与函数

  • CMake的函数与宏可用的变量
name description
ARGC 函数实参的个数
ARGV 所有实参列表
ARGN 保留函数形参列表以后的所有参数列表。
ARGV0 函数第1个实参
ARGV1 函数第2个实参
依次类推 依次类推
function
function(<name> [arg1 [arg2 [arg3 ...]]])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
endfunction(<name>)
macro
macro(<name> [arg1 [arg2 [arg3 ...]]])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
endmacro(<name>)
macro与function的区别

macro是CMake的宏定义,function为CMake的函数,其差异与C语言中宏和函数的差异类似,我们对比以下代码:

cmake_minimum_required(VERSION 2.8)
set(v1 "ABC")
set(v2 "XYZ")

macro(Macro v1 v2)
  message("ARGC = ${ARGC} ARGV = ${ARGV}")
  message("ARGV0 = ${ARGV0} ARGV1 = ${ARGV1} ARGN = ${ARGN}")
  message("----------------------------")
  message("v1 = ${v1} v2 = ${v2}")
  set(v1 "abc")
  set(v2 "xyz")
  message("v1 = ${v1} v2 = ${v2}")
endmacro()

Macro(${v1} v2 x y z)
message("v1 = ${v1} v2 = ${v2}")

message("----------------------------")

set(v1 "ABC")
set(v2 "XYZ")
function(Function  v1 v2)
  message("v1 = ${v1} v2 = ${v2}")
  set(v1 "abc")
  set(v2 "xyz" PARENT_SCOPE)
  message("v1 = ${v1} v2 = ${v2}")
endfunction()

Function(${v1} v2)
message("v1 = ${v1} v2 = ${v2}")

它的输出结果为

ARGC = 5 ARGV = ABC;v2;x;y;z
ARGV0 = ABC ARGV1 = v2 ARGN = x;y;z
----------------------------
v1 = ABC v2 = v2
v1 = ABC v2 = v2
v1 = abc v2 = xyz
----------------------------
v1 = ABC v2 = v2
v1 = abc v2 = v2
v1 = ABC v2 = xyz

通过上面的代码,我们首先可以看到marco与function的可用变量ARG*,同时可以看出marco与function的差异:

  1. marco没有SCOPE的概念,只是字符串的替换,有些类似于C语言中的define,在预处理阶段就进行了字符串的替换,通过v1的值的打印即可看出
  2. function有SCOPE的概念,虽然marco与function都完成了v2的赋值,但marco是字符串的替换,而function的入参写为v2形式,并且需要加上PARENT_SCOPE。

CMake安装 (install)

CMake install一般用于库、头文件的安装,当然也可以安装目录,我们写好CMakeLists.txt后在build目录执行cmake生成makefile,之后执行make进行编译,编译是不会进行安装的(这也是install用于安装文件与file的差别),需要额外执行make install进行安装。

目标文件的安装
INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME]
                [DESTINATION <dir>]
                [PERMISSIONS permissions...]
                [CONFIGURATIONS
                [Debug|Release|...]]
                [COMPONENT <component>]
                [OPTIONAL]] )

作用:目标文件的安装,目标文件TARGETS 后面跟的可以是二进制可执行文件(ADD_EXECUTABLE的target)或库文件(ADD_LIBRARY的target)。目标类型分为三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME 特指可执行目标二进制。可以一次安装多个目标文件。

普通文件的安装
INSTALL(FILES files... DESTINATION <dir>
              [PERMISSIONS permissions...]
              [CONFIGURATIONS [Debug|Release|...]]
              [COMPONENT <component>]
              [RENAME <name>] [OPTIONAL])

作用:一般文件的安装,可以指定访问权限,如果默认不定义权限PERMISSIONS,安装后的权限为:OWNER_WRITE & OWNER_READ & GROUP_READ & WORLD_READ。

非目标文件的可执行程序安装
INSTALL(PROGRAMS files... DESTINATION <dir>
     [PERMISSIONS permissions...]
     [CONFIGURATIONS [Debug|Release|...]]
     [COMPONENT <component>]
     [RENAME <name>] [OPTIONAL])

作用:非目标文件的可执行程序安装,默认的权限为OWNER_EXECUTE & GROUP_EXECUTE & WORLD_EXECUTE。

目录的安装
INSTALL(DIRECTORY dirs... DESTINATION <dir>
     [FILE_PERMISSIONS permissions...]
     [DIRECTORY_PERMISSIONS permissions...]
     [USE_SOURCE_PERMISSIONS]
     [CONFIGURATIONS [Debug|Release|...]]
     [COMPONENT <component>]
     [[PATTERN <pattern> | REGEX <regex>]
     [EXCLUDE] [PERMISSIONS permissions...]])

作用:目录的安装。特别注意:如果目录名以 /结束,则代表将这个目录中的内容安装到目标路径,但不包括这个目录本身;如果目录名不以/结尾,那么这个目录将被安装为目标路径下。

下面以一个例子对上述内容有个形象的认识,文件目录下存在Add.h,Add.cc 和CMakeLists.txt分别如下:(需求将Add.h安装到/usr/local/WalkeR-ZG/include目录下,将静态库文件libadd.a安装到/usr/local/WalkeR-ZG/lib目录下)
Add.h:

int add(int a, int b);

Add.cc:

#include "Add.h"
int add(int a, int b){
    return a + b;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
set(CMAKE_INSTALL_PREFIX /usr/local/WalkeR-ZG)
add_library(add STATIC Add.cc)
target_include_directories(add PRIVATE include "${PROJECT_SOURCE_DIR}")
install(TARGETS add ARCHIVE DESTINATION lib)
install(FILES Add.h DESTINATION include)

CMake模块

CMake模块主要的作用是当我们需要使用外部库时,需要知道外部库的头文件和链接库的位置,CMake模块主要就给出了头文件及链接库的查找方法。
模块使用find_package(xxx)被调用,每个模块会定义如下变量:

  • xxx__FOUND:用来判断模块是否被找到,如果没有找到,根据工程的需要关闭某些特性、给出提醒或者中止编译。
  • xxx_INCLUDE_DIR: 头文件的目录
  • xxx_LIBRARY (xxx_LIBRARIES):库文件目录

find_package(xxx)用来调用预定义在CMAKE_MODULE_PATH下的Findxxx.cmake模块,你也可以自己定义Find<name> 模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录供工程使用。
结合上面给出的代码编译安装的Add的头文件及静态库,编写一个cmake的模块。目录结构如下:
顶层目录是demo目录,存在一个子目录cmake用于放模块。代码和CMakeLists.txt直接放在demo目录下。
main.cc:

#include <Add.h>
#include <iostream>

int main(){
    int a = add(3, 4);
    std::cout<<a<<std::endl;
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
find_package(Add)
if(Add_FOUND)
    add_executable(demo main.cc)
    target_include_directories(demo PRIVATE Add_INCLUDE_DIR)
    target_link_libraries(demo Add_LIBRARY)
else(Add_FOUND)
    message(FATAL_ERROR "Add cannot find!!!")
endif(Add_FOUND)

cmake/FindAdd.cmake:

find_path(Add_INCLUDE_DIR Add.h /usr/local/WalkeR-ZG/include)
find_library(Add_LIBRARY libadd.a /usr/local/WalkeR-ZG/lib)
if (Add_INCLUDE_DIR AND Add_LIBRARY)
    set(Add_FOUND TRUE)
endif(Add_INCLUDE_DIR AND Add_LIBRARY)

if(Add_FOUND)
    if(NOT Add_FIND_QUIETLY)
    message(STATUS "Found Add: ${Add_LIBRARY}")
    endif(NOT Add_FIND_QUIETLY)
endif(Add_FOUND)

CMake的内容粗略阐述完毕。

WalkeR_ZG

相关文章

网友评论

      本文标题:CMake搭建项目工程(2)-CMake控制命令、函数与宏、安装

      本文链接:https://www.haomeiwen.com/subject/qaarbqtx.html