다음에 CMake를 사용할 때 나 자신에게 상기시켜줍니다. 그것은 고집하지 않으며 Google 결과는 좋지 않습니다.
CMake에서 변수를 설정하고 사용하는 구문은 무엇입니까?
답변
CMake 스크립트를 작성할 때 구문과 CMake에서 변수를 사용하는 방법에 대해 알아야 할 것이 많습니다.
구문
다음을 사용하는 문자열 set()
:
set(MyString "Some Text")
set(MyStringWithVar "Some other Text: ${MyString}")
set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")
또는과 string()
:
string(APPEND MyStringWithContent " ${MyString}")
를 사용하여 나열 set()
:
set(MyList "a" "b" "c")
set(MyList ${MyList} "d")
또는 더 나은 list()
:
list(APPEND MyList "a" "b" "c")
list(APPEND MyList "d")
파일 이름 목록 :
set(MySourcesList "File.name" "File with Space.name")
list(APPEND MySourcesList "File.name" "File with Space.name")
add_excutable(MyExeTarget ${MySourcesList})
설명서
- CMake / 언어 구문
- CMake : 변수 목록 문자열
- CMake : 유용한 변수
- CMake
set()
명령 - CMake
string()
명령 - CMake
list()
명령 - Cmake : 생성기 표현식
범위 또는 “변수에 어떤 값이 있습니까?”
먼저 “정상 변수”와 그 범위에 대해 알아야 할 사항이 있습니다.
- 일반 변수는에 볼 수 있습니다
CMakeLists.txt
그들이라는 설정 및 모든 있습니다에서가 (add_subdirectory()
,include()
,macro()
및function()
). add_subdirectory()
과function()
그들이 오픈까지 있기 때문에 자신의 범위를 명령은 특별하다.- 의미 변수는
set(...)
거기에만 표시되며 호출 된 범위 수준의 모든 일반 변수 (부모 범위)의 복사본을 만듭니다. - 따라서 하위 디렉토리 또는 함수에 있으면 다음을 사용하여 상위 범위의 기존 변수를 수정할 수 있습니다
set(... PARENT_SCOPE)
- 변수 이름을 함수 매개 변수로 전달하여 예를 들어 함수에서이를 사용할 수 있습니다. 될 예는
function(xyz _resultVar)
설정입니다set(${_resultVar} 1 PARENT_SCOPE)
- 의미 변수는
- 반면에 설정 한 모든 것
include()
또는macro()
스크립트는 변수가 호출되는 범위에서 변수를 직접 수정합니다.
두 번째로 “전역 변수 캐시”가 있습니다. 캐시에 대해 알아야 할 사항 :
- 주어진 이름의 정규 변수가 현재 범위에 정의되어 있지 않으면 CMake는 일치하는 캐시 항목을 찾습니다.
- 캐시 값은
CMakeCache.txt
이진 출력 디렉토리 의 파일에 저장됩니다 . -
캐시의 값 은 생성되기 전에 CMake의 GUI 응용 프로그램 에서 수정할 수 있습니다 . 따라서 정규 변수와 비교하여 a
type
와 a가docstring
있습니다. 나는 일반적으로 GUI를 사용하지 않으므로set(... CACHE INTERNAL "")
전역 및 지속 값을 설정 하는 데 사용 합니다.있습니다
INTERNAL
캐시 변수 유형을 의미 않는다FORCE
-
CMake 스크립트에서는
set(... CACHE ... FORCE)
구문 을 사용하는 경우 기존 캐시 항목 만 변경할 수 있습니다 . 이 동작은 일반적으로 캐시 항목 자체를 강제하지 않으므로 다른 값으로 미리 정의 할 수 있기 때문에 CMake 자체에 의해 사용됩니다. - 명령 줄을 사용하여 캐시에서 구문
cmake -D var:type=value
만으로cmake -D var=value
또는 항목으로 항목을 설정할 수 있습니다cmake -C CMakeInitialCache.cmake
. - 을 사용하여 캐시에서 항목을 설정 해제 할 수 있습니다
unset(... CACHE)
.
캐시는 전역 적이며 CMake 스크립트의 거의 모든 위치에 설정할 수 있습니다. 그러나 캐시 변수를 사용할 위치에 대해 두 번 생각하는 것이 좋습니다 (전역적이고 지속 가능합니다). 나는 일반적으로 비 구속 글로벌 변수를 정의하기 위해 set_property(GLOBAL PROPERTY ...)
and set_property(GLOBAL APPEND PROPERTY ...)
구문을 선호합니다 .
변수 함정 및 “변수 변경을 디버그하는 방법?”
함정을 피하려면 변수에 대해 다음을 알아야합니다.
- 로컬 변수는 모두 같은 이름을 가진 경우 캐시 된 변수를 숨 깁니다
find_...
성공하면 – – 명령 캐시 변수로 결과를 기록 할 “그래서 전화가 다시 검색되지 것”- CMake의 목록은 세미콜론 구분 기호가있는 문자열 이므로 따옴표가 중요합니다.
set(MyVar a b c)
이다"a;b;c"
와set(MyVar "a b c")
이다"a b c"
- 목록으로 목록을 제공하려는 경우 한 가지 예외를 제외하고 항상 따옴표를 사용하는 것이 좋습니다.
- 일반적으로
list()
목록 처리 명령을 선호 합니다
- 위에서 설명한 전체 범위 문제. 특히 지역 변수가 부모 범위에 표시되지 않도록하기
functions()
보다는 대신 사용 하는 것이 좋습니다macros()
. - CMake에서 사용하는 많은 변수는
project()
및enable_language()
호출 로 설정됩니다 . 따라서 해당 명령을 사용하기 전에 일부 변수를 설정하는 것이 중요 할 수 있습니다. - 환경 변수는 CMake가 make 환경을 생성 한 위치 및 make 파일을 사용할 때와 다를 수 있습니다.
- 환경 변수의 변경은 생성 프로세스를 다시 트리거하지 않습니다.
- 특히 생성 된 IDE 환경은 명령 행과 다를 수 있으므로 환경 변수를 캐시 된 환경으로 전송하는 것이 좋습니다.
때로는 디버깅 변수 만 도움이됩니다. 다음이 도움이 될 수 있습니다.
- 명령
printf
을 사용하여 이전 디버깅 스타일을 사용하십시오message()
. CMake 자체와 함께 제공되는 모듈을 사용할 준비가되었습니다 : CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmake CMakeCache.txt
바이너리 출력 디렉토리에서 파일을 찾으십시오 . 이 파일은 실제 make 환경 생성에 실패한 경우에도 생성됩니다.- variable_watch () 를 사용 하여 변수를 읽거나 쓰거나 제거하는 위치를 봅니다.
- 디렉토리 특성 CACHE_VARIABLES 및 VARIABLES를 살펴보십시오.
cmake --trace ...
CMake의 전체 구문 분석 프로세스를 보려면 전화 하십시오. 그것은 많은 양의 출력을 생성하기 때문에 일종의 마지막 예약입니다.
특수 구문
- 환경 변수
- 환경 변수를 읽고
$ENV{...}
쓸 수 있습니다set(ENV{...} ...)
- 환경 변수를 읽고
- 생성기 표현식
- 생성기 표현식
$<...>
은 CMake 생성기가 작성 환경을 작성할 때만 평가됩니다 (구문 분석기로 “제자리에서”대체되는 일반 변수와 비교) - 컴파일러 / 링커 명령 줄 및 다중 구성 환경에서 매우 편리합니다.
- 생성기 표현식
- 참고 문헌
- 와 함께
${${...}}
변수에 변수 이름을 부여하고 그 내용을 참조 할 수 있습니다. - 함수 / 매크로 파라미터로 변수 이름을 지정할 때 자주 사용됩니다.
- 와 함께
- 상수 값 (
if()
명령 참조 )- 으로
if(MyVariable)
당신이 직접 참 / 거짓에 대한 변수 (둘러싸는 여기를 필요 없음을 확인하실 수 있습니다${...}
) - 진정한 상수 인 경우
1
,ON
,YES
,TRUE
,Y
, 또는 비 제로의 수입니다. - 거짓 상수 인 경우
0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
, 빈 문자열, 또는 접미사의 끝-NOTFOUND
. - 이 구문은 종종와 같은 용도로 사용
if(MSVC)
되지만이 구문 단축키를 모르는 사람에게는 혼동 될 수 있습니다.
- 으로
- 재귀 대체
- 변수를 사용하여 변수 이름을 구성 할 수 있습니다. CMake가 변수를 대체 한 후 결과가 변수 자체인지 다시 확인합니다. 이것은 CMake 자체에서 사용되는 매우 강력한 기능입니다. 예를 들어 일종의 템플릿
set(CMAKE_${lang}_COMPILER ...)
- 그러나 인식 이 당신에게 두통을 줄 수있는
if()
명령. 다음은CMAKE_CXX_COMPILER_ID
is"MSVC"
와 is의 예MSVC
입니다"1"
.if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
그것은 평가하기 때문에 사실이다if("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
그것이 평가되기 때문에 거짓이다if("MSVC" STREQUAL "1")
- 여기서 가장 좋은 해결책은 위를 참조하여 직접 확인하는 것입니다.
if(MSVC)
- 좋은 소식은 이것이 CMake 3.1에서 정책 CMP0054 의 도입으로 수정되었다는 것 입니다. 항상 인용 부호가없는 경우 인수
cmake_policy(SET CMP0054 NEW)
만if()
변수 또는 키워드로 해석하도록 설정 하는 것이 좋습니다 .
- 변수를 사용하여 변수 이름을 구성 할 수 있습니다. CMake가 변수를 대체 한 후 결과가 변수 자체인지 다시 확인합니다. 이것은 CMake 자체에서 사용되는 매우 강력한 기능입니다. 예를 들어 일종의 템플릿
option()
명령- 주로
ON
또는 캐시 될 수 있고 의존성OFF
과 같은 특별한 처리를 허용 하는 캐시 된 문자열 - 그러나 인식 의 실수를하지 않는
option
와set
명령. 주어진 값option
은 실제로는 “초기 값”(첫 번째 구성 단계에서 캐시로 한 번 전송 됨) 일 뿐이며 이후 CMake의 GUI를 통해 사용자가 변경하도록되어 있습니다 .
- 주로
참고 문헌
답변
다음은 빠르고 더러운 시작을위한 몇 가지 기본 예입니다.
하나의 항목 변수
변수 설정 :
SET(INSTALL_ETC_DIR "etc")
변수 사용 :
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
다중 항목 변수 (예 : 목록)
변수 설정 :
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
변수 사용 :
add_executable(program "${PROGRAM_SRCS}")
답변
$ENV{FOO}
FOO
환경 변수에서 사용되는 곳 . 그렇지 않으면로 사용 하십시오. ${FOO}
여기 FOO
에는 다른 변수가 있습니다. 설정 SET(FOO "foo")
에 CMake에서 사용됩니다.