QMAKE: RPATH is cleared after linuxdeployqt - dll

Our project implements automatic deployment through linuxdeployqt , which is called in qmake. But after calling linuxdeployqt the RPATH is cleared and dynamic libraries cannot be found
( QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN/libs\'" is also cleared).
Can you tell me how to stop linuxdeployqt from changing the RPATH or is there a way to overwrite this path?

Related

How to debug Qt executable when use CMake + MSVC?

I create usual hello-world Qt executable via cmake+msvc.
But I cant launch or debug it - the launсh fails by the reason of the absence needed Qt dll.
I found that if I add the
D:\libs\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin;
D:\libs\Qt\Qt5.14.2\5.14.2\msvc2017_64\plugins\platforms;
to the PATH environment variable - the issue gone.
But I dont want that paths in the global environment variables (I plan to have few different versions of the Qt libraries, so all time switching global environment variables will be unusable).
How I could pass the paths to Qt librariles to the cmake for debug/launch executable without modifying the global environment variables?
here is my solution.
open Tools > Options > Debugging > Symbols > add new location.
the location is your qt MSVC bin floder, in my case is "D:\Qt\6.2.2\msvc2019_64\bin".
don't forget select new location, now you can use vs debug qt exe.
You can add the path to your local debugging environment to your CMake generated Visual Studio Solution, either by adding it in the GUI under Configuration Properties -> Debugging -> Environment
or (since CMake 3.13.0) in your CMakeLists.txt by setting the appropriate property on the target.
set_target_properties(exe_target PROPERTIES VS_DEBUGGER_ENVIRONMENT "PATH=D:\libs\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin;D:\libs\Qt\Qt5.14.2\5.14.2\msvc2017_64\plugins\platforms")
Although these properties are prefixed with VS_DEBUGGER_ they apply to both the Debug and Release versions.
Other VS_DEBUGGER_ properties might be of interest too.
See here for documentation.

Have cmake append a directory to the build RPATH

I'd like to add another directory to a target's BUILD_RPATH property, but I'd like it at the end of the list, so it's searched last, after the other directories that cmake automatically adds to target's BUILD_RPATH. But there doesn't seem to be way to add to the property after the automatic RPATH directories.
At build time, my system libraries are not in the normal locations, but in a staging area. In order to run uninstalled built binaries, I need to add this staging area to the binaries' RPATHs. And this part is straightforward to do and works fine, like this:
add_executable(mybinary ${BINARY_SOURCES})
set_property(TARGET mybinary APPEND PROPERTY BUILD_RPATH ${STAGING_LIB_DIR})
But mybinary also uses a library that it built as part of the same project:
add_library(mylib SHARED ${LIB_SOURCES})
target_link_libraries(mybinary PRIVATE mylib)
When mybinary is run, I'd like it to use the mylib that was just built and is in ${CMAKE_CURRENT_BINARY_DIR}, not another copy somewhere else, perhaps in the system library directory from the last time make install was run to install the project. Or, in my case, a copy of the library in ${STAGING_LIB_DIR}.
cmake will automatically add ${CMAKE_CURRENT_BINARY_DIR}, or whatever is appropriate, for any libraries not from the system to the build RPATH of produced binaries. So when one runs mybinary from the build directory it will search for the mylib in the build directory.
But the problem is it appends these automatic library directories to whatever I have set BUILD_RPATH to. So one gets a final RPATH of ${STAGING_LIB_DIR}:${CMAKE_CURRENT_BINARY_DIR} and the wrong copy of mylib is used.
You could set the SKIP_BUILD_RPATH target property:
SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic generation of an rpath allowing the target to run from the build tree. This property is initialized by the value of the variable CMAKE_SKIP_BUILD_RPATH if it is set when a target is created.
And then manually set the RPATH in whatever way/order you would like without worrying about CMake doing additional things to it.

How can I change the library path of an executable after it has been built/installed?

Let's say I build myTest with cmake. myTest uses /opt/path1/lib/lib.so at compile and link time. After running it a few times I decide that I want myTest to now use /opt/path2/lib.so (same lib name, same interfaces, just different path).
This might be cause I want to temporarily test changes to lib.so without affecting others that might be using it. I also may not have the source to myTest but know that it uses lib.so.
If I used a Makefile and used regular gnu/g++ make I can make this happen by setting LD_LIBRARY_PATH in the local folder. CMake ignores LD_LIB_PATH - so how do I make this happen?
For find a library at runtime, ldd uses (among other things) RPATH directories, embedded into the executable.
By default, when build the executable/library, CMake adds to RPATH directories, where linked libraries are located.
E.g., when link with library /opt/path1/lib/lib.so, CMake adds directory /opt/path1/lib to RPATH. So ldd always finds lib.so library as /opt/path1/lib/lib.so.
For tell CMake to not set RPATH, set CMAKE_SKIP_RPATH variable:
set(CMAKE_SKIP_RPATH TRUE)
After that, ldd will search lib.so in directory, listed in LD_LIBRARY_PATH environment variable.

Building MacOSX Frameworks with CMake

I am trying to build an OS X library using CMake. This libary also includes some amount of resource files (.pdfs used as icon images). In my initial attempts, I have been building the library and the resource files separately as libGeneric.a and generic-Resources.bundle - with, the bundle hosting all the relevant images that libGeneric.a uses.
set (SRC srcfile1.m srcfile2.m)
set (HEADERS srcfile1.h srcfile2.h)
set (ICONS icon1.pdf icon2.pdf)
set (SOURCE_FILE_PROPERTIES ${ICONS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
add_library(generic ${SRC} ${HEADERS})
add_library(generic-Resources MODULE ${ICONS})
set_target_properties(generic-Resources PROPERTIES LINKER_LANGUAGE C) # to suppress CMake error of not able to determine linker language for libary
set_target_properties(generic-Resources PROPERTIES BUNDLE TRUE)
This worked fine, except, I was not able to figure out how to directly include the .bundle in the build process of applications that was using libGeneric.a. The only way I could get CMake to load the bundle was to add it as a source file in the target application. But, since, the bundle had not yet been compiled while running CMake, it would complain that the source file did not exist. As a workaround, I resorted to manually adding the .bundle into xcode after CMake generated the App.xcodeproj file (and I actually compiled the bundle). As this was getting to be cumbersome, I figured I'd try to build a Mac OS X framework instead (to house both the library and the code)
set (SRC srcfile1.m srcfile2.m)
set (HEADERS srcfile1.h srcfile2.h)
set (ICONS icon1.pdf icon2.pdf)
set (SOURCE_FILE_PROPERTIES ${ICONS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
add_library(generic SHARED ${SRC} ${HEADERS} ${ICONS})
set_target_properties(generic PROPERTIES FRAMEWORK TRUE)
set_target_properties(generic PROPERTIES MACOSX_RPATH TRUE) #to suppress cmake warnings on rpath
However, this is creating a framework with just the Icons inside a Resources directory. The code library is missing. I would appreciate some assistance in getting this framework to build correctly. How, do I
get CMake to actually build a library with the indicated source file
and place it inside the framework
get CMake to copy the headers appropriately in the framework.
I am just setting rpath to true now, as I haven't really figured out what to actually do with it. What do I set this to? The objective is to build a private framework, that I would then bundle automatically with my application.
Alternatively, is there an easy way to get CMake to build the bundle file created in my earlier process, and then load that built file into my applications build process.

CMAKE RPATH not working - could not find shared object file

I am trying to get rid of setting LD_LIBRARY_PATH everytime time I run my program. After adding in the library and targeting my executable to the library, when I run it tells me it can not open shared object library, no such file or directory.
In my CMakeLists.txt I have:
add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)
set(CMAKE_SKIP_BUILD_PATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "~/person/target/usr/local/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
I set an absolute link to my library folder to test out whether this would create an rpath to my library and it seems like there isn't. I have checked and made sure that the shared library is indeed in lib. libheart.so is the file that is being linked. What else am I missing?
It is because you build heart and run from the same cmake project:
CMAKE_INSTALL_RPATH_USE_LINK_PATH is an interesting and very useful option. When building a target with RPATH, CMake determines the RPATH by using the directories of all libraries to which this target links. Some of these libraries may be located in the same build tree, e.g. libbar.so, these directories are also added to the RPATH.
If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly
You can try this:
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
More documentation here cmake rpath handling
EDIT:
Only this should work:
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)
install(
TARGETS heart run
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
)
Clean your build directory and then:
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/home/person/target/usr/local ..
make install
At the end of the g++ line Linking CXX executable run you should see like -Wl,-rpath,/home/person/target/usr/local/lib
If you want a fully relocatable package:
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
PS: are you sur that it is libheart.so that is not found ?
In your CMake file, set the RPATH before defining the targets. The CMAKE_INSTALL_RPATH must be defined before calling add_executable(), otherwise it has no effect.
I had a similar issue as the original post. I created executables which linked to external shared libraries. This approach compiled and executed fine from the build directory. However, the executable that was installed to a separate directory could not find a shared library at runtime:
error while loading shared libraries: libxxxx.so.1: cannot open shared object file: No such file or directory
To solve, I
1) upgraded to CMake 3.17
2) used Craig Scott's recommended:
set(CMAKE_INSTALL_RPATH $ORIGIN)
as explained in his talk
3) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) as directly mentioned to solve this error in the second common question in Kitware's documention
4) Put all this before adding the targets as mentioned in this post
5) Used the "$ORIGIN/../lib" syntax instead of Craig's Scott's mentioned $ORIGIN as mentioned by #explo91
In summary, and to my suprise, only the "$ORIGIN/../lib" before the target definition was necessary from above (I tested the other combinations which did not fix the cannot open shared object file runtime issue).
Anyway the solution I finally applied, which may be of better, fine-grained CMake style or at least may be helpful to others on their RPATH journey is:
set_target_properties(target_defined_above PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")