cmake函數參數解析,cmake函數解析
最近在遷移公司的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})<pre name="code" class="plain">tst_arguments(${SRC})==== output ====SRC = a.cppb.cppc.cppd.cppsrc_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()<pre name="code" class="plain"><pre name="code" class="plain">tst_arguments(${SRC})
<pre name="code" class="plain">==== output ====ARGC = 4ARGV = a.cppb.cppc.cppd.cpp
ARG = a.cppARG = b.cppARG = c.cppARG = d.cpp
當然,你也可以使用cmake的foreach迴圈遍曆參數。這招對付只有一個list的參數時十分有效,但是在出現多個參數的情況,如下:
##假設函數link_lib將src_list中的源檔案連結成庫,根據type制定是連結靜態庫還是動態庫#function(link_lib src_list type)<pre name="code" class="plain"> message("ARGC = "${ARGC})message("ARGV = "${ARGV})
#以下根據參數的實際情做了操作,以保證正確擷取src_list和typeset(INDEX 0)math(EXPR MAX "${ARGC} - 1") while(INDEX LESS ${MAX})#do something to linkmath(EXPR INDEX "${INDEX} + 1")endwhile()endfunction()
link_lib(${SRC} , so)<pre name="code" class="plain"><pre name="code" class="plain"><pre name="code" class="plain">==== 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/iWorkTEST_NAME is testisoTEST_COMMAND is RunMeTEST_ARGSLIST is a.cpp;b.cpp;c.cpp;d.cppTEST_BASELINE is /home/sakaue/iWork
可以看見,這裡調用時的參數傳遞如同map一樣<NAME ,testiso_${datafile} >,<COMMAND , "RunMe">,<ARGSLIST , ${SRC}>等等,在函數中,使用 首碼+KeyWord 來調用Value,這樣比自己解析參數方便許多,而且也不會在還有list參數時和其他類型函數混在一起的情況。
函數的每一個形式參數就是一個 A 運算式 B 常量 C 變數 D 函數調用
c
對於主函數main()的參數問題
主函數的參數就是輸入命令列的參數,主函數不能被其他函數調用
int main(int argc, char *argv[]);
int main(int argc, char **argv);
int main(void);
void main(int argc, char *argv[]);
void main(int argc, char **argv);
void main(void);
補充回答:
------------------------------------
WinMain()的第三個參數是LPSTR lpCmdLine,命令列參數
這個就相當於argv,需要自己解析出每個參數