【发布时间】: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 依赖项的位置。完成后我会报告。