CMake - 변수

mohadang·2022년 8월 7일
0

CMake

목록 보기
5/24
post-thumbnail

cmake 변수 특징

  • 모든 변수는 문자열 타입이다.
  • 변수는 대소문자를 구분한다.
  • 리스트형 변수 역시 문자열이며 다만 ; 로 구분된 것 뿐이다.

변수는 어떤 값도 포함 가능하다

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set("abc" "123") # 변수 이름 : 'abc', 값 : '123'
set("ab c" "456") # 변수 이름 : 'ab c', 값 : '456'
set("ab?c" "789") # 변수 이름 : 'ab?c', 값 : '789'
set("/usr/bin/bash" "987") # 변수 이름 : '/usr/bin/bash', 값 : '987'
set("C:\\Program Files\\" "654") # 변수 이름 : 'C:\Program Files\', 값 : '654'
set(" " "321") # 변수 이름 : ' ', 값 : '321'

function(print_name varname) # 함수
  message("Variable name: '${varname}', value: '${${varname}}'")
endfunction()

print_name("abc")   
print_name("ab c")    
print_name("ab?c")    
print_name("/usr/bin/bash")   
print_name("C:\\Program Files\\")   
print_name(" ")   

역참조(Dereferencing)

  • 역참조란 현재 변수가 가지고 있는 값을 출력 하는것이다.
cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(root "real val")
message(root) # root
message(${root}) # real val
  • 역참조는 중첩도 가능하다
cmake_minimum_required(VERSION 2.8)
project(foo NONE)

# 함수 인자로 들어온 arg1에 대해 역참조에 역참조를 하면 결국 
# real val 라는 원래 변수를 참조 가능하다
function(test arg1) 
  # ${arg1} => root
  # ${root} => real val
  message(${${arg1}}) # real val
endfunction()

set(root "real val")
test(root)
  • ${name}을 사용하면 역참조를 하여 변수명을 만들 수 있다.
cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(a "xyz") # a= xyz
set(b "${a}_321") # b = xyz_321, ${a} 참조를 하여 변수값 생성
set(${a}_1 "456") # xyz_1 = 456, ${a} 참조를 하여 변수명 생성
set(variable_${a} "${a} + ${b} + 155") # variable_xyz = 'xyz + xyz_321 + 155'

message("b: '${b}'")
message("xyz_1: '${xyz_1}'")
message("variable_xyz: '${variable_xyz}'")

중첩

  • ${name}는 중첩하여 사용 가능하다
message("${lang} + build type ${build_type}: ${CMAKE_${lang}_FLAGS_${build_type}}")

""로 묶은 변수값

  • ""로 몪으면 중간에 공백을 포함한 변수값 사용 가능
  • ""로 묶으면 리스트형 변수값 사용 가능
cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(a "Quoted argument") # 공백을 포함한 변수값
set(b x-"Unquoted argument") # x-가 연결되서 중간의 " 까지 변수값의 일부가 되었다
set(c "a;b;c") # 리스트형 변수값

message("a = '${a}'") # 'Quoted argument'
message("b = '${b}'") #'x-"Unquoted argument"'

message("c =")
foreach(x ${c}) # 리스트형 변수 출력
  message("  '${x}'")
endforeach()

#[[
c =
   'a'
   'b'
   'c'
]]

변수 타입

  • 변수 타입은 모두 문자열이지만 TRUE, FALSE, YES, NO, ON, OFF값을 사용하여 로직 처리가 가능 하다
  • EXISTS, TARGET 같은 키워드와 조합하여 사용하면 파일이나 출력 파일이 있는지 없는지 검사 가능
cmake_minimum_required(VERSION 2.8)
project(foo)

set(condition_a "TRUE")
set(condition_b "NO")

set(path_to_this "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt")

set(target_name foo)
add_library("${target_name}" foo.cpp)

if(condition_a)
  message("condition_a") # 출력
else()
  message("NOT condition_a")
endif()

if(condition_b)
  message("condition_b")
else()
  message("NOT condition_b") # 출력
endif()

if(EXISTS "${path_to_this}")
  # File exists: /.../usage-of-variables/types-of-variable/CMakeLists.txt
  message("File exists: ${path_to_this}")   
else()
  message("File not exist: ${path_to_this}")
endif()

if(TARGET "${target_name}")
  message("Target exists: ${target_name}") # 출력
else()
  message("Target not exist: ${target_name}")
endif()

리스트 변수

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

# 리스트형 변수를 선언하는 다양한 방법
set(l0 a b c) # a;b;c
set(l1 a;b;c) # a;b;c
set(l2 "a b" "c") #a b;c <-- a_공백_b를 하나의 변수로 인식
set(l3 "a;b;c") # a;b;c
set(l4 a "b;c") # a;b;c

message("l0 = 'a' + 'b' + 'c' = ${l0}")
message("l1 = 'a;b;c' = ${l1}")
message("l2 = 'a b' + 'c' = ${l2}")
message("l3 = \"'a;b;c'\" = ${l3}")
message("l4 = 'a' + 'b;c' = ${l4}")

# 문자열이 연속으로 이어져 있으면 문자열을 연결, C/C++과 같음
message("print by message: " "a" "b" "c") # abc

# " 로 묶이지 않아서 l3 변수를 배열로 해석하여 출력
message("print by message: " ${l3}) # abc

리스트 항목 열거

foreach(x ${c})
  message("  '${x}'")
endforeach()

리스트 추가

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

function(add_element list_name element_name)
  message("Add '${${element_name}}' to list '${${list_name}}'")
  list(APPEND "${list_name}" "${${element_name}}") # 리스트 추가
  list(LENGTH "${list_name}" list_len)
  message("Result: '${${list_name}}' (length = ${list_len})\n")
  set("${list_name}" "${${list_name}}" PARENT_SCOPE)
endfunction()

# non-empty 요소를 non-empty 리스트에 추가
set(mylist "a;b")
set(element "c")
foreach(i RANGE 3) # 0 ~ 3
  add_element(mylist element)
    # Result: 'a;b;c' (length = 3)
    # Result: 'a;b;c;c' (length = 4)
    # Result: 'a;b;c;c;c' (length = 5)
    # Result: 'a;b;c;c;c;c' (length = 6)      
endforeach()

# empty 요소를 non-empty 리스트에 추가
set(mylist "a;b")
set(element "")
foreach(i RANGE 3) # 0 ~ 3
  add_element(mylist element) # 비어 있는 값을 넣어도 길이는 증가
    # Result: 'a;b;' (length = 3)
    # Result: 'a;b;;' (length = 4)
    # Result: 'a;b;;;' (length = 5)
    # Result: 'a;b;;;;' (length = 6)    
endforeach()

# empty 요소를 empty 리스트에 추가
set(mylist "")
set(element "")
foreach(i RANGE 3) # 0 ~ 3
  add_element(mylist element) # 리스트 자체가 비어 있는 상태에서는 계속 빈 리스트
    # Result: '' (length = 0)
    # Result: '' (length = 0)
    # Result: '' (length = 0)
    # Result: '' (length = 0)    
endforeach()

리스트 길이, 인덱싱 제거

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(l0 "a;b;c")
set(l1 "a" "b;c")
set(l2 "a" "b c")

list(LENGTH l0 l0_len)
list(LENGTH l1 l1_len)
list(LENGTH l2 l2_len)

message("length of '${l0}' (l0) = ${l0_len}") # 3   
message("length of '${l1}' (l1) = ${l1_len}") # 3
message("length of '${l2}' (l2) = ${l2_len}") # 2

list(GET l1 2 l1_2) # 2번 인덱스 값 l1_2 변수에 가져옴
message("l1[2] = ${l1_2}") # c

message("Removing first item from l1 list: '${l1}'") # 'a;b;c'
list(REMOVE_AT l1 0) # 0번 인덱스 값 제거
message("l1 = '${l1}'") # 'b;c'

권고

  • 현재 스코프에서만 사용하고 짧게 사용하면 짧은 소문자 변수를 사용 (a, i, mylist, objects, etc.)
  • 모든 스코프에서 사용하고 길게 사용하면 긴 대분자 변수 사용 (FOO_FEATURE, BOO_ENABLE_SOMETHING, etc.)
# bad
function(foo_something)
  set(FOO_SOMETHING_A 1)
  # ...
endfunction()
Using just a will be fine:
# good
function(foo_something)
  set(a 1)
  # ...
endfunction()
- bad
# Foo/CMakeLists.txt
message("Files:")
foreach(FOO_FILES_ITERATOR ${files})
  message("  ${FOO_FILES_ITERATOR}")
endforeach()
- good
# Foo/CMakeLists.txt
message("Files:")
foreach(x ${files})
  message("  ${x}")
endforeach()
- C++ 문법 철학과도 맞는다
// pretty bad idea
#define a

// good one
#define MYPROJECT_ENABLE_A

// does it make sense?
for (int array_iterator = 0; array_iterator < array.size(); ++array_iterator) {
  // use 'array_iterator'
}

// good one
for (int i = 0; i < array.size(); ++i) {
  // use 'i'
}
profile
mohadang

0개의 댓글