Programing

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

crosscheck 2020. 7. 2. 07:53
반응형

변수를 설정하고 사용하는 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 ...)구문을 선호합니다 .

Variable Pitfalls and "How to debug variable changes?"

To avoid pitfalls you should know the following about variables:

  • Local variables do hide cached variables if both have the same name
  • The find_... commands - if successful - do write their results as cached variables "so that no call will search again"
  • Lists in CMake are just strings with semicolons delimiters and therefore the quotation-marks are important
    • set(MyVar a b c) is "a;b;c" and set(MyVar "a b c") is "a b c"
    • The recommendation is that you always use quotation marks with the one exception when you want to give a list as list
    • Generally prefer the list() command for handling lists
  • The whole scope issue described above. Especially it's recommended to use functions() instead of macros() because you don't want your local variables to show up in the parent scope.
  • A lot of variables used by CMake are set with the project() and enable_language() calls. So it could get important to set some variables before those commands are used.
  • Environment variables may differ from where CMake generated the make environment and when the the make files are put to use.
    • A change in an environment variable does not re-trigger the generation process.
    • Especially a generated IDE environment may differ from your command line, so it's recommended to transfer your environment variables into something that is cached.

Sometimes only debugging variables helps. The following may help you:

  • Simply use old printf debugging style by using the message() command. There also some ready to use modules shipped with CMake itself: CMakePrintHelpers.cmake, CMakePrintSystemInformation.cmake
  • Look into CMakeCache.txt file in your binary output directory. This file is even generated if the actual generation of your make environment fails.
  • Use variable_watch() to see where your variables are read/written/removed.
  • Look into the directory properties CACHE_VARIABLES and VARIABLES
  • Call cmake --trace ... to see the CMake's complete parsing process. That's sort of the last reserve, because it generates a lot of output.

Special Syntax

  • Environment Variables
    • You can can read $ENV{...} and write set(ENV{...} ...) environment variables
  • Generator Expressions
    • Generator expressions $<...> are only evaluated when CMake's generator writes the make environment (it comparison to normal variables that are replaced "in-place" by the parser)
    • Very handy e.g. in compiler/linker command lines and in multi-configuration environments
  • References
    • With ${${...}} you can give variable names in a variable and reference its content.
    • Often used when giving a variable name as function/macro parameter.
  • Constant Values (see if() command)
    • With if(MyVariable) you can directly check a variable for true/false (no need here for the enclosing ${...})
    • True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number.
    • False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in the suffix -NOTFOUND.
    • This syntax is often use for something like if(MSVC), but it can be confusing for someone who does not know this syntax shortcut.
  • Recursive substitutions
    • You can construct variable names using variables. After CMake has substituted the variables, it will check again if the result is a variable itself. This is very powerful feature used in CMake itself e.g. as sort of a template set(CMAKE_${lang}_COMPILER ...)
    • But be aware this can give you a headache in if() commands. Here is an example where CMAKE_CXX_COMPILER_ID is "MSVC" and MSVC is "1":
      • if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") is true, because it evaluates to if("1" STREQUAL "1")
      • if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") is false, because it evaluates to if("MSVC" STREQUAL "1")
      • So the best solution here would be - see above - to directly check for if(MSVC)
    • The good news is that this was fixed in CMake 3.1 with the introduction of policy CMP0054. I would recommend to always set cmake_policy(SET CMP0054 NEW) to "only interpret if() arguments as variables or keywords when unquoted."
  • The option() command
    • Mainly just cached strings that only can be ON or OFF and they allow some special handling like e.g. dependencies
    • But be aware, don't mistake the option with the set command. The value given to option is really only the "initial value" (transferred once to the cache during the first configuration step) and is afterwards meant to be changed by the user through CMake's GUI.

References


Here are a couple basic examples to get started quick and dirty.

One item variable

Set variable:

SET(INSTALL_ETC_DIR "etc")

Use variable:

SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")

Multi-item variable (ie. list)

Set variable:

SET(PROGRAM_SRCS
        program.c
        program_utils.c
        a_lib.c
        b_lib.c
        config.c
        )

Use variable:

add_executable(program "${PROGRAM_SRCS}")

CMake docs on variables


$ENV{FOO} for usage, where FOO is being picked up from the environment variable. otherwise use as ${FOO}, where FOO is some other variable. For setting, SET(FOO "foo") would be used in CMake.

참고URL : https://stackoverflow.com/questions/31037882/whats-the-cmake-syntax-to-set-and-use-variables

반응형