1. 程式人生 > >cmake函數參數解析

cmake函數參數解析

遍歷 man 而在 taf get reac ... pre val

近期在遷移公司的make系統到cmake上。發現cmake的function參數非常奇怪。比如,假設我們向一個function傳遞list作為參數,在function中,形參會變成例如以下狀況:

set(SRC)
list(APPEND SRC a.cpp b.cpp)
list(APPEND SRC c.cpp d.cpp)

function(tst_arguments src_list)
	message("src_list = "${src_list})
endfunction()

message("SRC = "${SRC})
tst_arguments(${SRC})

==== output ====
SRC = a.cppb.cppc.cppd.cpp
src_list = a.cpp


非常奇怪的是,這裏的${SRC}在function外是完整的4個元素。而在function卻僅僅剩下了頭一個元素(可能跟list的定長有關)。

假設我們要傳給function以n個源文件組成的list,這樣顯然不行。

一種簡單的解決方法是使用ARGV。ARGC配合,他們的含義如同C/C++中main的argv和argc。分別代表參數和參數個數。使用例如以下方法解析參數:

function(tst_arguments src_list)
	message("ARGC = "${ARGC})
	message("ARGV = "${ARGV})

        set(INDEX 0)
    
	while(INDEX LESS ${ARGC})
		message("ARG = "${ARGV${INDEX}})
		math(EXPR INDEX "${INDEX} + 1")
	endwhile()
endfunction()

tst_arguments(${SRC})

==== output ====
ARGC = 4
ARGV = a.cppb.cppc.cppd.cpp
ARG = a.cpp
ARG = b.cpp
ARG = c.cpp
ARG = d.cpp 





當然,你也能夠使用cmake的foreach循環遍歷參數。這招對付僅僅有一個list的參數時十分有效。可是在出現多個參數的情況就非常麻煩。例如以下:

#
#如果函數link_lib將src_list中的源文件鏈接成庫,依據type制定是鏈接靜態庫還是動態庫
#
function(link_lib src_list type)

        message("ARGC = "${ARGC})
	message("ARGV = "${ARGV})
        
        
        #下面依據參數的實際情做了操作,手動處理。以保證正確獲取src_list和type
        set(INDEX 0)
        math(EXPR MAX "${ARGC} - 1")
        while(INDEX LESS ${MAX})
             #do something to link
             math(EXPR INDEX "${INDEX} + 1")
        endwhile()
endfunction()

link_lib(${SRC} , so)

==== output ====
ARGC = 5
ARGV = a.cppb.cppc.cppd.cppso







原來,ARG把兩個參數混在了一起,盡管後面我們使用while進行了特殊處理,可是這對於cmake的函數不具備普遍性。移植起來非常麻煩。

決定版的solution是使用cmake的cmake_parse_arguments來解析函數參數,它有點像解析一個map鍵值對。首先看下它的函數原型:

include (CMakeParseArguments)  #必須包括這個cmake文件才幹使用<span class="highlighted">cmake_parse_arguments</span>

CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)

首先,prefix是一個前綴。等會兒在引用參數的時候會提到,<option>是一個列表。裏面能夠包括一些你感興趣的KeyWord,隨後能夠通過它來看看你所須要的KeyWord是否被設置。<one_value_keywords>是一個單值參數的KeyWord列表。<multi_value_keywords>是一個多值參數的KeyWord列表(如list),以下舉個樣例,看看怎樣使用它們,首先定義所須要的函數,因為參數是由CMAKE_PARSE_ARGUMENTS來解析的,所以在函數聲明中就不須要定義參數了:

function(tst_arguments)
  CMAKE_PARSE_ARGUMENTS(
    TEST "" "NAME;COMMAND;BASELINE"
       "ARGSLIST"
       ${ARGN}
  )

  message("TEST_DEFAULT_ARGS is ${TEST_DEFAULT_ARGS} from ${ARGN}")
  message("TEST_NAME is ${TEST_NAME}")
  message("TEST_COMMAND is ${TEST_COMMAND}")
  message("TEST_ARGSLIST is ${TEST_ARGSLIST}")
  message("TEST_BASELINE is ${TEST_BASELINE}")

endfunction(tst_arguments)
這裏的前綴是TEST,<one_value_keywords>我們設置單值參數的KeyWord(NAME;COMMAND;BASELINE)。這將在隨後的函數調用中註明KeyWord和Value的關系,<multi_value_keywords>我們設置多值參數的KeyWord("ARGSLIST"),調用函數:

TEST_ARGUMENT(
    NAME
      testiso
    COMMAND
      "RunMe"
    ARGSLIST
      ${SRC}
    BASELINE
      "/home/sakaue/iWork"
)

==== output ====
TEST_DEFAULT_ARGS is  from NAME;testiso;COMMAND;RunMe;ARGSLIST;a.cpp;b.cpp;c.cpp;d.cpp;BASELINE;/home/sakaue/iWork
TEST_NAME is testiso
TEST_COMMAND is RunMe
TEST_ARGSLIST is a.cpp;b.cpp;c.cpp;d.cpp
TEST_BASELINE is /home/sakaue/iWork






能夠看見,這裏調用時的參數傳遞如同map一樣<NAME ,testiso_${datafile} >,<COMMAND , "RunMe">,<ARGSLIST , ${SRC}>等等。在函數中。使用 前綴+KeyWord 來調用Value,這樣比自己解析參數方便很多,並且也不會在還有list參數時和其它類型函數混在一起的情況。

很多其它訊息參考:http://www.cmake.org/cmake/help/v3.0/module/CMakeParseArguments.html?highlight=cmake_parse_arguments


cmake函數參數解析