[cmake] 변수를 설정하고 사용하는 CMake 구문은 무엇입니까?

다음에 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})

설명서

범위 또는 “변수에 어떤 값이 있습니까?”

먼저 “정상 변수”와 그 범위에 대해 알아야 할 사항이 있습니다.

  • 일반 변수는에 볼 수 있습니다 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_VARIABLESVARIABLES를 살펴보십시오.
  • 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_IDis "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()변수 또는 키워드로 해석하도록 설정 하는 것이 좋습니다 .
  • option()명령
    • 주로 ON또는 캐시 될 수 있고 의존성OFF 과 같은 특별한 처리를 허용 하는 캐시 된 문자열
    • 그러나 인식 의 실수를하지 않는 optionset명령. 주어진 값 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}")

변수에 대한 CMake 문서


답변

$ENV{FOO}FOO환경 변수에서 사용되는 곳 . 그렇지 않으면로 사용 하십시오. ${FOO}여기 FOO에는 다른 변수가 있습니다. 설정 SET(FOO "foo")에 CMake에서 사용됩니다.


답변