Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
164 changes: 156 additions & 8 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,162 @@
image: ubuntu2004

skip_branch_with_pr: true

environment:
ANDROID_SDK_ROOT: /usr/lib/android-sdk
python_stack: python 3.12
PYTHON_VERSION: 3.12.6
PYTHON_VERSION_SHORT: 3.12
GITHUB_TOKEN:
secure: 9SKIwc3VSfYJ5IChvNR74rlTF9BMbAfhCGu1/TmYJBMtC6lkY+UDDkZNK7rC9xnQFUxMrNgoo9kNcNAbKbU8XAcrSwkP2H4mX04FI7P+YbxfiWC8nVHhGNxR4LzO+GO0

matrix:
- job_name: Build Python for iOS and macOS
APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma

- job_name: Build Python for Android
APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c
NDK_VERSION: r27

- job_name: Build Python for Linux
APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c
PYTHON_DIST_RELEASE: 20240909

- job_name: Build Python for Windows
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022

matrix:
fast_finish: true

stack: $python_stack

install:
- ls -al $ANDROID_SDK_ROOT
- python --version

for:
# ======================================
# Build Python for iOS and macOS
# ======================================

- matrix:
only:
- job_name: Build Python for iOS and macOS

build_script:
- cd darwin

# Build Python for iOS and macOS
- git clone --branch=$PYTHON_VERSION_SHORT https://github.com/beeware/Python-Apple-support.git
- mkdir -p dist
- sh: |
pushd Python-Apple-support
make iOS || exit 1
tar -czf ../dist/python-ios-mobile-forge-$PYTHON_VERSION_SHORT.tar.gz install support -C .
make macOS || exit 1
popd

# Package for Dart
- ./package-ios-for-dart.sh Python-Apple-support $PYTHON_VERSION_SHORT
- ./package-macos-for-dart.sh Python-Apple-support $PYTHON_VERSION_SHORT

# Push all archives to artifacts
- find dist -maxdepth 1 -type f -iname python-*.tar.gz -exec appveyor PushArtifact -DeploymentName python-darwin {} \;

test: off

deploy:
provider: GitHub
auth_token: $(GITHUB_TOKEN)
release: v$(PYTHON_VERSION_SHORT)
artifact: python-darwin

# ======================================
# Build Python for Android
# ======================================

- matrix:
only:
- job_name: Build Python for Android

build_script:
- cd android

# Build all Python ABIs
- ./build-all.sh $PYTHON_VERSION

# Package support package for use with mobile-forge
- mkdir -p dist
- tar -czf dist/python-android-mobile-forge-$PYTHON_VERSION_SHORT.tar.gz install support

# Package individual ABIs for use with serious_python Flutter package
- ./package-for-dart.sh install $PYTHON_VERSION arm64-v8a
- ./package-for-dart.sh install $PYTHON_VERSION armeabi-v7a
- ./package-for-dart.sh install $PYTHON_VERSION x86_64

# Push all archives to artifacts
- find dist -maxdepth 1 -type f -iname python-android-*.tar.gz -exec appveyor PushArtifact -DeploymentName python-android {} \;

test: off

deploy:
provider: GitHub
auth_token: $(GITHUB_TOKEN)
release: v$(PYTHON_VERSION_SHORT)
artifact: python-android

# ======================================
# Build Python for Linux
# ======================================

- matrix:
only:
- job_name: Build Python for Linux

build_script:
- cd linux
- ./package-for-linux.sh x86_64 "_v3"
- ./package-for-linux.sh aarch64 ""

# Push all archives to artifacts
- ls
- find . -maxdepth 1 -type f -iname "python-linux-dart-*.tar.gz" -exec appveyor PushArtifact -DeploymentName python-linux {} \;

test: off

deploy:
provider: GitHub
auth_token: $(GITHUB_TOKEN)
release: v$(PYTHON_VERSION_SHORT)
artifact: python-linux

# ======================================
# Build Python for Windows
# ======================================

- matrix:
only:
- job_name: Build Python for Windows

install:
- C:\Python312\python --version

build_script:
- cd windows
- curl -OL https://www.python.org/ftp/python/3.12.5/python-3.12.5-amd64.exe
- start /wait python-3.12.5-amd64.exe /uninstall /quiet

- curl -OL https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-amd64.exe
- start /wait python-%PYTHON_VERSION%-amd64.exe /quiet
- dir C:\python312-dist
- C:\python312-dist\python -m compileall -b C:\python312-dist\Lib
- 7z a -xr@exclude.txt python-windows-for-dart-%PYTHON_VERSION_SHORT%.zip C:\python312-dist\*

test: off

build_script:
- git clone https://github.com/beeware/cpython-android-source-deps
- cd cpython-android-source-deps
- ./build.sh
artifacts:
- path: windows\python-windows-for-dart-*.zip
name: python-windows

test: off
deploy:
provider: GitHub
auth_token: $(GITHUB_TOKEN)
release: v$(PYTHON_VERSION_SHORT)
artifact: python-windows
13 changes: 13 additions & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.envrc
.vscode/
build
dist
downloads
install
local
support
*.dist-info
__pycache__
*.log
*.gz
*.DS_Store
33 changes: 33 additions & 0 deletions android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Python for Android

Scripts and CI jobs for building Python 3 for Android.

* Can be run on both Linux and macOS.
* Build Python 3.12 - specific or the last minor version.
* Installs NDK r26d or use pre-installed one with path configured by `NDK_HOME` variable.
* Creates Python installation with a structure suitable for https://github.com/flet-dev/mobile-forge

## Usage

To build the latest minor version of Python 3.12 for selected Android API:

```
./build.sh 3.12 arm64-v8a
```

To build all ABIs:

```
./build-all.sh 3.12
```

## Credits

Build process depends on:
* https://github.com/beeware/cpython-android-source-deps

Based on the work from:
* https://github.com/chaquo/chaquopy/tree/master/target
* https://github.com/beeware/Python-Android-support
* https://github.com/beeware/cpython-android-source-deps
* https://github.com/GRRedWings/python3-android
107 changes: 107 additions & 0 deletions android/android-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
fail() {
echo "$1" >&2
exit 1
}

if [[ -z "${NDK_HOME-}" ]]; then
NDK_HOME=$HOME/ndk/$NDK_VERSION
echo "NDK_HOME environment variable is not set."
if [ ! -d $NDK_HOME ]; then
echo "Installing NDK $NDK_VERSION to $NDK_HOME"

if [ $(uname) = "Darwin" ]; then
seven_zip=$downloads/7zip/7zz
if ! test -f $seven_zip; then
echo "Installing 7-zip"
mkdir -p $(dirname $seven_zip)
cd $(dirname $seven_zip)
curl -#OL https://www.7-zip.org/a/7z2301-mac.tar.xz
tar -xf 7z2301-mac.tar.xz
cd -
fi

ndk_dmg=android-ndk-$NDK_VERSION-darwin.dmg
if ! test -f $downloads/$ndk_dmg; then
echo ">>> Downloading $ndk_dmg"
curl -#L -o $downloads/$ndk_dmg https://dl.google.com/android/repository/$ndk_dmg
fi

cd $downloads
$seven_zip x -snld $ndk_dmg
mkdir -p $(dirname $NDK_HOME)
mv Android\ NDK\ */AndroidNDK*.app/Contents/NDK $NDK_HOME
rm -rf Android\ NDK\ *
cd -
else
ndk_zip=android-ndk-$NDK_VERSION-linux.zip
if ! test -f $downloads/$ndk_zip; then
echo ">>> Downloading $ndk_zip"
curl -#L -o $downloads/$ndk_zip https://dl.google.com/android/repository/$ndk_zip
fi
cd $downloads
unzip -oq $ndk_zip
mkdir -p $(dirname $NDK_HOME)
mv android-ndk-$NDK_VERSION $NDK_HOME
cd -
echo "NDK installed to $NDK_HOME"
fi
else
echo "NDK $NDK_VERSION is already installed in $NDK_HOME"
fi
else
echo "NDK home: $NDK_HOME"
fi

if [ $host_triplet = "arm-linux-androideabi" ]; then
clang_triplet=armv7a-linux-androideabi
else
clang_triplet=$host_triplet
fi

# These variables are based on BuildSystemMaintainers.md above, and
# $NDK_HOME/build/cmake/android.toolchain.cmake.
toolchain=$(echo $NDK_HOME/toolchains/llvm/prebuilt/*)
export AR="$toolchain/bin/llvm-ar"
export AS="$toolchain/bin/llvm-as"
export CC="$toolchain/bin/${clang_triplet}$api_level-clang"
export CXX="${CC}++"
export LD="$toolchain/bin/ld"
export NM="$toolchain/bin/llvm-nm"
export RANLIB="$toolchain/bin/llvm-ranlib"
export READELF="$toolchain/bin/llvm-readelf"
export STRIP="$toolchain/bin/llvm-strip"

# The quotes make sure the wildcard in the `toolchain` assignment has been expanded.
for path in "$AR" "$AS" "$CC" "$CXX" "$LD" "$NM" "$RANLIB" "$READELF" "$STRIP"; do
if ! [ -e "$path" ]; then
fail "$path does not exist"
fi
done

# Use -idirafter so that package-specified -I directories take priority. For example,
# grpcio provides its own BoringSSL headers which must be used rather than our OpenSSL.
export CFLAGS="-idirafter ${prefix:?}/include"
export LDFLAGS="-L${prefix:?}/lib -Wl,--build-id=sha1 -Wl,--no-rosegment"

# Many packages get away with omitting this on standard Linux, but Android is stricter.
LDFLAGS+=" -lm"

case $abi in
armeabi-v7a)
CFLAGS+=" -march=armv7-a -mthumb"
;;
x86)
# -mstackrealign is unnecessary because it's included in the clang launcher script
# which is pointed to by $CC.
;;
esac

export PKG_CONFIG="pkg-config --define-prefix"
export PKG_CONFIG_LIBDIR="$prefix/lib/pkgconfig"

# conda-build variable name
if [ $(uname) = "Darwin" ]; then
export CPU_COUNT=$(sysctl -n hw.ncpu)
else
export CPU_COUNT=$(nproc)
fi
9 changes: 9 additions & 0 deletions android/build-all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
set -eu

python_version=${1:?}
abis="arm64-v8a armeabi-v7a x86_64 x86"

for abi in $abis; do
./build.sh $python_version $abi
done
Loading