# Use Ubuntu 24.04 as base image.  Pinned to linux/amd64: ifx and the
# ifx_linux-64 conda package are x86_64-only, but ubuntu:24.04 is
# multi-arch, so on an arm64 host (e.g. Apple Silicon) an unpinned `docker
# build` silently pulls the arm64 variant and environment.yaml's conda
# solve fails to resolve ifx_linux-64 against it.
FROM --platform=linux/amd64 ubuntu:24.04

# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive

# Version of the repository to build: leave unset (default) to build from
# this local checkout, including any uncommitted changes; set to a tag or
# commit hash (--build-arg GIT_REF=v0.9.0) to instead clone and check out
# that exact revision from GitHub, ignoring the local checkout.
ARG GIT_REF=""

# Install necessary packages
# g++/gcc/make/libz-dev/perl are needed to build TAU and its downloaded dependencies
RUN apt-get update && apt-get install -y \
    wget \
    bzip2 \
    ca-certificates \
    curl \
    git \
    nano \
    vim \
    g++ \
    gcc \
    make \
    libz-dev \
    perl \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Set up working directory for packages
WORKDIR /packages

# Install Anaconda
RUN wget https://repo.anaconda.com/archive/Anaconda3-2024.10-1-Linux-x86_64.sh -O /tmp/anaconda.sh \
    && bash /tmp/anaconda.sh -b -p /opt/anaconda \
    && rm /tmp/anaconda.sh

# Add Anaconda to PATH
ENV PATH="/opt/anaconda/bin:${PATH}"

# Initialize conda for bash shell
RUN echo ". /opt/anaconda/etc/profile.d/conda.sh" >> ~/.bash_profile
RUN echo ". /opt/anaconda/etc/profile.d/conda.sh" >> ~/.bashrc

# Copy environment.yaml file
COPY environment.yaml .

# Create conda environment from the yaml file (fpm and the python packages;
# no compiler -- environment.yaml is shared by every container, including
# the llvm/jupyter ones, which must never pull Intel's ifx), then add ifx on
# top of it, same as Dockerfile_intel.
#
# Ordering note: both of these must come before the TAU build below because
# TAU's configure step needs ifx from this environment.  It would be
# tempting to build TAU first (it takes by far the longest, and editing
# either of these commands invalidates the TAU layer), but the environment
# must be fully in place -- python packages and ifx alike -- before TAU's
# configure runs.
RUN conda env create -f environment.yaml
RUN conda install -n band -c https://software.repos.intel.com/python/conda ifx_linux-64 --yes
RUN echo "conda activate band" >> ~/.bash_profile
RUN echo "conda activate band" >> ~/.bashrc

# Source - https://stackoverflow.com/a/39777387
# Posted by Ahmad Abdelghany, modified by community. See post 'Timeline' for change history
# Retrieved 2025-11-09, License - CC BY-SA 4.0
# this command, together with putting conda activation in .bash_profile, means we have
# enabled the conda environment for every command
SHELL ["/bin/bash", "--login", "-c"]

# Check out TAU
RUN git clone https://github.com/UO-OACISS/tau2.git --depth=1

# Build TAU with Intel Fortran (ifx) and system gcc/g++ for C/C++
# -pthread to enable pthread support
# -bfd, -unwind, -dwarf, -otf enable sampling and tracing support
# Don't specify -mpi to build without MPI
RUN cd /packages/tau2 \
    && ./configure -cc=gcc -c++=g++ -fortran=ifx -bfd=download -unwind=download -dwarf=download -otf=download -pthread \
    && make -j install

# Add TAU binaries to PATH (TAU installs into <arch>/bin under its source tree)
ENV PATH="/packages/tau2/x86_64/bin:${PATH}"

# TAU's downloaded libelf installs as libelf.so but the dynamic linker looks for libelf.so.1
RUN ln -s /packages/tau2/x86_64/libelf-devel-0.158-6.1.x86_64/lib64/libelf.so \
          /packages/tau2/x86_64/libelf-devel-0.158-6.1.x86_64/lib64/libelf.so.1

# Make libelf and the Intel math libraries (from the band conda env) findable at runtime
ENV LD_LIBRARY_PATH="/packages/tau2/x86_64/libelf-devel-0.158-6.1.x86_64/lib64:/opt/anaconda/envs/band/lib:${LD_LIBRARY_PATH}"

WORKDIR /app

# Stage the source: defaults to this local checkout; if GIT_REF is set,
# the RUN step below discards this and clones that revision instead.
COPY src /tmp/band_src/src/
COPY test /tmp/band_src/test
COPY fpm.toml /tmp/band_src/
COPY python /tmp/band_src/python/
COPY scripts /tmp/band_src/scripts/

RUN if [ -n "$GIT_REF" ]; then \
        echo "Building band_distribution @ $GIT_REF (overriding local checkout)" && \
        rm -rf /tmp/band_src && \
        git clone https://github.com/det-lab/band_distribution.git /tmp/band_src && \
        cd /tmp/band_src && git checkout "$GIT_REF"; \
    else \
        echo "Building band_distribution from the local checkout"; \
    fi

RUN mkdir -p /app/src /app/test /app/python /app/scripts \
    && cp -r /tmp/band_src/src/. /app/src/ \
    && cp -r /tmp/band_src/test/. /app/test/ \
    && cp -r /tmp/band_src/python/. /app/python/ \
    && cp -r /tmp/band_src/scripts/. /app/scripts/ \
    && cp /tmp/band_src/fpm.toml /app/ \
    && rm -rf /tmp/band_src

# version.f90.inc (PpqFort_version(); not committed, see the script) must
# exist before fpm build/test -- it is a plain `include` in src/PpqFort_m.f90
RUN python scripts/generate_version_include.py

# Link the Intel OpenMP runtime into everything fpm builds here (including
# interactive fpm invocations inside the container); without -liomp5 the
# Python ctypes load of libband_distribution.so fails on __kmpc_* symbols.
ENV FPM_LDFLAGS="-liomp5"

# Published normalization tables (python/cli/table_registry.json), fetched and
# hash-checked at build time -- HPC compute nodes often have no internet.
# python/cli/normtables.py (and so PpqPDF(ppqn_table=NAME)) finds them here.
ENV BAND_TABLES_DIR=/app/tables
RUN mkdir -p /app/tables && python /app/python/cli/normtables.py fetch --all

# Now compile the fortran code
RUN fpm test --compiler ifx --flag "-fpp -O3 -qopenmp -DHAVE_MULTI_IMAGE_SUPPORT=0" --profile release \
    && fpm install --compiler ifx --flag "-fpp -O3 -qopenmp -DHAVE_MULTI_IMAGE_SUPPORT=0" --profile release --prefix .

# Needed to find the appropriate .so files from within python
ENV LD_LIBRARY_PATH=/app/lib:${LD_LIBRARY_PATH}
