【问题标题】:Linking OpenCV with static zlib using IPP, using CMake on Linux使用 IPP 将 OpenCV 与静态 zlib 链接,在 Linux 上使用 CMake
【发布时间】:2018-12-19 11:03:19
【问题描述】:

我正在使用独立 Intel 版本的 IPP 库从源代码构建 OpenCV。我还在使用英特尔优化的 zlib 版本,它(与 zlib 的标准版本不同)依赖于另外三个 IPP 库。另外,我正在静态链接 zlib,所以我需要让任何使用它的目标都知道这些依赖关系。

我已经在 Windows 上完成了所有工作,现在我正在尝试在 Linux 上做同样的事情。我已将以下文本添加到 Open CV 中的主 CMakeLists.txt 文件中,就在搜索和初始化所有其他依赖项的位置之后:

include(cmake/OpenCVFindLibsGrfmt.cmake)
include(cmake/OpenCVFindLibsGUI.cmake)
include(cmake/OpenCVFindLibsVideo.cmake)
include(cmake/OpenCVFindLibsPerf.cmake)
include(cmake/OpenCVFindLAPACK.cmake)
include(cmake/OpenCVFindProtobuf.cmake)

#---------------------------My changes start here-------------------------
# We insert this code here because this is the point where ZLIB_LIBRARIES 
# has just become defined, and by putting it here we ensure that our 
# changes are propagated throughout the rest of the project.
if (MSVC)

    add_library(ippdcmt STATIC IMPORTED)
    add_library(ippsmt STATIC IMPORTED)
    add_library(ippcoremt STATIC IMPORTED)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
        # We are compiling 64-bit code
        set_target_properties(ippdcmt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64_win/ippdcmt.lib")
        set_target_properties(ippsmt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64_win/ippsmt.lib")
        set_target_properties(ippcoremt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64_win/ippcoremt.lib")
    else()
        # We are compiling 32-bit code
        set_target_properties(ippdcmt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32_win/ippdcmt.lib")
        set_target_properties(ippsmt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32_win/ippsmt.lib")
        set_target_properties(ippcoremt PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32_win/ipcoremt.lib")
    endif()
    list(APPEND ZLIB_LIBRARIES ippdcmt ippsmt ippcoremt)

elseif(CMAKE_COMPILER_IS_GNUCC)

    add_library(libippdc STATIC IMPORTED)
    add_library(libipps STATIC IMPORTED)
    add_library(libippcore STATIC IMPORTED)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
        # We are compiling 64-bit code
        set_target_properties(libippdc PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64/libippdc.a")
        set_target_properties(libipps PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64/libipps.a")
        set_target_properties(libippcore PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/intel64/libippcore.a")        
    else()
        # We are compiling 32-bit code
        set_target_properties(libippdc PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32/libippdc.a")
        set_target_properties(libipps PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32/libipps.a")
        set_target_properties(libippcore PROPERTIES IMPORTED_LOCATION "${IPP_ROOT_DIR}/lib/ia32/libippcore.a")  
    endif()
    list(APPEND ZLIB_LIBRARIES libippdc libipps libippcore)

endif()
#---------------------------My changes end here---------------------------

在运行 CMake 然后 make 时,构建在几个小时后达到 99%,然后在要编译的最后一个模块上失败,抱怨它找不到 zlib 的 IPP 相关依赖项。在检查编译日志时,很容易看出原因:由于某种原因,makefile 将 zlib 作为链接行上的最后一个库,相关的英特尔 IPP 库之后,并且由于 gcc 读取link line in strict order 这意味着依赖关系没有被正确处理。

因此,我需要一种强制 CMake 构建 makefile 的方法,使得 IPP 库总是放在链接行上的 zlib 之后。

我已阅读elsewhere on this site,我应该能够使用 CMake 属性 IMPORTED_LINK_INTERFACE_LIBRARIES 来实现这一点。所以我尝试添加类似于

的行
set_target_properties([something to denote zlib] PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES libippdc libipps libippcore)

...紧跟在list(APPEND ZLIB_LIBRARIES libippdc libipps libippcore) 之后。但是,我不知道用什么代替 [something to denote zlib] 以便 CMake 理解并采取相应的行动。如果我用 ZLIB::ZLIB (CMake 的本机 FindZLIB 函数的通常输出)替换它,那么我不会收到任何错误消息,但它不会产生一点点差异;几个小时后,构建完全像以前一样失败。如果我尝试用我能想到的或在 OpenCV 的 CMake 文件的其他地方找到的任何其他东西替换 [something to denote zlib] - 到目前为止,'zlib'、'ZLIB'、'ZLIB_LIBRARY'、'zlib.a'、'libz.a ' - 然后 CMake 失败并显示错误消息:

set_target_properties Can not find target to add properties to: libz.a (or whatever)

所以我想我的问题是,OpenCV 的 CMake 系统如何在内部引用 zlib,以便我可以将这个属性添加到它?或者,我是否以完全错误的方式处理这个问题,是否有更好的方法来实现我的目标(简而言之,有一个 OpenCV 构建,将 zlib 的英特尔增强版本与其所有依赖项静态链接)?

【问题讨论】:

  • 我找到了确凿的证据;有问题的包 opencv_annotation 使用 IlmImf,并且它的依赖项(包括 zlib)是在执行上面给出的代码块之前设置的。我现在需要追查在主 CMakeLists.txt 文件中设置 IlmImf 依赖项的位置。完成后我会报告。

标签: opencv3.0 zlib intel-ipp


【解决方案1】:

事实证明,我的代码块没有任何问题。我不确定set_target_properties 行是否必要,但为了安全起见,我将其保留为最终语法:

  set_property(TARGET   ZLIB::ZLIB 
               PROPERTY INTERFACE_LINK_LIBRARIES libippdc libipps libippcore)

主要问题是我的代码块的位置。事实证明,在对include(cmake/OpenCVFindLibsGrfmt.cmake) 的调用中,zlib 本身被找到并被初始化以及 libtiff、libpng 和 libIlmImf,所有这些都依赖于它。因此,这些目标的属性包含对 zlib alone 的依赖,而我后来的代码块并没有改变这一点。我的代码块必须在 zlib 的初始化和依赖它的 everything 的初始化之间移动。

这有点棘手,但最终我所做的是:

  1. 将行 include(cmake/OpenCVFindLibsPerf.cmake) 移动到块中的第一个,以便找到 IPP 库并正确初始化 IPP_ROOT_DIR
  2. cmake/OpenCVFindLibsGrfmt.cmake 中提取前十行左右,其中 zlib 被初始化,并在 include(cmake/OpenCVFindLibsPerf.cmake) 之后立即将它们放入主 CMakeLists.txt 中。
  3. 然后我重新插入了我的自定义代码块。
  4. 最后我放入了其余的包含,以完成所有其他库的初始化。

最终的结果是一个干净的构建。

【讨论】:

    猜你喜欢
    • 2013-10-09
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多