我正在使用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>
答案 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和依赖它的一切初始化之间移动。
这有点棘手,但最后我做了:
include(cmake/OpenCVFindLibsPerf.cmake)
移动到块的第一行,以便找到IPP库并正确初始化IPP_ROOT_DIR
。cmake/OpenCVFindLibsGrfmt.cmake
提取前十行左右,在那里初始化zlib,并将它们放入include(cmake/OpenCVFindLibsPerf.cmake)
之后的主CMakeLists.txt中。最终结果是一个干净的构建。