web-dev-qa-db-ja.com

CMake-同じプロジェクト内のアプリ/ライブラリ間の依存関係(ヘッダー)

次のプロジェクト構造があります。

  • CMakeLists.txt
    • lib1/CMakeLists.txtおよびlibのすべてのcppおよびヘッダーファイル
    • lib2/CMakeLists.txtおよびlibのすべてのcppおよびヘッダーファイル
    • app/CMakeLists.txtおよびアプリのすべてのcppおよびヘッダーファイル

メインのCMakeLists.txtは次のようになります。

PROJECT( ${PROJECT_NAME} )
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)

Lib1/CMakeLists.txtは、たとえば(ストリップされた)ようになります。

SET(SOURCE
file.cpp
)
SET(HEADERS
    some_lib_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )

アプリ用のものは、ADD_EXECUTABLEを除いて同じように見えます。

SET(SOURCE
main.cpp
)
SET(HEADERS
    some_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
ADD_EXECUTABLE( app ${SOURCE} ${HEADERS} )

これにより、これら3つのプロジェクトすべてを含む1つのVisual Studioソリューションファイルを生成できるため、セットアップはこのようにうまく機能していることがわかりました。しかし、私の問題は、私のアプリにlib1(およびlib1に依存するlib2)のヘッダーファイルが含まれていることです。私がする時

$mkdir build
$cd build
$cmake -C ..\myproject

ソース外のVS .slnファイルを必要に応じて生成しますが、lib1のヘッダーファイルが見つからないため(明らかに)、アプリはコンパイルされません。

今、私はTARGET_LINK_LIBRARIES( app lib1 )(アプリがlib1とリンクするようになりましたが、ヘッダーインクルードの問題は解決しません)のような多くのものを読んで試しました。また、CMakeListsのさまざまなバリアントのadd_subdirectory( ../lib1 )のようなものアプリの.txt(すべて、修正できないエラーがスローされました)、およびfind_package(これは間違ったアプローチだと思います)。

それで、どうすればこの(私は簡単だと思います...)問題を解決できますか?

18
Ela782

考えられる解決策の1つを次に示します。

ルートCMakeLists.txt:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(${PROJECT_NAME})
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)


lib1/CMakeLists.txt:

project(Lib1)
add_library(lib1 lib1.cpp lib1.h)


lib2/CMakeLists.txt:

project(Lib2)
add_library(lib2 lib2.cpp lib2.h)

# Add /lib1 to #include search path
include_directories(${Lib1_SOURCE_DIR})
# Specify lib2's dependency on lib1
target_link_libraries(lib2 lib1)


app/CMakeLists.txt:

project(App)
add_executable(app main.cpp some_header.h)

# Add /lib1 and /lib2 to #include search path
include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR})
# Specify app's dependency on lib2.
# lib2's dependency on lib1 is automatically added.
target_link_libraries(app lib2)


ここで同じ最終結果を達成するには、さまざまな方法があります。比較的小さなプロジェクトの場合、おそらく単一のCMakeLists.txtを使用します。

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)

add_library(lib1 lib1/lib1.cpp lib1/lib1.h)
add_library(lib2 lib2/lib2.cpp lib2/lib2.h)
add_executable(app app/main.cpp app/some_header.h)

include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2)

target_link_libraries(lib2 lib1)
target_link_libraries(app lib2)


関連するコマンドとその根拠の詳細については、次を実行:

cmake --help-command add_subdirectory
cmake --help-command include_directories
cmake --help-command target_link_libraries
18
Fraser
Project
 CMakeLists.txt
 \-lib1
   CMakeLists.txt
   \- include \ lib1
   \- src
 \-lib2
   CMakeLists.txt
   \- include \ lib2
   \- src
 \-app
   CMakeLists.txt
   \- src

依存関係を次のように仮定します。

lib1 ---> lib2 ---> app 
   \--------------> app

このようなもの:

CMakeLists.txt:

add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)

lib1/CMakeLists.txt:

  file(GLOB_RECURSE _HDRS "include/*.hpp")
  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_library(lib1 ${_HDRS} ${_SRCS})
  #target_link_libraries(lib1)
  target_include_directories(lib1 PUBLIC include)

  install(TARGETS lib1 DESTINATION lib)
  install(FILES ${_HDRS} DESTINATION include/lib1)

lib2/CMakeLists.txt:

  file(GLOB_RECURSE _HDRS "include/*.hpp")
  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_library(lib2 ${_HDRS} ${_SRCS})
  target_link_libraries(lib2 lib1)
  target_include_directories(lib2 PUBLIC include)

  install(TARGETS lib2 DESTINATION lib)
  install(FILES ${_HDRS} DESTINATION include/lib2)

したがって、lib2/src/file.cppで#include <lib1/header.hpp>

app/CMakeLists.txt:

  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_executable(app ${_SRCS})
  target_link_libraries(app lib1 lib2)

  install(TARGETS app DESTINATION bin)

したがって、app/src/file.cppで#include <lib1/header.hpp>および#include <lib2/header.hpp>

魔法は target_include_directories で、「include」ディレクトリをターゲットにアタッチするので、リンクすると、includeディレクトリもプルされます;)

5
Mizux