Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CMake-链接到从ExternalProject_add()下载的库_Cmake_External Project - Fatal编程技术网

CMake-链接到从ExternalProject_add()下载的库

CMake-链接到从ExternalProject_add()下载的库,cmake,external-project,Cmake,External Project,我正在尝试使用ExternalProject_add()下载/安装依赖项。它安装得很好,但我不知道如何在下载库之后链接它们 我想在刚下载的库上调用target_link_libraries(),但是库的路径会因系统而异 如果这是一个系统依赖项,我可以调用find_package()-但是包没有安装在默认的搜索路径上。我认为您不能在模块模式下为find_包指定搜索路径 下面是我的CMakeLists.txt的一个片段,它不起作用: ExternalProject_Add( protobuf URL

我正在尝试使用ExternalProject_add()下载/安装依赖项。它安装得很好,但我不知道如何在下载库之后链接它们

我想在刚下载的库上调用target_link_libraries(),但是库的路径会因系统而异

如果这是一个系统依赖项,我可以调用find_package()-但是包没有安装在默认的搜索路径上。我认为您不能在模块模式下为find_包指定搜索路径

下面是我的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\u添加(
protobuf
统一资源定位地址http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz
CONFIGURE_命令/CONFIGURE--prefix=
前缀${MYPROJ_SOURCE_DIR}/dependencies
)
查找_包(需要protobuf)
集合(LIBS${LIBS}${PROTOBUF_库})
目标链接库(mybinary${LIBS})

当您使用ExternalProject\u Add时,您不能使用find\u软件包,因为当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_包方便。如果您可以使用预构建/预安装的软件包,那么您应该这样做,以便可以使用find_软件包。但是,如果您必须从源代码构建另一个包作为项目的一部分,那么ExternalProject\u Add非常有用,即使它无法为您提取所有详细信息。

您可以使用link\u 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)

您可以使用另一个成语来解决此问题:

  • 使find_包命令成为可选命令(删除“必需”)
  • 添加一些条件代码,仅在find_包成功时构建目标
  • find_包将失败,您的目标不会在第一次构建,但外部项目将被构建
  • 再次运行cmake/make,这次find_包将成功,您的目标将建立

  • 您可以在中看到这一习惯用法。

    要扩展上面的DLRdave答案,您不需要为静态库手动设置前缀和后缀,因为CMAKE为每个平台提供了正确的变量

    有关更多信息,请参阅

    例如:

    • CMAKE_共享_库_前缀
    • CMAKE_共享_库_后缀
    • CMAKE_静态_库_前缀
    • CMAKE_静态_库_后缀

    因为您正在下载外部项目,您已经知道所有内容的位置,因为您刚刚下载了它,所以它不需要“查找”

    我用add_库得到了它。这是我实际使用的代码:

    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)
    
    从这里开始,依赖它的每个程序都需要一个
    添加依赖项
    ,当然还有
    目标链接库
    。例如:

    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)
    
    • include_目录-告诉它在那里搜索目录
    • target_link_库-只需添加您命名的库(不是变量)
    add_依赖项使它在尝试包含所需的dir之前等待


    这对我来说很有用。与make-j4一起工作。让所有依赖项都正确无误。

    您可以使用
    find\u package
    ExternalProject\u 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)
    ####################################################################################################
    

    谢谢,这真的很有帮助。另外,为了不引起混淆,protobuf没有变量库位置,但是R有。cmake为您的平台提供前缀和后缀变量:
    “${install_dir}/lib/${cmake_SHARED_MODULE_prefix}protobufLib1${cmake_SHARED_library_suffix}”
    虽然这样做很有效,但我觉得很糟糕。如果我必须编写平台条件代码,那么使用cmake有什么意义?此外,我希望ExternalProject提供一种简单的方法来导入构建的目标,如果以后无法轻松导入它们,为什么我要构建一个外部项目呢?重点是什么?我遗漏了什么吗?你没有遗漏任何@Jens,但是这个场景不是在CMake中正常使用ExternalProject。事实上,我建议不要这样做。典型的场景是全部ExternalProject,或者没有ExternalProject,而不是一些外部的,一些不是的混合情况。当ExternalProject在所谓的“超级构建”场景中构建/安装所有组件时,以后构建的组件可以使用find_包来查找早期构建/安装的组件。这是使用ExternalProject的推荐方法。我觉得实际的
    link\u目录
    string应该更长,因为在我的例子中,我在lib下看到了类似MyExternalLibrary build/lib的内容。我尝试过这种技术,但在新的构建中它不起作用。您收到错误(找不到您的库)。由于cmake 3.2,您可以使用UPDATE_DISCONNECTED来避免自动更新。如果需要,您仍然可以添加自定义目标进行更新。它如何知道
    ForexConnect
    ?这里的示例
    add\u library(ForexConnect SHARED IMPORTED)
    真是一个很棒的解决方案,它甚至超越了简单的区分,管理依赖项和链接。看起来像一个优雅的解决方案。它适用于
    make
    ,但不适用于
    ninja
    。对于后者,您必须使用生成文件的路径设置外部项目的
    BUILD\u BYPRODUCTS
    属性。若并没有,忍者会尖叫着说它找不到你们的藏书室。@Lamda只是为了不让它不被回答:它并没有