<% image = "ubuntu:20.04" %>
FROM <%= image %>

ARG TARGETPLATFORM

##
## Install required base packages for compiling ruby
##
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
    apt-get install -y sudo wget curl git-core build-essential xz-utils unzip dirmngr && \
    apt-get install -y autoconf cmake pkg-config zlib1g-dev libreadline-dev libsqlite0-dev libssl-dev libyaml-dev libffi-dev && \
    rm -rf /var/lib/apt/lists/*

##
##  install rbenv and ruby-build
##
RUN groupadd -r rubyuser && useradd -r -g rubyuser -G sudo -p "" --create-home rubyuser

ENV RBENV_ROOT=/usr/local/rbenv

# chown after running `rbenv init` because that command creates some subdirectories
RUN git clone https://github.com/rbenv/rbenv.git      ${RBENV_ROOT} && \
    git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
    \
    echo "export RBENV_ROOT=/usr/local/rbenv" >> /etc/rubybashrc && \
    echo "export PATH=$RBENV_ROOT/bin:\$PATH" >> /etc/rubybashrc && \
    $RBENV_ROOT/bin/rbenv init - --no-rehash bash >> /etc/rubybashrc && \
    echo "source /etc/rubybashrc" >> /etc/bashrc && \
    echo "source /etc/rubybashrc" >> /etc/bash.bashrc && \
    \
    chown -R rubyuser:rubyuser ${RBENV_ROOT} && \
    find ${RBENV_ROOT} -type d -print0 | sudo xargs -0 chmod g+sw
ENV BASH_ENV=/etc/rubybashrc


##
##  set up rake-compiler and install bootstrap rubies
##
USER rubyuser

ENV RBENV_RUBIES="3.1.7 4.0.0"

# Install the bootstrap rubies
RUN bash -c " \
  echo 'gem: --no-ri --no-rdoc --no-document' >> ~/.gemrc && \
  export CFLAGS='-s -O3 -fno-fast-math -fPIC' && \
  for v in ${RBENV_RUBIES} ; do \
    rbenv install \$v -- --disable-install-doc ; \
  done && \
  find ${RBENV_ROOT} -type d -print0 | sudo xargs -0 chmod g+w \
"

# Install rake-compiler and patch it to build and install static libraries for Linux rubies
COPY build/patches /home/rubyuser/patches
RUN bash -c " \
  for v in ${RBENV_RUBIES} ; do \
    rbenv shell \$v && \
    gem install rake-compiler -v1.3.1 && \
    cd ${RBENV_ROOT}/versions/\$v/lib/ruby/gems/*/gems/rake-compiler-1.3.1 && \
    for patch in /home/rubyuser/patches/rake-compiler-1.3.1/*.patch ; do \
      patch -p1 < \$patch ; \
    done \
  done \
"

# Install rake-compiler's cross rubies in global dir instead of /root
RUN sudo mkdir -p /usr/local/rake-compiler && \
    sudo chown rubyuser.rubyuser /usr/local/rake-compiler && \
    ln -s /usr/local/rake-compiler ~/.rake-compiler

USER root

##
## Install cross compilers
##
<% if platform =~ /x64-mingw-ucrt/ %>
COPY --from=larskanis/mingw64-ucrt:20.04 \
    /build/binutils-mingw-w64-x86-64_*.deb \
    /build/g++-mingw-w64-x86-64_*.deb \
    /build/gcc-mingw-w64-base_*.deb \
    /build/gcc-mingw-w64-x86-64_*.deb \
    /build/mingw-w64-common_*.deb \
    /build/mingw-w64-x86-64-dev_*.deb \
    /debs/
RUN dpkg -i /debs/*.deb

<% elsif platform =~ /aarch64-mingw-ucrt/ %>

RUN <<EOF
    if [ "$TARGETPLATFORM" = "linux/amd64" ]; then
        DOWNLOAD_PLATFORM="x86_64";
    elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then
        DOWNLOAD_PLATFORM="aarch64";
    else
        echo "Unsupported platform $TARGETPLATFORM";
        exit 1;
    fi &&
    wget https://github.com/mstorsjo/llvm-mingw/releases/download/20250114/llvm-mingw-20250114-ucrt-ubuntu-20.04-$DOWNLOAD_PLATFORM.tar.xz &&
    tar xf llvm-mingw*.tar.xz &&
    mv `ls -d llvm-mingw-*/` /llvm-mingw &&
    echo "export PATH=/llvm-mingw/bin:\$PATH" >> /etc/rubybashrc &&
    rm -r /llvm-mingw/bin/i686-w64* /llvm-mingw/bin/armv7-w64* /llvm-mingw/bin/x86_64-w64* /llvm-mingw/i686-w64* /llvm-mingw/armv7-w64* /llvm-mingw/x86_64-w64*
EOF

<% elsif platform =~ /linux-musl/ %>
COPY build/mk_musl_cross.sh /tmp
RUN /tmp/mk_musl_cross.sh <%= target %>

<% else %>
RUN apt-get -y update && \
    apt-get install -y <%
if platform =~ /darwin/            %> clang python lzma-dev libxml2-dev libssl-dev libc++-10-dev <% end %><%
if platform =~ /aarch64-linux-gnu/ %> gcc-aarch64-linux-gnu g++-aarch64-linux-gnu <% end %><%
if platform =~ /arm-linux-gnu/     %> gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf <% end %><%
if platform =~ /x86-linux-gnu/     %> gcc-i686-linux-gnu g++-i686-linux-gnu <% end %><%
if platform =~ /x86_64-linux-gnu/  %> gcc-x86-64-linux-gnu g++-x86-64-linux-gnu <% end %><%
if platform =~ /x86-mingw32/       %> gcc-mingw-w64-i686 g++-mingw-w64-i686 <% end %><%
if platform =~ /x64-mingw32/       %> gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 <% end %> && \
    rm -rf /var/lib/apt/lists/*
<% end %>

<% if platform =~ /darwin/ %>
COPY build/mk_osxcross.sh /tmp
RUN /tmp/mk_osxcross.sh

# Install mig which is a Macos specific RPC code generator, which is part of xcode
RUN apt-get -y update && \
    apt-get install -y bison flex && \
    rm -rf /var/lib/apt/lists/*
RUN git clone --branch=cross_platform https://github.com/markmentovai/bootstrap_cmds && \
    cd bootstrap_cmds && \
    autoreconf --install && \
    sh configure && \
    make && \
    sed -E -i 's/^cppflags=(.*)/cppflags=(\1 "-D<%= platform =~ /arm64/ ? "__arm64__" : "__x86_64__" %>" "-I\/opt\/osxcross\/target\/SDK\/MacOSX11.1.sdk\/usr\/include")/' migcom.tproj/mig.sh && \
    sudo make install && \
    cd .. && \
    rm -rf bootstrap_cmds
<% end %>

USER rubyuser

<%
#
# Build ruby versions with ruby2_keywords using ruby-3.x
#
# Note that parallel builds of ruby with make flag `-j` are often flaky, see
# https://bugs.ruby-lang.org/issues/18506
#
xrubies_build_plan = if platform =~ /x64-mingw-ucrt/
  [
    # Rubyinstaller-3.1+ is platform x64-mingw-ucrt
    ["3.3.10:3.2.9:3.1.7", "3.1.7"],
    ["4.0.0:3.4.8", "4.0.0"],
  ]
elsif platform =~ /aarch64-mingw-ucrt/
  [
    ["4.0.0:3.4.8", "4.0.0"],
  ]
elsif platform =~ /x64-mingw32/
  [
    # Rubyinstaller prior to 3.1 is platform x64-mingw32
    ["3.0.7", "3.1.7"],
  ]
elsif platform =~ /x86-mingw32/
  [
    # There's no Rubyinstaller-4.x for platform x86-mingw32
    ["3.3.10:3.2.9:3.1.7:3.0.7", "3.1.7"],
    ["3.4.8", "4.0.0"],
  ]
else
  [
    ["3.3.10:3.2.9:3.1.7:3.0.7", "3.1.7"],
    ["4.0.0:3.4.8", "4.0.0"],
  ]
end

strip = '-s' if platform !~ /darwin|aarch64-mingw/

xrubies_build_plan.each do |xrubies, bootstrap_ruby_version| %>
RUN bash -c " \
  rbenv shell <%= bootstrap_ruby_version %> && \
  export CPPFLAGS='<%= "-D__USE_MINGW_ANSI_STDIO=1" if platform =~ /x64-mingw-ucrt/ %>' && \
  export CFLAGS='-O1 -fno-omit-frame-pointer -fno-fast-math -fstack-protector-strong <%= strip %>' && \
  export LDFLAGS='-pipe <%= strip %>' && \
  <%= "export LIBS='-l:libssp.a -lpthread' &&" if platform =~ /mingw/ %> \
  <%= "export CC=#{target}-clang &&" if platform =~ /darwin/ %> \
  export MAKE='make V=1' && \
  rake-compiler cross-ruby VERSION=<%= xrubies %> HOST=<%= target %> && \
  rm -rf ~/.rake-compiler/builds ~/.rake-compiler/sources \
"
<% end %>
# "

<% if platform =~ /linux/ %>
# Avoid linking against libruby shared object.
# See also https://github.com/rake-compiler/rake-compiler-dock/issues/13
RUN find /usr/local/rake-compiler/ruby/*linux*/ -name libruby.so | xargs rm
RUN find /usr/local/rake-compiler/ruby/*linux*/ -name libruby-static.a | while read f ; do cp $f `echo $f | sed s/-static//` ; done
RUN find /usr/local/rake-compiler/ruby/*linux*/ -name libruby.a | while read f ; do ar t $f | xargs ar d $f ; done
RUN find /usr/local/rake-compiler/ruby/*linux*/ -name mkmf.rb | while read f ; do sed -i ':a;N;$!ba;s/TRY_LINK = [^\n]*\n[^\n]*\n[^\n]*LOCAL_LIBS)/& -lruby-static -lpthread -lrt -ldl -latomic/' $f ; done
<% end %>

<% if platform =~ /mingw/ %>
# RubyInstaller doesn't install libgcc -> link it static.
RUN find /usr/local/rake-compiler/ruby/*mingw*/ -name rbconfig.rb | while read f ; do sed -i 's/."LDFLAGS". = "/&-static-libgcc /' $f ; done
# Don't link to static libruby
RUN find /usr/local/rake-compiler/ruby -name lib*-ruby*.dll.a | while read f ; do n=`echo $f | sed s/.dll//` ; mv $f $n ; done
<% end %>

<% if platform =~ /darwin/ %>
# for rubies which use `-bundle_loader` on darwin
# - the upstream change: https://github.com/ruby/ruby/pull/6193
# - how we got to this solution: https://github.com/rake-compiler/rake-compiler-dock/issues/87
#
# note that ruby/ruby#6193 was backported to 2.7.7, 3.0.5, and 3.1.3
# - see https://github.com/rake-compiler/rake-compiler-dock/issues/134 for more notes
RUN find /usr/local/rake-compiler/ruby/*/*/lib/ruby -name rbconfig.rb | while read f ; do \
      sed -E -i 's/(\["EXTDLDFLAGS"\] = ".*)(-bundle_loader)/\1-Wl,-flat_namespace \2/' $f ; \
    done
<% end %>


##
##  Final adjustments
##
USER root

<% if platform =~ /(x64|x86)-mingw/ %>
# Install wrappers for strip commands as a workaround for "Protocol error" in boot2docker.
COPY build/strip_wrapper_vbox /root/
RUN mv /usr/bin/<%= target %>-strip /usr/bin/<%= target %>-strip.bin && \
    ln /root/strip_wrapper_vbox /usr/bin/<%= target %>-strip

# Use posix pthread for mingw so that C++ standard library for thread could be
# available such as std::thread, std::mutex, so on.
# https://sourceware.org/pthreads-win32/
RUN printf "1\n" | update-alternatives --config <%= target %>-gcc && \
    printf "1\n" | update-alternatives --config <%= target %>-g++
<% end %>

<% if platform =~ /aarch64-mingw/ %>
# Fool libtool to allow building a shared library although linking to libclang_rt.builtins-aarch64.a
#
# Linker option "-llibclang_rt.builtins-aarch64.a" is required on Windows on ARM when compiling C++ and when clang is called with -nostdlib (due to be invoked by libtool).
# Unfortunately libtool then forces a static build.
# This is a ugly hack to make libtool beleave that the library is a DLL instead of an archive and to allow building a DLL instand.
#
RUN sudo cp /llvm-mingw/aarch64-w64-mingw32/bin/libc++.dll /llvm-mingw/aarch64-w64-mingw32/lib/libclang_rt.builtins-aarch64.0
<% end %>

<% if platform =~ /darwin/ %>
# Install wrapper around strip to re-sign binaries (ad-hoc signature)
COPY build/strip_wrapper_codesign /root/
RUN mv /opt/osxcross/target/bin/<%= target %>-strip /opt/osxcross/target/bin/<%= target %>-strip.bin && \
    ln /root/strip_wrapper_codesign /opt/osxcross/target/bin/<%= target %>-strip
<% end %>

<% if platform =~ /arm64-darwin/ %>
# Add a arm64 darwin target as alternative to aarch64
RUN grep -E 'rbconfig-aarch64-darwin' /usr/local/rake-compiler/config.yml | sed 's/rbconfig-[a-z0-9_]*-darwin/rbconfig-<%= platform %>/' >> /usr/local/rake-compiler/config.yml
<% end %>

# Install SIGINT forwarder
COPY build/sigfw.c /root/
RUN gcc $HOME/sigfw.c -o /usr/bin/sigfw

# Install user mapper
COPY build/runas /usr/bin/
COPY build/rcd-env.sh /etc/profile.d/
RUN echo 'source /etc/profile.d/rcd-env.sh' >> /etc/rubybashrc

# Install sudoers configuration
COPY build/sudoers /etc/sudoers.d/rake-compiler-dock

RUN bash -c "rbenv global 4.0.0"

ENV RUBY_CC_VERSION=4.0.0:3.4.8:3.3.10:3.2.9:3.1.7:3.0.7

CMD bash
