CMake有一个预定义的命令cmake_parse_arguments来解析function或macro的参数,并定义一组保存相应选项值的变量。它的格式如下:
cmake_parse_arguments(<prefix> <options> <one_value_keywords>
<multi_value_keywords> <args>...)
cmake_parse_arguments(PARSE_ARGV <N> <prefix> <options>
<one_value_keywords> <multi_value_keywords>)
第一个版本既可以在function中使用,也可以在macro中使用。参数说明:
(1).<prefix>:前缀字符串,位于所有变量名称之前。它后跟"_"和相应关键字的名称。
(2).<options>:包含相应macro或function的所有选项,例如,在调用macro时可以使用的关键字,后面不跟任何值。无论选项是否在参数列表中,这些关键字将始终定义为 TRUE或FALSE。如果传递将设置为TRUE,否则为FALSE。
(3).<one_value_keywords>:包含macro或function的所有关键字,后跟一个值,例如关键字DESTINATION: DESTINATION /usr/lib
(4).<multi_value_keywords>:包含macro或function的所有关键字,后跟多个值,例如关键字FILES: FILES test.cpp main.cpp
所有关键字均应是唯一的:即每个关键字只能在<options>、<one_value_keywords>或<multi_value_keywords>指定一次。如果违反唯一性,将触发警告。
所有剩余的参数都收集在变量<prefix>_UNPARSED_ARGUMENTS中,如果所有参数被识别,则该变量将未定义。可以用来检查调用的macro或function是否使用了无法识别的参数。
function的示例代码段如下:
message("1.test function 1: ARGN")
function(test_function1)
set(prefix FUNC1)
set(options CSDN GITHUB)
set(one_value_keywords DESTINATION)
set(multi_value_keywords FILES RES)
# ARGN:包含命名参数和可选参数的变量列表
cmake_parse_arguments(${prefix} "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
message("FUNC1_CSDN: ${FUNC1_CSDN}")
message("FUNC1_GITHUB: ${FUNC1_GITHUB}")
message("FUNC1_DESTINATION: ${FUNC1_DESTINATION}")
message("FUNC1_FILES: ${FUNC1_FILES}")
message("FUNC1_RES: ${FUNC1_RES}")
message("FUNC1_UNPARSED_ARGUMENTS: ${FUNC1_UNPARSED_ARGUMENTS}")
if(NOT DEFINED FUNC1_RES)
message("FUNC1_RES variable is not defined")
endif()
endfunction()
test_function1(FILES test.cpp main.cpp DESTINATION /usr/lib CSDN config DEBUG)
message("------------------------------")
test_function1(RES png txt model DESTINATION /usr/lib /opt GITHUB test)
执行结果如下图所示:
macro的示例代码段如下:
message("3.test macro 1: ARGN")
macro(test_macro1)
set(prefix MACRO1)
set(options CSDN GITHUB)
set(one_value_keywords DESTINATION)
set(multi_value_keywords FILES RES)
# ARGN:包含命名参数和可选参数的变量列表
cmake_parse_arguments(${prefix} "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
message("MACRO1_CSDN: ${MACRO1_CSDN}")
message("MACRO1_GITHUB: ${MACRO1_GITHUB}")
message("MACRO1_DESTINATION: ${MACRO1_DESTINATION}")
message("MACRO1_FILES: ${MACRO1_FILES}")
message("MACRO1_RES: ${MACRO1_RES}")
message("MACRO1_UNPARSED_ARGUMENTS: ${MACRO1_UNPARSED_ARGUMENTS}")
if(NOT DEFINED MACRO1_RES)
message("MACRO1_RES variable is not defined")
endif()
endmacro()
test_macro1(FILES test.cpp main.cpp DESTINATION /usr/lib CSDN config DEBUG)
message("------------------------------")
test_macro1(RES png txt model DESTINATION /usr/lib /opt GITHUB test)
执行结果如下图所示:结果与上面的function一致
第二个版本(PARSE_ARGV)只能在function中使用,在这种情况下,解析的参数来自调用function的ARGV#变量,解析从<N>-th参数开始,其中<N>是无符号整数。
此function的示例代码段如下:
message("2.test function 2: PARSE_ARGV")
function(test_function2 addr_csdn addr_github)
set(prefix FUNC2)
set(options CSDN GITHUB)
set(one_value_keywords DESTINATION)
set(multi_value_keywords FILES RES)
# 命名参数(names arguments) = 2
cmake_parse_arguments(PARSE_ARGV 2 ${prefix} "${options}" "${one_value_keywords}" "${multi_value_keywords}")
message("FUNC2_CSDN: ${FUNC2_CSDN}")
message("FUNC2_GITHUB: ${FUNC2_GITHUB}")
message("FUNC2_DESTINATION: ${FUNC2_DESTINATION}")
message("FUNC2_FILES: ${FUNC2_FILES}")
message("FUNC2_RES: ${FUNC2_RES}")
message("FUNC2_UNPARSED_ARGUMENTS: ${FUNC2_UNPARSED_ARGUMENTS}")
message("addr csdn: ${addr_csdn}")
message("addr github: ${addr_github}")
endfunction()
test_function2("https://blog.csdn.net/fengbingchun" "https://github.com/fengbingchun" FILES test.cpp main.cpp DESTINATION /usr/lib CSDN config DEBUG)
message("------------------------------")
test_function2("https://blog.csdn.net/fengbingchun" "https://github.com/fengbingchun" RES png txt model DESTINATION /usr/lib /opt GITHUB test)
执行结果如下图所示:结果与上面的function一致
执行上述测试代码需要3个文件:./build.sh, CMakeLists.txt, test_cmake_parse_arguments.cmake
build.sh内容如下:
#! /bin/bash
# supported input parameters
params=(function macro cmake_parse_arguments)
usage()
{
echo "Error: $0 needs to have an input parameter"
echo "supported input parameters:"
for param in ${params[@]}; do
echo " $0 ${param}"
done
exit -1
}
if [ $# != 1 ]; then
usage
fi
flag=0
for param in ${params[@]}; do
if [ $1 == ${param} ]; then
flag=1
break
fi
done
if [ ${flag} == 0 ]; then
echo "Error: parameter \"$1\" is not supported"
usage
exit -1
fi
if [[ ! -d "build" ]]; then
mkdir build
cd build
else
cd build
fi
echo "==== test $1 ===="
cmake -DTEST_CMAKE_FEATURE=$1 ..
CMakeLists.txt内容如下:
CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
PROJECT(cmake_feature_usage)
message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
if(TEST_CMAKE_FEATURE STREQUAL "function")
include(test_function.cmake)
elseif(TEST_CMAKE_FEATURE STREQUAL "macro")
include(test_macro.cmake)
elseif(TEST_CMAKE_FEATURE STREQUAL "cmake_parse_arguments")
include(test_cmake_parse_arguments.cmake)
endif()
message("==== test finish ====")
test_cmake_parse_arguments.cmake内容:为上面所示代码段