Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ jobs:
with:
persist-credentials: false
- name: Build and test
run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android
run: python3 Platforms/Android ci --fast-ci ${{ matrix.arch }}-linux-android

build-ios:
name: iOS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The Android build tools have been moved to the Platforms folder.
83 changes: 48 additions & 35 deletions Android/README.md → Platforms/Android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ Instead, use one of the tools listed
[here](https://docs.python.org/3/using/android.html), which will provide a much
easier experience.


## Prerequisites

If you already have an Android SDK installed, export the `ANDROID_HOME`
Expand All @@ -25,15 +24,14 @@ it:
`android-sdk/cmdline-tools/latest`.
* `export ANDROID_HOME=/path/to/android-sdk`

The `android.py` script will automatically use the SDK's `sdkmanager` to install
The `Platforms/Android` script will automatically use the SDK's `sdkmanager` to install
any packages it needs.

The script also requires the following commands to be on the `PATH`:

* `curl`
* `java` (or set the `JAVA_HOME` environment variable)


## Building

Python can be built for Android on any POSIX platform supported by the Android
Expand All @@ -43,29 +41,28 @@ First we'll make a "build" Python (for your development machine), then use it to
help produce a "host" Python for Android. So make sure you have all the usual
tools and libraries needed to build Python for your development machine.

The easiest way to do a build is to use the `android.py` script. You can either
The easiest way to do a build is to use the `Platforms/Android` script. You can either
have it perform the entire build process from start to finish in one step, or
you can do it in discrete steps that mirror running `configure` and `make` for
each of the two builds of Python you end up producing.

The discrete steps for building via `android.py` are:
The discrete steps for building via `Platforms/Android` are:

```sh
./android.py configure-build
./android.py make-build
./android.py configure-host HOST
./android.py make-host HOST
python3 Platforms/Android configure-build
python3 Platforms/Android make-build
python3 Platforms/Android configure-host HOST
python3 Platforms/Android make-host HOST
```

`HOST` identifies which architecture to build. To see the possible values, run
`./android.py configure-host --help`.
`python3 Platforms/Android configure-host --help`.

To do all steps in a single command, run:

```sh
./android.py build HOST
python3 Platforms/Android build HOST
```

In the end you should have a build Python in `cross-build/build`, and a host
Python in `cross-build/HOST`.

Expand All @@ -75,43 +72,33 @@ call. For example, if you want a pydebug build that also caches the results from
`configure`, you can do:

```sh
./android.py build HOST -- -C --with-pydebug
python3 Platforms/Android build HOST -- -C --with-pydebug
```


## Packaging

After building an architecture as described in the section above, you can
package it for release with this command:

```sh
./android.py package HOST
python3 Platforms/Android package HOST
```

`HOST` is defined in the section above.

This will generate a tarball in `cross-build/HOST/dist`, whose structure is
similar to the `Android` directory of the CPython source tree.


## Testing

The Python test suite can be run on Linux, macOS, or Windows.
Tests can be run on Linux, macOS, or Windows, using either an Android emulator
or a physical device.

On Linux, the emulator needs access to the KVM virtualization interface. This may
require adding your user to a group, or changing your udev rules. On GitHub
Actions, the test script will do this automatically using the commands shown
[here](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/).

You can run the test suite either:

* Within the CPython repository, after doing a build as described above. On
Windows, you won't be able to do the build on the same machine, so you'll have
to copy the `cross-build/HOST/prefix` directory from somewhere else.

* Or by taking a release package built using the `package` command, extracting
it wherever you want, and using its own copy of `android.py`.

The test script supports the following modes:

* In `--connected` mode, it runs on a device or emulator you have already
Expand All @@ -120,7 +107,7 @@ The test script supports the following modes:
script like this:

```sh
./android.py test --connected emulator-5554
python3 Platforms/Android test --connected emulator-5554
```

* In `--managed` mode, it uses a temporary headless emulator defined in the
Expand All @@ -131,29 +118,55 @@ The test script supports the following modes:
to our minimum and maximum supported Android versions. For example:

```sh
./android.py test --managed maxVersion
python3 Platforms/Android test --managed maxVersion
```

By default, the only messages the script will show are Python's own stdout and
stderr. Add the `-v` option to also show Gradle output, and non-Python logcat
messages.

Any other arguments on the `android.py test` command line will be passed through
to `python -m test` – use `--` to separate them from android.py's own options.
### Testing Python

You can run the test suite by doing a build as described above, and then running
`python3 Platforms/Android test`. On Windows, you won't be able to do the build
on the same machine, so you'll have to copy the `cross-build/HOST/prefix` directory
from somewhere else.

Extra arguments on the `Platforms/Android test` command line will be passed through
to `python -m test` – use `--` to separate them from `Platforms/Android`'s own options.
See the [Python Developer's
Guide](https://devguide.python.org/testing/run-write-tests/) for common options
– most of them will work on Android, except for those that involve subprocesses,
such as `-j`.

Every time you run `android.py test`, changes in pure-Python files in the
Every time you run `python3 Platforms/Android test`, changes in pure-Python files in the
repository's `Lib` directory will be picked up immediately. Changes in C files,
and architecture-specific files such as sysconfigdata, will not take effect
until you re-run `android.py make-host` or `build`.
until you re-run `python3 Platforms/Android make-host` or `build`.

### Testing a third-party package

The `Platforms/Android` script is also included as `android.py` in the root of a
release package (i.e., the one built using `Platforms/Android package`).

You can use this script to test third-party packages by taking a release
package, extracting it wherever you want, and using the `android.py` script to
run the test suite for your third-party package.

Any argument that can be passed to `python3 Platforms/Android test` can also be
passed to `android.py`. The following options will be of particular use when
configuring the execution of a third-party test suite:

* `--cwd`: the directory of content to copy into the testbed app as the working
directory.
* `--site-packages`: the directory to copy into the testbed app to use as site
packages.

The testbed app can also be used to test third-party packages. For more details,
run `android.py test --help`, paying attention to the options `--site-packages`,
`--cwd`, `-c` and `-m`.
Extra arguments on the `android.py test` command line will be passed through to
Python – use `--` to separate them from `android.py`'s own options. You must include
either a `-c` or `-m` argument to specify how the test suite should be started.

For more details, run `android.py test --help`.

## Using in your own app

Expand Down
14 changes: 10 additions & 4 deletions Android/android.py → Platforms/Android/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@


SCRIPT_NAME = Path(__file__).name
if SCRIPT_NAME.startswith("__"):
SCRIPT_NAME = "Python/Android"
Comment thread
freakboy3742 marked this conversation as resolved.
Outdated

ANDROID_DIR = Path(__file__).resolve().parent
PYTHON_DIR = ANDROID_DIR.parent
PYTHON_DIR = ANDROID_DIR.parent.parent
in_source_tree = (
ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists()
)
Expand Down Expand Up @@ -763,7 +766,7 @@ def package(context):
prefix_dir = subdir(context.host, "prefix")
version = package_version(prefix_dir)

with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir:
temp_dir = Path(temp_dir)

# Include all tracked files from the Android directory.
Expand All @@ -772,7 +775,10 @@ def package(context):
cwd=ANDROID_DIR, capture_output=True, text=True, log=False,
).stdout.splitlines():
src = ANDROID_DIR / line
dst = temp_dir / line
# "__main__.py" is renamed "android.py" for distribution purpose
dst = temp_dir / {
"__main__.py": "android.py"
}.get(line, line)
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst, follow_symlinks=False)

Expand Down Expand Up @@ -838,7 +844,7 @@ def ci(context):
"emulator on this platform."
)
else:
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir:
print("::group::Tests")

# Prove the package is self-contained by using it to run the tests.
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

val ANDROID_DIR = file("../..")
val PYTHON_DIR = ANDROID_DIR.parentFile!!
val PYTHON_DIR = ANDROID_DIR.parentFile.parentFile!!
val PYTHON_CROSS_DIR = file("$PYTHON_DIR/cross-build")
val inSourceTree = (
ANDROID_DIR.name == "Android" && file("$PYTHON_DIR/pyconfig.h.in").exists()
Expand Down
Loading