[cmake] CMake의 함수 대 매크로

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

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

그리고 약 function

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

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



답변

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

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 범위 제어를 원하면 함수 명령을 확인해야합니다.


답변

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


답변

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

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

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

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


답변

사이 또 다른 주목할만한 차이 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


답변

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


답변