How to correctly set dynamic lib path using CMake? - c++

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.

Related

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.

CMake search for shared libraries in relative path

Is there a way to specify the shared library path from CMakeLists.txt?
I want to make an executable which uses OpenCV but I don't want the final user to install OpenCV. Instead I would like to deliver a folder containing my executable and the shared libraries it needs. The final structure should be something like
Delivery
MyApp
OpenCV (folder containing opencv dylibs)
In the end MyApp should search for the shared libs in OpenCV folder.
I tried to use the info from https://cmake.org/Wiki/CMake_RPATH_handling but for some reason I don't seem to understand what i really have to do to achieve what I want.
I tried to set CMAKE_INSTALL_RPATH to #loader_path or #executable_path but don't see any change. It still searches for opencv libs in /lib folder.
Running otool -L MyApp results in:
lib/libopencv_imgproc.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_imgcodecs.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_highgui.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_core.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

Qt: Linking Framework on Mac: using rpath

I want to create a custom framework with Qt. I am able to create the framework itself, but Qt fails to find the framework when run:
dyld: Library not loaded: QSettingsDialog.framework/Versions/0/QSettingsDialog
Referenced from: /Users/sky/QtProjects/build-QSettingsDialog-Desktop_Qt_5_7_0_clang_64bit-Debug/Examples/SimpleExample/SimpleExample.app/Contents/MacOS/SimpleExample
Reason: image not found
The reason is simple: The binary does not know where to look for the framework.
I used otool on the binary and saw this:
otool -L Examples/SimpleExample/SimpleExample.app/Contents/MacOS/SimpleExample
Examples/SimpleExample/SimpleExample.app/Contents/MacOS/SimpleExample:
QSettingsDialog.framework/Versions/0/QSettingsDialog (compatibility version 0.1.0, current version 0.1.2)
#rpath/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.7.0, current version 5.7.0)
#rpath/QtGui.framework/Versions/5/QtGui (compatibility version 5.7.0, current version 5.7.0)
#rpath/QtCore.framework/Versions/5/QtCore (compatibility version 5.7.0, current version 5.7.0)
/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
So, my question is as follows (For more details check the stuff below):
How can tell qmake to set the path for my library to:
#rpath/QSettingsDialog.framework/Versions/0/QSettingsDialog (compatibility version 0.1.0, current version 0.1.2)
Is there even a way to do this with qmake? I do know how to change this with the install_name_tool, but I would like to add it to the .pro file directly.
What I did so far:
I modified my pro file to change to rpath of the binary to include the path where the library is located at build-time:
otool -l Examples/SimpleExample/SimpleExample.app/Contents/MacOS/SimpleExample
Load command 22
cmd LC_RPATH
cmdsize 136
path /Users/sky/QtProjects/build-QSettingsDialog-Desktop_Qt_5_7_0_clang_64bit-Debug/Examples/SimpleExample/../../QSettingsDialog (offset 12)
Load command 23
cmd LC_RPATH
cmdsize 48
path /Users/sky/Qt/5.7/clang_64/lib (offset 12)
This way I can simply modify the rpath for a release without having to use the install_name_tool. However, for this to work, I need to change the first line to:
#rpath/QSettingsDialog.framework/Versions/0/QSettingsDialog (compatibility version 0.1.0, current version 0.1.2)
In my pro file for the application, i specified the following:
mac {
QMAKE_LFLAGS += -F$$OUT_PWD/../../QSettingsDialog/
QMAKE_LFLAGS += '-Wl,-rpath,\'$$OUT_PWD/../../QSettingsDialog\''
LIBS += -F$$OUT_PWD/../../QSettingsDialog/ -framework QSettingsDialog
}
The last missing piece is how to add the #rpath/. Thanks for your help.
Thanks to the links in the comment of #peppe, I was able to solve the problem:
I had to add
QMAKE_LFLAGS_SONAME = -Wl,-install_name,#rpath/
to the libraries pro file. This way Qt automatically uses #rpath/QSettingsDialog.framework/Versions/0/QSettingsDialog when creating the reference to the framework.

Incongruence with dynamic library directories in MAC

I am trying to include a dynamic library in my project and I am setting up the compilation using the following CMake script:
find_package( DLIB 18.18.0 REQUIRED )
include_directories( ${DLIB_INCLUDE_DIRS} )
add_executable( executable executable.cxx )
target_link_libraries( executable ${dlib_LIBRARIES} )
If I print the directories of the variable ${dlib_LIBRARIES} I get:
/Users/../INSTALL/lib/libdlib.dylib
Which is correct and compiles.
The problem comes when executing the executable and gives the following runtime error:
dyld: Library not loaded: libdlib.18.18.0.dylib
Referenced from: /Users/.../bin/executable
Reason: image not found
Trace/BPT trap: 5
And this seem logic because if I run otool -L executable I get a relative path instead of an absolute path:
$otool -L executable
libdlib.18.18.0.dylib (compatibility version 0.0.0, current version 18.18.0)
Why the path shown by otool is not the same as the path added with target_link_libraries and how could I solve this issue with cmake?

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

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