qt5 deployment with opencv, how to fix the lib install paths? - c++

A similar problem have been partially addressed here dyld: Library not loaded: lib/libopencv_core.3.0.dylib Reason: image not found
that lead to a solution there that do not work for me.
I use Qt 5, with openCV 3 with Mac OS X 10.10.5.
When I use macdeployqt, this process does not have the proper paths for the openCV .dylib files. It complains with:
ERROR: no file at "/lib/libopencv_core.3.0.dylib"
ERROR: no file at "/lib/libopencv_highgui.3.0.dylib"
ERROR: no file at "/lib/libopencv_imgproc.3.0.dylib"
which relates to wrong file paths, given as relative but interpreted as absolute, according to:
$ otool -L myApp.app/Contents/MacOS/myApp
myApp.app/Contents/MacOS/myApp:
(...)
lib/libopencv_core.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
lib/libopencv_highgui.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
lib/libopencv_imgproc.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
(...)
And of course, the app crash when it runs in a different computer, complaining about the missing libraries above.
How can I fix this given that the solution mentioned above did not work? Or how can I "better" apply the solution above in this case? (I may not have adapted them properly).
I tried 3 different installation of opencv 3: CMake, homebrew, and macports. The problem remained identical.

A kind soul at work helped me to better understand how I could adapt the above solutions that use the install_name_tool. Because the above solutions did not work apply to my case, here is a script with comments that describe each step in detail. This script assumes that you have used macdeployedqt already, and that you got a .app file. This fix works with opencv 3 when linking the opencv_core, opencv_highgui, and opencv_imgproc libraries. For your own case, you need to change the LIB_DIR and APP_DIR to (resp.) the directory where your opencv library files (.dylib) are, and the path to your .app package (here my app is called Qtfits_openmp). Of course, there could be a more compact script to make out of this, but I hope the detailed steps will help anyone to adapt to his/her own case.
#! /bin/bash
LIB_DIR=~/Dev/opencv3_tbb_opencl/lib
APP_DIR=~/Dev/build-Qtfits_openmp-clang_omp-Release/Qtfits_openmp.app
# This script supposes here that you are in the parent directory of the app.
# check to what libs your app is "explicitly" linked to with otool -L $APP_DIR/Contents/MacOS/Qtfits_openmp
# If originally linking with LIBS += -lopencv_core -lopencv_highgui -lopencv_imgproc, you'd need to copy them in the .app with their dependencies.
# However, opencv has the path of symbolic links, ending with 3.0. , so we need to copy the actual files, i.e., with the whole version number 3.0.0.
cp $LIB_DIR/libopencv_core.3.0.0.dylib $APP_DIR/Contents/Frameworks/libopencv_core.3.0.0.dylib
cp $LIB_DIR/libopencv_highgui.3.0.0.dylib $APP_DIR/Contents/Frameworks/libopencv_highgui.3.0.0.dylib
cp $LIB_DIR/libopencv_imgproc.3.0.0.dylib $APP_DIR/Contents/Frameworks/libopencv_imgproc.3.0.0.dylib
# Extra dependencies exist: otool -L libopencv_* will show you all the dependencies that you need to copy.
# Here we will also need to add imgcodecs and videoio to the .app
cp $LIB_DIR/libopencv_imgcodecs.3.0.0.dylib $APP_DIR/Contents/Frameworks/libopencv_imgcodecs.3.0.0.dylib
cp $LIB_DIR/libopencv_videoio.3.0.0.dylib $APP_DIR/Contents/Frameworks/libopencv_videoio.3.0.0.dylib
# With otool -L $APP_DIR/Contents/MacOS/yourApp , look at the .lib files with a wrong path. With the following result:
# lib/libopencv_core.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
# lib/libopencv_highgui.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
# lib/libopencv_imgproc.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
# we need to fix the 3 libraries core, highgui and imgproc which are given here with an incorrect relative path.
# Note that again, opencv kept the basename of the symbolic links (ending with 3.0.dylib), not the basename of the actual files (ending with 3.0.0.dylib)
# So we have to keep things consistent with what we did above.
install_name_tool -change lib/libopencv_core.3.0.dylib #executable_path/../Frameworks/libopencv_core.3.0.0.dylib $APP_DIR/Contents/MacOS/Qtfits_openmp
install_name_tool -change lib/libopencv_highgui.3.0.dylib #executable_path/../Frameworks/libopencv_highgui.3.0.0.dylib $APP_DIR/Contents/MacOS/Qtfits_openmp
install_name_tool -change lib/libopencv_imgproc.3.0.dylib #executable_path/../Frameworks/libopencv_imgproc.3.0.0.dylib $APP_DIR/Contents/MacOS/Qtfits_openmp
# Now we need to fix the path to all the dependencies of each library file.
cd $APP_DIR/Contents/Frameworks
# Change the IDs
for i in libopencv*.dylib; do install_name_tool -id #executable_path/../Frameworks/$i $i; done
# Again, with otool -L libopencv_* , you will see that you need to change their paths so that your copied libraries are pointed to within the app.
# for each opencv lib that is not properly referenced, change it from the absolute or wrong-relative path to #executable_path/../Frameworks/
# fix libopencv_highgui
install_name_tool -change $LIB_DIR/libopencv_imgcodecs.3.0.dylib #executable_path/../Frameworks/libopencv_imgcodecs.3.0.0.dylib libopencv_highgui.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_core.3.0.dylib #executable_path/../Frameworks/libopencv_core.3.0.0.dylib libopencv_highgui.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_imgproc.3.0.dylib #executable_path/../Frameworks/libopencv_imgproc.3.0.0.dylib libopencv_highgui.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_videoio.3.0.dylib #executable_path/../Frameworks/libopencv_videoio.3.0.0.dylib libopencv_highgui.3.0.0.dylib
# fix libopencv_imgproc
install_name_tool -change $LIB_DIR/libopencv_core.3.0.dylib #executable_path/../Frameworks/libopencv_core.3.0.0.dylib libopencv_imgproc.3.0.0.dylib
# fix libopencv_videoi
install_name_tool -change $LIB_DIR/libopencv_imgcodecs.3.0.dylib #executable_path/../Frameworks/libopencv_imgcodecs.3.0.0.dylib libopencv_videoio.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_imgproc.3.0.dylib #executable_path/../Frameworks/libopencv_imgproc.3.0.0.dylib libopencv_videoio.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_core.3.0.dylib #executable_path/../Frameworks/libopencv_core.3.0.0.dylib libopencv_videoio.3.0.0.dylib
# fix libopencv_imgcodecs
install_name_tool -change $LIB_DIR/libopencv_imgproc.3.0.dylib #executable_path/../Frameworks/libopencv_imgproc.3.0.0.dylib libopencv_imgcodecs.3.0.0.dylib
install_name_tool -change $LIB_DIR/libopencv_core.3.0.dylib #executable_path/../Frameworks/libopencv_core.3.0.0.dylib libopencv_imgcodecs.3.0.0.dylib

Related

How set CMake to find a local package FFmpeg?

I am trying write CMakeLists with FFmpeg package, with compile on Windows and Linux.
First downloaded from FFmpeg-Builds shared releases
I imagine the structure of the project like this:
<project root>
deps/
ffmpeg/
win-x64/
incluve/
lib/
bin/
linux-x64/
incluve/
lib/
bin/
src/
CMakeLists.txt
How to help CMake find libraries: avcodec, avformat, avutil, etc?
Maybe in the folder lib/pkgconfig using PkgConfig it is possible to specify the path.
But I dont know how
The following worked well for me on Linux with cmake.
You will have to find the equivalents for Windows.
I used ffmpeg on Windows, but without cmake (i.e. directly in a Visual Studio project).
Install pkg-config, nasm:
sudo apt-get install -y pkg-config
sudo apt-get install nasm
Download ffmpeg source code:
https://ffmpeg.org/download.html
Build ffmpeg and install it:
tar -xvf <downloaded_filename>
cd /root/folder/with/ffmpeg/src
./configure
make
sudo make install
Add the following to your CMakeLists.txt:
In the beginning:
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
libavdevice
libavfilter
libavformat
libavcodec
libswresample
libswscale
libavutil
)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
In the linker area:
target_link_libraries(${PROJECT_NAME} PUBLIC PkgConfig::LIBAV)

Build cmake library without RPATH (use executable_path instead)

I am using CMake to build a library. Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(simpleLibrary)
set(CMAKE_CXX_STANDARD 17)
add_library(simpleLibrary SHARED main.cpp)
It is very simple and clear. It builds a library in cmake-build-debug. I use otool to check shared library id:
➜ cmake-build-debug git:(master) ✗ otool -L libsimpleLibrary.dylib
libsimpleLibrary.dylib:
#rpath/libsimpleLibrary.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
➜ cmake-build-debug git:(master) ✗
It builds with #rpath by default. In my case I need to use #executable_path because I am facing linkage problems in the Mac OS without Xcode installed. Is there a way to change it in CMake build? I could change it using install_name_tool but I have to make that on build stage. Thanks in advance.

Link tbb library with qtcreator with a cmake project

I have a cmake project and i'm using qtcreator 4.5 to develop on a Ubuntu environment. Right now i try to use the TBB library to parallelize my code but i get this error on compilation:
/usr/include/tbb/parallel_for.h:87: error: undefined reference to `tbb::task_group_context::~task_group_context()'
From what i understand I'm not linking my TBB library, is that the problem ? If yes, how to do so ?
EDIT 1: I installed TBB trough the command sudo apt-get install libtbb-dev, so i am not sure where it is installed, but there is a libtbb.so in /usr/lib/x86_64-linux-gnu, is that it ?
EDIT 2: I founded the solution, I didn't have to go through th cmake files because I am adding the library path through Qtcreator. I founded the lib in /usr/include.
So, if you have the same problem you can link your library by going to projects section in Qtcreator, the find TBB in the window and give the path of your lib.
I do not know if you have installed the developnment lib in your Ubuntu:
sudo apt-get install libtbb-dev
The next step should be link in the .pro file against the tbb lib (-ltbb)
In my case, also I am working "indirectly" with tbb lib and I am setting the next lines in my .pro file for a static compilation:
## OTHER LIBS
LIBS += -L/myopencvpath/share/OpenCV/3rdparty/lib
LIBS += -lIlmImf -lippicv -llibjasper -llibjpeg -llibpng -llibtiff -ltbb -lzlib
Also this entry could help you: how to get Threaded Building Blocks working in Ubuntu 14.04
I hope this helps you.
EDIT1: I am so far away of being a cmake expert, but you could try something like this:
IF ( USE_TBB )
MESSAGE( STATUS "Including TBB on MyLib build" )
FIND_PACKAGE( tbb REQUIRED )
LINK_DIRECTORIES( ${LIBRARYPATH} )
ENDIF ()

How to correctly set dynamic lib path using CMake?

I'm trying to use OpenMP on Mac.
After compiling, when running binary file,
I get
dyld: Library not loaded: #rpath/libomp.dylib
Referenced from: ./lab1
Reason: image not found
[1] 64552 trace trap ./lab1
I used otool to find out what path it expects.
otool -L lab1
lab1:
#rpath/libomp.dylib (compatibility version 5.0.0, current version 5.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
This required library libomp.dylib is at path /usr/local/opt/llvm/lib.
How to make the binary can find it ?
Try adding the required path to the executable's rpaths by using a CMake POST_BUILD action:
add_custom_command(TARGET lab1
POST_BUILD COMMAND
${CMAKE_INSTALL_NAME_TOOL} -add_rpath /usr/local/opt/llvm/lib
$<TARGET_FILE:lab1>)
This only works if lab1 is a CMake executable target that is created with add_executable.

How do you add libraries to CMakeLists?

After searching everywhere I could not find anything or anyone to help me figure out how to add GL GLEW and SDL2 Libraries to my CMakeLists.txt. I am using Ubuntu 14.04 LTS and I installed the following libraries with
sudo apt-get install libsdl2-dev #for SDL-2
sudo apt-get install libgl-dev #for GL
sudo apt-get install libglew-dev #for GLEW
This all worked great, and i was able to compile in g++ with this commmand
g++ ./main.cpp ./display.h ./display.cpp ./shader.cpp ./shader.h -l SDL2 -l GL -l GLEW
Now I need to switch to CMake Compiler and I have no clue how to add the libraries GL, GLEW, and SDL2 to the CMakeLists.txt.
The way to include the libraries depends on a few things. Some packages such as sdl2 have pkgconfig files that define the libraries and includes to use.
Cmake comes with a FindPkgConfig module that can get it for you.
For example:
include(FindPkgConfig)
pkg_check_modules(SDL2 REQUIRED sdl2)
target_link_libraries(executablename ${SDL2_LIBRARIES})
You can also manually add them with the target_link_libraries function.
Other packages have "Find" modules like GLEW: /usr/share/cmake-*/Modules/FindGLEW.cmake
CMake has lots of great docs in the man pages, and on their wiki as #Mikael Persson mentioned.