CMake中function的使用

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake中function的使用相关的知识,希望对你有一定的参考价值。

      function的定义格式如下:后面可作为命令供调用

function(<name> [<arg1> ...])
  <commands>
endfunction()

      其中name是function的名字,参数为arg1, arg2等。function名称不区分大小写,但强烈建议使用function定义中声明的相同名称。通常,function使用全小写名称。示例代码段如下:

message("1.function名称不区分大小写,但始终建议使用function定义中声明的相同名称")
function(csdn_addr)
    message("csdn addr: https://blog.csdn.net/fengbingchun")
endfunction()

csdn_addr()
CSDN_ADDR()
csdn_ADDR()

      function参数:一个cmake function可以采用两种类型的参数:
      (1).命名参数或关键字参数(named or keyword arguments):是必须的,如果未提供将触发error。参数名称之间不需要逗号。示例代码段如下:

message("2.命名参数是必须的,如果未提供将触发error.参数名称之间不需要逗号")
function(addr csdn github)
    message("csdn addr: $csdn")
    message("github addr: $github")
endfunction()

addr("https://blog.csdn.net/fengbingchun" "https://github.com/fengbingchun")

      (2).可选参数(optional arguments):可以使用一些预定义的变量访问可选参数,示例代码段如下:
      ARGC:参数总数(命名参数+可选参数)。
      ARGV:包含命名参数和可选参数的变量列表
      ARGN:仅包含可选参数的变量列表

message("3.可以使用一些预定义的变量访问可选参数:ARGC, ARGV, ARGN")
function(name_list name1 name2)
    message("argument count: $ARGC")
    message("all arguments: $ARGV")
    message("optional arguments: $ARGN")
endfunction()

name_list(Jack Kate Jony Tom)
# only named arguments
name_list(Jack Kate)

      除了这三个变量之外,cmake还提供了ARGV0,ARGV1,ARGV2,...,这将具有传入参数的实际值。引用ARGC之外的ARGV#参数将导致未定义的行为。示例代码段如下:

message("4.cmake还提供了ARGV0,ARGV1,ARGV2,...,这将具有传入参数的实际值.引用ARGC之外的ARGV#参数将导致未定义的行为")
function(programming_language name1 name2)
    if(DEFINED ARGV0)
        message("ARGV0: $ARGV0")
    else()
        message("ARGV0 not defined")
    endif()

    math(EXPR last_index "$ARGC-1")
    foreach(index RANGE 0 $last_index)
        message("argument at index $index: $ARGV$index")
    endforeach()

    # 通常,使用变量访问命名参数,使用ARGN访问可选参数
    message("name1: $name1")
    message("name2: $name2")

    foreach(arg IN LISTS ARGN)
        message("optional name: $arg")
    endforeach()
endfunction()

programming_language(C++ Python Go Matlab)

      通常,使用变量访问命名参数,使用ARGN访问可选参数
      使用DEFINED关键字,你可以检查是否定义了给定的变量、缓存变量或环境变量。变量的值无关紧要。

      变量作用域(variable scope):在function内部修改的变量在function外部将无法访问。function不返回任何值
      cmake提供了关键字PARENT_SCOPE以在父作用域(parent scope)中设置变量。示例代码段如下:

message("5.cmake提供了关键字PARENT_SCOPE以在父作用域(parent scope)中设置变量.你可以将变量名称作为function参数发送.该function将在父作用域中设置变量")
set(development_language "C++")

function(set_development_language name)
    set($name "Python" PARENT_SCOPE)
endfunction()

message("development language: $development_language")
set_development_language(development_language)
message("development language: $development_language")

      你可以将变量名称作为function参数发送。该function将在父作用域中设置变量。

      return()命令:可以在function里调用return()命令提前退出function。示例代码段如下:

message("6.可以在function里调用return()命令提前退出function")
function(early_return)
    message("csdn")
    return()
    message("github") # it will not be printed
endfunction()

early_return()

      如果定义了一个已经存在的function时,将覆盖上一个function。可以使用"_"加function name的方式访问上一个function。如果再次重新定义同一个function,"_"加function name版本将调用先前定义的function。原始function将永远不可用。如果开发人员在编写function时不知道该function已用于某些cmake库function,则原始function有可能永远隐藏。

message("7.如果定义了一个已经存在的function时,将覆盖上一个function.可以使用\\"_\\"加function name的方式访问上一个function.如果再次重新定义同一个function,\\"_\\"加function name版本将调用先前定义的function.原始function将永远不可用")
function(csdn_addr)
    message("csdn addr: https://github.com/fengbingchun")
endfunction()

csdn_addr() # csdn addr: https://github.com/fengbingchun
_csdn_addr() # csdn addr: https://blog.csdn.net/fengbingchun

function(csdn_addr)
    message("csdn addr: https://www.baidu.com/")
endfunction()

csdn_addr() # csdn addr: https://www.baidu.com/
_csdn_addr() # csdn addr: https://github.com/fengbingchun

      也可通过cmake的预定义的命令cmake_parse_arguments来解析function的参数。

      function和macro的不同
      (1).变量作用域不同:function会引入新的作用域,而macro不会,即,默认,function内新增的变量外部不可见;而macro内新增的变量外部可见。
      (2).cmake提供的变量ARGV0,ARGV1,ARGV2,...,在function中有效,在macro中无效。在某些情况下,macro中的ARGN也不会生效,在macro中,它们是字符串替换,就像C预处理器对macro所做的那样。
      (3).function内调用return()命令是退出当前function;而macro内调用return()是退出当前cmake文件。建议在macro中完全避免使用return()。
      (4).CMAKE_CURRENT_FUNCTION, CMAKE_CURRENT_FUNCTION_LIST_DIR, CMAKE_CURRENT_FUNCTION_LIST_FILE, CMAKE_CURRENT_FUNCTION_LIST_LIN这些变量应用于function中而不是macro中。

     CMake中macro的使用:https://blog.csdn.net/fengbingchun/article/details/127145153

     测试代码组织结构如下:

     build.sh内容如下:

#! /bin/bash

# supported input parameters
params=(function macro)

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)

if(TEST_CMAKE_FEATURE STREQUAL "function")
	include(test_function.cmake)
elseif(TEST_CMAKE_FEATURE STREQUAL "macro")
	include(test_macro.cmake)
endif()

message("==== test finish ====")

     test_function.cmake内容:为上面所示代码段

     执行结果如下图所示:

      GitHubhttps://github.com/fengbingchun/Linux_Code_Test

以上是关于CMake中function的使用的主要内容,如果未能解决你的问题,请参考以下文章

CMake中macro的使用

CMake中macro的使用

使用cmake为vs2013配置cuda项目出现“invalid device function”错误

cmake函数參数解析

使用 CMake 时如何在 Emscripten 中导出 C 函数

CMake中cmake_parse_arguments的使用