# FROM must be called before other ARGS except for ARG BASE_IMAGE
ARG BASE_IMAGE=nvidia/cuda:12.1.0-cudnn8-devel-ubuntu20.04
FROM ${BASE_IMAGE}

# Customizable build arguments from cuda.yml
ARG DEVELOPER_BUILD
ARG CCACHE_TAR_NAME
ARG CMAKE_VERSION
ARG CCACHE_VERSION
ARG PYTHON_VERSION
ARG BUILD_TENSORFLOW_OPS
ARG BUILD_PYTORCH_OPS
ARG CI

# Forward all ARG to ENV
# ci_utils.sh requires these environment variables
ENV DEVELOPER_BUILD=${DEVELOPER_BUILD}
ENV CCACHE_TAR_NAME=${CCACHE_TAR_NAME}
ENV CMAKE_VERSION=${CMAKE_VERSION}
ENV CCACHE_VERSION=${CCACHE_VERSION}
ENV PYTHON_VERSION=${PYTHON_VERSION}
ENV BUILD_PYTORCH_OPS=${BUILD_PYTORCH_OPS}
ENV BUILD_TENSORFLOW_OPS=${BUILD_TENSORFLOW_OPS}

# Prevent interactive inputs when installing packages
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=America/Los_Angeles
ENV SUDO=command

# Miniconda requires bash as the default shell.
SHELL ["/bin/bash", "-c"]

# Fix Nvidia repo key rotation issue
# https://forums.developer.nvidia.com/t/notice-cuda-linux-repository-key-rotation/212771
# https://forums.developer.nvidia.com/t/18-04-cuda-docker-image-is-broken/212892/10
# https://code.visualstudio.com/remote/advancedcontainers/reduce-docker-warnings#:~:text=Warning%3A%20apt%2Dkey%20output%20should,not%20running%20from%20a%20terminal.
RUN export APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn \
 && apt-key del 7fa2af80 \
 && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/3bf863cc.pub \
 && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/7fa2af80.pub

# Dependencies: basic
RUN apt-get update && apt-get install -y \
    git  \
    wget \
    curl \
 && rm -rf /var/lib/apt/lists/*

# Dependencies: cmake
RUN CMAKE_VERSION_NUMBERS=$(echo "${CMAKE_VERSION}" | cut -d"-" -f2) \
 && wget -q https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION_NUMBERS}/${CMAKE_VERSION}.tar.gz \
 && tar -xf ${CMAKE_VERSION}.tar.gz \
 && cp -ar ${CMAKE_VERSION} ${HOME}
ENV PATH=${HOME}/${CMAKE_VERSION}/bin:${PATH}

# Dependencies: ccache
WORKDIR /root
RUN git clone https://github.com/ccache/ccache.git \
 && cd ccache \
 && git checkout v${CCACHE_VERSION} -b ${CCACHE_VERSION} \
 && mkdir build \
 && cd build \
 && cmake -DCMAKE_BUILD_TYPE=Release -DZSTD_FROM_INTERNET=ON .. \
 && make install -j$(nproc) \
 && which ccache \
 && ccache --version \
 && ccache -s

# Download ccache from GCS bucket (optional)
# Example directory structure:
# CCACHE_DIR        = ~/.cache/ccache
# CCACHE_DIR_NAME   = ccache
# CCACHE_DIR_PARENT = ~/.cache
RUN CCACHE_DIR=$(ccache -p | grep cache_dir | grep -oE "[^ ]+$") \
 && CCACHE_DIR_NAME=$(basename ${CCACHE_DIR}) \
 && CCACHE_DIR_PARENT=$(dirname ${CCACHE_DIR}) \
 && mkdir -p ${CCACHE_DIR_PARENT} \
 && cd ${CCACHE_DIR_PARENT} \
 && (wget -q https://storage.googleapis.com/open3d-ci-cache/${CCACHE_TAR_NAME}.tar.gz || true) \
 && if [ -f ${CCACHE_TAR_NAME}.tar.gz ]; then tar -xf ${CCACHE_TAR_NAME}.tar.gz; fi
# We need to set ccache size explicitly with -M, otherwise the default size is
# *not* determined by ccache's default, but the downloaded ccache file's config.
RUN ccache -M 5G \
 && ccache -s

# Miniconda
ENV PATH="/root/miniconda3/bin:${PATH}"
RUN wget -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
 && bash Miniconda3-latest-Linux-x86_64.sh -b \
 && rm Miniconda3-latest-Linux-x86_64.sh \
 && conda --version
ENV PATH="/root/miniconda3/envs/open3d/bin:${PATH}"
RUN conda create -y -n open3d python=${PYTHON_VERSION} \
 && source activate open3d
RUN which python \
 && python --version

# Checkout Open3D-ML main branch
# TODO: We may add support for local Open3D-ML repo or pinned ML repo tag
ENV OPEN3D_ML_ROOT=/root/Open3D-ML
RUN git clone --depth 1 https://github.com/isl-org/Open3D-ML.git ${OPEN3D_ML_ROOT}

# Open3D C++ dependencies
# Done before copying the full Open3D directory for better Docker caching
COPY ./util/install_deps_ubuntu.sh /root/Open3D/util/
RUN /root/Open3D/util/install_deps_ubuntu.sh assume-yes \
 && rm -rf /var/lib/apt/lists/*

# Open3D Python dependencies
COPY ./util/ci_utils.sh /root/Open3D/util/
COPY ./python/requirements.txt /root/Open3D/python/
COPY ./python/requirements_jupyter_build.txt /root/Open3D/python/
COPY ./python/requirements_jupyter_install.txt /root/Open3D/python/
RUN source /root/Open3D/util/ci_utils.sh \
 && install_python_dependencies with-jupyter

# Open3D Jupyter dependencies
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
 && apt-get install -y nodejs \
 && rm -rf /var/lib/apt/lists/* \
 && node --version
RUN npm install -g yarn \
 && yarn --version

# Open3D repo
# Always keep /root/Open3D as the WORKDIR
COPY . /root/Open3D
WORKDIR /root/Open3D

# Build python wheel
RUN export NPROC=$(nproc) \
 && export BUILD_SHARED_LIBS=OFF \
 && source /root/Open3D/util/ci_utils.sh \
 && build_pip_package build_azure_kinect build_jupyter \
 && if [ ${CI:-}a != a ]; then cd /root/Open3D/build/ && ls | grep -Ev '^lib$' | xargs rm -rf ; fi
 # remove build folder (except lib) to save CI space on Github

# Compress ccache folder, move to / directory
RUN ccache -s \
 && CCACHE_DIR=$(ccache -p | grep cache_dir | grep -oE "[^ ]+$") \
 && CCACHE_DIR_NAME=$(basename ${CCACHE_DIR}) \
 && CCACHE_DIR_PARENT=$(dirname ${CCACHE_DIR}) \
 && cd ${CCACHE_DIR_PARENT} \
 && tar -czf /${CCACHE_TAR_NAME}.tar.gz ${CCACHE_DIR_NAME}

RUN echo "Docker build done."
