[解決済み] CMakeと他のプロジェクトとその依存関係の検索
2023-04-12 16:18:10
質問
次のようなシナリオを想像してください。プロジェクト A は、いくつかの依存関係 (LibA、LibB、LibC) を持つ共有ライブラリです。プロジェクト B は、プロジェクト A に依存する実行可能ファイルであり、したがって、ビルドするためにプロジェクト A のすべての依存関係も必要とします。
さらに、両方のプロジェクトは CMake を使用してビルドされ、プロジェクト B がそれを使用するために、開発者にとって迷惑になる可能性があるため、プロジェクト A を (「インストール」ターゲットによって) インストールする必要はありません。
CMake を使用してこれらの依存関係を解決する最良の方法は何でしょうか。理想的なソリューションは、可能な限りシンプルで (ただし、より単純ではない)、最小限のメンテナンスを必要とすることです。
どのように解決するのですか?
簡単です。以下は、私の頭の中にある例です。
トップレベルの
CMakeLists.txt
:
cmake_minimum_required(VERSION 2.8.10)
# You can tweak some common (for all subprojects) stuff here. For example:
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(SEND_ERROR "In-source builds are not allowed.")
endif ()
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
# Remove 'lib' prefix for shared libraries on Windows
if (WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif ()
# When done tweaking common stuff, configure the components (subprojects).
# NOTE: The order matters! The most independent ones should go first.
add_subdirectory(components/B) # B is a static library (depends on Boost)
add_subdirectory(components/C) # C is a shared library (depends on B and external XXX)
add_subdirectory(components/A) # A is a shared library (depends on C and B)
add_subdirectory(components/Executable) # Executable (depends on A and C)
CMakeLists.txt
で
components/B
:
cmake_minimum_required(VERSION 2.8.10)
project(B C CXX)
find_package(Boost
1.50.0
REQUIRED)
file(GLOB CPP_FILES source/*.cpp)
include_directories(${Boost_INCLUDE_DIRS})
add_library(${PROJECT_NAME} STATIC ${CPP_FILES})
# Required on Unix OS family to be able to be linked into shared libraries.
set_target_properties(${PROJECT_NAME}
PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${PROJECT_NAME})
# Expose B's public includes (including Boost transitively) to other
# subprojects through cache variable.
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include
${Boost_INCLUDE_DIRS}
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
CMakeLists.txt
で
components/C
:
cmake_minimum_required(VERSION 2.8.10)
project(C C CXX)
find_package(XXX REQUIRED)
file(GLOB CPP_FILES source/*.cpp)
add_definitions(${XXX_DEFINITIONS})
# NOTE: Boost's includes are transitively added through B_INCLUDE_DIRS.
include_directories(${B_INCLUDE_DIRS}
${XXX_INCLUDE_DIRS})
add_library(${PROJECT_NAME} SHARED ${CPP_FILES})
target_link_libraries(${PROJECT_NAME} B
${XXX_LIBRARIES})
# Expose C's definitions (in this case only the ones of XXX transitively)
# to other subprojects through cache variable.
set(${PROJECT_NAME}_DEFINITIONS ${XXX_DEFINITIONS}
CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
# Expose C's public includes (including the ones of C's dependencies transitively)
# to other subprojects through cache variable.
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include
${B_INCLUDE_DIRS}
${XXX_INCLUDE_DIRS}
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
CMakeLists.txt
で
components/A
:
cmake_minimum_required(VERSION 2.8.10)
project(A C CXX)
file(GLOB CPP_FILES source/*.cpp)
# XXX's definitions are transitively added through C_DEFINITIONS.
add_definitions(${C_DEFINITIONS})
# NOTE: B's and Boost's includes are transitively added through C_INCLUDE_DIRS.
include_directories(${C_INCLUDE_DIRS})
add_library(${PROJECT_NAME} SHARED ${CPP_FILES})
# You could need `${XXX_LIBRARIES}` here too, in case if the dependency
# of A on C is not purely transitive in terms of XXX, but A explicitly requires
# some additional symbols from XXX. However, in this example, I assumed that
# this is not the case, therefore A is only linked against B and C.
target_link_libraries(${PROJECT_NAME} B
C)
# Expose A's definitions (in this case only the ones of C transitively)
# to other subprojects through cache variable.
set(${PROJECT_NAME}_DEFINITIONS ${C_DEFINITIONS}
CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
# Expose A's public includes (including the ones of A's dependencies
# transitively) to other subprojects through cache variable.
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include
${C_INCLUDE_DIRS}
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
CMakeLists.txt
で
components/Executable
:
cmake_minimum_required(VERSION 2.8.10)
project(Executable C CXX)
file(GLOB CPP_FILES source/*.cpp)
add_definitions(${A_DEFINITIONS})
include_directories(${A_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${CPP_FILES})
target_link_libraries(${PROJECT_NAME} A C)
わかりやすくするために、対応するソースツリーの構造を示します。
Root of the project
├───components
│ ├───Executable
│ │ ├───resource
│ │ │ └───icons
│ │ ├───source
| | └───CMakeLists.txt
│ ├───A
│ │ ├───include
│ │ │ └───A
│ │ ├───source
| | └───CMakeLists.txt
│ ├───B
│ │ ├───include
│ │ │ └───B
│ │ ├───source
| | └───CMakeLists.txt
│ └───C
│ ├───include
│ │ └───C
│ ├───source
| └───CMakeLists.txt
└───CMakeLists.txt
特定のニーズを満たすために、これを微調整/カスタマイズしたり変更したりできる点はたくさんありますが、これは少なくともあなたが始めるべきものです。
注意 私はこの構造をいくつかの中規模および大規模なプロジェクトで採用し、成功させてきました。
関連
-
[解決済み] CMakeは "make uninstall "をサポートしていますか?
-
[解決済み] CMake の add_definitions が動作しないようです。
-
[解決済み] cmake --verbose=1` は冗長なcmake出力をしますが、`cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON` はそうならないのはなぜですか?
-
[解決済み] .cmakeファイルの目的は何ですか?
-
[解決済み】CMake:スクリプト内のアクセス可能なすべての変数を出力する
-
[解決済み】変数を設定・使用するCMakeの構文とは?
-
[解決済み] CMakeはどのように使われるのですか?[クローズド]。
-
[解決済み] CMakeにソースディレクトリにある静的ライブラリをリンクするように指示するには?
-
[解決済み] CMakeにおける関数とマクロの比較
-
[解決済み] cmake` から `pkg-config` を使用する正しい方法は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] CMake の add_definitions が動作しないようです。
-
[解決済み] CMAKE_SOURCE_DIRはどこですか?
-
[解決済み] cmake --verbose=1` は冗長なcmake出力をしますが、`cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON` はそうならないのはなぜですか?
-
[解決済み] .cmakeファイルの目的は何ですか?
-
[解決済み】CMakeをGNU Makeと一緒に使う:正確なコマンドを見るにはどうすればいい?
-
[解決済み】CMake:スクリプト内のアクセス可能なすべての変数を出力する
-
[解決済み】変数を設定・使用するCMakeの構文とは?
-
[解決済み】CMakeは具体的にどのように動作するのですか?
-
[解決済み] CMake target_include_directories スコープの意味
-
[解決済み] cmake の `file(GLOB ... )` パターンから単一のファイルを除外するにはどうすればよいですか?