在Linux上使用CMake,使用IPP将OpenCV与静态zlib链接

时间:2018-12-19 11:03:19

标签: opencv3.0 zlib intel-ipp

我正在使用IPP库的独立Intel版本从源代码构建OpenCV。我还使用了Intel优化的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读取了严格按顺序链接线,这意味着未正确处理依赖项。

因此,我需要的是一种强制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)之后。但是,我无法弄清楚该用什么代替[zlib表示],以便CMake理解并采取相应的措施。如果我将其替换为ZLIB :: ZLIB(CMake的本机FindZLIB函数的通常输出),那么我不会收到任何错误消息,但不会造成任何区别。几个小时后,构建完全像以前一样失败了。如果我尝试用[我可以想到的东西]代替[表示zlib的东西]或在OpenCV的CMake文件中的其他地方找到-到目前为止,'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构建,该构建将Intel增强的zlib版本与其所有依赖项静态链接在一起)? / p>

1 个答案:

答案 0 :(得分:0)

事实证明,我的代码块没有错。我不确定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和依赖它的一切初始化之间移动。

这有点棘手,但最后我做了:

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

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