Связывание OpenCV со статическим zlib с использованием IPP с использованием CMake в Linux - PullRequest
0 голосов
/ 19 декабря 2018

Я собираю OpenCV из исходного кода, используя автономную версию Intel библиотек IPP.Я также использую оптимизированную для Intel версию zlib, которая (в отличие от стандартной версии zlib) связана с тремя другими библиотеками IPP.Кроме того, я статически связываю zlib, поэтому мне нужно, чтобы любая цель, использующая его, знала об этих зависимостях.

У меня уже все работает на Windows, и теперь я пытаюсь сделатьто же самое в Linux.Я добавил следующий текст в основной файл CMakeLists.txt в Open CV сразу после места, где ищутся и инициализируются все другие зависимости:

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 и затем созданииbuild достигает 99% через пару часов, а затем завершается неудачно на одном из последних последних компилируемых модулей, жалуясь, что не может найти зависимости, связанные с IPP для zlib.Изучив журнал компиляции, легко понять, почему: по какой-то причине make-файл поместил zlib в качестве самой последней библиотеки в строке ссылок, после соответствующих библиотек Intel IPP, а поскольку gcc читает ссылкуСтрока в строгом порядке, это означает, что зависимости не обрабатываются правильно.

Поэтому мне нужен способ заставить CMake создать make-файл таким образом, чтобы библиотеки IPP всегда помещались после zlib на линии связи.

IЧитал в другом месте на этом сайте , что я должен быть в состоянии достичь этого, используя свойство 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] на что-то еще, что я могу придумать или найти в других местах в файлах CMake OpenCV - пока что, 'zlib', 'ZLIB', 'ZLIB_LIBRARY', 'zlib.a', 'libz.a'- тогда CMake завершается ошибкой с сообщением об ошибке:

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

Итак, я предполагаю, что мой вопрос заключается в том, как система CMake OpenCV внутренне ссылается на zlib, чтобы я мог добавить это свойство к нему?В качестве альтернативы, я подхожу к этому совершенно неверным образом, и есть ли лучший способ достичь моей цели (то есть иметь сборку OpenCV, которая статически связывает версию zlib для Intel со всеми ее зависимостями)?

1 Ответ

0 голосов
/ 21 декабря 2018

Оказалось, что с моим блоком кода все в порядке.Я не уверен, была ли вообще необходима строка set_target_properties, хотя, чтобы быть в безопасности, я оставил ее с последним синтаксисом:

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

Основной проблемой было расположение моего блокакод.Оказалось, что в вызове include(cmake/OpenCVFindLibsGrfmt.cmake) был найден и инициализирован сам zlib вместе с libtiff, libpng и libIlmImf, все из которых зависели от него.Следовательно, свойства этих целей содержали зависимость только от zlib , и мой блок кода, который появился позже, не изменил этого.Мой блок кода должен был быть перемещен между инициализацией zlib и инициализацией всего , которое зависело от него.

Это было немного сложно, но в итоге я сделал следующее:

  1. Переместил строку include(cmake/OpenCVFindLibsPerf.cmake) на первую позицию в блоке, чтобы библиотека IPP была найдена и IPP_ROOT_DIR правильно инициализирована.
  2. Извлечены первые десять строк или около того из cmake/OpenCVFindLibsGrfmt.cmake, где zlib инициализируется и помещает их в основной файл CMakeLists.txt сразу после include(cmake/OpenCVFindLibsPerf.cmake).
  3. Затем я снова вставляю свой блок пользовательского кода.
  4. Наконец я ставлюв остальной части включает завершающую инициализацию всех других библиотек.

В итоге получилась чистая сборка.

...