はじめに
みなさん、こんにちは。今回は、変数のスコープについて書いていきます。
スコープ
実は、CMakeの変数にはスコープが存在し、スコープには親子関係があります。 新しいスコープを作るとき、現在のスコープのすべての変数を、作成したスコープにコピーしてきます。つまり、スコープ内で作成した変数のほかに親スコープで生成した変数も存在するということです。ただし、コピーなので、親スコープ由来の変数を変更しても、親スコープには影響しません。また、スコープを抜けるとスコープ内の変数はすべて破棄されます。このスコープには以下の種類があります。
Directory Scope
ディレクトリごとにひとつ存在するスコープです。このスコープはadd_subdirectory()
コマンドが呼び出されたときに作成されます。
set(value1 1)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:
add_subdirectory(subdir)
message("value1: ${value1}") # value1: 1
message("value2: ${value2}") # value2:
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: コマンド定義』です。