ExternalProject_add()を使用して依存関係をダウンロード/インストールしようとしています。インストールはうまくいきますが、ダウンロードしたライブラリを実際にリンクする方法がわかりません。
ダウンロードしたばかりのライブラリでtarget_link_libraries()を呼び出したいのですが、ライブラリへのパスはシステムによって異なります。
これがシステムの依存関係である場合、find_package()を呼び出すだけで済みますが、パッケージはデフォルトの検索パスにインストールされていません。モジュールモードでfind_packageの検索パスを指定できないと思います。
動作しないCMakeLists.txtのスニペットを次に示します。
ExternalProject_Add(
protobuf
URL http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
PREFIX ${MYPROJ_SOURCE_DIR}/dependencies
)
find_package(protobuf REQUIRED)
set(LIBS ${LIBS} ${PROTOBUF_LIBRARIES})
target_link_libraries (mybinary ${LIBS})
ExternalProject_Addを使用している場合は、CMakeを実行して外部プロジェクトを構成するときに何も検出されないため、find_packageを使用できません。
したがって、ライブラリの場所がプラットフォームによって異なる場合は、プラットフォームに基づいた条件付きロジックが必要になります。 (ここではprotobufのライブラリや構造がわからないので、これは単なる例ですが、正しい方向に進むはずです...)次のようなもの:
if(WIN32)
set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/win"
set(prefix "")
set(suffix ".lib")
elseif(Apple)
set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/mac"
set(prefix "lib")
set(suffix ".a")
else()
set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/linux"
set(prefix "lib")
set(suffix ".a")
endif()
set(PROTOBUF_LIBRARIES
"${PROTOBUF_LIB_DIR}/${prefix}protobufLib1${suffix}"
"${PROTOBUF_LIB_DIR}/${prefix}protobufLib2${suffix}")
確かに、これはfind_packageを使用するよりも便利ではありません。ビルド済み/インストール済みのパッケージを使用できる場合は、find_packageを使用できるようにする必要があります。ただし、プロジェクトの一部としてソースコードから他のパッケージをビルドする必要がある場合、ExternalProject_Addは、すべての詳細を抽象化することはできませんが、便利です。
外部プロジェクトをダウンロードしているので、ダウンロードしたばかりなので、どこにあるのかすでにわかっているので、「検索」する必要はありません。
私はそれをadd_libraryで動作させました。これは私の実際のコードです:
ExternalProject_Add(ForexConnectDownload
PREFIX 3rd_party
#--Download step--------------
URL http://fxcodebase.com/bin/forexconnect/1.3.1/ForexConnectAPI-1.3.1-Linux-x86_64.tar.gz
URL_HASH SHA1=7fdb90a2d45085feb8b76167cae419ad4c211d6b
#--Configure step-------------
CONFIGURE_COMMAND ""
#--Build step-----------------
BUILD_COMMAND ""
#--Install step---------------
UPDATE_COMMAND "" # Skip annoying updates for every build
INSTALL_COMMAND ""
)
SET(FXCM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/include)
SET(FXCM_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/lib)
add_library(ForexConnect SHARED IMPORTED)
set_target_properties(ForexConnect PROPERTIES IMPORTED_LOCATION ${FXCM_LIB_DIR}/libForexConnect.so)
そこから、それに依存する各プログラムにはadd_dependencies
そしてもちろん target_link_libraries
。例えば:
include_directories(${FXCM_INCLUDE_DIR})
add_executable(syncDatabase syncDatabase.cpp trader/database.cpp trader/fxcm.cpp)
target_link_libraries(syncDatabase ForexConnect)
add_dependencies(syncDatabase ForexConnectDownload)
Add_dependenciesは、必要なディレクトリを含める前に待機させます。
それは私にとってはトリックです。 make -j4で動作します。すべての依存関係を正しく取得します。
上記のDLRdaveの回答を拡張するには、CMAKEが各プラットフォームに適切な変数を提供するため、静的ライブラリの接頭辞と接尾辞を手動で設定する必要はありません。
詳細については、 CMake有用な変数 を参照してください。
例えば:
この問題を解決するために使用できる別のイディオム:
このイディオムの動作は https://github.com/biometrics/likely で確認できます。
link_directoriesコマンドを使用して、特定のディレクトリ内のライブラリをリンクできます。あなたの場合、ディレクトリは外部プロジェクトがビルドされたものでした。
ExternalProject_Add(MyExternalLibrary ...)
出力ディレクトリを検索パスに追加します。
link_directories(${CMAKE_BINARY_DIR}/lib/MyExternalLibrary-prefix/lib)
リンクディレクトリを指定して、実行可能ファイルafterを必ず追加してください。
add_executable(MyProgram main.c)
プロジェクトをリンクするライブラリを指定します。
target_link_libraries(MyProgram ExternalLibraryName)
外部プロジェクトに依存することを忘れないでください:
add_dependencies(MyProgram MyExternalLibrary)