OSGeo / gdal

GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
https://gdal.org
Other
4.67k stars 2.46k forks source link

cmake `GDAL_SET_INSTALL_RELATIVE_RPATH` is not taken into account for `jp2kak` #9365

Closed tjay closed 3 months ago

tjay commented 4 months ago

Building GDAL with GDAL_SET_INSTALL_RELATIVE_RPATH=ON or with CMAKE_INSTALL_RPATH='$ORIGIN:$ORIGIN/../lib' these options result in all libs, except the jp2kak-libs receiving a correct RPATH.

Expected behavior and actual behavior.

Actual behavior

chrpath /opt/mycustomdir/lib/libgdal.so
/opt/giz/mycustomdir/lib/libgdal.so: RPATH=$ORIGIN:$ORIGIN/../lib

ldd /opt/mycustomdir/lib/libgdal.so
        linux-vdso.so.1 (0x00007ffc67d7d000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f052b8d0000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f052b852000)
...
        /opt/giz/mycustomdir/lib/libkdu_v84R.so (0x00007f052a629000)
        /opt/giz/mycustomdir/lib/libkdu_a84R.so (0x00007f052a23f000)
...
        libgeos.so.3.12.1 => /opt/giz/mycustomdir/lib/../lib/libgeos.so.3.12.1 (0x00007f0529875000)
        libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007f0529755000)
...

Expected behavior

chrpath /opt/mycustomdir/lib/libgdal.so
/opt/giz/mycustomdir/lib/libgdal.so: RPATH=$ORIGIN:$ORIGIN/../lib

ldd /opt/mycustomdir/lib/libgdal.so
        linux-vdso.so.1 (0x00007ffc67d7d000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f052b8d0000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f052b852000)
...
        libkdu_v84R.so => /opt/giz/mycustomdir/lib/libkdu_v84R.so (0x00007f052a629000)
        libkdu_a84R.so => /opt/giz/mycustomdir/lib/libkdu_a84R.so (0x00007f052a23f000)
...
        libgeos.so.3.12.1 => /opt/giz/mycustomdir/lib/../lib/libgeos.so.3.12.1 (0x00007f0529875000)
        libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007f0529755000)
...

Steps to reproduce the problem.

PREFIX=/opt/mycustomdir
cmake3 \
...
-D CMAKE_PREFIX_PATH=$PREFIX \
-D CMAKE_INSTALL_PREFIX=$PREFIX \
-D CMAKE_INSTALL_LIBDIR=lib \
-D CMAKE_SKIP_BUILD_RPATH=FALSE \
-D CMAKE_INSTALL_RPATH='$ORIGIN:$ORIGIN/../lib' \
-D CMAKE_BUILD_TYPE=Release \
-D KDU_ROOT=/tmp/v8_4-01854L \
-D GDAL_ENABLE_DRIVER_JP2KAK:BOOL=ON \
gdal-config --dep-libs
-ldl -lssl -lcrypto -lzstd -llzma -L/opt/mycustomdir/lib -ljpeg -ltiff -lpng -lgif -lz -lkdu_v84R -lkdu_a84R -lpcre2-8 -lexpat -lsqlite3 -lpq -lxml2 -lgeos_c -lcurl -lproj -lstdc++ -lm

the kadadu-Libs ( libkdu_v84R.so libkdu_a84R.so) were copied to $PREFIX/lib before build.

Operating system

RHEL 9.2

GDAL version and provenance

GDAL 3.8.4

rouault commented 4 months ago

I'm always struggling to understand those RPATH things but given that you specify an absolute KDU_ROOT, I don't think that any RPATH setting will change it to something relative to the GDAL installation. In any case, GDAL uses standard CMake mechanisms to handle RPATH things, so I don't think we've much control on this.

tjay commented 4 months ago

As far I understand is KDU_ROOT used to find the header files while compiling the plugin (aka /include). https://github.com/OSGeo/gdal/blob/master/cmake/modules/packages/FindKDU.cmake

the precompiled libs have no special references:

ldd /opt/mycustomdir/lib/libkdu_v84R.so
        linux-vdso.so.1 (0x00007ffee4f3a000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ff3614dd000)
        libm.so.6 => /lib64/libm.so.6 (0x00007ff361402000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ff3613e7000)
        libc.so.6 => /lib64/libc.so.6 (0x00007ff3611de000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff361905000)

so maybe in https://github.com/OSGeo/gdal/blob/master/frmts/jp2kak/CMakeLists.txt there is something missing like set_target_properties(... PROPERTIES INSTALL_RPATH ...)

rouault commented 4 months ago

there is something missing like set_target_properties(... PROPERTIES INSTALL_RPATH ...)

I'm skeptical. I let you figure it out. But I'm not sure your expectations are correct

tjay commented 4 months ago

Hi, according to cmake.org/#LINK_INTERFACE_LIBRARIES the part from FindKDU.cmake is used wrong. KDU_LIBRARY and KDU_AUX_LIBRARY are always absolute Paths to .so-files. So the resulting Binary is not relocatable (independent from RPATH or LD_LIBRARY_PATH):

        set_target_properties(KDU::KDU_MAIN PROPERTIES
                            INTERFACE_INCLUDE_DIRECTORIES "${KDU_INCLUDE_DIR}/coresys/common"
                            IMPORTED_LINK_INTERFACE_LANGUAGES "C"
                            IMPORTED_LOCATION "${KDU_LIBRARY}")

        set_target_properties(KDU::KDU_AUX PROPERTIES
                            INTERFACE_INCLUDE_DIRECTORIES "${KDU_INCLUDE_DIR}/apps/compressed_io;${KDU_INCLUDE_DIR}/apps/jp2;${KDU_INCLUDE_DIR}/apps/image;${KDU_INCLUDE_DIR}/apps/args;${KDU_INCLUDE_DIR}/apps/support;${KDU_INCLUDE_DIR}/apps/kdu_compress"
                            IMPORTED_LINK_INTERFACE_LANGUAGES "C"
                            IMPORTED_LOCATION "${KDU_AUX_LIBRARY}")

My issue is fixed by overwrite the KDU_ROOT-automatism just using the archive libraries (.a) generated from the KAKADU build, by setting:

-D KDU_INCLUDE_DIR=/tmp/v8_4 \
-D KDU_LIBRARY="/tmp/v8_4/lib/Linux-x86-64-gcc/libkdu.a" \
-D KDU_AUX_LIBRARY="/tmp/v8_4/lib/Linux-x86-64-gcc/libkdu_aux.a" \

But that might not help everyone ...

dg0yt commented 4 months ago

I'm not expert on these aspects but ... The absolute path in IMPORTED_LOCATION doesn't matter. But do the original libkdu .so files have a SONAME? What is the output of

objdump -p /opt/giz/mycustomdir/lib/libkdu_v84R.so | grep SONAME

AFAIU this would be the name on the left side of =>.

tjay commented 4 months ago

@dg0yt

objdump -p /opt/giz/mycustomdir/lib/libkdu_v84R.so | grep SONAME

is empty. So there is no SONAME. After reading a few docs it looks like this may be the reason why dynamic linking doesn't work as expected. i will contact the deleveloper of libkakadu.

palemieux commented 4 months ago

I simply use the following to include KDU as a library:

find_path(KDU_INCLUDE_DIR kdu_args.h PATH_SUFFIXES kakadu)
find_library(KDU_LIBRARY NAMES kdu_a84R)
include_directories(${KDU_INCLUDE_DIR})
target_link_libraries(... ${KDU_LIBRARY} ...)

See https://github.com/sandflow/libench/blob/main/CMakeLists.txt

tjay commented 4 months ago

@palemieux: Is the binary file you created in this way, correctly dynamically linked? What does ldd say on your final binary? Is there a => for the libkdu*.so files, as in the "Expected behavior" from the issue description?

palemieux commented 4 months ago
ldd libench
...
libkdu_a84R.so => /home/pal/.local/lib/v8_4_1-01908E/libkdu_a84R.so
dg0yt commented 4 months ago

@palemieux For completeness, what is the output for your case:

objdump -p /home/pal/.local/lib/v8_4_1-01908E/libkdu_a84R.so | grep SONAME
palemieux commented 4 months ago

@palemieux For completeness, what is the output for your case:

objdump -p /home/pal/.local/lib/v8_4_1-01908E/libkdu_a84R.so | grep SONAME

No ouput.

rouault commented 3 months ago

Closing as likely not a GDAL bug