FoulDev / Spraymaker

Spraymaker is a tool to create high quality sprays in Source engine games
GNU General Public License v3.0
2 stars 1 forks source link

Docker Container for x86_64 Windows target #1

Open FoulDev opened 1 month ago

FoulDev commented 1 month ago

A docker container is needed to reliably build Spraymaker for Windows on x86_64.

I've been using the following container as a starting point, but haven't had success in getting Spraymaker to link against libvips.

FROM ubuntu:22.04
ENTRYPOINT ["/bin/bash"]

# https://mxe.cc/#requirements-debian and other necessary packages
RUN \
    apt-get -y update && \
    apt-get -y upgrade && \
    apt-get -y install \
        autoconf automake autopoint bash bison bzip2 flex g++ g++-multilib \
        gettext git gperf intltool libc6-dev-i386 libgdk-pixbuf2.0-dev \
        libltdl-dev libgl-dev libpcre3-dev libssl-dev libtool-bin \
        libxml-parser-perl lzip make openssl p7zip-full patch perl python3 \
        python3-distutils python3-mako python3-packaging python3-pkg-resources \
        python-is-python3 ruby sed sqlite3 unzip wget xz-utils \
        python3-tomli python3-pip cpio unzip wget && \
    apt-get -y autoremove && \
    apt-get -y autoclean && \
    apt-get -y clean && \
    rm -rf /var/lib/apt/lists/* && \
    exit 0

RUN \
    pip install --upgrade conan && \
    exit 0

RUN \
    cd /opt && \
    git clone https://github.com/mxe/mxe.git && \
    echo 'MXE_TARGETS := x86_64-w64-mingw32.shared'  >> /opt/mxe/settings.mk && \
    echo 'MXE_USE_CCACHE := $(false)'                >> /opt/mxe/settings.mk && \
    echo 'override MXE_PLUGIN_DIRS += plugins/gcc14' >> /opt/mxe/settings.mk && \
    exit 0

ENV PATH="${PATH}:/opt/mxe/usr/bin"

RUN \
    cd /opt/mxe && \
    make -j$(nproc) cc && \
    make -j$(nproc) cmake && \
    make -j$(nproc) ffmpeg && \
    make -j$(nproc) qt6 && \
    make -j$(nproc) qt6-conf && \
    make -j$(nproc) qt6-qtcharts && \
    make -j$(nproc) qt6-qtdeclarative && \
    make -j$(nproc) qt6-qthttpserver && \
    make -j$(nproc) qt6-qtimageformats && \
    make -j$(nproc) qt6-qtmultimedia && \
    make -j$(nproc) qt6-qtscxml && \
    make -j$(nproc) qt6-qtserialport && \
    make -j$(nproc) qt6-qtservice && \
    make -j$(nproc) qt6-qtshadertools && \
    make -j$(nproc) qt6-qtsvg && \
    make -j$(nproc) qt6-qttools && \
    make -j$(nproc) qt6-qttranslations && \
    make -j$(nproc) qt6-qtwebsockets && \
    make -j$(nproc) qt6-qtbase && \
    exit 0

ENV PATH="${PATH}:/opt/mxe/usr/x86_64-w64-mingw32.shared/qt6/bin"

RUN \
    set -eux && \
    echo $PATH && \
    ln -s /opt/mxe/usr/bin/x86_64-w64-mingw32.shared-cmake /usr/local/bin/cmake && \
    cmake --version && \
    qmake --version && \
    exit 0

# crunch/crnlib
RUN \
    cd && \
    git clone https://github.com/DaemonEngine/crunch.git && \
    cd crunch && \
    cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_CRUNCH=OFF -DBUILD_SHARED_LIBCRN=ON . && \
    make -j$(nproc) && \
    make install && \
    find ./crnlib -name "*.h" | cpio -pdm /opt/mxe/usr/x86_64-w64-mingw32.shared/include/crunch && \
    find ./inc    -name "*.h" | cpio -pdm /opt/mxe/usr/x86_64-w64-mingw32.shared/include/crunch && \
    exit 0

Using the prebuilt binary from https://github.com/libvips/build-win64-mxe/releases/tag/v8.15.3

docker run --rm -it -u $(id -u):$(id -g) -v vips-dev-w64-all-8.15.3:/data/libvips -v $(pwd):/app spraymaker-win64-shared

Attempting to compile via

export PKG_CONFIG_PATH=/data/libvips/lib/pkgconfig
cmake -DPKG_CONFIG_EXECUTABLE=/usr/bin/pkg-config -DPKG_CONFIG_ARGN=--define-prefix ..
make -j$(nproc)

Results in

/opt/mxe/usr/bin/x86_64-w64-mingw32.shared-ld: cannot find -lvips-cpp: No such file or directory
/opt/mxe/usr/bin/x86_64-w64-mingw32.shared-ld: cannot find -lvips: No such file or directory

Manually passing the link library directory results in

/opt/mxe/usr/bin/x86_64-w64-mingw32.shared-ld: CMakeFiles/Spraymaker.dir/objects.a(spraymaker.cpp.obj):spraymaker.cpp:(.text+0x69b5): undefined reference to `vips::VOption::set(char const*, std::vector<double, std::allocator<double> >)'
/opt/mxe/usr/bin/x86_64-w64-mingw32.shared-ld: CMakeFiles/Spraymaker.dir/objects.a(imagemanager.cpp.obj):imagemanager.c:(.text+0x1d75): undefined reference to `vips::VImage::bandjoin_const(std::vector<double, std::allocator<double> >, vips::VOption*) const'

Which is one of the tamer linker errors I've gotten attempting this.

FoulDev commented 1 month ago

Problem identified: libvips was linked with libc++, whereas we're linking with libstdc++, resulting in an API match and ABI mismatch.

Example:

// _ZNK4vips6VImage14bandjoin_constE St    6vectorId S           aIdEE  PNS_7VOptionE
// _ZNK4vips6VImage14bandjoin_constENSt3__16vectorIdNS1_9allocatorIdEEEEPNS_7VOptionE
vips::VImage::bandjoin_const(std::     vector<double, std::     allocator<double> >, vips::VOption*) const;
vips::VImage::bandjoin_const(std::__1::vector<double, std::__1::allocator<double> >, vips::VOption*) const;

Possible solutions: