Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-30386: Add a build infrastructure for Android. #1629

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
65edf88
bpo-30386: Add a build infrastructure for Android.
xdegaye May 17, 2017
67b40a7
bpo-30386: Support the new NDK Unified Headers.
xdegaye May 19, 2017
543a287
Add Makefile targets to implement the buildbot steps.
xdegaye May 27, 2017
88c9e5f
Merge branch 'master' into bpo-30386
xdegaye May 28, 2017
408c05d
Update the native interpreter build on Setup.dist and version changes.
xdegaye May 30, 2017
7a2fc54
Add build a distribution for an application on a device
xdegaye Aug 8, 2017
3161893
The device/emulator distributions include now only the shared librari…
xdegaye Aug 9, 2017
648f3a9
The WITH_LIBRARIES environment variable selects the external libraries
xdegaye Aug 16, 2017
fbedffc
Add the whatsnew and Misc/NEWS.d entries
xdegaye Aug 16, 2017
d78ff4e
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Oct 21, 2017
3cf267a
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Nov 3, 2017
23172d8
Fix a regression from 3161893d933538f4bd93c674e52cc8043885694e
xdegaye Nov 3, 2017
fde2fc7
Patch libffi to set FFI_MMAP_EXEC_WRIT in configure
xdegaye Nov 5, 2017
71a45d6
Java 8 is now required to create an avd.
xdegaye Nov 5, 2017
863a083
Build ctypes with the headers of the cross-compiled libffi
xdegaye Nov 20, 2017
21fd663
Disable _ctypes on x86_64 (all long double tests fail)
xdegaye Nov 20, 2017
fd259a3
Disable uuid, Android has no uuid/uuid.h header
xdegaye Nov 20, 2017
61d0cf5
Disable grp, some grp.h functions are __INTRODUCED_IN_FUTURE
xdegaye Nov 20, 2017
ab0e4ef
Disable _crypt, Android does not have crypt.h
xdegaye Nov 20, 2017
937e864
Install also the README(s), test_normalization needs the test/data di…
xdegaye Nov 25, 2017
ebb493a
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Nov 25, 2017
1b749ed
Add the EMULATOR_CMD_LINE_OPTIONS environment variable
xdegaye Nov 27, 2017
50129e6
The default for ANDROID_API is now 24
xdegaye Nov 27, 2017
406d044
Disable _ctypes on arm64 platforms
xdegaye Nov 29, 2017
616ff20
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Nov 29, 2017
6f4ab84
Do not update Modules/Setup if it already lists the disabled modules
xdegaye Nov 30, 2017
57c59ab
Remove the support of the arm architecture
xdegaye Nov 30, 2017
3e1bdc5
Do not use an SD card partition image (not anymore mounted on 26.1.4)
xdegaye Dec 1, 2017
4e340bb
Fix the build of libffi on armv7
xdegaye Dec 1, 2017
715b876
Add support for multiple emulators running concurrently
xdegaye Dec 2, 2017
10581d5
Add the pythoninfo make target
xdegaye Dec 3, 2017
a997662
Update the build system to run on buildbots
xdegaye Dec 4, 2017
8b295c6
Exit with the return code of the shell run remotely by adb
xdegaye Dec 5, 2017
204c821
Run pythoninfo on the emulator and add the NDK version
xdegaye Dec 6, 2017
c0ca089
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Dec 7, 2017
332f0bb
Call pybuildbot.identify in the buildbottest target
xdegaye Dec 8, 2017
b176b43
Print the external libraries versions
xdegaye Dec 8, 2017
387b463
Do not set now (after bpo-32059) '--sysroot' in CFLAGS
xdegaye Dec 9, 2017
9884413
Remove useless CFLAGS options
xdegaye Dec 9, 2017
57e432b
Update the README
xdegaye Dec 10, 2017
67992a3
'--sysroot' is needed in CFLAGS by distutils
xdegaye Dec 10, 2017
a12c1c6
Do not run nl_langinfo.sh
xdegaye Dec 10, 2017
47614b4
Merge remote-tracking branch 'origin/master' into bpo-30386
xdegaye Dec 10, 2017
dbbca8b
There is now only one method to build Python
xdegaye Dec 17, 2017
96fa8c8
Support openssl-1.1.0g on all architectures
xdegaye Jan 31, 2018
1f0ce9d
Support ctypes also on 64 bits architectures
xdegaye Feb 1, 2018
77a30e9
Support pip
xdegaye Feb 2, 2018
cb9f4e3
Remove the Doc/whatsnew/3.7rst and Misc/NEWS.d entries
xdegaye Feb 4, 2018
f109722
Set the python version in build.mk instead of the Makefile
xdegaye Feb 5, 2018
5bbf5e2
Do not use a symlink for inputrc
xdegaye Feb 18, 2018
0a51515
Add the 'setup' target to build third-party extension modules
xdegaye Feb 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
447 changes: 447 additions & 0 deletions Android/README.rst

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions Android/build-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Android/build-config

ndk_version=14

# Set default values if not defined.
: ${ANDROID_NDK_ROOT:=$HOME/android/android-ndk}
: ${ANDROID_SDK_ROOT:=$HOME/android/android-sdk}
: ${ANDROID_API:=24}
: ${ANDROID_ARCH:=x86_64}

build_config_error ()
{
echo "Error: $1" >&2
exit 1
}

! test -d "$ANDROID_NDK_ROOT" && build_config_error "\$ANDROID_NDK_ROOT ($ANDROID_NDK_ROOT) is not a directory."
version=$(cat "$ANDROID_NDK_ROOT/source.properties" | \
sed -e "s/^.*Pkg.Revision[ \t]*=[ \t]*\([0-9]\+\).*$\|^.*$/\1/" -e "/^$/d")
test "$version" != $ndk_version &&
build_config_error "The installed NDK version is $version but version $ndk_version is required."
unset ndk_version version

test $((ANDROID_API)) -lt 21 && \
build_config_error "\$ANDROID_API ($ANDROID_API) must be 21 or greater."
test $((ANDROID_API)) -lt 24 && test "$ANDROID_ARCH" = arm64 && \
build_config_error "Cannot build or run arm64 at an API level less than 24."

# No NDK has been released at SDK API level 22, use NDK API 21 instead.
test "$ANDROID_API" = 22 && ANDROID_API=21

test -n "$PY_SRCDIR" && ANDROID_BUILD=$($PY_SRCDIR/config.guess)
gcc_version=4.9
case "$ANDROID_ARCH" in
armv7)
ANDROID_HOST=arm-linux-androideabi
APP_ABI=armeabi-v7a
target=armv7-none-linux-androideabi
toolchain=$ANDROID_HOST-$gcc_version
SYSROOT="$ANDROID_NDK_ROOT/platforms/android-$ANDROID_API/arch-arm"
;;
arm64)
ANDROID_HOST=aarch64-linux-android
APP_ABI=arm64-v8a
target=aarch64-none-linux-android
toolchain=$ANDROID_HOST-$gcc_version
;;
x86)
ANDROID_HOST=i686-linux-android
APP_ABI=x86
target=i686-none-linux-androideabi
toolchain=x86-$gcc_version
;;
x86_64)
ANDROID_HOST=x86_64-linux-android
APP_ABI=x86_64
target=x86_64-none-linux-androideabi
toolchain=x86_64-$gcc_version
;;
*)
build_config_error "ANDROID_ARCH must be set to armv7, arm64, x86 or x86_64."
;;
esac
unset gcc_version
if test "$ANDROID_ARCH" != armv7; then
SYSROOT="$ANDROID_NDK_ROOT/platforms/android-$ANDROID_API/arch-$ANDROID_ARCH"
fi

machine=$(uname -m)
kernel=$(uname -s | tr A-Z a-z)
tool_path ()
{
echo "$ANDROID_NDK_ROOT/toolchains/$1/prebuilt/${kernel}-${machine}"
}
toolchain=$(tool_path $toolchain)

# Build variables.
CC="$(tool_path llvm)/bin/clang -target $target -gcc-toolchain $toolchain"
GCC="$toolchain/bin/$ANDROID_HOST-gcc"
AR="$toolchain/bin/$ANDROID_HOST-ar"
LD="$toolchain/bin/$ANDROID_HOST-ld"
RANLIB="$toolchain/bin/$ANDROID_HOST-ranlib"
READELF="$toolchain/bin/$ANDROID_HOST-readelf"
STRIP="$toolchain/bin/$ANDROID_HOST-strip --strip-debug --strip-unneeded"
unset target toolchain machine kernel tool_path

# We need to set '--sysroot' both in CFLAGS and CPPFLAGS:
# * configure needs to have '--sysroot' set in CPPFLAGS when it runs CPP.
# * Extension modules are not compiled by distutils with CPPFLAGS.
ndk_flags="--sysroot=$ANDROID_NDK_ROOT/sysroot -D__ANDROID_API__=$ANDROID_API -isystem $ANDROID_NDK_ROOT/sysroot/usr/include/$ANDROID_HOST"
CPPFLAGS="$CPPFLAGS $ndk_flags"
CFLAGS="$CFLAGS $ndk_flags"
LDFLAGS="$LDFLAGS --sysroot=$SYSROOT"
unset ndk_flags

ccache -V >/dev/null 2>&1 && { CC="ccache $CC"; GCC="ccache $GCC"; \
CFLAGS="$CFLAGS -Wno-parentheses-equality"; }
249 changes: 249 additions & 0 deletions Android/build.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
# Android/build.mk

# Directory names.
export BUILD_DIR := $(CURDIR)/build
export DIST_DIR := $(CURDIR)/dist
avd_dir := $(CURDIR)/avd
native_build_dir := $(BUILD_DIR)/python-native
py_name := python$(py_version)
export BUILD_TYPE := android-$(ANDROID_API)-$(ANDROID_ARCH)
py_host_dir := $(BUILD_DIR)/$(py_name)-$(BUILD_TYPE)
export PY_EXTDIR := $(BUILD_DIR)/$(py_name)-extlibs-$(BUILD_TYPE)
PY_DESTDIR := $(BUILD_DIR)/$(py_name)-install-$(BUILD_TYPE)
abiflags = $(shell echo $$(cat $(py_host_dir)/Makefile | \
sed -e "s/^ABIFLAGS[= \t]*\(.*\)[ \t]*$$\|^.*$$/\1/" -e "/^$$/d"))
py_fullname = python$(py_version)$(abiflags)
export STDLIB_DIR := lib/python$(py_version)


ROOT_MAKE := $(MAKE) -f Makefile-$(BUILD_TYPE)

# Target variables names.
python := $(py_host_dir)/python
config_status := $(py_host_dir)/config.status
export PYTHON_ZIP := $(DIST_DIR)/$(py_name)-$(BUILD_TYPE).zip
export PY_STDLIB_ZIP := $(DIST_DIR)/$(py_name)-$(BUILD_TYPE)-stdlib.zip


# Rules.
build: $(python)
ifdef DEVICE_PREFIXES
dist: python_dist
else
dist: $(PYTHON_ZIP) $(PY_STDLIB_ZIP)
endif

ifndef DEVICE_PREFIXES
include $(py_srcdir)/Android/emulator.mk
endif

$(native_build_dir)/Modules/Setup: $(py_srcdir)/Modules/Setup.dist
cp $(py_srcdir)/Modules/Setup.dist $(native_build_dir)/Modules/Setup

$(native_build_dir)/config.status: $(py_srcdir)/configure
@# Run distclean upon the switch to a new Python release.
@# 'Touch' the 'Makefile' target first to prevent a useless run of configure.
@cur=$$(cat $(py_srcdir)/configure | sed -e "s/^VERSION=\([0-9]\+\.[0-9]\+\)$$\|^.*$$/\1/" -e "/^$$/d"); \
prev=$$cur; \
if test -f "$(native_build_dir)/python"; then \
prev=$$($(native_build_dir)/python -c "from sys import version_info; print('.'.join(str(i) for i in version_info[:2]))"); \
fi; \
if test "$$prev" != "$$cur"; then \
echo "---> Cleanup before the switch from Python version $$prev to $$cur"; \
$(MAKE) -C $(native_build_dir) -t Makefile; \
$(MAKE) -C $(native_build_dir) distclean; \
fi
@echo "---> Run the native configure script."
mkdir -p $(native_build_dir)
cd $(native_build_dir); $(py_srcdir)/configure

native_python: $(native_build_dir)/config.status $(native_build_dir)/Modules/Setup
@echo "---> Build the native interpreter."
$(MAKE) -C $(native_build_dir)

# Target-specific exported variables.
$(config_status): export CPPFLAGS := -I$(PY_EXTDIR)/$(SYS_EXEC_PREFIX)/include
$(config_status): export LDFLAGS := -L$(PY_EXTDIR)/$(SYS_EXEC_PREFIX)/lib
build configure host python_dist: \
export PATH := $(native_build_dir):$(PATH)
external_libraries: export CC := $(CC)
external_libraries openssl: export AR := $(AR)
external_libraries openssl: export LD := $(LD)
external_libraries openssl: export RANLIB := $(RANLIB)
external_libraries openssl: export READELF := $(READELF)
external_libraries openssl: export CFLAGS := $(CFLAGS)
external_libraries openssl: export LDFLAGS := $(LDFLAGS)
external_libraries openssl: export ANDROID_ARCH := $(ANDROID_ARCH)
openssl: export GCC := $(GCC)
openssl: export SYSROOT := $(SYSROOT)
openssl: export ANDROID_API := android-$(ANDROID_API)

external_libraries:
mkdir -p $(BUILD_DIR)/external-libraries
ifdef WITH_LIBFFI
$(MAKE) -C $(py_srcdir)/Android/external-libraries libffi
endif
ifdef WITH_NCURSES
$(MAKE) -C $(py_srcdir)/Android/external-libraries ncurses
endif
ifdef WITH_READLINE
$(MAKE) -C $(py_srcdir)/Android/external-libraries readline
endif
ifdef WITH_SQLITE
$(MAKE) -C $(py_srcdir)/Android/external-libraries sqlite
endif

openssl:
ifdef WITH_OPENSSL
ifneq ($(ANDROID_ARCH), x86_64)
ifneq ($(ANDROID_ARCH), arm64)
mkdir -p $(BUILD_DIR)/external-libraries
$(MAKE) -C $(py_srcdir)/Android/external-libraries -f Makefile.openssl
endif
endif
endif

$(config_status): $(makefile) $(py_srcdir)/configure
mkdir -p $(py_host_dir)
@#echo "---> Ensure that nl_langinfo is broken."
@#cd $(py_host_dir); PY_SRCDIR=$(py_srcdir) $(py_srcdir)/Android/tools/nl_langinfo.sh
@echo "---> Run configure for $(BUILD_TYPE)."
cd $(py_host_dir); \
PKG_CONFIG_PATH=$(PY_EXTDIR)/$(SYS_EXEC_PREFIX)/lib/pkgconfig \
$(py_srcdir)/configure-android \
--prefix=$(SYS_PREFIX) --exec-prefix=$(SYS_EXEC_PREFIX) \
$(config_args)

$(python): native_python external_libraries openssl $(config_status)
$(ROOT_MAKE) host

configure: native_python external_libraries openssl
@rm -f $(config_status)
$(ROOT_MAKE) $(config_status)

disabled_modules: setup_tmp := $(py_host_dir)/Modules/_Setup.tmp
disabled_modules: setup_file := $(py_host_dir)/Modules/Setup
disabled_modules:
cp $(py_srcdir)/Modules/Setup.dist $(setup_tmp)
echo "*disabled*" >> $(setup_tmp)
echo "_uuid" >> $(setup_tmp)
echo "grp" >> $(setup_tmp)
echo "_crypt" >> $(setup_tmp)
ifneq ($(filter x86_64 arm64,$(ANDROID_ARCH)), )
@# Disable _ctypes on x86_64 and arm64 platforms.
echo "_ctypes" >> $(setup_tmp)
endif
@if test -f $(setup_file); then \
if test $$(md5sum $(setup_tmp) | awk '{print $$1}') != \
$$(md5sum $(setup_file) | awk '{print $$1}'); then \
cp $(setup_tmp) $(setup_file); \
fi \
fi

host: disabled_modules
@echo "---> Build Python for $(BUILD_TYPE)."
@if test -f $(config_status); then \
$(MAKE) -C $(py_host_dir) all; \
else \
echo "Error: please run 'make config', missing $(config_status)"; \
false; \
fi

python_dist: $(python)
@echo "---> Install Python for $(BUILD_TYPE)."
$(MAKE) DESTDIR=$(PY_DESTDIR) -C $(py_host_dir) install > make_install.log
cp --no-dereference $(PY_EXTDIR)/$(SYS_EXEC_PREFIX)/lib/*.so* $(PY_DESTDIR)/$(SYS_EXEC_PREFIX)/lib
chmod u+w $(PY_DESTDIR)/$(SYS_EXEC_PREFIX)/lib/*.so*
tdir=$(SYS_EXEC_PREFIX)/share/terminfo/l; mkdir -p $(PY_DESTDIR)/$$tdir && \
cp $(PY_EXTDIR)/$$tdir/linux $(PY_DESTDIR)/$$tdir
ifdef DEVICE_PREFIXES
# This won't be needed anymore when issue 31046 is fixed.
rm -rf $(PY_DESTDIR)/usr
endif

$(PYTHON_ZIP): python_dist
@echo "---> Zip the machine-specific Python library."
mkdir -p $(DIST_DIR)
rm -f $(BUILD_DIR)/$(ZIPBASE_DIR)
ln -s $(PY_DESTDIR)/$(SYS_EXEC_PREFIX) $(BUILD_DIR)/$(ZIPBASE_DIR)
rm -f $(PYTHON_ZIP)

cd $(BUILD_DIR)/$(ZIPBASE_DIR)/bin; \
ln -sf python3 python

mkdir -p $(BUILD_DIR)/$(ZIPBASE_DIR)/etc; \
ln -sf $(py_srcdir)/Android/resources/inputrc $(BUILD_DIR)/$(ZIPBASE_DIR)/etc

cd $(BUILD_DIR)/$(ZIPBASE_DIR); \
$(STRIP) bin/python$(py_version); \
chmod 755 lib/*.so*; find . -type f -name "*.so*" -print0 | xargs -0 $(STRIP)

cd $(BUILD_DIR); \
zip -g $(PYTHON_ZIP) $(ZIPBASE_DIR)/bin/python3 \
$(ZIPBASE_DIR)/bin/python $(ZIPBASE_DIR)/bin/python$(py_version); \
zip -rg $(PYTHON_ZIP) \
$(ZIPBASE_DIR)/include/$(py_fullname)/pyconfig.h \
$(ZIPBASE_DIR)/$(STDLIB_DIR)/ \
$(ZIPBASE_DIR)/share/terminfo/l/linux \
$(ZIPBASE_DIR)/etc/inputrc \
-x \*failed.so

# Zip the shared libraries excluding symlinks.
cd $(BUILD_DIR); \
libs=""; \
for l in $(ZIPBASE_DIR)/lib/*.so*; do \
test ! -h $$l && libs="$$libs $$l"; \
done; \
zip -g $(PYTHON_ZIP) $$libs

$(PY_STDLIB_ZIP): python_dist
@echo "---> Zip the Python library."
mkdir -p $(DIST_DIR)
rm -f $(PY_STDLIB_ZIP)
cd $(PY_DESTDIR)/$(SYS_PREFIX); \
zip -Drg $(PY_STDLIB_ZIP) $(STDLIB_DIR)* \
-x \*.so \*.pyo \*opt-\*.pyc

# Make things clean, before making a distribution.
distclean: kill_emulator hostclean
rm -f $(PYTHON_ZIP)
rm -f $(PY_STDLIB_ZIP)
rm -f $(DIST_DIR)/*.sh
-rmdir $(DIST_DIR)
rm -f $(BUILD_DIR)/python
rm -rf $(PY_DESTDIR)

hostclean:
-$(MAKE) -C $(py_host_dir) distclean

# Remove everything for the given ANDROID_API and ANDROID_ARCH except the avd.
clean: distclean
rm -rf $(BUILD_DIR)/python-native
rm -rf $(py_host_dir)
rm -rf $(BUILD_DIR)/external-libraries/*-$(BUILD_TYPE)
-rmdir $(BUILD_DIR)/external-libraries
rm -rf $(PY_EXTDIR)
-rmdir $(BUILD_DIR)
-rmdir $(avd_dir)
rm -rf $(DIST_DIR)/gdb/android-$(ANDROID_API)-$(ANDROID_ARCH)
-rmdir $(DIST_DIR)/gdb
-rmdir $(DIST_DIR)
rm Makefile Makefile-android-$(ANDROID_API)-$(ANDROID_ARCH)


# Tool names.
wget := $(shell which wget 2>/dev/null)
curl := $(shell which curl 2>/dev/null)
ifeq (curl, $(findstring curl, $(curl)))
export DOWNLOAD := $(curl) -O
else ifeq (wget, $(findstring wget, $(wget)))
export DOWNLOAD := $(wget)
else
$(warning *** Cannot download the external libraries with wget or curl, \
please download those libraries to the 'Android/external-libraries' \
directory.)
endif

.PHONY: build configure host native_python \
external_libraries openssl \
dist python_dist distclean hostclean clean
Loading