diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb7e29c..86a55a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,7 @@ jobs: context: . push: true target: alfalfa-dependencies - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64, linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.output.labels }} cache-from: type=gha diff --git a/Dockerfile b/Dockerfile index 582651a..5c9b6b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.10.14 +ARG PYTHON_VERSION=3.12.2 ARG DEBIAN_VERSION=bookworm # Build modelica-dependencies on bullseye (this uses an older version of GLibc which allows for making manylinux wheels) @@ -8,9 +8,6 @@ ARG ASSIMULO_VERSION=3.5.2 RUN apt-get update \ && apt-get install -y \ cmake \ - liblapack-dev \ - libsuitesparse-dev \ - libhypre-dev \ curl \ git \ build-essential \ @@ -26,41 +23,12 @@ RUN python3 -m pip install \ auditwheel \ patchelf -RUN gnuArch="$(dpkg-architecture --query DEB_HOST_MULTIARCH)"; \ -ln -s /usr/lib/$gnuArch/libblas.so /usr/lib/$gnuArch/libblas_OPENMP.so - WORKDIR /build -RUN curl -fSsL https://portal.nersc.gov/project/sparse/superlu/superlu_mt_3.1.tar.gz | tar xz \ - && cd SuperLU_MT_3.1 \ - && make CFLAGS="-O2 -fPIC -fopenmp" BLASLIB="-lblas" PLAT="_OPENMP" MPLIB="-fopenmp" lib -j1 \ - && cp -v ./lib/libsuperlu_mt_OPENMP.a /usr/lib \ - && cp -v ./SRC/*.h /usr/include - -RUN git clone --depth 1 -b ${SUNDIALS_VERSION} https://github.com/LLNL/sundials.git \ - && cd sundials \ - && mkdir build && cd build \ - && cmake \ - -LAH \ - -DSUPERLUMT_BLAS_LIBRARIES=blas \ - -DSUPERLUMT_LIBRARIES=blas \ - -DSUPERLUMT_INCLUDE_DIR=/usr/include \ - -DSUPERLUMT_LIBRARY=/usr/lib/libsuperlu_mt_OPENMP.a \ - -DSUPERLUMT_THREAD_TYPE=OpenMP \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DSUPERLUMT_ENABLE=ON \ - -DSUNDIALS_INDEX_SIZE=32 \ - -DLAPACK_ENABLE=ON \ - -DEXAMPLES_ENABLE=OFF \ - -DEXAMPLES_ENABLE_C=OFF \ - .. \ - && make -j4 \ - && make install - RUN gnuArch="$(dpkg-architecture --query DEB_HOST_MULTIARCH)" \ && git clone --depth 1 -b Assimulo-3.5.2 https://github.com/modelon-community/Assimulo.git \ && cd Assimulo \ - && python3 setup.py bdist_wheel --sundials-home=/usr --blas-home=/usr/lib/${gnuArch} --lapack-home=/usr/lib/${gnuArch} --superlu-home=/usr \ + && python3 setup.py bdist_wheel \ && auditwheel repair --plat manylinux_2_31_$(uname -m) build/dist/*.whl \ && pip3 install wheelhouse/*.whl @@ -70,12 +38,13 @@ RUN git clone --depth 1 -b 2.4.1 https://github.com/modelon-community/fmi-librar && mkdir fmi_build && cd fmi_build \ && mkdir fmi_library \ && cmake -DCMAKE_INSTALL_PREFIX=/build/fmi-libary/fmi_library .. \ - && make -j4 \ + && make -j$(nproc) \ && make install -RUN git clone --depth 1 -b PyFMI-2.13.1 https://github.com/modelon-community/PyFMI.git \ +RUN git clone --depth 1 -b PyFMI-2.14.0 https://github.com/modelon-community/PyFMI.git \ && cd PyFMI \ - && python3 setup.py bdist_wheel --fmil-home=/build/fmi-libary/fmi_library --with-openmp\ + && python3 setup.py build --fmil-home=/build/fmi-libary/fmi_library -j $(nproc)\ + && python3 setup.py bdist_wheel --fmil-home=/build/fmi-libary/fmi_library\ && auditwheel repair --plat manylinux_2_31_$(uname -m) dist/*.whl WORKDIR /artifacts @@ -90,131 +59,25 @@ RUN gnuArch="$(dpkg-architecture --query DEB_HOST_ARCH_CPU)"\ && curl -SfL https://archive.debian.org/debian/pool/main/g/gcc-6/libgfortran3_6.3.0-18+deb9u1_${gnuArch}.deb -o libgfortran3.deb FROM python:${PYTHON_VERSION}-slim-${DEBIAN_VERSION} AS energyplus-dependencies -ARG OPENSTUDIO_VERSION=3.8.0 -ARG OPENSTUDIO_VERSION_SHA=f953b6fcaf -ARG ENERGYPLUS_VERSION=24.1.0 -ARG ENERGYPLUS_VERSION_SHA=9d7789a3ac +ARG OPENSTUDIO_VERSION=3.9.0 +ARG OPENSTUDIO_VERSION_SHA=c77fbb9569 +ARG ENERGYPLUS_VERSION=24.2.0 +ARG ENERGYPLUS_VERSION_SHA=94a887817b RUN apt-get update \ && apt-get install -y \ curl \ + binutils \ && rm -rf /var/lib/apt/lists/* WORKDIR /artifacts -RUN export gnuArch=x86_64; if [ "$(uname -m)" = "aarch64" ]; then gnuArch=arm64; fi; export gnuArch \ - && echo https://github.com/NREL/EnergyPlus/releases/download/v${ENERGYPLUS_VERSION}/EnergyPlus-${ENERGYPLUS_VERSION}-${ENERGYPLUS_VERSION_SHA}-Linux-Ubuntu22.04-${gnuArch}.tar.gz \ - && curl -SfL https://github.com/NREL/EnergyPlus/releases/download/v${ENERGYPLUS_VERSION}/EnergyPlus-${ENERGYPLUS_VERSION}-${ENERGYPLUS_VERSION_SHA}-Linux-Ubuntu22.04-${gnuArch}.tar.gz -o energyplus.tar.gz \ - && curl -SfL https://github.com/NREL/OpenStudio/releases/download/v${OPENSTUDIO_VERSION}/OpenStudio-${OPENSTUDIO_VERSION}+${OPENSTUDIO_VERSION_SHA}-Ubuntu-22.04-${gnuArch}.deb -o openstudio.deb \ - && curl -SfL https://openstudio-resources.s3.amazonaws.com/bcvtb-linux.tar.gz -o bcvtb.tar.gz - -FROM python:${PYTHON_VERSION}-slim-${DEBIAN_VERSION} AS dual-python +RUN set -eux; \ + export gnuArch=x86_64; if [ "$(uname -m)" = "aarch64" ]; then gnuArch=arm64; fi; export gnuArch; \ + curl -SfL https://github.com/NREL/EnergyPlus/releases/download/v${ENERGYPLUS_VERSION}a/EnergyPlus-${ENERGYPLUS_VERSION}-${ENERGYPLUS_VERSION_SHA}-Linux-Ubuntu22.04-${gnuArch}.tar.gz -o energyplus.tar.gz; \ + curl -SfL https://github.com/NREL/OpenStudio/releases/download/v${OPENSTUDIO_VERSION}/OpenStudio-${OPENSTUDIO_VERSION}+${OPENSTUDIO_VERSION_SHA}-Ubuntu-22.04-${gnuArch}.deb -o openstudio.deb - ENV PYTHON_VERSION=3.8.19 - ENV GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568 - - RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - dpkg-dev \ - gcc \ - gnupg \ - libbluetooth-dev \ - libbz2-dev \ - libc6-dev \ - libdb-dev \ - libexpat1-dev \ - libffi-dev \ - libgdbm-dev \ - liblzma-dev \ - libncursesw5-dev \ - libreadline-dev \ - libsqlite3-dev \ - libssl-dev \ - make \ - tk-dev \ - uuid-dev \ - wget \ - xz-utils \ - zlib1g-dev \ - ; \ - \ - wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz"; \ - wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc"; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$GPG_KEY"; \ - gpg --batch --verify python.tar.xz.asc python.tar.xz; \ - gpgconf --kill all; \ - rm -rf "$GNUPGHOME" python.tar.xz.asc; \ - mkdir -p /usr/src/python; \ - tar --extract --directory /usr/src/python --strip-components=1 --file python.tar.xz; \ - rm python.tar.xz; \ - \ - cd /usr/src/python; \ - gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ - ./configure \ - --build="$gnuArch" \ - --enable-loadable-sqlite-extensions \ - --enable-optimizations \ - --enable-option-checking=fatal \ - --enable-shared \ - --with-system-expat \ - --without-ensurepip \ - ; \ - nproc="$(nproc)"; \ - EXTRA_CFLAGS="$(dpkg-buildflags --get CFLAGS)"; \ - LDFLAGS="$(dpkg-buildflags --get LDFLAGS)"; \ - LDFLAGS="${LDFLAGS:--Wl},--strip-all"; \ - make -j "$nproc" \ - "EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \ - "LDFLAGS=${LDFLAGS:-}" \ - "PROFILE_TASK=${PROFILE_TASK:-}" \ - ; \ - # https://github.com/docker-library/python/issues/784 - # prevent accidental usage of a system installed libpython of the same version - rm python; \ - make -j "$nproc" \ - "EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \ - "LDFLAGS=${LDFLAGS:--Wl},-rpath='\$\$ORIGIN/../lib'" \ - "PROFILE_TASK=${PROFILE_TASK:-}" \ - python \ - ; \ - make altinstall; \ - \ - cd /; \ - rm -rf /usr/src/python; \ - \ - find /usr/local -depth \ - \( \ - \( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \ - -o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name 'libpython*.a' \) \) \ - -o \( -type f -a -name 'wininst-*.exe' \) \ - \) -exec rm -rf '{}' + \ - ; \ - \ - ldconfig; \ - \ - apt-mark auto '.*' > /dev/null; \ - apt-mark manual $savedAptMark; \ - find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ - | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \ - | sort -u \ - | xargs -r dpkg-query --search \ - | cut -d: -f1 \ - | sort -u \ - | xargs -r apt-mark manual \ - ; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ - rm -rf /var/lib/apt/lists/*; \ - \ - python3.8 --version - - RUN python3.8 -m ensurepip --altinstall - - -FROM dual-python AS alfalfa-dependencies +FROM python:${PYTHON_VERSION}-slim-${DEBIAN_VERSION} AS alfalfa-dependencies ENV ENERGYPLUS_DIR=/usr/local/EnergyPlus ENV HOME=/alfalfa @@ -223,30 +86,31 @@ WORKDIR /artifacts # Install EnergyPlus RUN --mount=type=bind,from=energyplus-dependencies,source=/artifacts,target=/artifacts set -eux; \ - mkdir ${ENERGYPLUS_DIR}; \ + mkdir -p ${ENERGYPLUS_DIR}; \ tar -C $ENERGYPLUS_DIR/ --strip-components=1 -xzf energyplus.tar.gz; \ cd ${ENERGYPLUS_DIR}; \ + cp -n -r ${ENERGYPLUS_DIR}/python_lib/* /usr/local/lib/python3.12; \ rm -rf \ ExampleFiles \ DataSets \ Documentation \ MacroDataSets \ - python_standard_lib \ + python_lib \ WeatherData \ - libpython3.8.so.1.0 \ + libpython3.12.so.1.0 \ ; \ ln -s $ENERGYPLUS_DIR/energyplus /usr/local/bin/; \ ln -s $ENERGYPLUS_DIR/ExpandObjects /usr/local/bin/; \ ln -s $ENERGYPLUS_DIR/runenergyplus /usr/local/bin/; \ - ln -s /usr/local/lib/python3.8 ${ENERGYPLUS_DIR}/python_standard_lib; \ - ln -s /usr/local/lib/libpython3.8.so.1.0 ${ENERGYPLUS_DIR}/libpython3.8.so.1.0 + ln -s /usr/local/lib/python3.12 ${ENERGYPLUS_DIR}/python_lib; \ + ln -s /usr/local/lib/libpython3.12.so.1.0 ${ENERGYPLUS_DIR}/libpython3.12.so.1.0 # Install OpenStudio RUN --mount=type=bind,from=energyplus-dependencies,source=/artifacts,target=/artifacts set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ gdebi-core \ - openjdk-17-jre-headless \ + binutils \ ; \ gdebi -o "APT::Install-Recommends=0" -n openstudio.deb; \ cd /usr/local/openstudio*; \ @@ -258,6 +122,7 @@ RUN --mount=type=bind,from=energyplus-dependencies,source=/artifacts,target=/art ln -s ${ENERGYPLUS_DIR} EnergyPlus; \ apt-get purge -y \ gdebi-core \ + binutils \ ; \ apt-get autoremove -y; \ rm -rf /var/lib/apt/lists/* @@ -265,8 +130,8 @@ RUN --mount=type=bind,from=energyplus-dependencies,source=/artifacts,target=/art # Install Assimulo, PyFMI and Old Fortran Libraries RUN --mount=type=bind,from=modelica-dependencies,source=/artifacts,target=/artifacts set -eux; \ - python3.10 -m pip install 'numpy>=1.19.5' 'scipy>=1.10.1' 'matplotlib>3'; \ - python3.10 -m pip install --no-deps Assimulo*.whl PyFMI*.whl; \ + python3.12 -m pip install 'numpy>=1.19.5' 'scipy>=1.10.1' 'matplotlib>3'; \ + python3.12 -m pip install --no-deps Assimulo*.whl PyFMI*.whl; \ pip3 cache purge; \ apt-get update; \ apt-get install -y --no-install-recommends \ @@ -283,7 +148,5 @@ RUN --mount=type=bind,from=modelica-dependencies,source=/artifacts,target=/artif apt-get autoremove -y; \ rm -rf /var/lib/apt/lists/* +ENV PYTHONPATH="${ENERGYPLUS_DIR}:/usr/local/openstudio-3.9.0/Python" WORKDIR $HOME - -# Only the xml lib component of bcvtb is actaully required for communication, so we just extract that to save space -RUN --mount=type=bind,from=energyplus-dependencies,source=/artifacts,target=/artifacts tar -xzf /artifacts/bcvtb.tar.gz bcvtb/lib/xml