【CMake入門・上級編(14)】CMakeの変数のスコープ(コード付き)

        C 言語と同様に、cmake にも変数にスコープという概念があり、この記事では cmake における変数のスコープについて説明します。

        関数スコープの場合、変数 var が関数内の set を通じて現在の関数スコープにバインドされている場合、このスコープの外に同じ名前の変数 var がある場合、変数 var はこのスコープの外の関数スコープ内でのみ有効です。の場合、ドメイン外の同じ名前を持つ変数 var が使用されます。func1() は内部で func2() を呼び出します。入れ子の関数 func2() も変数 var を参照する場合、変数 var は func1 内で定義された変数である必要があります。 (), if any ; func1() 内にバインドされた変数 var がない場合は、func1() のスコープ外で定義された変数 var を使用して順番に外側に向かって検索します。

        上記の説明は理解しにくいかもしれませんが、いくつかの例を通して関数のスコープを見てみましょう。

        ①. 関数が関数の外で定義した変数を内部的に参照している

        サンプルコードは次のとおりです。

# 函数 xyz
function(xyz)
    message(${ABC}) #引用变量 ABC
endfunction()

set(ABC "Hello World") #定义变量 ABC

xyz() # 调用函数

        ABC は関数の外で定義された変数で、関数 xyz で参照され、出力される情報は次のとおりです。

         したがって、関数の外で定義された変数は関数内で参照できることがわかります。

        ②. 関数内で定義した変数が外部参照可能かどうか

# 函数 xyz
function(xyz)
    set(ABC "Hello World")#定义变量 ABC
endfunction()

xyz() # 调用函数

if(DEFINED ABC)
    message("true")
    message("${ABC}") #引用函数内定义的变量 ABC
else()
    message("false")
endif()

        変数ABCが関数内で定義されています。関数が外部から呼び出された後、if(DEFINED ABC)を使用して変数ABCが定義されているかどうかを判定します。変数が定義されている場合はtrueを出力し、変数を出力します。変数が定義されていない場合は、trueを出力します。定義されている場合は false を出力します。テスト結果は次のとおりです。

         したがって、関数内で定義した変数は関数内でのみ使用でき、関数を解放すると無効になることがわかります。これは実際には C 言語に似ています。関数内で定義された変数はローカルと考えることができます。変数であり、当然ながら外部から参照することはできません。

        ③. 関数内に外部と同名の変数を定義

        テストコードは次のようになります。

# 函数 xyz
function(xyz)
    message("函数内部")
    message("${ABC}")
    set(ABC "Hello China!")#设置变量 ABC
    message("${ABC}")
endfunction()

set(ABC "Hello World!")#定义变量 ABC
xyz() # 调用函数
message("函数外部")
message("${ABC}")

        このコードでは、関数の外側で変数 ABC="Hello World!" を定義し、関数の内側で変数 ABC="Hello China!" を設定します。関数の実行後、外部で message() を呼び出して変数 ABC を出力します。 。C 言語の理解によれば、関数の外に出力される ABC 変数の値は「Hello China!」に等しいはずです (変数の定義を関数定義の前に置く必要があるかどうかには注意しないでください)。この概念は言語で宣言されていますが、関数は定義されていますが、関数は変数が定義された後に呼び出されます)。ただし、これは当てはまりません。印刷情報を見てみましょう。

         出力された情報から、事実が上記の想定と異なることがわかります。関数内で set を呼び出して変数 ABC を設定すると、外部変数 ABC の値は設定されませんが、関数内に新しい変数 ABC が作成されます。はい、C 言語とは異なりますが、Python と非常によく似ており、Python を学習したことがあれば、それを知っているはずです。

        したがって、関数内のコードでは、set を呼び出す前に、変数 ABC が参照されます。このとき、変数が関数内で定義されているかどうかが検索されます。set を呼び出した後、内部で最初に出力されるメッセージは「Hello World!」です。 , 関数内には変数ABCも作成されており、このとき再度ABCを参照すると外部で定義された変数ではなく関数内で定義された変数が使用されるため、最初に出力される2つのメッセージは「Hello China!」です。

        ④外部定義変数を関数に設定する方法

        では、関数内で外部定義された変数を変更する必要がある場合はどうすればよいでしょうか? たとえば、次のコード:

# 函数 xyz
function(xyz)
    set(ABC "Hello China!")
endfunction()

set(ABC "Hello World!")
xyz() # 调用函数
message("${ABC}")

        前の説明から、xyz() 関数は、外部で定義された変数 ABC を変更するのではなく、set を通じて関数内で使用される変数 ABC を作成するだけであることがわかります。では、この関数はどのようにして外部で定義された変数を変更できるのでしょうか? ? 実際、これも非常に簡単で、set コマンドにはオプションの PARENT_SCOPE オプションが用意されており、以下に示すように、set コマンドを呼び出すときにパラメータ リストの最後に PARENT_SCOPE キーワードを追加するだけです。

# 函数 xyz
function(xyz)
    set(ABC "Hello China!" PARENT_SCOPE) #加上 PARENT_SCOPE
endfunction()
set(ABC "Hello World!")
xyz() # 调用函数
message("${ABC}")

         印刷情報をもう一度見てください。

         情報を出力すると、実際に PARENT_SCOPE を追加できることがわかります。では、PARENT_SCOPE オプションとは何でしょうか? 公式の説明は次のとおりです。 PARENT_SCOPE オプションが追加された場合、変数は現在のスコープより上のスコープに設定され、各ディレクトリ (ここでの「ディレクトリ」は CMakeLists.txt ディレクトリを含むディレクトリを指します) または関数によって作成されます。新しいスコープの場合、このコマンドは変数の値を親ディレクトリまたは上位の呼び出し関数に設定します。

        ⑤関数の戻り値をどのように実現するか?

        関数を紹介した際に、cmakeの関数にも戻り値を持たせることができると書きましたが、return()コマンドでは実現できず、当時はPARENT_SCOPEが導入されていなかったため、その方法を説明することができませんでした。戻り値を実現する PARENT_SCOPE オプションの機能はすでにわかりましたが、実際には、このオプションは関数の戻り値機能を実現するために使用されます。

        まず例を見てみましょう。

# 顶层 CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(TEST)

# 定义一个函数 xyz
# 实现两个数相加,并将结果通过 out 参数返回给调用者
function(xyz out var1 var2)
    math(EXPR temp "${var1} + ${var2}")
    set(${out} ${temp} PARENT_SCOPE)
endfunction()
xyz(out_var 5 10)
message("${out_var}")

        印刷結果は次のとおりです。

         これを見て、皆さんが理解できるかどうかはわかりませんが、実際は非常に単純です。xyz() 関数を呼び出すとき、渡された out_var は変数名ではなくパラメータとして渡されますが、今度はこれを次のように変更する必要があります。変数名を指定するにはどうすればよいですか? つまり、関数内でパラメータ out の値を取得し、パラメータ out の値を変数名として使用し、set で変数を作成し、PARENT_SCOPE オプションを追加します。この変数はソース コードで定義されているため、メッセージを通じて変数を出力できます。


        cmake については、作者がこれだけ紹介しているので、基本的には十分ですが、実際にはまだ紹介していないコマンドや変数がたくさんありますが、実際に見て、実際の戦闘テストに行ってください。

        このコラムは終わりました~

おすすめ

転載: blog.csdn.net/cj_lsk/article/details/131348993