Spaces:
Paused
Paused
Update Dockerfile
Browse files- Dockerfile +72 -46
Dockerfile
CHANGED
|
@@ -3,42 +3,66 @@ FROM ubuntu:22.04
|
|
| 3 |
# === 1. Установка системных зависимостей ===
|
| 4 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 5 |
RUN apt-get update && apt-get install -y \
|
| 6 |
-
wget unzip git python3 python3-pip python3-venv \
|
| 7 |
build-essential cmake ninja-build pkg-config \
|
| 8 |
-
|
| 9 |
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
|
| 11 |
-
# === 2. Настройка переменных окружения ===
|
| 12 |
ENV WORKDIR=/build
|
| 13 |
WORKDIR ${WORKDIR}
|
| 14 |
ENV OUTDIR=/output
|
| 15 |
RUN mkdir -p ${OUTDIR}
|
| 16 |
|
| 17 |
-
#
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
unzip -q android-ndk-${NDK_VERSION}-linux.zip && \
|
| 26 |
-
rm android-ndk-${NDK_VERSION}-linux.zip
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
ENV PATH=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}
|
| 30 |
|
| 31 |
-
#
|
| 32 |
-
#
|
| 33 |
-
RUN
|
| 34 |
-
|
| 35 |
-
rm aarch64-linux-android-11-r25c-gcc-12.2.0-binutils-2.40.tar.xz
|
| 36 |
|
| 37 |
-
#
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
# === 5. Создание Cross-File для Meson ===
|
| 41 |
-
# Этот файл объясняет системе сборки, как компилировать под Android
|
| 42 |
RUN echo "[binaries]" > android.cross && \
|
| 43 |
echo "c = 'aarch64-linux-android30-clang'" >> android.cross && \
|
| 44 |
echo "cpp = 'aarch64-linux-android30-clang++'" >> android.cross && \
|
|
@@ -53,49 +77,51 @@ RUN echo "[binaries]" > android.cross && \
|
|
| 53 |
echo "cpu = 'armv8-a'" >> android.cross && \
|
| 54 |
echo "endian = 'little'" >> android.cross
|
| 55 |
|
| 56 |
-
# ===
|
| 57 |
-
#
|
|
|
|
| 58 |
RUN git clone --branch v${OPENBLAS_VERSION} --depth 1 https://github.com/OpenMathLib/OpenBLAS.git
|
| 59 |
WORKDIR ${WORKDIR}/OpenBLAS
|
| 60 |
-
|
|
|
|
|
|
|
| 61 |
RUN make install PREFIX=${WORKDIR}/openblas_install
|
| 62 |
|
| 63 |
-
#
|
| 64 |
ENV PKG_CONFIG_PATH=${WORKDIR}/openblas_install/lib/pkgconfig
|
| 65 |
|
| 66 |
-
# ===
|
| 67 |
WORKDIR ${WORKDIR}
|
| 68 |
-
# Устанавливаем зависимости сборки
|
| 69 |
-
|
|
|
|
| 70 |
|
| 71 |
-
# ===
|
| 72 |
-
#
|
|
|
|
| 73 |
RUN pip3 download scipy==${SCIPY_VERSION} --no-binary=:all: --no-deps
|
| 74 |
RUN tar -xf scipy-${SCIPY_VERSION}.tar.gz
|
| 75 |
WORKDIR ${WORKDIR}/scipy-${SCIPY_VERSION}
|
| 76 |
|
| 77 |
-
#
|
| 78 |
-
|
| 79 |
|
| 80 |
-
#
|
| 81 |
-
#
|
| 82 |
-
# Мы используем --no-deps, чтобы pip не пытался собрать numpy под android (это отдельно),
|
| 83 |
-
# но при этом на хосте numpy уже стоит для генерации заголовков.
|
| 84 |
RUN python3 -m build --wheel --no-isolation --skip-dependency-check \
|
| 85 |
-Csetup-args="--cross-file=${WORKDIR}/android.cross" \
|
| 86 |
-Csetup-args="-Dblas=openblas" \
|
| 87 |
-
-Csetup-args="-Dlapack=openblas"
|
|
|
|
| 88 |
|
| 89 |
-
#
|
|
|
|
| 90 |
RUN mv dist/*.whl ${OUTDIR}/
|
| 91 |
|
| 92 |
-
# === 9. Запуск сервера для отдачи файла ===
|
| 93 |
WORKDIR ${OUTDIR}
|
| 94 |
-
|
| 95 |
-
# Меняем название файла, чтобы добавить теги платформы (pip build может дать linux тег, меняем на android)
|
| 96 |
-
# Это "грязный" хак, но для pip install на андроиде это часто необходимо, если wheel не помечен правильно.
|
| 97 |
RUN for f in *.whl; do mv "$f" "$(echo $f | sed s/linux_aarch64/android_30_arm64_v8a/)"; done || true
|
| 98 |
|
| 99 |
-
#
|
| 100 |
EXPOSE 7860
|
| 101 |
CMD ["python3", "-m", "http.server", "7860"]
|
|
|
|
| 3 |
# === 1. Установка системных зависимостей ===
|
| 4 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 5 |
RUN apt-get update && apt-get install -y \
|
| 6 |
+
wget curl unzip git python3 python3-pip python3-venv \
|
| 7 |
build-essential cmake ninja-build pkg-config \
|
| 8 |
+
bison flex jq file libffi-dev \
|
| 9 |
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
|
|
|
|
| 11 |
ENV WORKDIR=/build
|
| 12 |
WORKDIR ${WORKDIR}
|
| 13 |
ENV OUTDIR=/output
|
| 14 |
RUN mkdir -p ${OUTDIR}
|
| 15 |
|
| 16 |
+
# === 2. Умная установка NDK и GFortran ===
|
| 17 |
+
# Мы используем Python скрипт для поиска последней рабочей версии gfortran
|
| 18 |
+
# и скачиваем соответствующую ей версию NDK, чтобы избежать ошибок совместимости.
|
| 19 |
+
RUN python3 -c 'import requests, os, sys; \
|
| 20 |
+
print("Searching for latest gfortran release..."); \
|
| 21 |
+
repo = "mzakharo/android-gfortran"; \
|
| 22 |
+
r = requests.get(f"https://api.github.com/repos/{repo}/releases/latest"); \
|
| 23 |
+
data = r.json(); \
|
| 24 |
+
# Ищем ассет для aarch64 (целевая архитектура) под Linux (хост) \
|
| 25 |
+
asset = next((a for a in data["assets"] if "aarch64" in a["name"] and "linux" in a["name"] and "tar.xz" in a["name"]), None); \
|
| 26 |
+
if not asset: print("Error: No suitable gfortran asset found"); sys.exit(1); \
|
| 27 |
+
url = asset["browser_download_url"]; \
|
| 28 |
+
name = asset["name"]; \
|
| 29 |
+
print(f"Found gfortran: {name}"); \
|
| 30 |
+
# Пытаемся извлечь версию NDK из имени файла (например, r21e, r25c) \
|
| 31 |
+
import re; \
|
| 32 |
+
ndk_match = re.search(r"(r\d+[a-z]?)", name); \
|
| 33 |
+
ndk_ver = ndk_match.group(1) if ndk_match else "r25c"; \
|
| 34 |
+
print(f"Detected NDK version requirement: {ndk_ver}"); \
|
| 35 |
+
# Сохраняем переменные в файл для следующих шагов \
|
| 36 |
+
with open("env_vars.sh", "w") as f: \
|
| 37 |
+
f.write(f"export GFORTRAN_URL={url}\n"); \
|
| 38 |
+
f.write(f"export GFORTRAN_ARCHIVE={name}\n"); \
|
| 39 |
+
f.write(f"export NDK_VERSION={ndk_ver}\n"); \
|
| 40 |
+
'
|
| 41 |
+
|
| 42 |
+
# Загружаем переменные и скачиваем NDK и GFortran
|
| 43 |
+
RUN . ./env_vars.sh && \
|
| 44 |
+
echo "Downloading NDK ${NDK_VERSION}..." && \
|
| 45 |
+
wget -q https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip && \
|
| 46 |
unzip -q android-ndk-${NDK_VERSION}-linux.zip && \
|
| 47 |
+
rm android-ndk-${NDK_VERSION}-linux.zip && \
|
| 48 |
+
mv android-ndk-${NDK_VERSION} android-ndk && \
|
| 49 |
+
\
|
| 50 |
+
echo "Downloading GFortran..." && \
|
| 51 |
+
wget -q ${GFORTRAN_URL} && \
|
| 52 |
+
tar -xf ${GFORTRAN_ARCHIVE} -C android-ndk && \
|
| 53 |
+
rm ${GFORTRAN_ARCHIVE}
|
| 54 |
+
|
| 55 |
+
# Настройка путей
|
| 56 |
+
ENV ANDROID_NDK_HOME=${WORKDIR}/android-ndk
|
| 57 |
ENV PATH=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}
|
| 58 |
|
| 59 |
+
# Создаем симлинки для gfortran (делаем его доступным под стандартным именем для кросс-компиляции)
|
| 60 |
+
# Scipy/Meson ищут aarch64-linux-android-gfortran или аналогичные
|
| 61 |
+
RUN ln -sf ${ANDROID_NDK_HOME}/bin/aarch64-linux-android-gfortran ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-gfortran && \
|
| 62 |
+
ln -sf ${ANDROID_NDK_HOME}/bin/aarch64-linux-android-gfortran ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/gfortran
|
|
|
|
| 63 |
|
| 64 |
+
# === 3. Создание Cross-File для Meson ===
|
| 65 |
+
# На��траиваем параметры кросс-компиляции для Android API 30
|
|
|
|
|
|
|
|
|
|
| 66 |
RUN echo "[binaries]" > android.cross && \
|
| 67 |
echo "c = 'aarch64-linux-android30-clang'" >> android.cross && \
|
| 68 |
echo "cpp = 'aarch64-linux-android30-clang++'" >> android.cross && \
|
|
|
|
| 77 |
echo "cpu = 'armv8-a'" >> android.cross && \
|
| 78 |
echo "endian = 'little'" >> android.cross
|
| 79 |
|
| 80 |
+
# === 4. Сборка OpenBLAS (Критический шаг) ===
|
| 81 |
+
# Версия OpenBLAS должна быть стабильной. 0.3.21 хорошо работает с андроидом.
|
| 82 |
+
ENV OPENBLAS_VERSION=0.3.21
|
| 83 |
RUN git clone --branch v${OPENBLAS_VERSION} --depth 1 https://github.com/OpenMathLib/OpenBLAS.git
|
| 84 |
WORKDIR ${WORKDIR}/OpenBLAS
|
| 85 |
+
# Сборка под ARMv8. Важно: NO_SHARED=0, чтобы собрать .so библиотеку, но для Scipy часто лучше статик,
|
| 86 |
+
# однако мы соберем статик для вшивки внутрь wheel.
|
| 87 |
+
RUN make TARGET=ARMV8 AR=llvm-ar CC="aarch64-linux-android30-clang" FC="aarch64-linux-android30-gfortran" HOSTCC=gcc -j$(nproc)
|
| 88 |
RUN make install PREFIX=${WORKDIR}/openblas_install
|
| 89 |
|
| 90 |
+
# Указываем pkg-config путь
|
| 91 |
ENV PKG_CONFIG_PATH=${WORKDIR}/openblas_install/lib/pkgconfig
|
| 92 |
|
| 93 |
+
# === 5. Подготовка окружения Python ===
|
| 94 |
WORKDIR ${WORKDIR}
|
| 95 |
+
# Устанавливаем зависимости для сборки Scipy
|
| 96 |
+
# Используем numpy 1.24.x, так как 1.26 иногда вызывает проблемы при кросс-компиляции старых Scipy
|
| 97 |
+
RUN pip3 install --upgrade pip wheel build meson ninja "numpy==1.24.3" cython pybind11 pythran requests
|
| 98 |
|
| 99 |
+
# === 6. Сборка Scipy ===
|
| 100 |
+
# Версия 1.10.1 более стабильна для кастомных сборок, чем 1.11+
|
| 101 |
+
ENV SCIPY_VERSION=1.10.1
|
| 102 |
RUN pip3 download scipy==${SCIPY_VERSION} --no-binary=:all: --no-deps
|
| 103 |
RUN tar -xf scipy-${SCIPY_VERSION}.tar.gz
|
| 104 |
WORKDIR ${WORKDIR}/scipy-${SCIPY_VERSION}
|
| 105 |
|
| 106 |
+
# Патчим meson.build, если он требует numpy > установленного (иногда бывает в новых версиях),
|
| 107 |
+
# но для 1.10.1 это не нужно.
|
| 108 |
|
| 109 |
+
# Запускаем сборку
|
| 110 |
+
# -Csetup-args="-Dblas=openblas" указывает использовать наш скомпилированный OpenBLAS
|
|
|
|
|
|
|
| 111 |
RUN python3 -m build --wheel --no-isolation --skip-dependency-check \
|
| 112 |
-Csetup-args="--cross-file=${WORKDIR}/android.cross" \
|
| 113 |
-Csetup-args="-Dblas=openblas" \
|
| 114 |
+
-Csetup-args="-Dlapack=openblas" \
|
| 115 |
+
-Csetup-args="-Duse-g77-abi=true"
|
| 116 |
|
| 117 |
+
# === 7. Финализация ===
|
| 118 |
+
# Перемещаем результат
|
| 119 |
RUN mv dist/*.whl ${OUTDIR}/
|
| 120 |
|
|
|
|
| 121 |
WORKDIR ${OUTDIR}
|
| 122 |
+
# Переименовываем файл для Android совместимости (хак тегов)
|
|
|
|
|
|
|
| 123 |
RUN for f in *.whl; do mv "$f" "$(echo $f | sed s/linux_aarch64/android_30_arm64_v8a/)"; done || true
|
| 124 |
|
| 125 |
+
# === 8. Отдача файла ===
|
| 126 |
EXPOSE 7860
|
| 127 |
CMD ["python3", "-m", "http.server", "7860"]
|