Skip to content

Commit 0754074

Browse files
committed
Simplify image tagging, and allow for build log exfiltration.
1 parent 152fd7f commit 0754074

File tree

7 files changed

+97
-38
lines changed

7 files changed

+97
-38
lines changed

main.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ function build_one_abi() {
100100
# We do also use a temporary tag name so that we can use `rsync` to pull some
101101
# data out of the image.
102102
#
103-
# For debugging the Docker image, you can use the name python-android-support-local:latest.
104-
TAG_NAME="python-android-support-local:$(python3 -c 'import random; print(random.randint(0, 1e16))')"
105-
DOCKER_BUILDKIT=1 docker build --platform linux/amd64 --tag ${TAG_NAME} --tag python-android-support-local:latest \
103+
# For debugging the Docker image, you can use the name python-android-support-<version>:<abi>.
104+
# e.g. python-android-support-3.7:arm64-v8a
105+
TAG_NAME="python-android-support-${PYTHON_VERSION}:${TARGET_ABI_SHORTNAME}"
106+
DOCKER_BUILDKIT=1 docker build --platform linux/amd64 --tag ${TAG_NAME} \
106107
--build-arg PYTHON_VERSION="${PYTHON_VERSION}" --build-arg PYTHON_SOVERSION="${PYTHON_SOVERSION}" \
107108
--build-arg COMPRESS_LEVEL="${COMPRESS_LEVEL}" --build-arg COMPILER_TRIPLE="${COMPILER_TRIPLE}" \
108109
--build-arg OPENSSL_BUILD_TARGET="$OPENSSL_BUILD_TARGET" --build-arg TARGET_ABI_SHORTNAME="$TARGET_ABI_SHORTNAME" \
@@ -113,6 +114,8 @@ function build_one_abi() {
113114
docker run -v "${PWD}"/build/"${PYTHON_VERSION}"/:/mnt/ --rm --entrypoint rsync "$TAG_NAME" -a /opt/python-build/approot/. /mnt/.
114115
# Extract header files
115116
docker run -v "${PWD}"/build/"${PYTHON_VERSION}"/app/include/:/mnt/ --rm --entrypoint rsync "$TAG_NAME" -a /opt/python-build/built/python/include/ /mnt/
117+
# Extract log files
118+
docker run -v "${PWD}"/build/"${PYTHON_VERSION}"/logs/:/mnt/ --rm --entrypoint rsync "$TAG_NAME" -a /opt/python-build/logs/ /mnt/
116119

117120
# Docker creates files as root; reown as the local user
118121
fix_permissions
@@ -121,8 +124,6 @@ function build_one_abi() {
121124
mv "${PWD}"/build/"${PYTHON_VERSION}"/app/include/python"${PYTHON_SOVERSION}"/pyconfig.h "${PWD}"/build/"${PYTHON_VERSION}"/app/include/python"${PYTHON_SOVERSION}"/pyconfig-${TARGET_ABI_SHORTNAME}.h
122125
# Inject a platform-agnostic pyconfig.h wrapper.
123126
cp "${PWD}/patches/all/pyconfig.h" "${PWD}"/build/"${PYTHON_VERSION}"/app/include/python"${PYTHON_SOVERSION}"/
124-
# Remove temporary local tag.
125-
docker rmi "$TAG_NAME" > /dev/null
126127
}
127128

128129
# Download a file into downloads/$name/$filename and verify its sha256sum.

patches/3.10/Setup.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*disabled*
2+
3+
_gdbm
4+
_dbm
5+
grp

patches/3.11/Setup.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*disabled*
2+
3+
_gdbm
4+
_dbm
5+
grp

patches/3.7/Setup.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*disabled*
2+
3+
_gdbm
4+
_dbm
5+
grp

patches/3.8/Setup.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*disabled*
2+
3+
_gdbm
4+
_dbm
5+
grp

patches/3.9/Setup.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*disabled*
2+
3+
_gdbm
4+
_dbm
5+
grp

python.Dockerfile

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ ENV NDK /opt/ndk/android-ndk
1212
WORKDIR /opt/jdk
1313
ADD downloads/jdk/* .
1414
RUN mv jdk* jdk_home
15-
ENV JAVA_HOME /opt/jdk/jdk_home/
15+
ENV JAVA_HOME /opt/jdk/jdk_home
1616
ENV PATH "/opt/jdk/jdk_home/bin:${PATH}"
1717

1818
# Store output here; the directory structure corresponds to our Android app template.
@@ -44,18 +44,21 @@ ENV AR=$TOOLCHAIN/bin/llvm-ar \
4444
READELF=$TOOLCHAIN/bin/llvm-readelf \
4545
CFLAGS="-fPIC -Wall -O0 -g"
4646

47-
# We build sqlite using a tarball from Ubuntu. We need to patch config.sub & config.guess so
48-
# autoconf can accept our weird TOOLCHAIN_TRIPLE value. It requires tcl8.6-dev and build-essential
47+
# Set up a directory for logs.
48+
ENV LOGS_DIR=${BUILD_HOME}/logs/${TARGET_ABI_SHORTNAME}
49+
RUN mkdir -p ${LOGS_DIR}
50+
51+
# We build sqlite from official sources. It requires tcl8.6-dev and build-essential
4952
# because the compile process build and executes some commands on the host as part of the build process.
5053
# We hard-code avoid_version=yes into libtool so that libsqlite3.so is the SONAME.
5154
FROM toolchain as build_sqlite
5255
RUN apt-get update -qq && apt-get -qq install make autoconf autotools-dev tcl8.6-dev build-essential
5356
ADD downloads/sqlite3/* .
5457
RUN unzip -q version-*.zip && mv sqlite-* sqlite3-src
5558
RUN cd sqlite3-src && autoreconf
56-
RUN cd sqlite3-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$BUILD_HOME/built/sqlite"
59+
RUN cd sqlite3-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$BUILD_HOME/built/sqlite" | tee -a $LOGS_DIR/sqlite3.configure.log
5760
RUN cd sqlite3-src && sed -i -E 's,avoid_version=no,avoid_version=yes,' ltmain.sh libtool
58-
RUN cd sqlite3-src && make install
61+
RUN cd sqlite3-src && make install | tee -a $LOGS_DIR/sqlite3.install.log
5962

6063
# Install bzip2 & lzma libraries, for stdlib's _bzip2 and _lzma modules.
6164
FROM toolchain as build_xz
@@ -64,8 +67,8 @@ ADD downloads/xz/* .
6467
RUN mv xz-* xz-src
6568
ENV LIBXZ_INSTALL_DIR="$BUILD_HOME/built/xz"
6669
RUN mkdir -p "$LIBXZ_INSTALL_DIR"
67-
RUN cd xz-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$LIBXZ_INSTALL_DIR"
68-
RUN cd xz-src && make install
70+
RUN cd xz-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$LIBXZ_INSTALL_DIR" | tee -a $LOGS_DIR/xz.configure.log
71+
RUN cd xz-src && make install | tee -a $LOGS_DIR/xz.install.log
6972

7073
FROM toolchain as build_bz2
7174
RUN apt-get update -qq && apt-get -qq install make
@@ -75,7 +78,7 @@ RUN mv bzip2-* bzip2-src
7578
RUN mkdir -p "$LIBBZ2_INSTALL_DIR" && \
7679
cd bzip2-src && \
7780
sed -i -e 's,[.]1[.]0.8,,' -e 's,[.]1[.]0,,' -e 's,ln -s,#ln -s,' -e 's,rm -f libbz2.so,#rm -f libbz2.so,' -e 's,^CC=,#CC=,' Makefile-libbz2_so
78-
RUN cd bzip2-src && make -f Makefile-libbz2_so
81+
RUN cd bzip2-src && make -f Makefile-libbz2_so | tee -a $LOGS_DIR/bz2.log
7982
RUN mkdir -p "${LIBBZ2_INSTALL_DIR}/lib"
8083
RUN cp bzip2-src/libbz2.so "${LIBBZ2_INSTALL_DIR}/lib"
8184
RUN mkdir -p "${LIBBZ2_INSTALL_DIR}/include"
@@ -88,18 +91,18 @@ ADD downloads/libffi/* .
8891
RUN mv libffi-* libffi-src
8992
ENV LIBFFI_INSTALL_DIR="$BUILD_HOME/built/libffi"
9093
RUN mkdir -p "$LIBFFI_INSTALL_DIR"
91-
RUN cd libffi-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$LIBFFI_INSTALL_DIR"
92-
RUN cd libffi-src && make install
94+
RUN cd libffi-src && ./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --prefix="$LIBFFI_INSTALL_DIR" | tee -a $LOGS_DIR/libffi.configure.log
95+
RUN cd libffi-src && make install | tee -a $LOGS_DIR/libffi.install.log
9396

9497
FROM toolchain as build_openssl
9598
# OpenSSL requires libfindlibs-libs-perl. make is nice, too.
9699
RUN apt-get update -qq && apt-get -qq install libfindbin-libs-perl make
97100
ADD downloads/openssl/* .
98101
RUN mv openssl-* openssl-src
99102
ARG OPENSSL_BUILD_TARGET
100-
RUN cd openssl-src && ANDROID_NDK_HOME="$NDK" ./Configure ${OPENSSL_BUILD_TARGET} -D__ANDROID_API__="$ANDROID_API_LEVEL" --prefix="$BUILD_HOME/built/openssl" --openssldir="$BUILD_HOME/built/openssl"
101-
RUN cd openssl-src && make SHLIB_EXT='${SHLIB_VERSION_NUMBER}.so'
102-
RUN cd openssl-src && make install SHLIB_EXT='${SHLIB_VERSION_NUMBER}.so'
103+
RUN cd openssl-src && ANDROID_NDK_HOME="$NDK" ./Configure ${OPENSSL_BUILD_TARGET} -D__ANDROID_API__="$ANDROID_API_LEVEL" --prefix="$BUILD_HOME/built/openssl" --openssldir="$BUILD_HOME/built/openssl" | tee -a $LOGS_DIR/openssl.configure.log
104+
RUN cd openssl-src && make SHLIB_EXT='${SHLIB_VERSION_NUMBER}.so' | tee -a $LOGS_DIR/openssl.build.log
105+
RUN cd openssl-src && make install SHLIB_EXT='${SHLIB_VERSION_NUMBER}.so' | tee -a $LOGS_DIR/openssl.install.log
103106

104107
# This build container builds Python, rubicon-java, and any dependencies. Each Python version
105108
# requires itself to be installed globally during a cross-compile.
@@ -108,18 +111,25 @@ RUN apt-get update -qq && apt-get -qq install software-properties-common dirmngr
108111
RUN apt-add-repository ppa:deadsnakes/ppa
109112
RUN apt-get update -qq && apt-get -qq install python3.7 python3.8 python3.9 python3.10 python3.11 pkg-config zip quilt
110113

111-
# Get libs & vars
114+
# Get libs & vars from the build stages
112115
COPY --from=build_openssl /opt/python-build/built/openssl /opt/python-build/built/openssl
113116
COPY --from=build_bz2 /opt/python-build/built/libbz2 /opt/python-build/built/libbz2
114117
COPY --from=build_xz /opt/python-build/built/xz /opt/python-build/built/xz
115118
COPY --from=build_libffi /opt/python-build/built/libffi /opt/python-build/built/libffi
116119
COPY --from=build_sqlite /opt/python-build/built/sqlite /opt/python-build/built/sqlite
117120

121+
# Copy logs from the build stages
122+
COPY --from=build_openssl $LOGS_DIR/* $LOGS_DIR
123+
COPY --from=build_bz2 $LOGS_DIR/* $LOGS_DIR
124+
COPY --from=build_xz $LOGS_DIR/* $LOGS_DIR
125+
COPY --from=build_libffi $LOGS_DIR/* $LOGS_DIR
126+
COPY --from=build_sqlite $LOGS_DIR/* $LOGS_DIR
127+
118128
ENV OPENSSL_INSTALL_DIR=/opt/python-build/built/openssl
119129
ENV LIBBZ2_INSTALL_DIR="$BUILD_HOME/built/libbz2"
120130
ENV LIBXZ_INSTALL_DIR="$BUILD_HOME/built/xz"
121131
RUN mkdir -p "$JNI_LIBS" && cp -a "$OPENSSL_INSTALL_DIR"/lib/*.so "$LIBBZ2_INSTALL_DIR"/lib/*.so /opt/python-build/built/libffi/lib/*.so /opt/python-build/built/xz/lib/*.so /opt/python-build/built/sqlite/lib/*.so "$JNI_LIBS"
122-
ENV PKG_CONFIG_PATH="/opt/python-build/built/libffi/lib/pkgconfig:/opt/python-build/built/xz/lib/pkgconfig"
132+
ENV PKG_CONFIG_PATH="/opt/python-build/built/libffi/lib/pkgconfig:/opt/python-build/built/openssl/lib/pkgconfig:/opt/python-build/built/sqlite/lib/pkgconfig:/opt/python-build/built/xz/lib/pkgconfig"
123133

124134
# Download & patch Python. We assume that there is only one Python-${VERSION}.*.tar.xz file.
125135
ARG PYTHON_VERSION
@@ -136,9 +146,9 @@ RUN sed -i -e s,'test $(INSTSONAME) != $(LDLIBRARY)',true, -e s,'$(LN) -f $(INST
136146
ARG PYTHON_SOVERSION
137147
# Apply a C extensions linker hack; already fixed in Python 3.8+; see https://github.com/python/cpython/commit/254b309c801f82509597e3d7d4be56885ef94c11
138148
RUN sed -i -e s,'libraries or \[\],\["pythonPYTHON_SOVERSION"] + libraries if libraries else \["pythonPYTHON_SOVERSION"\],' -e "s,pythonPYTHON_SOVERSION,python${PYTHON_SOVERSION},g" python-src/Lib/distutils/extension.py
139-
# Apply a hack to get the NDK library paths into the Python build. Python 3.6 (but not 3.7+) needs OpenSSL here as well.
149+
# Apply a hack to get the NDK library paths into the Python build.
140150
# TODO(someday): Discuss with e.g. Kivy and see how to remove this.
141-
RUN sed -i -e "s# dirs = \[\]# dirs = \[os.environ.get('SYSROOT_INCLUDE'), os.environ.get('SYSROOT_LIB'), os.environ.get('OPENSSL_INSTALL_DIR') + '/include', os.environ.get('OPENSSL_INSTALL_DIR') + '/lib' \]#" python-src/setup.py
151+
RUN sed -i -e "s# dirs = \[\]# dirs = \[os.environ.get('SYSROOT_INCLUDE'), os.environ.get('SYSROOT_LIB') \]#" python-src/setup.py
142152
# Apply a hack to get the sqlite include path into setup.py. TODO(someday): Discuss with upstream Python if we can use pkg-config for sqlite.
143153
RUN sed -i -E 's,sqlite_inc_paths = [[][]],sqlite_inc_paths = ["/opt/python-build/built/sqlite/include"],' python-src/setup.py
144154
# Apply a hack to make platform.py stop looking for a libc version.
@@ -148,27 +158,50 @@ RUN sed -i -e "s#Linux#DisabledLinuxCheck#" python-src/Lib/platform.py
148158
ADD patches/${PYTHON_VERSION} python-src/patches
149159
RUN cd python-src && if [ "$(wc -l < patches/series)" != "0" ] ; then quilt push -a; else echo "No patches." ; fi
150160

161+
# Add a Setup.local configuration
162+
RUN cp python-src/patches/Setup.local python-src/Modules
163+
151164
# Build Python, pre-configuring some values so it doesn't check if those exist.
152165
ENV SYSROOT_LIB=${TOOLCHAIN}/sysroot/usr/lib/${TOOLCHAIN_TRIPLE}/${ANDROID_API_LEVEL}/ \
153-
SYSROOT_INCLUDE=${NDK}/sysroot/usr/include/
166+
SYSROOT_INCLUDE=${TOOLCHAIN}/sysroot/usr/include/
154167
# Add any version-specific configuration flags
155168
ARG PYTHON_EXTRA_CONFIGURE_FLAGS
156169
ENV PYTHON_EXTRA_CONFIGURE_FLAGS $PYTHON_EXTRA_CONFIGURE_FLAGS
157-
# Call ./configure with enough parameters to work properly on Python 3.6 and 3.7.
158-
# Python 3.6 needs OpenSSL's headers in CFLAGS; Python 3.7+ consumes it from --with-openssl=.
159-
# Python 3.6 needs ac_cv_header_langinfo_h=no because it lacks a more specific check for nl_langinfo
160-
# (which Android lacks).
170+
# Call ./configure with enough parameters to work.
161171
RUN cd python-src && LDFLAGS="$(pkg-config --libs-only-L libffi) $(pkg-config --libs-only-L liblzma) -L${LIBBZ2_INSTALL_DIR}/lib -L$OPENSSL_INSTALL_DIR/lib" \
162-
CFLAGS="${CFLAGS} -I${LIBBZ2_INSTALL_DIR}/include $(pkg-config --cflags-only-I libffi) $(pkg-config --cflags-only-I liblzma) -I$OPENSSL_INSTALL_DIR/include" \
163-
./configure --host "$TOOLCHAIN_TRIPLE" --build "$COMPILER_TRIPLE" --enable-shared \
164-
--enable-ipv6 ac_cv_file__dev_ptmx=yes \
165-
--with-openssl=$OPENSSL_INSTALL_DIR \
166-
ac_cv_header_langinfo_h=no \
167-
ac_cv_file__dev_ptc=no --without-ensurepip ac_cv_little_endian_double=yes \
172+
CFLAGS="${CFLAGS} -I${LIBBZ2_INSTALL_DIR}/include $(pkg-config --cflags-only-I libffi) $(pkg-config --cflags-only-I liblzma)" \
173+
./configure \
174+
--host "$TOOLCHAIN_TRIPLE" \
175+
--build "$COMPILER_TRIPLE" \
168176
--prefix="$PYTHON_INSTALL_DIR" \
177+
--enable-shared \
178+
--enable-ipv6 \
179+
--with-openssl=$OPENSSL_INSTALL_DIR \
180+
--without-ensurepip \
181+
ac_cv_file__dev_ptmx=yes \
182+
ac_cv_file__dev_ptc=no \
183+
ac_cv_little_endian_double=yes \
169184
$PYTHON_EXTRA_CONFIGURE_FLAGS \
170-
ac_cv_func_setuid=no ac_cv_func_seteuid=no ac_cv_func_setegid=no ac_cv_func_getresuid=no ac_cv_func_setresgid=no ac_cv_func_setgid=no ac_cv_func_sethostname=no ac_cv_func_setresuid=no ac_cv_func_setregid=no ac_cv_func_setreuid=no ac_cv_func_getresgid=no ac_cv_func_setregid=no ac_cv_func_clock_settime=no ac_cv_header_termios_h=no ac_cv_func_sendfile=no ac_cv_header_spawn_h=no ac_cv_func_posix_spawn=no \
171-
ac_cv_func_setlocale=no ac_cv_working_tzset=no ac_cv_member_struct_tm_tm_zone=no ac_cv_func_sched_setscheduler=no
185+
ac_cv_func_setuid=no \
186+
ac_cv_func_seteuid=no \
187+
ac_cv_func_setegid=no \
188+
ac_cv_func_getresuid=no \
189+
ac_cv_func_setresgid=no \
190+
ac_cv_func_setgid=no \
191+
ac_cv_func_sethostname=no \
192+
ac_cv_func_setresuid=no \
193+
ac_cv_func_setregid=no \
194+
ac_cv_func_setreuid=no \
195+
ac_cv_func_getresgid=no \
196+
ac_cv_func_setregid=no \
197+
ac_cv_func_clock_settime=no \
198+
ac_cv_func_sendfile=no \
199+
ac_cv_header_spawn_h=no \
200+
ac_cv_func_posix_spawn=no \
201+
ac_cv_func_setlocale=no \
202+
ac_cv_working_tzset=no \
203+
ac_cv_member_struct_tm_tm_zone=no \
204+
ac_cv_func_sched_setscheduler=no | tee -a $LOGS_DIR/python.configure.log
172205
# Override ./configure results to futher force Python not to use some libc calls that trigger blocked syscalls.
173206
# TODO(someday): See if HAVE_INITGROUPS has another way to disable it.
174207
RUN cd python-src && sed -i -E 's,#define (HAVE_CHROOT|HAVE_SETGROUPS|HAVE_INITGROUPS) 1,,' pyconfig.h
@@ -180,7 +213,7 @@ RUN cd python-src && sed -i -E 's,#define.*(HAVE_EXECV|HAVE_FORK).*1,,' Modules/
180213
# Copy libbz2 into the SYSROOT_LIB. This is the IMHO the easiest way for setup.py to find it.
181214
RUN cp "${LIBBZ2_INSTALL_DIR}/lib/libbz2.so" $SYSROOT_LIB
182215
# Compile Python. We can still remove some tests from the test suite before `make install`.
183-
RUN cd python-src && make
216+
RUN cd python-src && make | tee -a $LOGS_DIR/python.build.log
184217

185218
# Modify stdlib & test suite before `make install`.
186219

@@ -216,7 +249,7 @@ RUN cd python-src && rm Lib/test/test_xmlrpc.py
216249
RUN cd python-src && rm Lib/test/test_wsgiref.py
217250

218251
# Install Python.
219-
RUN cd python-src && make install
252+
RUN cd python-src && make install | tee -a $LOGS_DIR/python.install.log
220253
RUN cp -a $PYTHON_INSTALL_DIR/lib/libpython${PYTHON_SOVERSION}.so "$JNI_LIBS"
221254

222255
# Download & install rubicon-java's Java & C parts. The *.py files in rubicon-java are
@@ -225,7 +258,7 @@ RUN cp -a $PYTHON_INSTALL_DIR/lib/libpython${PYTHON_SOVERSION}.so "$JNI_LIBS"
225258
ADD downloads/rubicon-java/* .
226259
RUN mv rubicon-java-* rubicon-java-src
227260
RUN cd rubicon-java-src && \
228-
LDFLAGS='-landroid -llog' PYTHON_CONFIG=$PYTHON_INSTALL_DIR/bin/python3-config make
261+
LDFLAGS='-landroid -llog' PYTHON_CONFIG=$PYTHON_INSTALL_DIR/bin/python3-config make | tee -a $LOGS_DIR/rubicon.log
229262
RUN mv rubicon-java-src/build/librubicon.so $JNI_LIBS
230263
RUN mkdir -p /opt/python-build/app/libs/ && mv rubicon-java-src/build/rubicon.jar $APPROOT/app/libs/
231264

0 commit comments

Comments
 (0)