web-dev-qa-db-ja.com

cmake、グローバル変数(およびPARENT_SCOPEまたはadd_subdirectoryの代替)の概念で失われました

私はいくつかのモジュールを持っているcmakeプロジェクトを持っており、アプリケーションに共有モジュールを含めるためにFind-*。cmakeを使用しています。追加するすべてのモジュールを考慮しないために、リンカーに対して一種のグローバルLIB変数を定義しました。

# inside a Find-*.cmake or in the CMakeLists.txt of the modules:
set(LIB ${LIB} ...)

したがって、いくつかのモジュールを使用する最終的なアプリケーションの1つで、次のことができます。

target_link_libraries(${APP_NAME} ${LIB})

次に、コンパイルされたモジュールを/project_path/modules/foo/buildに入れて、モジュールが本当に大きい場合に、それを使用するすべてのアプリケーションに対して1回コンパイルできるようにします。私がこれを達成する方法は、次の方法でFind-*。cmakeからモジュールのCMakeLists.txtをロードすることです。

# Inside FindFoo.cmake, for loading /project_path/modules/foo/CMakeLists.txt
# and compile it in /project_path/modules/foo/build
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME} 
                 ${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/build
)
include_directories(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/include)

しかし、add_subdirectoryが新しいスコープを作成し、LIBを正しくロードできるが、それを書き込むことができないように、一部のモジュールが別のモジュールを必要とする場合がありました(setを使用すると、より深くなります)スコープであり、上位スコープは変更されません)。これをバイパスするには、set)にPARENT_SCOPEを追加する必要があります。したがって、いくつかの依存関係でネストおよび非表示にできると思われるモジュールに追加しようとしましたが、すべてをコンパイルしました。私が突然直面したアプリケーション:

CMake Warning (dev) at /path_to_repo/cmake/FindFooX.cmake:6 (set):
  Cannot set "LIB": current scope has no parent.
Call Stack (most recent call first):
  CMakeLists.txt:14 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

これは、必要なモジュールに関して、またはモジュール自体の依存関係ツリーに関して、アプリごとに変わる可能性があるため、よりクリーンなソリューションを探しています。

11
nkint

CMakeのすべての変数はデフォルトでローカルです。 PARENT_SCOPEパラメーターを使用してローカル変数のスコープを1層増やすことができますが、これはほとんどの場合、 functions の戻り値には意味があります。

一方、findスクリプトの場合、通常はグローバル変数の動作が必要です。findスクリプトが誰かによって呼び出されたら、結果をどこでも利用できるようにする必要があります。特に、同じ検索スクリプトへの2回目の呼び出しでは、最初の呼び出しの結果を再利用する必要があります。 CMakeでは、これは変数をキャッシュに保存することで実現されます。さまざまなfind_*呼び出しはすでにこれを自動的に実行するため、該当する場合はそれらを使用することをお勧めします。追加のカスタム変数の場合、 set は、キャッシュに保存する機能も提供します。

set(MY_GLOBAL_VARIABLE "Some value" CACHE STRING "Description")

ローカル変数は、スコープ内で同じ名前のキャッシュされた変数を非表示にできることに注意してください。

23
ComicSansMS

GLOBALスコープのプロパティを使用して、GLOBAL変数の動作を「シミュレート」できます。

SET_PROPERTY(GLOBAL PROPERTY MyGlobalProperty "MyGlobalPropertyValue")

次に、を使用してグローバルプロパティを抽出できます

GET_PROPERTY(MyLocalVariable GLOBAL PROPERTY MyGlobalProperty)

次に、MyLocalVariableには「MyGlobalPropertyValue」が含まれます。

PARENT_SCOPEは変数定義を(その親ではなく)唯一の親ディレクトリに拡張するため、たとえば、深いソースツリーがある場合など、それだけでは不十分な場合があります。

32
andufaure