2017-10-12 5 views
0

「app」と「lib」の兄弟ディレクトリを持つプロジェクトを指定します。「app」は「lib」で構築された静的ライブラリに応じて実行可能ファイルを作成します。私が望むのは、通常のビルドプロセスがライブラリのみをビルドする状況ですが、 "app"をビルドすると "lib"と "app"の両方がビルドされます。add_subdirectoryを使用するのではなく、ビルドされた静的ライブラリとリンクしていますか?

私は現在、今やっていることはappで、私はadd_subdirectorylibが含まれていることですが、何らかの理由で、これは私はありませんメカニズムを介してリンクラインにlibの間接的な依存関係のすべてに引っ張っています知っている。私はのような私のアプリだけでlibmylib.alibmylib.pcを構築することです、appちょうどlibmylib.pc(または手動で指定)から独自のリンクラインを計算することができますが、私はどのように行われているのか分かりません。

ここで私は今、セットアップ持っ最小作業例です:へ

のlib/CMakeLists.txt

cmake_minimum_required(VERSION 3.8.0) 
project(mylib CXX) 

find_package(PkgConfig REQUIRED) 
pkg_check_modules("mylib" "libssl") 

find_package(Boost REQUIRED) 
set(LIBDIR "${PROJECT_SOURCE_DIR}") 


set(HEADERS "${LIBDIR}/map_printer.hpp") 
set(SOURCES "${LIBDIR}/map_printer.cpp") 

add_library("mylib" "${SOURCES}") 

target_include_directories("mylib" PUBLIC "${LIBDIR}" 
              "${Boost_INCLUDE_DIR}" 
              "${mylib_INCLUDE_DIRS}") 
target_link_libraries("mylib" "${Boost_LIBRARIES}" "${mylib_LIBRARIES}") 

install(TARGETS "mylib" ARCHIVE DESTINATION "lib") 
install(FILES ${HEADERS} DESTINATION "include") 

アプリ/ CMakeLists.txt

cmake_minimum_required(VERSION 3.8.0) 
project(mylib CXX) 

set(APPDIR "${PROJECT_SOURCE_DIR}") 
set(LIBDIR "${APPDIR}/../lib") 

set(SOURCES "${APPDIR}/main.cpp") 

add_subdirectory("${LIBDIR}" "build") 
list(APPEND LIBS "mylib") 

add_executable("myapp" "${SOURCES}") 

target_include_directories("myapp" PUBLIC "${LIBDIR}") 
target_link_libraries("myapp" "${LIBS}") 

install(TARGETS "myapp" DESTINATION "bin") 

実際の例を得て、ここにlibのlibsslを引くソースファイルがあります(しかし、この楽しいctionアプリで使用されていない) - 彼らは唯一の完全性のために含まれているので、私は要旨に入れて、私は質問のテキストを乱雑たくありませんでした:

問題はときに私cmake appとはmake VERBOSE=1を行うことで、生成されたリンカ・コマンドは次のとおりです。

/usr/lib/hardening-wrapper/bin/c++  CMakeFiles/myapp.dir/main.cpp.o -o myapp build/libmylib.a -lssl 

-lsslはどこでもappに指定されていません。通常これは問題ありませんが、私のリアルアプリでは、-lsslと他のいくつかの不要なシンボルが間接的な依存関係のために.soファイルとしてインクルードされています。リンカコマンドから手動でそれらを削除すると、タスクは正常に構築され実行されます。理想的には、.a.pcファイル(この例では生成されていません)を使用していますが、余分な依存関係が必然的に引き込まれている場合、手動でリンク線を微調整できますが、この方法では、他のもの)がlibスコープから漏れていると私は理解できません。

+1

['target_link_libraries'](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)のドキュメントをご覧ください。ターゲットの依存関係を伝播させたくない場合は、 'PRIVATE'またはデフォルトで使用する' PUBLIC'以外のものを指定する必要があります。 – legalize

+0

@legalize Aaaaah!それは非常に物事を明確にする、ありがとう!あなたがその答えをしたいのなら、それはどんな答えとしても良いようです。 – Paul

答えて

0

リンクすることは、最終的なターゲット(スタンドアロンの実行可能ファイルまたは共有オブジェクト)が起動するために必要なものすべてを持つようにシンボルを解決することです。単一のライブラリにのみ依存しているライブラリや、それ以外のライブラリに依存しているライブラリのコレクションに依存している場合は、シンプルです。これは、中程度以上の大きさのプログラムの場合はあまりありません。根本的な問題は、過渡的な依存関係をどのように扱うかである。あなたのプログラムによって直接使用されるものの依存関係。

CMakeはこれをすべて理解しており、依存グラフ全体を理解することなくライブラリを簡単に使用できるように設計されています。 target_link_librariesのドキュメントを見ると、PRIVATE,PUBLIC、およびINTERFACEというキーワードが記載されています。これにより、ライブラリの構築時に必要となるライブラリのプライベート要件(定義のコンパイル、引数のコンパイル、依存ライブラリなど)を記述することができます。パブリック部分では、ライブラリとその扶養者(消費者)の両方が必要とするものを指定することができます。インタフェース部分では、扶養家族が必要とするものを指定できますが、ライブラリ自体は指定できません。コマンドtarget_compile_definitionstarget_include_directoriesも同様に動作します。

このすべての結論は、CMakeのでは正しく宣言依存し、その依存関係のクライアントだけで、独自のtarget_link_librariesコマンドで依存関係のリストに追加していることであり、それは当然すべて、定義をコンパイルしたディレクトリが含まピックアップし、コンパイルとリンクの成功に必要な一時的なリンクの依存関係。

A CppCon2017プレゼンテーションModern CMake for modular designがさらに詳細に説明されています。

関連する問題