I have an issue with a binary that is installed via cmake. The binary needs to link to a custom build of OpenCV (in /home/user/opencv
). The normal build of the binary links and runs against the OpenCV just fine. However, the installed version cannot find the OpenCV library that I need.
I do not have much experience with installing binaries via Cmake. So it isn't clear to me whether I am doing something obviously stupid, or whether this is an OpenCV issue.
The minimal example that reproduces the issue looks like this:
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.25)
project(bad_opencv_install)
list(APPEND CMAKE_PREFIX_PATH "/usr/local/cuda-11.4")
set(CMAKE_CXX_STANDARD 11)
set(OpenCV_DIR "$ENV{HOME}/opencv/lib/cmake/opencv4")
message("OpenCV_DIR = ${OpenCV_DIR}")
find_package(OpenCV 4 REQUIRED COMPONENTS cudaimgproc)
add_executable(foo main.cpp)
target_link_libraries(foo PUBLIC opencv_cudaimgproc)
install(TARGETS foo
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/installed/)
main.cpp
:
#include <iostream>
#include <opencv2/cudaimgproc.hpp>
int main() {
cv::cuda::GpuMat mat;
std::cout << "All good" << std::endl;
}
The following shows that the code builds fine:
user@xd:~/bad_opencv$ mkdir build ; cd build && cmake .. && make install
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
OpenCV_DIR = /home/user/opencv/lib/cmake/opencv4
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found CUDA: /usr/local/cuda-11.4 (found suitable exact version "11.4")
-- Found OpenCV: /home/user/opencv (found suitable version "4.6.0", minimum required is "4") found components: cudaimgproc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/bad_opencv/build
[ 50%] Building CXX object CMakeFiles/foo.dir/main.cpp.o
[100%] Linking CXX executable foo
[100%] Built target foo
Install the project...
-- Install configuration: ""
-- Installing: /home/user/bad_opencv/build/installed/foo
-- Set runtime path of "/home/user/bad_opencv/build/installed/foo" to ""
Furthermore, the normal build works:
user@xd:~/bad_opencv/build$ ./foo
All good
But the installed version is not:
user@xd:~/bad_opencv/build$ ./installed/foo
./installed/foo: error while loading shared libraries: libopencv_core.so.406: cannot open shared object file: No such file or directory
user@xd:~/bad_opencv/build$
I don't understand what the install
command is doing, but if I ldd
the binary, the installed version is missing a lot of libraries:
user@xd:~/bad_opencv/build$ ldd foo
linux-vdso.so.1 (0x00007ffe7f5e1000)
libopencv_core.so.406 => /home/user/opencv/lib/libopencv_core.so.406 (0x00007feeee9e8000)
libstdc .so.6 => /lib/x86_64-linux-gnu/libstdc .so.6 (0x00007feeee7c2000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007feeee7a7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007feeee5b5000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007feeee5af000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007feeee58a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007feeee580000)
libtbb.so => /home/user/opencv/lib/libtbb.so (0x00007feeee543000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007feeee527000)
libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007feeee4f3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007feeee3a4000)
/lib64/ld-linux-x86-64.so.2 (0x00007feef014d000)
libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007feeee2ea000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007feeee1ab000)
libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007feeee181000)
libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007feeee17b000)
libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007feeee173000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007feeee157000)
user@xd:~/bad_opencv/build$ ldd ./installed/foo
linux-vdso.so.1 (0x00007ffd251dc000)
libopencv_core.so.406 => not found
libstdc .so.6 => /lib/x86_64-linux-gnu/libstdc .so.6 (0x00007f3ebad7f000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3ebad64000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3ebab72000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3ebaa23000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3ebafac000)
CodePudding user response:
TLDR: I needed to add the following line to CMake:
set_target_properties(foo PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
Apparently, the runpath is stripped off of the binary when installing. I guess that is what this line of the CMake output was trying to tell me:
-- Set runtime path of "/home/user/bad_opencv/build/installed/foo" to ""
I determined this by comparing the readelf output:
readelf -d ./foo
vs
readelf -d ./installed/foo
The former had some output that looked like
0x00000000000000 (RUNPATH) Library runpath: [/usr/local/cuda-11.4/lib64:/home/user/opencv/lib:]
but the latter had no RUNPATH set.