weserv / images

Source code of wsrv.nl (formerly images.weserv.nl), to be used on your own server(s).
https://wsrv.nl/
BSD 3-Clause "New" or "Revised" License
1.84k stars 187 forks source link

How to Build With kleisauke/libvips-packaging? #338

Closed dsimunic closed 2 years ago

dsimunic commented 2 years ago

I'm trying to build weserv module on Debian 11 and link it against the pre-built libvips-cpp.so from kleisauke/libvips-packaging.

The build succeeds, but linking fails with

[100%] Linking CXX executable ../../../bin/weserv-cli
/usr/bin/ld: ../../../lib/libweserv.so.5.0.0: undefined reference to `vips::VImage::new_from_buffer(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, vips::VOption*)'
collect2: error: ld returned 1 exit status
make[2]: *** [src/tools/CMakeFiles/weserv-cli.dir/build.make:104: ../bin/weserv-cli] Error 1
make[1]: *** [CMakeFiles/Makefile2:182: src/tools/CMakeFiles/weserv-cli.dir/all] Error 2
make: *** [Makefile:149: all] Error 2

A simple example .c file linked against that same libvips setup works, so I presume the library and paths are correct. Building against libvips-dev from apt also works, but that version depends on hundreds of files, not fun to copy around.

I made my own pkg-config for vips and vips-cpp, the files are here: https://gist.github.com/dsimunic/1d4bc350191505595071ebd7cdbc3d74, and the build script is here.

What do I need to change to successfully build weserv nginx module with the packaged libvips?

kleisauke commented 2 years ago

Hi @dsimunic,

Sorry for the delay. The pre-built binaries in the kleisauke/libvips-packaging repository were compiled with the devtoolset packages on RHEL/CentOS 7 which forcefully disabled the -D_GLIBCXX_USE_CXX11_ABI=1 compiler flag, see: https://stackoverflow.com/a/52611576.

You can verify this with the readelf utility:

$ readelf -Ws libvips-cpp.so.42 | c++filt | grep -qF "::__cxx11::" && echo "C++11 ABI used" || echo "C++03 ABI used"
C++03 ABI used

So, to take advantage of these pre-built binaries, you should build this project with:

CFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0"
CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0"

This will fix the linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace.

Here is an sample Dockerfile that seems to work for me:

Details ```Dockerfile FROM debian:bullseye LABEL maintainer="Kleis Auke Wolthuizen " ARG NGINX_VERSION=1.21.6 ARG VIPS_VERSION=8.12.2 # https://gist.github.com/kleisauke/91ef7315adbe1ca7455a38b24d28081e ARG PKG_CONFIG_TARBALL=https://gist.github.com/kleisauke/91ef7315adbe1ca7455a38b24d28081e/archive/7f024426a686539b051d6239f84d9d5a6719394c.tar.gz WORKDIR /opt/libvips # Update packages RUN apt-get update -q \ # Install curl && apt-get install -qy --no-install-recommends \ ca-certificates \ curl \ # Download pre-built libvips binaries && curl -Ls https://github.com/kleisauke/libvips-packaging/releases/download/v$VIPS_VERSION/libvips-$VIPS_VERSION-linux-x64.tar.gz | tar -xzC . \ # Download pkgconfig files && mkdir -p lib/pkgconfig \ && curl -Ls $PKG_CONFIG_TARBALL | tar -xzC lib/pkgconfig --strip-components=1 WORKDIR /var/www/imagesweserv # Set default timezone (can be overridden with -e "TZ=Continent/City") ENV TZ=Europe/Amsterdam \ # Update the PKG_CONFIG_PATH environment variable, # since libvips is installed in a non-standard prefix PKG_CONFIG_PATH=/opt/libvips/lib/pkgconfig \ # Ensure dynamic linker finds the pre-built libvips binaries LD_LIBRARY_PATH=/opt/libvips/lib # Setup nginx user and group RUN groupadd nginx \ && useradd -r -g nginx -s /sbin/nologin -c "Nginx web server" nginx \ # Install needed dependencies && apt-get install -qy --no-install-recommends \ cmake \ git \ g++ \ make \ pkg-config \ libpcre2-dev \ libssl-dev \ zlib1g-dev \ # Clone the repository && git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/weserv/images.git . \ # Build CMake-based project && cmake -S . -B _build \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TOOLS=ON \ -DNGX_VERSION=$NGINX_VERSION \ -DCUSTOM_NGX_FLAGS="--prefix=/usr/share/nginx;\ --sbin-path=/usr/sbin/nginx;\ --modules-path=/usr/lib/nginx/modules;\ --conf-path=/etc/nginx/nginx.conf;\ --error-log-path=/var/log/nginx/error.log;\ --http-log-path=/var/log/nginx/access.log;\ --http-client-body-temp-path=/var/lib/nginx/tmp/client_body;\ --http-proxy-temp-path=/var/lib/nginx/tmp/proxy;\ --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi;\ --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi;\ --http-scgi-temp-path=/var/lib/nginx/tmp/scgi;\ --pid-path=/run/nginx.pid;\ --lock-path=/run/lock/subsys/nginx;\ --user=nginx;\ --group=nginx" \ && cmake --build _build -- -j$(nproc) \ && ldconfig \ # Remove build directory and dependencies && rm -rf _build \ && apt-get autoremove --purge -qy \ libpcre2-dev \ libssl-dev \ zlib1g-dev \ && rm -rf /var/lib/apt/lists/* \ # Ensure nginx directories exist with the correct permissions && mkdir -m 700 /var/lib/nginx \ && mkdir -m 700 /var/lib/nginx/tmp \ && mkdir -m 700 /usr/lib/nginx \ && mkdir -m 755 /usr/lib/nginx/modules \ # Forward request and error logs to docker log collector && ln -sf /dev/stdout /var/log/nginx/weserv-access.log \ && ln -sf /dev/stderr /var/log/nginx/weserv-error.log \ # Copy nginx configuration to the appropriate location && cp ngx_conf/*.conf /etc/nginx EXPOSE 80 STOPSIGNAL SIGQUIT CMD ["nginx", "-g", "daemon off;"] ```
kleisauke commented 2 years ago

Thinking about this further, we can also avoid calling the string overload of VImage::new_from_buffer, so that mixed C++ ABIs will work without any issues.

I just did this with commit https://github.com/weserv/images/commit/2b51dd828c220f2b5fed010b6fabca5757f03117, so please ignore the above comment. Thanks for reporting this!

dsimunic commented 2 years ago

Didn't know that compilation output can differ between distributions. TIL a lot.

Thanks so much for taking the time to look into this and sorting it out. And thanks for the awesome plugin.