변수를 설정하고 사용하는 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})
설명서
- 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 ...)
구문을 선호합니다 .
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"
andset(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 ofmacros()
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()
andenable_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 themessage()
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 writeset(ENV{...} ...)
environment variables
- You can can read
- 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
- Generator expressions
- 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.
- With
- 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.
- With
- 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 whereCMAKE_CXX_COMPILER_ID
is"MSVC"
andMSVC
is"1"
:if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
is true, because it evaluates toif("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
is false, because it evaluates toif("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 interpretif()
arguments as variables or keywords when unquoted."
- 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
- The
option()
command- Mainly just cached strings that only can be
ON
orOFF
and they allow some special handling like e.g. dependencies - But be aware, don't mistake the
option
with theset
command. The value given tooption
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.
- Mainly just cached strings that only can be
References
- How is CMake used?
- cmake, lost in the concept of global variables (and PARENT_SCOPE or add_subdirectory alternatives)
- Looping over a string list
- How to store CMake build settings
- CMake compare to empty string with STREQUAL failed
- When should I quote variables?
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}")
$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
'Programing' 카테고리의 다른 글
REST API-DTO? (0) | 2020.07.02 |
---|---|
$ 적용 진행 중 오류 (0) | 2020.07.02 |
컨트롤러의 Hibernate / JPA에서 게으른 페치 된 항목을로드하는 방법 (0) | 2020.07.02 |
표준 정규화와 달리 softmax를 사용하는 이유는 무엇입니까? (0) | 2020.07.02 |
BigDecimal 세트 스케일 및 라운드 (0) | 2020.07.02 |