# Development environment for webserv.
#
# Target platform is Linux, because that is what the Codam VMs run and what the
# official testers are built for. The base is Ubuntu 22.04, the same release
# those VMs run, so this image is that environment rather than something close
# to it. A newer base would be the permissive side of the difference: its glibc
# accepts everything the older one does and more, so code that cannot run at
# school would still build clean here. On 24.04 a plain std::strtoul compiles
# into a call to __isoc23_strtoul, a GLIBC_2.38 symbol that 22.04 does not have,
# at every -std= and not only at C++23.
#
# 22.04 ships neither compiler this project needs, so two repositories are
# added: ubuntu-toolchain-r/test for g++ 14, apt.llvm.org for clang 18. Both
# publish builds made for 22.04, which is what keeps the produced binary
# runnable there.
#
# libc++ is installed alongside libstdc++ for one specific reason: clang 18
# reports __cpp_concepts as 201907, and libstdc++ gates <expected> on 202002L,
# so clang + libstdc++ compiles "#include <expected>" into nothing at all. The
# control build with clang — a second opinion on warnings, and the sanitizers —
# would die on the first function returning Result<T>. "make check-clang" passes
# -stdlib=libc++ for exactly this.
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
      ca-certificates \
      gnupg \
      wget \
      lsb-release \
      software-properties-common \
 && add-apt-repository -y ppa:ubuntu-toolchain-r/test \
 && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
      | gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg \
 && echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg]" \
         "http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" \
      > /etc/apt/sources.list.d/llvm.list \
 && apt-get update

RUN apt-get install -y --no-install-recommends \
      build-essential \
      g++-14 \
      clang-18 \
      clang-tidy-18 \
      clang-format-18 \
      libc++-18-dev \
      libc++abi-18-dev \
      libclang-rt-18-dev \
      gdb \
      valgrind \
      strace \
      make \
      git \
      curl \
      siege \
      python3 \
      python3-pip \
      net-tools \
      iproute2 \
      procps \
      less \
      vim \
    && rm -rf /var/lib/apt/lists/*

# Make the versioned tools the defaults, so "c++", "g++", "clang++",
# "clang-tidy" and "clang-format" all point at something that understands C++23.
# Without the last two the Makefile would have to hardcode Ubuntu's versioned
# names, which are wrong everywhere else — Codam included.
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100 \
 && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100 \
 && update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100 \
 && update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-14 100 \
 && update-alternatives --install /usr/bin/clang-tidy clang-tidy \
      /usr/bin/clang-tidy-18 100 \
 && update-alternatives --install /usr/bin/clang-format clang-format \
      /usr/bin/clang-format-18 100

# Run as a normal user whose uid/gid match the host account, so files created
# inside the container (object files, uploads, test output) do not end up owned
# by root on the macOS side of the bind mount.
ARG UID=1000
ARG GID=1000
RUN if getent passwd ${UID} >/dev/null; then userdel -r "$(getent passwd ${UID} | cut -d: -f1)"; fi \
 && groupadd -g ${GID} dev 2>/dev/null || true \
 && useradd -m -u ${UID} -g ${GID} -s /bin/bash dev

USER dev
WORKDIR /webserv

CMD ["/bin/bash"]
