CMake의 함수 대 매크로


89

CMake 2.8.12의 공식 문서 에 대해 말한다macro

호출 될 때 매크로에 기록 된 명령은 먼저 형식 매개 변수 ($ {arg1})를 전달 된 인수로 대체하여 수정 한 다음 일반 명령으로 호출됩니다.

그리고 약 function

호출 될 때 함수에 기록 된 명령은 먼저 형식 매개 변수 ($ {arg1})를 전달 된 인수로 대체하여 수정 한 다음 일반 명령으로 호출합니다.

분명히 두 개의 따옴표가 거의 동일하지만 혼란 스럽습니다. 매크로처럼 함수를 호출 할 때 처음에 매개 변수를 대체합니까?


8
사이에 적어도 하나의 다른 중요한,이기는하지만 아주 분명한 차이가 functionmacro의 의미 : return()A의 사용했을 때 macro, 매크로에서하지만, 호출 함수에서 반환하지 않습니다는.
Joachim W

1
또 다른 중요한 점은 함수가 단 하나 인 경우 매크로는 인수에 대해 2 단계 확장 단계를 갖는다는 것입니다. 이 매크로와 함수를 만들고 ${ARGV}내부에서 macro(my_macro), function(my_func). 그리고 그들을 사용 : set(a 123), my_macro("\\\${a}\\\\;\\\;;"), my_func(\${a}\\;\;;). 당신은 당신이 모든 이중 탈출해야 발견 할 것이다 $, \ , ;제대로 중첩 된 명령에 변화가 전체 문자열을 전달합니다. 이것은 cmake 3.14+.
Andry

답변:


93

아래에 샘플 코드를 작성했습니다.

set(var "ABC")

macro(Moo arg)
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endmacro()
message("=== Call macro ===")
Moo(${var})

function(Foo arg)
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endfunction()
message("=== Call function ===")
Foo(${var})

출력은 다음과 같습니다.

=== Call macro ===
arg = ABC
# After change the value of arg.
arg = ABC
=== Call function ===
arg = ABC
# After change the value of arg.
arg = abc

보인다 그래서 arg값 할당 var호출 할 때를 Foo${arg}로 대체 단지 문자열 ${var}호출 할 때가 Moo.

따라서 공식 문서에서도 다음 같이 말했지만 위의 두 인용문이 하나를 혼동하기가 매우 쉽다고 생각합니다 .

매크로에 대한 매개 변수 와 ARGN과 같은 은 일반적인 CMake 의미에서 변수가 아닙니다. 그것들은 C 전처리 기가 매크로를 사용하는 것과 매우 유사한 문자열 대체입니다. 진정한 CMake 변수 및 / 또는 더 나은 CMake 범위 제어를 원하면 함수 명령을 확인해야합니다.


나는 그것을 잊었다. 그러나 나는 그럴지도 모른다고 생각한다.
Yantao시에

2
@robert 귀하의 질문에 즉시 답변하는 것은 헬프 센터에 따라 허용됩니다 (특히 다른 사람들에게 일반적으로 관심이있는 좋고 중복되지 않는 질문 인 경우). 이것은 SO가 더 나은 지식 기반이되도록 돕는 것입니다. 해당 도움말 센터 항목에 링크 된 블로그 게시물을 읽었습니까? stackoverflow.blog/2011/07/01/…
Emile Cormier

1
@robert 나는 SO의 창립자 가이 관행에 대해 생각하는 것을 전달하고 있습니다. 그에게 가져 가라. ;-)
Emile Cormier

2
이 같은 예제를 실행하면 cmake --trace-expand계몽

1
각 호출 후에 다음 명령을 추가하는 것을 고려하십시오. message("# arg in main scope = '${arg}'")+ 매크로 앞에 함수 호출.
MarcH

34

즉, 함수는 새 변수 범위 (생성 및 변경된 변수는 함수에만 존재)를 푸시하고 팝하지만 매크로는 그렇지 않습니다. 그러나 명령 의 PARENT_SCOPE매개 변수를 사용하여 함수 기본 동작을 재정의 할 수 있습니다 set.


8

인용 한 cmake 문서는 너무 오해의 소지가있어서 기본적으로 잘못되었습니다. 다음과 같이 명확히 / 수정되어야합니다.

  • 매크로 : 호출 될 때 매크로에 기록 된 명령은 먼저 형식 매개 변수 ($ {arg1})를 전달 된 인수로 대체하여 실행되기 전에 모두 수정 됩니다.

cmake --trace-expand 정확히 무슨 일이 일어나는지 보여줍니다.

cmake 3.13.3 문서는 이와 관련하여 2.8.12와 비교하여 변경되지 않았습니다.


3

사이 또 다른 주목할만한 차이 function()macro()의 동작입니다 return().

return ()cmake 문서에서 :

함수와 달리 매크로는 제자리에서 확장되므로 return ()을 처리 할 수 ​​없습니다.

따라서 제자리에서 확장 macro()되었으므로 호출자로부터 반환됩니다. 함수에있는 동안function()

예:

macro(my_macro)
    return()
endmacro()

function(my_function)
    return()
endfunction()

my_function()
message(hello) # is printed
my_macro()
message(hi) # is not printed

2

Yantao시에 응답 매크로 확장은 정말 내 눈을 열어!

또한 아래 자습서에는 변수 범위 개념을 이해하는 데 도움이되는 몇 가지 구체적인 예제가 포함되어 있습니다.

15 분 내에 Learn cmake에서 인용 :

CMake에서 function/ endfunction명령 쌍 을 사용하여 함수를 정의 할 수 있습니다. 다음은 인수의 숫자 값을 두 배로 늘린 다음 결과를 인쇄하는 것입니다.

function(doubleIt VALUE)
    math(EXPR RESULT "${VALUE} * 2")
    message("${RESULT}")
endfunction()

doubleIt("4")                           # Prints: 8

함수는 자체 범위에서 실행됩니다. 함수에 정의 된 변수는 호출자의 범위를 오염시키지 않습니다. 값을 반환하려면 변수 이름을 함수에 전달한 다음 set특수 인수를 사용 하여 명령 을 호출 할 수 있습니다 PARENT_SCOPE.

function(doubleIt VARNAME VALUE)
    math(EXPR RESULT "${VALUE} * 2")
    set(${VARNAME} "${RESULT}" PARENT_SCOPE)    # Set the named variable in caller's scope
endfunction()

doubleIt(RESULT "4")                    # Tell the function to set the variable named RESULT
message("${RESULT}")                    # Prints: 8

마찬가지로 macro/ endmacro명령 쌍은 매크로를 정의합니다. 함수와 달리 매크로는 호출자와 동일한 범위에서 실행됩니다. 따라서 매크로 내부에 정의 된 모든 변수는 호출자의 범위에 설정됩니다. 이전 함수를 다음으로 바꿀 수 있습니다.

macro(doubleIt VARNAME VALUE)
    math(EXPR ${VARNAME} "${VALUE} * 2")        # Set the named variable in caller's scope
endmacro()

doubleIt(RESULT "4")                    # Tell the macro to set the variable named RESULT
message("${RESULT}")                    # Prints: 8

함수와 매크로 모두 임의 개수의 인수를 허용합니다. 이름이 지정되지 않은 인수는라는 특수 변수를 통해 함수에 목록으로 노출됩니다 ARGN.

다음은 수신하는 모든 인수를 두 배로 늘리고 각 인수를 별도의 행에 인쇄하는 함수입니다.

function(doubleEach)
    foreach(ARG ${ARGN})                # Iterate over each argument
        math(EXPR N "${ARG} * 2")       # Double ARG's numeric value; store result in N
        message("${N}")                 # Print N
    endforeach()
endfunction()

doubleEach(5 6 7 8)                     # Prints 10, 12, 14, 16 on separate lines
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.