sterepando commited on
Commit
58f4d98
·
verified ·
1 Parent(s): 01e6fee

Update Dockerfile

Browse files
Files changed (1) hide show
  1. 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
- gfortran bison flex \
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
- ENV NDK_VERSION=r25c
19
- ENV OPENBLAS_VERSION=0.3.26
20
- ENV SCIPY_VERSION=1.11.4
21
- # Примечание: Scipy 1.12+ требует более сложной настройки Meson, 1.11.x стабильнее для Android
22
-
23
- # === 3. Установка Android NDK ===
24
- RUN wget -q https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip && \
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  unzip -q android-ndk-${NDK_VERSION}-linux.zip && \
26
- rm android-ndk-${NDK_VERSION}-linux.zip
27
-
28
- ENV ANDROID_NDK_HOME=${WORKDIR}/android-ndk-${NDK_VERSION}
 
 
 
 
 
 
 
29
  ENV PATH=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}
30
 
31
- # === 4. Установка GFortran для Android (Критически важно для Scipy) ===
32
- # Используем готовые бинарники gfortran для NDK r25c
33
- RUN wget -q https://github.com/mzakharo/android-gfortran/releases/download/r25c/aarch64-linux-android-11-r25c-gcc-12.2.0-binutils-2.40.tar.xz && \
34
- tar -xf aarch64-linux-android-11-r25c-gcc-12.2.0-binutils-2.40.tar.xz -C ${ANDROID_NDK_HOME} && \
35
- rm aarch64-linux-android-11-r25c-gcc-12.2.0-binutils-2.40.tar.xz
36
 
37
- # Создаем симлинки для gfortran, чтобы meson его нашел как aarch64-linux-android30-gfortran
38
- RUN ln -s ${ANDROID_NDK_HOME}/bin/aarch64-linux-android-gfortran ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-gfortran
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
- # === 6. Сборка OpenBLAS (статическая линковка) ===
57
- # Scipy нужен BLAS. Собираем его вручную под ARM64
 
58
  RUN git clone --branch v${OPENBLAS_VERSION} --depth 1 https://github.com/OpenMathLib/OpenBLAS.git
59
  WORKDIR ${WORKDIR}/OpenBLAS
60
- RUN make TARGET=ARMV8 AR=llvm-ar CC="aarch64-linux-android30-clang" FC="aarch64-linux-android30-gfortran" HOSTCC=gcc -j$(nproc) NO_SHARED=1
 
 
61
  RUN make install PREFIX=${WORKDIR}/openblas_install
62
 
63
- # Настраиваем PKG_CONFIG, чтобы Scipy нашел наш OpenBLAS
64
  ENV PKG_CONFIG_PATH=${WORKDIR}/openblas_install/lib/pkgconfig
65
 
66
- # === 7. Подготовка Python окружения ===
67
  WORKDIR ${WORKDIR}
68
- # Устанавливаем зависимости сборки на хосте (внутри докера)
69
- RUN pip3 install --upgrade pip wheel build meson ninja numpy==1.26.4 cython pybind11 pythran
 
70
 
71
- # === 8. Сборка Scipy ===
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
- # Флаг для передачи cross-file в meson через pip
78
- ENV MESON_ARGS="--cross-file=${WORKDIR}/android.cross"
79
 
80
- # Патчим setup.py или pyproject.toml если нужно, но через meson-python и переменные среды это должно работать.
81
- # Запускаем сборку Wheel.
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
- # Перемещаем готовый wheel в папку output
 
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
- # Hugging Face слушает порт 7860
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"]