# ============================================================================
# Copyright 2017-2022, Schlumberger
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#      http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================

# base image
FROM ubuntu:20.04 AS dev

# build as root
USER 0

# library path
ARG LIBRARIES_INSTALL_PATH=/usr/local

# install required build tools via packet manager
RUN apt-get -y update && apt-get -y install wget git g++ make libtool pkgconf liblzma-dev

# temporary working directory
WORKDIR /tmp

# [CMAKE]
ARG CMAKE_VERSION=3.19.4
RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \
    && tar -zxvf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz -C /usr/local \
    && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/cmake /usr/bin/cmake \
    && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/ctest /usr/bin/ctest \
    && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/cpack /usr/bin/cpack \
    && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/ccmake /usr/bin/ccmake \
    && rm -rf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz

# ----------------------------------------------------------------------------------------------------------------------------
# if we want to avoid adding shared libraries as depdendencies ( since in linux most of them export all their symbols)
# we need to see if static libraries with Position Indepdent Code are built ( aka, .a that can be used to build .so later on)
#
# the analysis is done with :
#  for slib in /usr/local/lib*/*.a; do echo $slib; readelf --relocs ${slib} | egrep -c '(GOT|PLT|JUMP_SLO)'; done
#
# aka : for all archives, read relocations, see if they are pointing to the global offset table, 
#       the procedure linkage table or are calls to shared libraries ( jump )
#       not quite sure this is exhaustive as this indicates _some relocatable code present_ 
#       not absence of relocations without indirections.
#
# otherwise we'd have to play with visibiliy at library build time, linker version scripts etc.
# ----------------------------------------------------------------------------------------------------------------------------
RUN echo "{" > /versions.json

FROM dev as zlib-dev

# [ZLIB]
ARG LIB_ZLIB_VERSION=1.3.1
RUN wget https://www.zlib.net/zlib-${LIB_ZLIB_VERSION}.tar.gz \
    && tar -zxvf zlib-${LIB_ZLIB_VERSION}.tar.gz \
    && cd zlib-${LIB_ZLIB_VERSION} \
    && CFLAGS=-fPIC ./configure --prefix=${LIBRARIES_INSTALL_PATH} --static \
    && make -j $(nproc) \
    && make install \
    && cd .. \
    && rm -rf zlib-${LIB_ZLIB_VERSION}.tar.gz \
              zlib-${LIB_ZLIB_VERSION}

RUN echo " \"zlib\": { \"version\" : \"${LIB_ZLIB_VERSION}\", \"url\" : \"https://www.zlib.net\" }," >> /versions.json

FROM zlib-dev as openssl-dev
ARG LIBRARIES_INSTALL_PATH=/usr/local

# [OPENSSL]
# this has TCC implications
# consider instead RUN apt-get install openssl-libs openssl-dev
ARG LIB_OPENSSL_VERSION=1.1.1g
RUN wget https://www.openssl.org/source/openssl-${LIB_OPENSSL_VERSION}.tar.gz \
    && tar -zxvf openssl-${LIB_OPENSSL_VERSION}.tar.gz \
    && cd openssl-${LIB_OPENSSL_VERSION} \
    && ./config --prefix=${LIBRARIES_INSTALL_PATH} no-shared \
    && make -j $(nproc) \
    && make install_sw \ 
    && cd .. \
    && rm -rf openssl-${LIB_OPENSSL_VERSION}.tar.gz \
              openssl-${LIB_OPENSSL_VERSION}

RUN echo " \"openssl\": { \"version\" : \"${LIB_OPENSSL_VERSION}\", \"url\" : \"https://www.openssl.org/\" }," >> /versions.json

FROM openssl-dev as uuid-dev

# [UUID]
ARG LIB_UUID_VERSION=1.0.3
RUN wget https://sourceforge.net/projects/libuuid/files/libuuid-${LIB_UUID_VERSION}.tar.gz \
    && tar -zxvf libuuid-${LIB_UUID_VERSION}.tar.gz \
    && cd /tmp/libuuid-${LIB_UUID_VERSION}  \
    && ./configure --prefix=${LIBRARIES_INSTALL_PATH} --with-pic --enable-shared=no --enable-static=yes \
    && make -j $(nproc) \
    && make install \
    && cd .. \
    && rm -rf libuuid-${LIB_UUID_VERSION}.tar.gz \
              libuuid-${LIB_UUID_VERSION}

RUN echo " \"libuuid\":           { \"version\" : \"${LIB_UUID_VERSION}\",              \"url\" : \"https://sourceforge.net/projects/libuuid/\"      }," >> /versions.json

FROM uuid-dev as curl-dev

# [CURL]
# this is not equivalent to the system one built with libtool ... soname, versions are not done the same way.
# may require a patch for locally built nghttp2? or http3 librarie
ARG LIB_CURL_VERSION=7.74.0
RUN git clone -b curl-$(echo "$LIB_CURL_VERSION" | tr . _) https://github.com/curl/curl.git curl --recursive \
    && cd curl \
    && mkdir build \
    && cd build \
    && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. \
    && make -j $(nproc) \
    && make install \
    && cd ../.. \
    && rm -rf curl \
    && ldconfig

RUN echo " \"curl\":              { \"version\" : \"${LIB_CURL_VERSION}\",              \"url\" : \"https://github.com/curl/curl\"                   }," >> /versions.json

FROM curl-dev as boost-dev

# [BOOST]
ARG LIB_BOOST_VERSION=1.73.0
RUN wget https://boostorg.jfrog.io/artifactory/main/release/${LIB_BOOST_VERSION}/source/boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \
    && tar -zxvf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \
    && cd boost_$(echo "$LIB_BOOST_VERSION" | tr . _) \
    && ./bootstrap.sh --prefix=${LIBRARIES_INSTALL_PATH} \
    && ./b2 stage -j $(nproc) threading=multi link=static cxxflags='-fPIC' linkflags='-pie' -q \
    && ./b2 install threading=multi link=static  cxxflags='-fPIC' linkflags='-pie' \
    && ln -svf detail/sha1.hpp ${LIBRARIES_INSTALL_PATH}/include/boost/uuid/sha1.hpp \
    && cd .. \
    && rm -rf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \
              boost_$(echo "$LIB_BOOST_VERSION" | tr . _)

RUN echo " \"boost\":             { \"version\" : \"${LIB_BOOST_VERSION}\",             \"url\" : \"https://boost.org\"                              }," >> /versions.json

FROM boost-dev as azure-dev
ARG LIBRARIES_INSTALL_PATH=/usr/local

# [XML2]
ARG LIB_XML2_VERSION=2.9.10
RUN wget https://github.com/GNOME/libxml2/archive/v${LIB_XML2_VERSION}.tar.gz \
    && tar -zxvf v${LIB_XML2_VERSION}.tar.gz \
    && cd libxml2-${LIB_XML2_VERSION} \
    && ./autogen.sh --prefix=${LIBRARIES_INSTALL_PATH} --with-pic --enable-static=yes --enable-shared=no \
    && make -j $(nproc) \
    && make install \
    && cd .. \
    && rm -rf v${LIB_XML2_VERSION}.tar.gz \
              libxml2-${LIB_XML2_VERSION}

RUN echo " \"libxml2\":           { \"version\" : \"${LIB_XML2_VERSION}\",              \"url\" : \"https://github.com/GNOME/libxml2\"               }," >> /versions.json

# [CPPRESTSDK]
ARG LIB_CPPREST_VERSION=2.10.16
RUN git clone -b v${LIB_CPPREST_VERSION} https://github.com/microsoft/cpprestsdk.git cpprestsdk --recursive \
    && cd cpprestsdk \
    && mkdir build \
    && cd build \
    && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBoost_USE_STATIC_LIBS=ON -DBUILD_SAMPLES=OFF .. \
    && make -j $(nproc) \
    && make install \
    && cd ../.. \
    && rm -rf cpprestsdk \
    && ldconfig

RUN echo " \"cpprest\":           { \"version\" : \"${LIB_CPPREST_VERSION}\",           \"url\" : \"https://github.com/microsoft/cpprestsdk\"        }," >> /versions.json

# [AZURESTORAGECPP]
ARG LIB_AZURE_STORAGE_VERSION=7.5.0
RUN git clone -b v${LIB_AZURE_STORAGE_VERSION} https://github.com/Azure/azure-storage-cpp.git azure-storage-cpp --recursive \
    && cd azure-storage-cpp/Microsoft.WindowsAzure.Storage \
    && mkdir build.release \
    && cd build.release \
    && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBoost_USE_STATIC_LIBS=ON .. \
    && make -j $(nproc) \
    && make install \
    && cd ../../.. \
    && rm -rf azure-storage-cpp \
    && ldconfig

RUN echo " \"azurestorage\":      { \"version\" : \"${LIB_AZURE_STORAGE_VERSION}\",     \"url\" : \"http://github.com/Azure/azure-storage-cpp\"      }," >> /versions.json

# [AZURE-STORAGE-FOR-CPP]
ARG AZURE_STORAGE_FOR_CPP_VERSION=12.4.0
RUN wget https://github.com/Azure/azure-sdk-for-cpp/archive/refs/tags/azure-storage-blobs_${AZURE_STORAGE_FOR_CPP_VERSION}.tar.gz \
    && tar -zxvf azure-storage-blobs_${AZURE_STORAGE_FOR_CPP_VERSION}.tar.gz \
    && cd azure-sdk-for-cpp-azure-storage-blobs_${AZURE_STORAGE_FOR_CPP_VERSION} \
    && mkdir build \
    && cd build \
    && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS:BOOL=NO -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON -DBUILD_TRANSPORT_CURL:BOOL=ON .. \
    && make -j $(nproc) \
    && make install \
    && cd ../../ \
    && rm -rf azure-sdk-for-cpp-azure-storage-blobs_${AZURE_STORAGE_FOR_CPP_VERSION} \
              azure-storage-blobs_${AZURE_STORAGE_FOR_CPP_VERSION}.tar.gz \
    && ldconfig

RUN echo " \"azure_sdk_for_cpp\": { \"version\" : \"${AZURE_STORAGE_FOR_CPP_VERSION}\", \"url\" : \"https://github.com/Azure/azure-sdk-for-cpp\"     }," >> /versions.json

FROM azure-dev as aws-dev

# [CRC32C]
ARG CRC32C_VERSION=1.1.1
RUN wget -O crc32c_${CRC32C_VERSION}.tar.gz https://github.com/google/crc32c/archive/refs/tags/${CRC32C_VERSION}.tar.gz --no-check-certificate \
    && tar -zxvf crc32c_${CRC32C_VERSION}.tar.gz \
    && cd crc32c-${CRC32C_VERSION} \
    && cd .. \
    && cd crc32c-${CRC32C_VERSION} \
    && mkdir build \
    && cd build \
    && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=NO -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCRC32C_BUILD_TESTS=0 -DCRC32C_BUILD_BENCHMARKS=0 -DCRC32C_USE_GLOG=OFF -DENABLE_TESTING=OFF ..  \
    && make -j $(nproc) \
    && make install \
    && rm -rf crc32c_${CRC32C_VERSION} \
              crc32c_${CRC32C_VERSION}.tar.gz \
    && ldconfig

RUN echo " \"crc32c\":            { \"version\" : \"${CRC32C_VERSION}\",            \"url\" : \"https://github.com/google/crc32c\"               }," >> /versions.json

# [AWS SDK PATCHED] # AWS SHOULD FIX IT!
ARG AWS_SDK_CPP_PATCHED_COMMIT=95b4403042458bb1de9697052d6da43c09579ee8
RUN git clone --recursive  https://github.com/alichnewsky/aws-sdk-cpp aws-sdk-cpp \
    && cd aws-sdk-cpp \
    && git checkout ${AWS_SDK_CPP_PATCHED_COMMIT} \
    && cd .. \
    && cd aws-sdk-cpp \
    && mkdir build && cd build \
    && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DCMAKE_PREFIX_PATH=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_ONLY="s3;transfer" -DENABLE_TESTING=OFF .. \
    && make -j $(nproc) \
    && make install \
    && cd ../.. \
    && rm -rf aws-sdk-cpp \
    && ldconfig

FROM aws-dev as gcs-cl-dev

# Google cloud storage client library - dependencies

## Abseil
ARG ABSEIL_VERSION=20211102.0
ARG ABSEIL_DIR=abseil-cpp-${ABSEIL_VERSION}
RUN mkdir -p ${ABSEIL_DIR} \
    && wget -q https://github.com/abseil/abseil-cpp/archive/${ABSEIL_VERSION}.tar.gz \
    && tar -xf ${ABSEIL_VERSION}.tar.gz -C ${ABSEIL_DIR} --strip-components=1 \
    && rm -rf ${ABSEIL_VERSION}.tar.gz

RUN cmake -DCMAKE_CXX_STANDARD=14 \
          -DCMAKE_BUILD_TYPE=Release \
          -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \
          -DBUILD_TESTING=OFF \
          -DBUILD_SHARED_LIBS=NO \
          -DCMAKE_POSITION_INDEPENDENT_CODE=ON  \
          -H${ABSEIL_DIR} \
          -B${ABSEIL_DIR}/cmake-out \
    && cmake --build ${ABSEIL_DIR}/cmake-out \
             --target install -- -j $(nproc) \
    && rm -rf ${ABSEIL_DIR} \
    && ldconfig

RUN echo " \"abseil_cpp\": { \"version\" : \"${ABSEIL_VERSION}\", \"url\" : \"https://github.com/abseil/abseil-cpp/archive/${ABSEIL_VERSION}.tar.gz\" }," >> /versions.json

## nlohmann/json
ARG NLOHMANN_JSON_VERSION="3.10.5"
RUN git clone --depth 1 --branch v${NLOHMANN_JSON_VERSION} https://github.com/nlohmann/json

RUN cmake -DCMAKE_BUILD_TYPE=Release \
          -DBUILD_SHARED_LIBS=NO \
          -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
          -DBUILD_TESTING=OFF \
          -DJSON_BuildTests=OFF \
          -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \
          -Hjson -Bjson/cmake-out \
    && cmake --build json/cmake-out --target install -- -j $(nproc) \
    && rm -rf json \
    && ldconfig

RUN echo " \"nlohmann_json\": { \"version\" : \"${NLOHMANN_JSON_VERSION}\", \"url\" : \"https://github.com/nlohmann/json\" }," >> /versions.json

# Google cloud storage client library
ARG GCS_SDK_VERSION="1.33.0"
ARG GCS_SDK_DIR=google-cloud-cpp-${GCS_SDK_VERSION}

RUN mkdir -p ${GCS_SDK_DIR} \
    && wget -q https://github.com/googleapis/google-cloud-cpp/archive/v${GCS_SDK_VERSION}.tar.gz \
    && tar -xf v${GCS_SDK_VERSION}.tar.gz -C ${GCS_SDK_DIR} --strip=1 \
    && rm -rf v${GCS_SDK_VERSION}.tar.gz

RUN cmake -DGOOGLE_CLOUD_CPP_ENABLE=storage \
          -DBUILD_TESTING=OFF \
          -DGOOGLE_CLOUD_CPP_ENABLE_EXAMPLES=OFF \
          -DBUILD_SHARED_LIBS=NO \
          -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
          -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \
          -H${GCS_SDK_DIR} \
          -B${GCS_SDK_DIR}/cmake-out \
    && cmake --build ${GCS_SDK_DIR}/cmake-out \
             --target install -- -j $(nproc) \
    && rm -rf ${GCS_SDK_DIR} \
    && ldconfig

RUN echo " \"google_cloud_cpp\": { \"version\" : \"${GCS_SDK_VERSION}\", \"url\" : \"https://github.com/googleapis/google-cloud-cpp/archive/v${GCS_SDK_VERSION}.tar.gz\" }," >> /versions.json

FROM gcs-cl-dev as abi-check-dev

# ABI checker
WORKDIR /
RUN git clone https://github.com/lvc/abi-compliance-checker \
    && cd abi-compliance-checker \
    && git checkout 8e819827e8d707c7addc4a08f5cf74045f2302bb
WORKDIR /tmp

# Clang sanitizers
RUN apt-get -y update \
    && apt-get -y install liblsan0 libubsan1 libtsan0 libasan6 clang-format-10 clang-tidy-10


RUN ldconfig /usr/local/lib*

RUN echo "\"end\":\"end\" }" >> /versions.json

RUN perl -pi -e 's/ +/ /g' /versions.json \
    && cat /versions.json

# Shell basics

RUN echo 'export PS1="\\[\\e[32m\\]\\w\\[\\e[m\\]\\[\\e[36m\\]-\\[\\e[m\\]\\[\\e[36m\\]\\\\$\\[\\e[m\\] " \n\
alias ll="ls -AlF" \n\
alias h="history" \n\
' >> ~/.bashrc
