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

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +91 -80
Dockerfile CHANGED
@@ -1,90 +1,101 @@
1
- FROM python:3.11-slim
2
 
 
 
3
  RUN apt-get update && apt-get install -y \
4
- wget unzip git build-essential \
 
 
5
  && rm -rf /var/lib/apt/lists/*
6
 
7
- WORKDIR /build
 
 
 
 
8
 
9
- # 1. NDK
10
- ENV NDK_VERSION=r26b
 
 
 
 
 
11
  RUN wget -q https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip && \
12
  unzip -q android-ndk-${NDK_VERSION}-linux.zip && \
13
  rm android-ndk-${NDK_VERSION}-linux.zip
14
 
15
- ENV NDK_ROOT=/build/android-ndk-${NDK_VERSION}
16
- ENV TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
17
- ENV API_LEVEL=30
18
- ENV TARGET=aarch64-linux-android
19
- ENV CC="$TOOLCHAIN/bin/${TARGET}${API_LEVEL}-clang"
20
- ENV LD="$TOOLCHAIN/bin/ld"
21
- ENV AR="$TOOLCHAIN/bin/llvm-ar"
22
- ENV STRIP="$TOOLCHAIN/bin/llvm-strip"
23
-
24
- # 2. Dependencies
25
- RUN pip install cython
26
-
27
- # 3. Download Source
28
- RUN wget -O MandreLib.py https://github.com/coidarashka/MandreLib/raw/refs/heads/main/MandreLib.py
29
-
30
- # ==============================================================================
31
- # 4. MAGIC PATCHER: Convert 'import org...' to 'jclass("org...")'
32
- # ==============================================================================
33
- # Мы пишем микро-скрипт на питоне, который переделает импорты MandreLib
34
- # чтобы они работали в скомпилированном виде.
35
- RUN echo "import re\n\
36
- code = open('MandreLib.py', 'r', encoding='utf-8').read()\n\
37
- \n\
38
- # 1. Добавляем импорт jclass в начало\n\
39
- code = 'from java import jclass\\n' + code\n\
40
- \n\
41
- # 2. Функция замены импортов\n\
42
- def replace_java_import(match):\n\
43
- pkg = match.group(1) # например 'org.telegram.messenger'\n\
44
- imports = match.group(2).replace(' ', '').split(',') # ['ApplicationLoader', 'AndroidUtilities']\n\
45
- lines = []\n\
46
- for cls in imports:\n\
47
- # Превращаем в: ApplicationLoader = jclass('org.telegram.messenger.ApplicationLoader')\n\
48
- lines.append(f'{cls} = jclass(\"{pkg}.{cls}\")')\n\
49
- return '\\n'.join(lines)\n\
50
- \n\
51
- # 3. Патчим 'from org... import' и 'from android... import'\n\
52
- # Игнорируем обычные питоновские импорты\n\
53
- code = re.sub(r'^from (org[\.\w]+|android[\.\w]+|java[\.\w]+) import ([\w, ]+)', replace_java_import, code, flags=re.MULTILINE)\n\
54
- \n\
55
- # 4. Удаляем несовместимые с Cython конструкции (если есть)\n\
56
- # Например, прямые вызовы, которые могут крашнуть компилятор\n\
57
- \n\
58
- open('MandreLib.py', 'w', encoding='utf-8').write(code)\n\
59
- print('Java imports patched successfully!')\n\
60
- " > patcher.py && python3 patcher.py
61
-
62
- # 5. Mocks for Cython (чтобы компилятор знал о существовании jclass)
63
- RUN echo "try:\n import java\nexcept ImportError:\n class _M:\n def __getattr__(self, n): return _M()\n def __call__(self, *a, **k): return _M()\n java = _M()\n jclass = _M()\n" > mocks.py && \
64
- cat mocks.py MandreLib.py > MandreLib_final.py && \
65
- mv MandreLib_final.py MandreLib.py
66
-
67
- # 6. Generate C
68
- RUN cython -3 MandreLib.py -o MandreLib.c
69
-
70
- # 7. Fake Linker (чтобы библиотека знала про Python)
71
- RUN echo "int Py_Main(void){return 0;}" > stub.c && \
72
- $CC -shared -o libpython3.11.so stub.c
73
-
74
- # 8. Compile
75
- ENV PYTHON_INCLUDE=/usr/local/include/python3.11
76
- ENV CFLAGS="-fPIC -O3 -Wall -target ${TARGET}${API_LEVEL} -Wno-unused-command-line-argument"
77
-
78
- RUN $CC $CFLAGS \
79
- -I$PYTHON_INCLUDE \
80
- -L. -lpython3.11 \
81
- -o MandreLib.so \
82
- MandreLib.c \
83
- -shared \
84
- -Wl,--allow-shlib-undefined
85
-
86
- # 9. Strip & Serve
87
- RUN $STRIP --strip-unneeded MandreLib.so
88
- RUN mkdir /output && mv MandreLib.so /output/MandreLib.so
89
- WORKDIR /output
90
  CMD ["python3", "-m", "http.server", "7860"]
 
1
+ FROM ubuntu:22.04
2
 
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 && \
45
+ echo "fortran = 'aarch64-linux-android30-gfortran'" >> android.cross && \
46
+ echo "ar = 'llvm-ar'" >> android.cross && \
47
+ echo "strip = 'llvm-strip'" >> android.cross && \
48
+ echo "pkgconfig = 'pkg-config'" >> android.cross && \
49
+ echo "" >> android.cross && \
50
+ echo "[host_machine]" >> android.cross && \
51
+ echo "system = 'android'" >> android.cross && \
52
+ echo "cpu_family = 'aarch64'" >> 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"]