8000 AAB support related changes (#2467) · bahawk/python-for-android@41c6cc0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 41c6cc0

Browse files
authored
AAB support related changes (kivy#2467)
* Added support for aab * Move to build:gradle:3.5.4 (adds support for API 30), fix some tests * Github actions test apps (apk + aab) * Add missing bdistaab * Fix automated tests * ndk lib folder (or ndk platform) now is ABI specific * Fixes dist lookup + some tests * Added .aab and .apks to blacklist * Interrupt build and alert the user if tried to build an aab in debug mode * Updates troubleshooting instructions to reflect current structure. * Exclude gdbserver and gdb.setup from release builds * Add a paragraph in history + fixes --arch docs * Fix versioning * Minor fixes to docs * Some code cleanup * Removes unusued versioning logic in unpackPyBundle and add a FIXME
1 parent 54139ea commit 41c6cc0

File tree

67 files changed

+486
-313
lines changed
  • tests
  • Some content is hidden

    Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

    67 files changed

    +486
    -313
    lines changed

    .github/workflows/push.yml

    Lines changed: 32 additions & 8 deletions
    Original file line numberDiff line numberDiff line change
    @@ -41,14 +41,10 @@ jobs:
    4141
    pip install tox>=2.0
    4242
    make test
    4343
    44-
    build:
    44+
    build_apk:
    4545
    name: Unit test apk
    4646
    needs: [flake8]
    4747
    runs-on: ubuntu-latest
    48-
    strategy:
    49-
    fail-fast: false
    50-
    matrix:
    51-
    build-arch: ['arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86']
    5248
    steps:
    5349
    - name: Checkout python-for-android
    5450
    uses: actions/checkout@v2
    @@ -64,15 +60,43 @@ jobs:
    6460
    - name: Pull docker image
    6561
    run: |
    6662
    make docker/pull
    67-
    - name: Build apk Python 3 ${{ matrix.build-arch }}
    63+
    - name: Build multi-arch apk Python 3 (armeabi-v7a, arm64-v8a, x86_64, x86)
    6864
    run: |
    6965
    mkdir -p apks
    70-
    make docker/run/make/with-artifact/testapps-with-numpy/${{ matrix.build-arch }}
    66+
    make docker/run/make/with-artifact/apk/testapps-with-numpy
    7167
    - uses: actions/upload-artifact@v1
    7268
    with:
    73-
    name: bdist_test_app_unittests__${{ matrix.build-arch }}-debug-1.1.apk
    69+
    name: bdist_unit_tests_app-debug-1.1-.apk
    7470
    path: apks
    7571

    72+
    build_aab:
    73+
    name: Unit test aab
    74+
    needs: [flake8]
    75+
    runs-on: ubuntu-latest
    76+
    steps:
    77+
    - name: Checkout python-for-android
    78+
    uses: actions/checkout@v2
    79+
    # helps with GitHub runner getting out of space
    80+
    - name: Free disk space
    81+
    run: |
    82+
    df -h
    83+
    sudo swapoff -a
    84+
    sudo rm -f /swapfile
    85+
    sudo apt -y clean
    86+
    docker rmi $(docker image ls -aq)
    87+
    df -h
    88+
    - name: Pull docker image
    89+
    run: |
    90+
    make docker/pull
    91+
    - name: Build Android App Bundle Python 3 (armeabi-v7a, arm64-v8a, x86_64, x86)
    92+
    run: |
    93+
    mkdir -p aabs
    94+
    make docker/run/make/with-artifact/aab/testapps-with-numpy-aab
    95+
    - uses: actions/upload-artifact@v1
    96+
    with:
    97+
    name: bdist_unit_tests_app-release-1.1-.aab
    98+
    path: aabs
    99+
    76100
    rebuild_updated_recipes:
    77101
    name: Test updated recipes
    78102
    needs: [flake8]

    Makefile

    Original file line numberDiff line numberDiff line change
    @@ -34,12 +34,17 @@ rebuild_updated_recipes: virtualenv
    3434
    ANDROID_SDK_HOME=$(ANDROID_SDK_HOME) ANDROID_NDK_HOME=$(ANDROID_NDK_HOME) \
    3535
    $(PYTHON) ci/rebuild_updated_recipes.py
    3636

    37-
    testapps-with-numpy/%: virtualenv
    38-
    $(eval $@_APP_ARCH := $(shell basename $*))
    37+
    testapps-with-numpy: virtualenv
    3938
    . $(ACTIVATE) && cd testapps/on_device_unit_tests/ && \
    4039
    python setup.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
    4140
    --requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,urllib3,chardet,idna,sqlite3,setuptools,numpy \
    42-
    --arch=$($@_APP_ARCH)
    41+
    --arch=armeabi-v7a --arch=arm64-v8a --arch=x86_64 --arch=x86
    42+
    43+
    testapps-with-numpy-aab: virtualenv
    44+
    . $(ACTIVATE) && cd testapps/on_device_unit_tests/ && \
    45+
    python setup.py aab --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
    46+
    --requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,urllib3,chardet,idna,sqlite3,setuptools,numpy \
    47+
    --arch=armeabi-v7a --arch=arm64-v8a --arch=x86_64 --arch=x86 --release
    4348

    4449
    testapps/%: virtualenv
    4550
    $(eval $@_APP_ARCH := $(shell basename $*))
    @@ -69,14 +74,18 @@ docker/run/test: docker/build
    6974
    docker/run/command: docker/build
    7075
    docker run --rm --env-file=.env $(DOCKER_IMAGE) /bin/sh -c "$(COMMAND)"
    7176

    72-
    docker/run/make/%: docker/build
    73-
    docker run --rm --env-file=.env $(DOCKER_IMAGE) make $*
    77+
    docker/run/make/with-artifact/apk/%: docker/build
    78+
    docker run --name p4a-latest --env-file=.env $(DOCKER_IMAGE) make $*
    79+
    docker cp p4a-latest:/home/user/app/testapps/on_device_unit_tests/bdist_unit_tests_app-debug-1.1-.apk ./apks
    80+
    docker rm -fv p4a-latest
    7481

    75-
    docker/run/make/with-artifact/%: docker/build
    76-
    $(eval $@_APP_ARCH := $(shell basename $*))
    82+
    docker/run/make/with-artifact/aab/%: docker/build
    7783
    docker run --name p4a-latest --env-file=.env $(DOCKER_IMAGE) make $*
    78-
    docker cp p4a-latest:/home/user/app/testapps/on_device_unit_tests/bdist_unit_tests_app__$($@_APP_ARCH)-debug-1.1-.apk ./apks
    84+
    docker cp p4a-latest:/home/user/app/testapps/on_device_unit_tests/bdist_unit_tests_app-release-1.1-.aab ./aabs
    7985
    docker rm -fv p4a-latest
    8086

    87+
    docker/run/make/%: docker/build
    88+
    docker run --rm --env-file=.env $(DOCKER_IMAGE) make $*
    89+
    8190
    docker/run/shell: docker/build
    8291
    docker run --rm --env-file=.env -it $(DOCKER_IMAGE)

    README.md

    Lines changed: 8 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@ python-for-android
    88

    99
    python-for-android is a packaging tool for Python apps on Android. You can
    1010
    create your own Python distribution including the modules and
    11-
    dependencies you want, and bundle it in an APK along with your own code.
    11+
    dependencies you want, and bundle it in an APK or AAB along with your own code.
    1212

    1313
    Features include:
    1414

    @@ -19,6 +19,7 @@ Features include:
    1919
    sqlalchemy.
    2020
    - Multiple architecture targets, for APKs optimised on any given
    2121
    device.
    22+
    - AAB: Android App Bundle support.
    2223

    2324
    For documentation and support, see:
    2425

    @@ -30,7 +31,7 @@ For documentation and support, see:
    3031

    3132
    Follow the [quickstart
    3233
    instructions](<https://python-for-android.readthedocs.org/en/latest/quickstart/>)
    33-
    to install and begin creating APKs.
    34+
    to install and begin creating APKs and AABs.
    3435

    3536
    **Quick instructions**: install python-for-android with:
    3637

    @@ -52,6 +53,8 @@ With everything installed, build an APK with SDL2 with e.g.:
    5253

    5354
    p4a apk --requirements=kivy --private /home/username/devel/planewave_frozen/ --package=net.inclem.planewavessdl2 --name="planewavessdl2" --version=0.5 --bootstrap=sdl2
    5455

    56+
    **If you need to deploy your app on Google Play, Android App Bundle (aab) is required since 1 August 2021:**
    57+
    5558
    **For full instructions and parameter options,** see [the
    5659
    documentation](https://python-for-android.readthedocs.io/en/latest/quickstart/#usage).
    5760

    @@ -109,6 +112,9 @@ api level below 21, you should use an older version of python-for-android
    109112
    On March of 2020 we dropped support for creating apps that use Python 2. The latest
    110113
    python-for-android release that supported building Python 2 was version 2019.10.6.
    111114

    115+
    On August of 2021, we added support for Android App Bundle (aab). As a collateral,
    116+
    now We support multi-arch apk.
    117+
    112118
    ## Contributors
    113119

    114120
    This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].

    doc/source/commands.rst

    Lines changed: 3 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -71,8 +71,9 @@ supply those that you need.
    7171
    Whether the distribution must be compiled from scratch.
    7272

    7373
    ``--arch``
    74-
    The architecture to build for. Currently only one architecture can be
    75-
    targeted at a time, and a given distribution can only include one architecture.
    74+
    The architecture to build for. You can specify multiple architectures to build for
    75+
    at the same time. As an example ``p4a ... --arch arm64-v8a --arch armeabi-v7a ...``
    76+
    will build a distribution for both ``arm64-v8a`` and ``armeabi-v7a``.
    7677

    7778
    ``--bootstrap BOOTSTRAP``
    7879
    The Java bootstrap to use for your application. You mostly don't

    doc/source/quickstart.rst

    Lines changed: 18 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -213,6 +213,24 @@ You can also replace flask with another web framework.
    213213
    Replace ``--port=5000`` with the port on which your app will serve a
    214214
    website. The default for Flask is 5000.
    215215

    216+
    Exporting the Android App Bundle (aab) for distributing it on Google Play
    217+
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    218+
    219+
    Starting from August 2021 for new apps and from November 2021 for updates to existings apps,
    220+
    Google Play Console will require the Android App Bundle instead of the long lived apk.
    221+
    222+
    python-for-android handles by itself the needed work to accomplish the new requirements:
    223+
    224+
    p4a aab --private $HOME/code/myapp --package=org.example.myapp --name="My App" --version 0.1 --bootstrap=sdl2 --requirements=python3,kivy --arch=arm64-v8a --arch=armeabi-v7a --release
    225+
    226+
    This `p4a aab ...` command builds a distribution with `python3`,
    227+
    `kivy`, and everything else you specified in the requirements.
    228+
    It will be packaged using a SDL2 bootstrap, and produce
    229+
    an `.aab` file that contains binaries for both `armeabi-v7a` and `arm64-v8a` ABIs.
    230+
    231+
    The Android App Bundle, is supposed to be used for distributing your app.
    232+
    If you need to test it locally, on your device, you can use `bundletool <https://developer.android.com/studio/command-line/bundletool>`
    233+
    216234
    Other options
    217235
    ~~~~~~~~~~~~~
    218236

    doc/source/troubleshooting.rst

    Lines changed: 19 additions & 15 deletions
    Original file line numberDiff line numberDiff line change
    @@ -85,31 +85,35 @@ At the top level, this will always contain the same set of files::
    8585
    AndroidManifest.xml classes.dex META-INF res
    8686
    assets lib YourApk.apk resources.arsc
    8787

    88-
    The Python distribution is in the assets folder::
    88+
    The user app data (code, images, fonts ..) is packaged into a single tarball contained in the assets folder::
    8989

    9090
    $ cd assets
    9191
    $ ls
    92-
    private.mp3
    92+
    private.tar
    9393

    94-
    ``private.mp3`` is actually a tarball containing all your packaged
    95-
    data, and the Python distribution. Extract it::
    94+
    ``private.tar`` is a tarball containing all your packaged
    95+
    data. Extract it::
    9696

    97-
    $ tar xf private.mp3
    97+
    $ tar xf private.tar
    9898

    99-
    This will reveal all the Python-related files::
    99+
    This will reveal all the user app data (the files shown below are from the touchtracer demo)::
    100100

    101101
    $ ls
    102-
    android_runnable.pyo include interpreter_subprocess main.kv pipinterface.kv settings.pyo
    103-
    assets __init__.pyo interpreterwrapper.pyo main.pyo pipinterface.pyo utils.pyo
    104-
    editor.kv interpreter.kv _python_bundle menu.kv private.mp3 widgets.pyo
    105-
    editor.pyo interpreter.pyo libpymodules.so menu.pyo settings.kv
    102+
    README.txt android.txt icon.png main.pyc p4a_env_vars.txt particle.png
    103+
    private.tar touchtracer.kv
    106104

    107-
    Most of these files have been included by the user (in this case, they
    108-
    come from one of my own apps), the rest relate to the python
    109-
    distribution.
    105+
    Due to how We're required to ship ABI-specific things in Android App Bundle,
    106+
    the Python installation is packaged separately, as (most of it) is ABI-specific.
    107+
    108+
    For example, the Python installation for ``arm64-v8a`` is available in ``lib/arm64-v8a/libpybundle.so``
    109+
    110+
    ``libpybundle.so`` is a tarball (but named like a library for packaging requirements), that contains our ``_python_bundle``::
    111+
    112+
    $ tar xf libpybundle.so
    113+
    $ cd _python_bundle
    114+
    $ ls
    115+
    modules site-packages stdlib.zip
    110116

    111-
    The python installation, along with all side-packages, is mostly contained
    112-
    inside the `_python_bundle` folder.
    113117

    114118

    115119
    Common errors

    pythonforandroid/archs.py

    Lines changed: 23 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,9 +1,10 @@
    11
    from distutils.spawn import find_executable
    22
    from os import environ
    3-
    from os.path import join, split
    3+
    from os.path import join, split, exists
    44
    from multiprocessing import cpu_count
    55
    from glob import glob
    66

    7+
    from pythonforandroid.logger import warning
    78
    from pythonforandroid.recipe import Recipe
    89
    from pythonforandroid.util import BuildInterruptingException, build_platform
    910

    @@ -30,7 +31,7 @@ class Arch:
    3031
    common_cppflags = [
    3132
    '-DANDROID',
    3233
    '-D__ANDROID_API__={ctx.ndk_api}',
    33-
    '-I{ctx.ndk_dir}/sysroot/usr/include/{command_prefix}',
    34+
    '-I{ctx.ndk_sysroot}/usr/include/{command_prefix}',
    3435
    '-I{python_includes}',
    3536
    ]
    3637

    @@ -57,6 +58,24 @@ def __init__(self, ctx):
    5758
    def __str__(self):
    5859
    return self.arch
    5960

    61+
    @property
    62+
    def ndk_lib_dir(self):
    63+
    return join(self.ctx.ndk_sysroot, 'usr', 'lib', self.command_prefix, str(self.ctx.ndk_api))
    64+
    65+
    @property
    66+
    def ndk_platform(self):
    67+
    warning("ndk_platform is deprecated and should be avoided in new recipes")
    68+
    ndk_platform = join(
    69+
    self.ctx.ndk_dir,
    70+
    'platforms',
    71+
    'android-{}'.format(self.ctx.ndk_api),
    72+
    self.platform_dir)
    73+
    if not exists(ndk_platform):
    74+
    BuildInterruptingException(
    75+
    "The requested platform folder doesn't exist. If you're building on ndk >= r22, and seeing this error, one of the required recipe is using a removed feature."
    76+
    )
    77+
    return ndk_platform
    78+
    6079
    @property
    6180
    def include_dirs(self):
    6281
    return [
    @@ -133,7 +152,7 @@ def get_env(self, with_flags_in_cc=True):
    133152
    ctx=self.ctx,
    134153
    command_prefix=self.command_prefix,
    135154
    python_includes=join(
    136-
    self.ctx.get_python_install_dir(),
    155+
    self.ctx.get_python_install_dir(self.arch),
    137156
    'include/python{}'.format(self.ctx.python_recipe.version[0:3]),
    138157
    ),
    139158
    )
    @@ -213,7 +232,7 @@ def get_env(self, with_flags_in_cc=True):
    213232
    # Android's arch/toolchain
    214233
    env['ARCH'] = self.arch
    215234
    env['NDK_API'] = 'android-{}'.format(str(self.ctx.ndk_api))
    216-
    env['TOOLCHAIN_PREFIX'] = self.ctx.toolchain_prefix
    235+
    env['TOOLCHAIN_PREFIX'] = self.toolchain_prefix
    217236
    env['TOOLCHAIN_VERSION'] = self.ctx.toolchain_version
    218237

    219238
    # Custom linker options

    pythonforandroid/bdistapk.py

    Lines changed: 9 additions & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -128,21 +128,23 @@ def prepare_build_dir(self):
    128128

    129129

    130130
    class BdistAPK(Bdist):
    131-
    """
    132-
    distutil command handler for 'apk'
    133-
    """
    131+
    """distutil command handler for 'apk'."""
    134132
    description = 'Create an APK with python-for-android'
    135133
    package_type = 'apk'
    136134

    137135

    138136
    class BdistAAR(Bdist):
    139-
    """
    140-
    distutil command handler for 'aar'
    141-
    """
    137+
    """distutil command handler for 'aar'."""
    142138
    description = 'Create an AAR with python-for-android'
    143139
    package_type = 'aar'
    144140

    145141

    142+
    class BdistAAB(Bdist):
    143+
    """distutil command handler for 'aab'."""
    144+
    description = 'Create an AAB with python-for-android'
    145+
    package_type = 'aab'
    146+
    147+
    146148
    def _set_user_options():
    147149
    # This seems like a silly way to do things, but not sure if there's a
    148150
    # better way to pass arbitrary options onwards to p4a
    @@ -156,6 +158,7 @@ def _set_user_options():
    156158
    user_options.append((arg[2:], None, None))
    157159

    158160
    BdistAPK.user_options = user_options
    161+
    BdistAAB.user_options = user_options
    159162

    160163

    161164
    _set_user_options()

    pythonforandroid/bootstrap.py

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -374,7 +374,7 @@ def strip_libraries(self, arch):
    374374
    if len(tokens) > 1:
    375375
    strip = strip.bake(tokens[1:])
    376376

    377-
    libs_dir = join(self.dist_dir, '_python_bundle',
    377+
    libs_dir = join(self.dist_dir, f'_python_bundle__{arch.arch}',
    378378
    '_python_bundle', 'modules')
    379379
    filens = shprint(sh.find, libs_dir, join(self.dist_dir, 'libs'),
    380380
    '-iname', '*.so', _env=env).stdout.decode('utf-8')

    0 commit comments

    Comments
     (0)
    0