我正在尝试使用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})
答案 0 :(得分:19)
当您使用ExternalProject_Add时,您不能使用find_package,因为当CMake运行以配置外部项目时无法找到任何内容。
因此,如果库位置因平台而异,则需要基于平台的条件逻辑。 (我不知道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很有用,即使它无法为您抽象出所有细节。
答案 1 :(得分:18)
要扩展上面的DLRdave答案,您不需要为静态库设置手动前缀和后缀,因为CMAKE为每个平台提供了正确的变量。
有关详细信息,请参阅CMake Useful Variables。
例如:
答案 2 :(得分:17)
因为您正在下载外部项目,所以您已经知道所有内容的位置,因为您刚刚下载了它,所以它不需要“查找”。
我使用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。得到所有依赖关系。
答案 3 :(得分:4)
您可以用另一个成语来解决这个问题:
您可以在https://github.com/biometrics/likely中看到这个习惯用法。
答案 4 :(得分:3)
您可以使用 link_directories 命令链接特定目录中的库。在您的情况下,目录是您的外部项目是构建。
ExternalProject_Add(MyExternalLibrary ...)
将输出目录添加到搜索路径:
link_directories(${CMAKE_BINARY_DIR}/lib/MyExternalLibrary-prefix/lib)
确保在之后添加可执行文件指定链接目录:
add_executable(MyProgram main.c)
指定项目应链接到的库:
target_link_libraries(MyProgram ExternalLibraryName)
不要忘记依赖外部项目:
add_dependencies(MyProgram MyExternalLibrary)
答案 5 :(得分:2)
您可以将find_package
与ExternalProject_add
结合使用,如以下代码片段所示:
# --------------------------------------------------
function (build_external_project target file_name)
set(CMAKELIST_CONTENT "
cmake_minimum_required(VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
project(build_external_project)
file(MD5 \"${file_name}\" FILE_HASH)
include(ExternalProject)
ExternalProject_add(${target}
URL \"${file_name}\"
URL_MD5 \${FILE_HASH}
CMAKE_GENERATOR \"${CMAKE_GENERATOR}\"
CMAKE_GENERATOR_PLATFORM \"${CMAKE_GENERATOR_PLATFORM}\"
CMAKE_GENERATOR_TOOLSET \"${CMAKE_GENERATOR_TOOLSET}\"
CMAKE_GENERATOR_INSTANCE \"${CMAKE_GENERATOR_INSTANCE}\"
CMAKE_ARGS ${ARGN})
add_custom_target(build_external_project)
add_dependencies(build_external_project ${target})
")
set(TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}/ExternalProjects/${target}")
file(WRITE "${TARGET_DIR}/CMakeLists.txt" "${CMAKELIST_CONTENT}")
file(MAKE_DIRECTORY "${TARGET_DIR}" "${TARGET_DIR}/build")
execute_process(COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-T "${CMAKE_GENERATOR_TOOLSET}"
..
WORKING_DIRECTORY "${TARGET_DIR}/build")
execute_process(COMMAND ${CMAKE_COMMAND}
--build .
--config ${CMAKE_BUILD_TYPE}
WORKING_DIRECTORY "${TARGET_DIR}/build")
endfunction()
#----------------------------------------------------------------------------------------------------
set(THIDR_PARTY_DIR "${CMAKE_CURRENT_LIST_DIR}")
set(THIDR_PARTY_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ThirdParty")
#----------------------------------------------------------------------------------------------------
# OpenCV.
set(OPENCV_OPTIONS "")
list(APPEND OPENCV_OPTIONS -D WITH_1394=ON)
list(APPEND OPENCV_OPTIONS -D WITH_ADE=ON)
list(APPEND OPENCV_OPTIONS -D WITH_CUDA=OFF)
list(APPEND OPENCV_OPTIONS -D WITH_EIGEN=ON)
list(APPEND OPENCV_OPTIONS -D WITH_FFMPEG=ON)
list(APPEND OPENCV_OPTIONS -D WITH_IPP=ON)
list(APPEND OPENCV_OPTIONS -D WITH_ITT=ON)
list(APPEND OPENCV_OPTIONS -D WITH_JASPER=ON)
list(APPEND OPENCV_OPTIONS -D WITH_JPEG=ON)
list(APPEND OPENCV_OPTIONS -D WITH_OPENCL=ON)
list(APPEND OPENCV_OPTIONS -D WITH_OPENEXR=ON)
list(APPEND OPENCV_OPTIONS -D WITH_OPENJPEG=ON)
list(APPEND OPENCV_OPTIONS -D WITH_PNG=ON)
list(APPEND OPENCV_OPTIONS -D WITH_PROTOBUF=ON)
list(APPEND OPENCV_OPTIONS -D WITH_QT=OFF)
list(APPEND OPENCV_OPTIONS -D WITH_TBB=ON)
list(APPEND OPENCV_OPTIONS -D WITH_TIFF=ON)
list(APPEND OPENCV_OPTIONS -D WITH_WEBP=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_CUDA_STUBS=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_DOCS=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_EXAMPLES=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_IPP_IW=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_ITT=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_JASPER=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_JAVA=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_JPEG=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_OPENEXR=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_PACKAGE=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_PERF_TESTS=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_PNG=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_PROTOBUF=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_TBB=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_TESTS=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_TIFF=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_WEBP=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_ZLIB=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_apps=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_java_bindings_generator=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_js=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_python_bindings_generator=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_python_tests=OFF)
list(APPEND OPENCV_OPTIONS -D BUILD_opencv_world=OFF)
list(APPEND OPENCV_OPTIONS -D OPENCV_ENABLE_NONFREE=OFF)
list(APPEND OPENCV_OPTIONS -D OPENCV_FORCE_3RDPARTY_BUILD=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_WITH_STATIC_CRT=OFF)
list(APPEND OPENCV_OPTIONS -D CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
list(APPEND OPENCV_OPTIONS -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
list(APPEND OPENCV_OPTIONS -D CMAKE_POSITION_INDEPENDENT_CODE=ON)
list(APPEND OPENCV_OPTIONS -D BUILD_SHARED_LIBS=OFF)
list(APPEND OPENCV_OPTIONS -D CMAKE_INSTALL_PREFIX=${THIDR_PARTY_INSTALL_DIR}/OpenCV)
build_external_project(OpenCV "${THIDR_PARTY_DIR}/OpenCV/opencv-4.3.0+cache.zip" ${OPENCV_OPTIONS})
set(OpenCV_STATIC ON)
#----------------------------------------------------------------------------------------------------
# Dlib.
set(DLIB_OPTIONS "")
list(APPEND DLIB_OPTIONS -D USE_SSE2_INSTRUCTIONS=ON)
list(APPEND DLIB_OPTIONS -D USE_SSE4_INSTRUCTIONS=ON)
list(APPEND DLIB_OPTIONS -D USE_AVX_INSTRUCTIONS=ON)
list(APPEND DLIB_OPTIONS -D DLIB_GIF_SUPPORT=ON)
list(APPEND DLIB_OPTIONS -D DLIB_JPEG_SUPPORT=ON)
list(APPEND DLIB_OPTIONS -D DLIB_PNG_SUPPORT=ON)
list(APPEND DLIB_OPTIONS -D DLIB_USE_BLAS=ON)
list(APPEND DLIB_OPTIONS -D DLIB_USE_CUDA=OFF)
list(APPEND DLIB_OPTIONS -D DLIB_USE_LAPACK=ON)
list(APPEND DLIB_OPTIONS -D DLIB_USE_MKL_FFT=OFF)
list(APPEND DLIB_OPTIONS -D DLIB_LINK_WITH_SQLITE3=OFF)
list(APPEND DLIB_OPTIONS -D DLIB_NO_GUI_SUPPORT=OFF)
list(APPEND DLIB_OPTIONS -D DLIB_ENABLE_ASSERTS=OFF)
list(APPEND DLIB_OPTIONS -D DLIB_ENABLE_STACK_TRACE=OFF)
list(APPEND DLIB_OPTIONS -D CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
list(APPEND DLIB_OPTIONS -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
list(APPEND DLIB_OPTIONS -D CMAKE_POSITION_INDEPENDENT_CODE=ON)
list(APPEND DLIB_OPTIONS -D BUILD_SHARED_LIBS=OFF)
list(APPEND DLIB_OPTIONS -D CMAKE_INSTALL_PREFIX=${THIDR_PARTY_INSTALL_DIR}/dlib)
build_external_project(dlib ${THIDR_PARTY_DIR}/Dlib/dlib-19.20.tar.bz2 ${DLIB_OPTIONS})
#----------------------------------------------------------------------------------------------------
####################################################################################################
# Now, you can use find_package:
find_package(OpenCV REQUIRED PATHS "${THIDR_PARTY_INSTALL_DIR}/OpenCV" NO_DEFAULT_PATH)
find_package(dlib REQUIRED PATHS "${THIDR_PARTY_INSTALL_DIR}/dlib" NO_DEFAULT_PATH)
####################################################################################################
https://gist.github.com/amir-saniyan/4339e6f3ef109c75eda8018f7d5192a7