cmake使用教程(八)-macro和function

【cmake系列使用教程】linux

cmake使用教程(一)-起步git

cmake使用教程(二)-添加庫github

cmake使用教程(三)-安裝、測試、系統自檢shell

cmake使用教程(四)-文件生成器macos

cmake使用教程(五)-cpack生成安裝包數組

cmake使用教程(六)-蛋疼的語法bash

cmake使用教程(七)-流程和循環函數

cmake使用教程(八)-macro和functionoop

cmake使用教程(九)-關於安卓的交叉編譯post

這個系列的文章翻譯自官方cmake教程:cmake tutorial

示例程序地址:github.com/rangaofei/t…

不會僅僅停留在官方教程。本人做爲一個安卓開發者,實在是沒有linux c程序開發經驗,望大佬們海涵。教程是在macos下完成,大部分linux我也測試過,有特殊說明的我會標註出來。本教程基於cmake-3.10.2,同時認爲你已經安裝好cmake。

cmake中有兩個類似的關鍵字,macro和function。這兩個都是建立一段有名字的代碼稍後能夠調用,還能夠傳參數。

macro宏定義與function函數的相同點

macro形式以下:

macro(<name> [arg1 [arg2 [arg3 ...]]])
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endmacro(<name>)
複製代碼

function形式以下:

function(<name> [arg1 [arg2 [arg3 ...]]])
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
function(<name>)
複製代碼

定義一個名稱爲name的宏(函數),arg1...是傳入的參數。咱們除了能夠用${arg1}來引用變量之外,系統爲咱們提供了一些特殊的變量:

變量 說明
ARGV# #是一個下標,0指向第一個參數,累加
ARGV 全部的定義時要求傳入的參數
ARGN 定義時要求傳入的參數之外的參數,好比定義宏(函數)時,要求輸入1個,書記輸入了3個,則剩下的兩個會以數組形式存儲在ARGN中
ARGC 傳入的實際參數的個數,也就是調用函數是傳入的參數個數

macro宏定義與function函數的不一樣點

宏的ARGN、ARGV等參數不是一般CMake意義上的變量。 它們是字符串替換,很像C預處理器對宏的處理。 所以,以下命令是錯誤的:

if(ARGV1) # ARGV1 is not a variable 
if(DEFINED ARGV2) # ARGV2 is not a variable
if(ARGC GREATER 2) # ARGC is not a variable
foreach(loop_var IN LISTS ARGN) # ARGN is not a variable
複製代碼

正確寫法以下:

if(${ARGV1})
if(DEFINED ${ARGV2})
if(${ARGC} GREATER 2)
foreach(loop_var IN LISTS ${ARGN})
or
set(list_var "${ARGN}")
foreach(loop_var IN LISTS list_var)

複製代碼

一個簡單的例子

macro(FOO arg1 arg2 arg3)
    message(STATUS "this is arg1:${arg1},ARGV0=${ARGV0}")
    message(STATUS "this is arg2:${arg2},ARGV1=${ARGV1}")
    message(STATUS "this is arg3:${arg3},ARGV2=${ARGV2}")
    message(STATUS "this is argc:${ARGC}")
    message(STATUS "this is args:${ARGV},ARGN=${ARGN}")
    if(arg1 STREQUAL one)
        message(STATUS "this is arg1")
    endif()
    if(ARGV2 STREQUAL "two")
        message(STATUS "this is arg2")
    endif()
    set(${arg1} nine)
    message(STATUS "after set arg1=${${arg1}}")
endmacro(FOO)

function(BAR arg1)
    message(STATUS "this is arg1:${arg1},ARGV0=${ARGV0}")
    message(STATUS "this is argn:${ARGN}")
    if(arg1 STREQUAL first)
        message(STATUS "this is first")
    endif()
    set(arg1 ten)
    message(STATUS "after set arg1=${arg1}")
endfunction(BAR arg1)

set(p1 one)
set(p2 two)
set(p3 three)
set(p4 four)
set(p5 five)
set(p6 first)
set(p7 second)

FOO(${p1} ${p2} ${p3} ${p4} ${p5})
BAR(${p6} ${p7})
message(STATUS "after bar p6=${p6}")
複製代碼

輸出結果以下:

-- this is arg1:one,ARGV0=one
-- this is arg2:two,ARGV1=two
-- this is arg3:three,ARGV2=three
-- this is argc:5
-- this is args:one;two;three;four;five,ARGN=four;five
-- after set arg1=nine
-- this is arg1:first,ARGV0=first
-- this is argn:second
-- this is first
-- after set arg1=ten
-- after bar p6=first
複製代碼

接下來看一個讓咱們蛋都能疼碎了的例子,簡直不想用cmake:

macro(_bar)
  foreach(arg IN LISTS ARGN)
    message(STATUS "this is in macro ${arg}")
  endforeach()
endmacro()

function(_foo)
    foreach(arg IN LISTS ARGN)
        message(STATUS "this in function is ${arg}")
    endforeach()
  _bar(x y z)
endfunction()

_foo(a b c)
複製代碼

看一下輸出:

-- this in function is a
-- this in function is b
-- this in function is c
-- this is in macro a
-- this is in macro b
-- this is in macro c
複製代碼

就是這麼蛋疼,咱們傳給了_bar(x y z),結果打印出來的是a b c,那咱們把第二行的foreach改爲foreach(arg IN LISTS ${ARGN}), 看一下結果:

-- this in function is a
-- this in function is b
-- this in function is c
複製代碼

沒有輸出_bar中的信息。爲啥?由於這個ARGN的做用域是在function中的,也就是_foo函數中的那個ARGN。有興趣的話能夠試試在macro中調用function。

相關文章
相關標籤/搜索