Home > Net >  Using custom OpenCV build in installed library via CMake
Using custom OpenCV build in installed library via CMake

Time:01-20

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.

  • Related