forked from kivy/python-for-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrebuild_updated_recipes.py
More file actions
executable file
·129 lines (109 loc) · 4.3 KB
/
rebuild_updated_recipes.py
File metadata and controls
executable file
·129 lines (109 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Continuous Integration helper script.
Automatically detects recipes modified in a changeset (compares with master)
and recompiles them.
To run locally, set the environment variables before running:
```
ANDROID_SDK_HOME=~/.buildozer/android/platform/android-sdk-20
ANDROID_NDK_HOME=~/.buildozer/android/platform/android-ndk-r9c
./ci/rebuild_update_recipes.py
```
Current limitations:
- will fail on conflicting requirements
e.g. https://travis-ci.org/AndreMiras/python-for-android/builds/438840800
the list of recipes was huge and result was:
[ERROR]: Didn't find any valid dependency graphs.
[ERROR]: This means that some of your requirements pull in conflicting dependencies.
"""
import sh
import os
import sys
import argparse
from pythonforandroid.build import Context
from pythonforandroid import logger
from pythonforandroid.toolchain import current_directory
from pythonforandroid.recipe import Recipe
from ci.constants import TargetPython, CORE_RECIPES, BROKEN_RECIPES
def modified_recipes(branch='origin/develop'):
"""
Returns a set of modified recipes between the current branch and the one
in param.
"""
# using the contrib version on purpose rather than sh.git, since it comes
# with a bunch of fixes, e.g. disabled TTY, see:
# https://stackoverflow.com/a/20128598/185510
git_diff = sh.contrib.git.diff('--name-only', branch).split("\n")
recipes = set()
for file_path in git_diff:
if 'pythonforandroid/recipes/' in file_path:
recipe = file_path.split('/')[2]
recipes.add(recipe)
return recipes
def build(target_python, requirements, archs):
"""
Builds an APK given a target Python and a set of requirements.
"""
if not requirements:
return
android_sdk_home = os.environ['ANDROID_SDK_HOME']
android_ndk_home = os.environ['ANDROID_NDK_HOME']
requirements.add(target_python.name)
requirements_str = ','.join(requirements)
logger.info('requirements: {}'.format(requirements_str))
# Detect bootstrap based on requirements
# SDL3 recipes conflict with SDL2, so we need the sdl3 bootstrap
# when any SDL3-related recipe (sdl3, sdl3_image, sdl3_mixer, sdl3_ttf) is present
bootstrap = None
if any(r.startswith('sdl3') for r in requirements):
bootstrap = 'sdl3'
logger.info('Detected sdl3 recipe in requirements, using sdl3 bootstrap')
build_command = [
'setup.py', 'apk',
'--sdk-dir', android_sdk_home,
'--ndk-dir', android_ndk_home,
'--requirements', requirements_str
]
if bootstrap:
build_command.extend(['--bootstrap', bootstrap])
build_command.extend([f"--arch={arch}" for arch in archs])
build_command_str = " ".join(build_command)
logger.info(f"Build command: {build_command_str}")
with current_directory('testapps/on_device_unit_tests/'):
# iterates to stream the output
for line in sh.python(*build_command, _err_to_out=True, _iter=True):
print(line)
def main():
parser = argparse.ArgumentParser("rebuild_updated_recipes")
parser.add_argument(
"--arch",
help="The archs to build for during tests",
action="append",
default=[],
)
args, unknown = parser.parse_known_args(sys.argv[1:])
logger.info(f"Building updated recipes for the following archs: {args.arch}")
target_python = TargetPython.python3
recipes = modified_recipes()
logger.info('recipes modified: {}'.format(recipes))
recipes -= CORE_RECIPES
logger.info('recipes to build: {}'.format(recipes))
context = Context()
# removing the deleted recipes for the given target (if any)
for recipe_name in recipes.copy():
try:
Recipe.get_recipe(recipe_name, context)
except ValueError:
# recipe doesn't exist, so probably we remove it
recipes.remove(recipe_name)
logger.warning(
'removed {} from recipes because deleted'.format(recipe_name)
)
# removing the known broken recipe for the given target
broken_recipes = BROKEN_RECIPES[target_python]
recipes -= broken_recipes
logger.info('recipes to build (no broken): {}'.format(recipes))
build(target_python, recipes, args.arch)
if __name__ == '__main__':
main()