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시에 응답 매크로 확장은 정말 내 눈을 열어!
또한 아래 자습서에는 변수 범위 개념을 이해하는 데 도움이되는 몇 가지 구체적인 예제가 포함되어 있습니다.
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