OSGeo / gdal

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

cmake --install installs Python bindings without RUNPATH set #10432

Open dbaston opened 1 month ago

dbaston commented 1 month ago

What is the bug?

I am trying to build and install the GDAL Python bindings on a Linux system where I have neither write access to system directories nor the ability to set LD_LIBRARY_PATH. I have created a Python virtual environment and am trying to build GDAL by setting CMAKE_INSTALL_PREFIX, CMAKE_INSTALL_RPATH, and GDAL_PYTHON_INSTALL_PREFIX to point to this environment. When doing this, the build creates two copies of the Python shared libraries: one in swig/python/osgeo that does not set the RUNPATH, and a second in swig/python/for_install/osgeo that does set the RUNPATH. When running cmake --install, the libraries that do not have the RUNPATH set are installed under GDAL_PYTHON_INSTALL_PREFIX.

I am able to install the version with the RUNPATH set by copying setup.py into swig/python/for_install and then running python3 setup.py install. However, I would have expected this to be done by cmake --install. Am I misunderstanding something about how this should function?

Related: #6273, #6371

Steps to reproduce the issue

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y ant cmake doxygen g++ git libproj-dev make openjdk-11-jdk-headless swig unzip
RUN apt-get install -y python3 python3-pip python3-venv python3-numpy

RUN adduser rtd --disabled-password
WORKDIR /home/rtd
USER rtd

RUN python3 -m venv rtd

RUN git clone --depth 1 --branch master https://github.com/osgeo/gdal

RUN mkdir gdal/build && cd gdal/build && cmake \
    -DCMAKE_BUILD_TYPE=Debug \
    -DCMAKE_INSTALL_PREFIX=${HOME}/rtd \
    -DCMAKE_INSTALL_RPATH=${HOME}/rtd/lib \
    -DGDAL_PYTHON_INSTALL_PREFIX=${HOME}/rtd \
    -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \
    -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \
    -DBUILD_APPS=ON \
    -DBUILD_PYTHON_BINDINGS=ON \
    -DBUILD_JAVA_BINDINGS=ON \
    -DBUILD_TESTING=OFF \
    -DGDAL_JAVA_GENERATE_JAVADOC=ON \
    -DBASH_COMPLETIONS_DIR="" \
    ..

RUN cd gdal/build && cmake --build . -j$(nproc)

RUN cmake --install gdal/build

RUN readelf -d rtd/bin/gdalinfo | grep RUNPATH # succeeds
RUN readelf -d rtd/local/lib/python3.12/dist-packages/osgeo/_gdal.cpython-312-x86_64-linux-gnu.so | grep RUNPATH # fails

Versions and provenance

master

Additional context

No response

rouault commented 1 month ago

When running cmake --install, the libraries that do not have the RUNPATH set are installed under GDAL_PYTHON_INSTALL_PREFIX

That's on purpose. CMake default behaviour is to have artifacts in the build directory to have the RPATH set, for convenience of developers. But this is seen as undesirable when installing artifacts, hence CMake removes the rpath on installation. We replicate that behavior for the Python bindings.

dbaston commented 1 month ago

I'm talking not about the default behavior, but the behavior when CMAKE_INSTALL_RPATH is set. This sets RUNPATH for the installed executables but not the installed Python bindings. #6371 makes a fix for the issue when setuptools does the install, but the issue remains with cmake --install.

rouault commented 1 month ago

oh, I see. Your issue might actually be that comment of https://github.com/OSGeo/gdal/pull/6382/files#diff-551e48cf6490157c9880dfacac6e870873440f0de93dc9fb85c65a5994cb6f60R215 (Python bindings building is really dark magic. swig/python/CMakeLists.txt is certainly the most challenging CMake scripts of the whole GDAL tree)

dbaston commented 1 month ago

I think the problem may be that the python .so files are installed via the SCRIPT form of install(), rather than the TARGET form. cmake never knows it's installing them, so it can't apply CMAKE_INSTALL_RPATH.