LoginSignup
15
11

More than 5 years have passed since last update.

はじめに

みなさん、こんにちは。今回は、変数のスコープについて書いていきます。

スコープ

実は、CMakeの変数にはスコープが存在し、スコープには親子関係があります。 新しいスコープを作るとき、現在のスコープのすべての変数を、作成したスコープにコピーしてきます。つまり、スコープ内で作成した変数のほかに親スコープで生成した変数も存在するということです。ただし、コピーなので、親スコープ由来の変数を変更しても、親スコープには影響しません。また、スコープを抜けるとスコープ内の変数はすべて破棄されます。このスコープには以下の種類があります。

Directory Scope

ディレクトリごとにひとつ存在するスコープです。このスコープはadd_subdirectory()コマンドが呼び出されたときに作成されます。

CMakeLists.txt
set(value1 1)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:
add_subdirectory(subdir)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:
subdir/CMakeLists.txt
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:
set(value1 2)
set(value2 2)
message("value1: ${value1}") # value1: 2
message("value2: ${value2}") # value2: 2

Function Scope

コマンドを呼び出すときに生成されるスコープです。つまり呼び出す文脈によって、引き継がれる変数が異なります。

function(func1)
  message("value1: ${value1}")
  message("value2: ${value2}")
  set(value1 2)
  set(value2 2)
  message("value1: ${value1}")
  message("value2: ${value2}")
endfunction()

function(func2)
  set(value1 3)
  set(value2 3)
  func1()
endfunction()

set(value1 1)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:

func1() #[[
  value1: 1
  value2: 
  value1: 2
  value2: 2
]]
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:

func2() #[[
  value1: 3
  value2: 3
  value1: 2
  value2: 2
]]
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:

Foreach Scope

このスコープはforeach()コマンドが評価された時に生成されるスコープで、ループを抜けたときに破棄されます。前述した2つのスコープとはだいぶ異なっていて、ループ変数以外は親スコープのままです。また、ループ変数と同名の変数が親スコープに存在していたときは、親スコープの変数はループを抜けるまで隠蔽されます。

set(value1 1)
set(value2 1)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2: 1

foreach(value1 IN ITEMS a;b;c)
  message("value1: ${value1}")
  message("value2: ${value2}")
  set(value1 "${value1}'")
  set(value2 "${value2}'")
  message("value1: ${value1}")
  message("value2: ${value2}")
  message("")
endforeach() #[[
  value1: a
  value2: 1
  value1: a'
  value2: 1'

  value1: b
  value2: 1'
  value1: b'
  value2: 1''

  value1: c
  value2: 1''
  value1: c'
  value2: 1'''
]]

message("value1: ${value1}") # 1
message("value2: ${value2}") # 1'''

親スコープの変数を操作

上記で、親スコープ由来の変数を操作しても親スコープには影響をあたえないと述べました。しかし、コマンドの戻り値を呼び出し元の変数に代入するときなど、親スコープの変数を操作したいときがあります。この場合は、set()コマンドのPARENT_SCOPEオプションを付与することで、これが可能となります。

function(func output_variable)
  set(${output_variable} 1 PARENT_SCOPE)
endfunction()

message("result: ${result}") # result: 
func(result)
message("result: ${result}") # result: 1

おわりに

以上、変数のスコープでした。add_subdirectory()コマンドやfunction()で定義したコマンドを多用している場合は、思わぬ変数を受け継ついでいる可能性があるので、十分に注意する必要があります。

明日は、mrk_21 さんの『CMake: コマンド定義』です。

15
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11