Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
11
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

CMake: 変数のスコープ

はじめに

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

スコープ

実は、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: コマンド定義』です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
11
Help us understand the problem. What are the problem?