Merge branch 'master' into master
This commit is contained in:
commit
f9b1acf4a0
19 changed files with 346 additions and 113 deletions
25
.deepsource.toml
Normal file
25
.deepsource.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
test_patterns = ["tests/**"]
|
||||||
|
|
||||||
|
[[analyzers]]
|
||||||
|
name = "python"
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[analyzers.meta]
|
||||||
|
runtime_version = "3.x.x"
|
||||||
|
|
||||||
|
|
||||||
|
[[analyzers]]
|
||||||
|
name = "docker"
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[analyzers.meta]
|
||||||
|
dockerfile_paths = [
|
||||||
|
"dockerfile_dev",
|
||||||
|
"dockerfile_prod"
|
||||||
|
]
|
||||||
|
|
||||||
|
[[analyzers]]
|
||||||
|
name = "ruby"
|
||||||
|
enabled = true
|
|
@ -15,7 +15,7 @@ your application requirements and settings such as title, icon, included modules
|
||||||
etc. Buildozer will use that spec to create a package for Android, iOS, Windows,
|
etc. Buildozer will use that spec to create a package for Android, iOS, Windows,
|
||||||
OSX and/or Linux.
|
OSX and/or Linux.
|
||||||
|
|
||||||
Buildozer currently supports packaging for Android via the [python-for-android](http://github.com/kivy/python-for-android/)
|
Buildozer currently supports packaging for Android via the [python-for-android](https://github.com/kivy/python-for-android/)
|
||||||
project, and for iOS via the kivy-ios project. iOS and OSX are still under work.
|
project, and for iOS via the kivy-ios project. iOS and OSX are still under work.
|
||||||
|
|
||||||
For Android, buildozer will automatically download and prepare the
|
For Android, buildozer will automatically download and prepare the
|
||||||
|
@ -24,7 +24,7 @@ build dependencies. For more information, see
|
||||||
Note that only Python 3 is supported.
|
Note that only Python 3 is supported.
|
||||||
|
|
||||||
Note that this tool has nothing to do with the eponymous online build service
|
Note that this tool has nothing to do with the eponymous online build service
|
||||||
[buildozer.io](http://buildozer.io).
|
[buildozer.io](https://buildozer.io).
|
||||||
|
|
||||||
## Installing Buildozer with target Python 3 (default):
|
## Installing Buildozer with target Python 3 (default):
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ For [debugging on Android](https://python-for-android.readthedocs.io/en/stable/t
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
We love pull requests and discussing novel ideas. Check out our
|
We love pull requests and discussing novel ideas. Check out our
|
||||||
[contribution guide](http://kivy.org/docs/contribute.html) and
|
[contribution guide](https://kivy.org/docs/contribute.html) and
|
||||||
feel free to improve buildozer.
|
feel free to improve buildozer.
|
||||||
|
|
||||||
The following mailing list and IRC channel are used exclusively for
|
The following mailing list and IRC channel are used exclusively for
|
||||||
|
|
|
@ -19,7 +19,7 @@ from buildozer.jsonstore import JsonStore
|
||||||
from sys import stdout, stderr, exit
|
from sys import stdout, stderr, exit
|
||||||
from re import search
|
from re import search
|
||||||
from os.path import join, exists, dirname, realpath, splitext, expanduser
|
from os.path import join, exists, dirname, realpath, splitext, expanduser
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE, TimeoutExpired
|
||||||
from os import environ, unlink, walk, sep, listdir, makedirs
|
from os import environ, unlink, walk, sep, listdir, makedirs
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from shutil import copyfile, rmtree, copytree, move
|
from shutil import copyfile, rmtree, copytree, move
|
||||||
|
@ -253,7 +253,7 @@ class Buildozer:
|
||||||
|
|
||||||
def cmd(self, command, **kwargs):
|
def cmd(self, command, **kwargs):
|
||||||
# prepare the environ, based on the system + our own env
|
# prepare the environ, based on the system + our own env
|
||||||
env = copy(environ)
|
env = environ.copy()
|
||||||
env.update(self.environ)
|
env.update(self.environ)
|
||||||
|
|
||||||
# prepare the process
|
# prepare the process
|
||||||
|
@ -269,15 +269,18 @@ class Buildozer:
|
||||||
get_stderr = kwargs.pop('get_stderr', False)
|
get_stderr = kwargs.pop('get_stderr', False)
|
||||||
break_on_error = kwargs.pop('break_on_error', True)
|
break_on_error = kwargs.pop('break_on_error', True)
|
||||||
sensible = kwargs.pop('sensible', False)
|
sensible = kwargs.pop('sensible', False)
|
||||||
|
run_condition = kwargs.pop('run_condition', None)
|
||||||
|
quiet = kwargs.pop('quiet', False)
|
||||||
|
|
||||||
if not sensible:
|
if not quiet:
|
||||||
self.debug('Run {0!r}'.format(command))
|
if not sensible:
|
||||||
else:
|
self.debug('Run {0!r}'.format(command))
|
||||||
if type(command) in (list, tuple):
|
|
||||||
self.debug('Run {0!r} ...'.format(command[0]))
|
|
||||||
else:
|
else:
|
||||||
self.debug('Run {0!r} ...'.format(command.split()[0]))
|
if isinstance(command, (list, tuple)):
|
||||||
self.debug('Cwd {}'.format(kwargs.get('cwd')))
|
self.debug('Run {0!r} ...'.format(command[0]))
|
||||||
|
else:
|
||||||
|
self.debug('Run {0!r} ...'.format(command.split()[0]))
|
||||||
|
self.debug('Cwd {}'.format(kwargs.get('cwd')))
|
||||||
|
|
||||||
# open the process
|
# open the process
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
|
@ -297,9 +300,9 @@ class Buildozer:
|
||||||
|
|
||||||
ret_stdout = [] if get_stdout else None
|
ret_stdout = [] if get_stdout else None
|
||||||
ret_stderr = [] if get_stderr else None
|
ret_stderr = [] if get_stderr else None
|
||||||
while True:
|
while not run_condition or run_condition():
|
||||||
try:
|
try:
|
||||||
readx = select.select([fd_stdout, fd_stderr], [], [])[0]
|
readx = select.select([fd_stdout, fd_stderr], [], [], 1)[0]
|
||||||
except select.error:
|
except select.error:
|
||||||
break
|
break
|
||||||
if fd_stdout in readx:
|
if fd_stdout in readx:
|
||||||
|
@ -322,7 +325,13 @@ class Buildozer:
|
||||||
stdout.flush()
|
stdout.flush()
|
||||||
stderr.flush()
|
stderr.flush()
|
||||||
|
|
||||||
process.communicate()
|
try:
|
||||||
|
process.communicate(
|
||||||
|
timeout=(1 if run_condition and not run_condition() else None)
|
||||||
|
)
|
||||||
|
except TimeoutExpired:
|
||||||
|
pass
|
||||||
|
|
||||||
if process.returncode != 0 and break_on_error:
|
if process.returncode != 0 and break_on_error:
|
||||||
self.error('Command failed: {0}'.format(command))
|
self.error('Command failed: {0}'.format(command))
|
||||||
self.log_env(self.ERROR, kwargs['env'])
|
self.log_env(self.ERROR, kwargs['env'])
|
||||||
|
@ -337,10 +346,12 @@ class Buildozer:
|
||||||
self.error('raising an issue with buildozer itself.')
|
self.error('raising an issue with buildozer itself.')
|
||||||
self.error('In case of a bug report, please add a full log with log_level = 2')
|
self.error('In case of a bug report, please add a full log with log_level = 2')
|
||||||
raise BuildozerCommandException()
|
raise BuildozerCommandException()
|
||||||
|
|
||||||
if ret_stdout:
|
if ret_stdout:
|
||||||
ret_stdout = b''.join(ret_stdout)
|
ret_stdout = b''.join(ret_stdout)
|
||||||
if ret_stderr:
|
if ret_stderr:
|
||||||
ret_stderr = b''.join(ret_stderr)
|
ret_stderr = b''.join(ret_stderr)
|
||||||
|
|
||||||
return (ret_stdout.decode('utf-8', 'ignore') if ret_stdout else None,
|
return (ret_stdout.decode('utf-8', 'ignore') if ret_stdout else None,
|
||||||
ret_stderr.decode('utf-8') if ret_stderr else None,
|
ret_stderr.decode('utf-8') if ret_stderr else None,
|
||||||
process.returncode)
|
process.returncode)
|
||||||
|
@ -349,7 +360,7 @@ class Buildozer:
|
||||||
from pexpect import spawnu
|
from pexpect import spawnu
|
||||||
|
|
||||||
# prepare the environ, based on the system + our own env
|
# prepare the environ, based on the system + our own env
|
||||||
env = copy(environ)
|
env = environ.copy()
|
||||||
env.update(self.environ)
|
env.update(self.environ)
|
||||||
|
|
||||||
# prepare the process
|
# prepare the process
|
||||||
|
@ -924,8 +935,7 @@ class Buildozer:
|
||||||
|
|
||||||
if not meth.__doc__:
|
if not meth.__doc__:
|
||||||
continue
|
continue
|
||||||
doc = [x for x in
|
doc = list(meth.__doc__.strip().splitlines())[0].strip()
|
||||||
meth.__doc__.strip().splitlines()][0].strip()
|
|
||||||
print(' {0:<18} {1}'.format(name, doc))
|
print(' {0:<18} {1}'.format(name, doc))
|
||||||
|
|
||||||
print('')
|
print('')
|
||||||
|
|
|
@ -87,6 +87,10 @@ fullscreen = 0
|
||||||
# Lottie files can be created using various tools, like Adobe After Effect or Synfig.
|
# Lottie files can be created using various tools, like Adobe After Effect or Synfig.
|
||||||
#android.presplash_lottie = "path/to/lottie/file.json"
|
#android.presplash_lottie = "path/to/lottie/file.json"
|
||||||
|
|
||||||
|
# (str) Adaptive icon of the application (used if Android API level is 26+ at runtime)
|
||||||
|
#icon.adaptive_foreground.filename = %(source.dir)s/data/icon_fg.png
|
||||||
|
#icon.adaptive_background.filename = %(source.dir)s/data/icon_bg.png
|
||||||
|
|
||||||
# (list) Permissions
|
# (list) Permissions
|
||||||
#android.permissions = INTERNET
|
#android.permissions = INTERNET
|
||||||
|
|
||||||
|
@ -178,6 +182,11 @@ fullscreen = 0
|
||||||
# (list) Gradle dependencies to add
|
# (list) Gradle dependencies to add
|
||||||
#android.gradle_dependencies =
|
#android.gradle_dependencies =
|
||||||
|
|
||||||
|
# (bool) Enable AndroidX support. Enable when 'android.gradle_dependencies'
|
||||||
|
# contains an 'androidx' package, or any package from Kotlin source.
|
||||||
|
# android.enable_androidx requires android.api >= 28
|
||||||
|
#android.enable_androidx = False
|
||||||
|
|
||||||
# (list) add java compile options
|
# (list) add java compile options
|
||||||
# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
|
# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
|
||||||
# see https://developer.android.com/studio/write/java8-support for further information
|
# see https://developer.android.com/studio/write/java8-support for further information
|
||||||
|
@ -235,6 +244,9 @@ fullscreen = 0
|
||||||
# (str) Android logcat filters to use
|
# (str) Android logcat filters to use
|
||||||
#android.logcat_filters = *:S python:D
|
#android.logcat_filters = *:S python:D
|
||||||
|
|
||||||
|
# (bool) Android logcat only display log for activity's pid
|
||||||
|
#android.logcat_pid_only = False
|
||||||
|
|
||||||
# (str) Android additional adb arguments
|
# (str) Android additional adb arguments
|
||||||
#android.adb_args = -H host.docker.internal
|
#android.adb_args = -H host.docker.internal
|
||||||
|
|
||||||
|
@ -260,16 +272,25 @@ android.allow_backup = True
|
||||||
# Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"]
|
# Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"]
|
||||||
# android.manifest_placeholders = [:]
|
# android.manifest_placeholders = [:]
|
||||||
|
|
||||||
|
# (bool) disables the compilation of py to pyc/pyo files when packaging
|
||||||
|
# android.no-compile-pyo = True
|
||||||
|
|
||||||
#
|
#
|
||||||
# Python for android (p4a) specific
|
# Python for android (p4a) specific
|
||||||
#
|
#
|
||||||
|
|
||||||
# (str) python-for-android fork to use, defaults to upstream (kivy)
|
# (str) python-for-android URL to use for checkout
|
||||||
|
#p4a.url =
|
||||||
|
|
||||||
|
# (str) python-for-android fork to use in case if p4a.url is not specified, defaults to upstream (kivy)
|
||||||
#p4a.fork = kivy
|
#p4a.fork = kivy
|
||||||
|
|
||||||
# (str) python-for-android branch to use, defaults to master
|
# (str) python-for-android branch to use, defaults to master
|
||||||
#p4a.branch = master
|
#p4a.branch = master
|
||||||
|
|
||||||
|
# (str) python-for-android specific commit to use, defaults to HEAD, must be within p4a.branch
|
||||||
|
#p4a.commit = HEAD
|
||||||
|
|
||||||
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
|
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
|
||||||
#p4a.source_dir =
|
#p4a.source_dir =
|
||||||
|
|
||||||
|
@ -317,9 +338,27 @@ ios.codesign.allowed = false
|
||||||
# Get a list of available identities: buildozer ios list_identities
|
# Get a list of available identities: buildozer ios list_identities
|
||||||
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
|
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
|
||||||
|
|
||||||
|
# (str) The development team to use for signing the debug version
|
||||||
|
#ios.codesign.development_team.debug = <hexstring>
|
||||||
|
|
||||||
# (str) Name of the certificate to use for signing the release version
|
# (str) Name of the certificate to use for signing the release version
|
||||||
#ios.codesign.release = %(ios.codesign.debug)s
|
#ios.codesign.release = %(ios.codesign.debug)s
|
||||||
|
|
||||||
|
# (str) The development team to use for signing the release version
|
||||||
|
#ios.codesign.development_team.release = <hexstring>
|
||||||
|
|
||||||
|
# (str) URL pointing to .ipa file to be installed
|
||||||
|
# This option should be defined along with `display_image_url` and `full_size_image_url` options.
|
||||||
|
#ios.manifest.app_url =
|
||||||
|
|
||||||
|
# (str) URL pointing to an icon (57x57px) to be displayed during download
|
||||||
|
# This option should be defined along with `app_url` and `full_size_image_url` options.
|
||||||
|
#ios.manifest.display_image_url =
|
||||||
|
|
||||||
|
# (str) URL pointing to a large icon (512x512px) to be used by iTunes
|
||||||
|
# This option should be defined along with `app_url` and `display_image_url` options.
|
||||||
|
#ios.manifest.full_size_image_url =
|
||||||
|
|
||||||
|
|
||||||
[buildozer]
|
[buildozer]
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ class Target:
|
||||||
|
|
||||||
This will clone the contents of a git repository to
|
This will clone the contents of a git repository to
|
||||||
`buildozer.platform_dir`. The location of this repo can be
|
`buildozer.platform_dir`. The location of this repo can be
|
||||||
speficied via URL and branch name, or via a custom (local)
|
specified via URL and branch name, or via a custom (local)
|
||||||
directory name.
|
directory name.
|
||||||
|
|
||||||
:Parameters:
|
:Parameters:
|
||||||
|
|
|
@ -33,6 +33,7 @@ from os.path import exists, join, realpath, expanduser, basename, relpath
|
||||||
from platform import architecture
|
from platform import architecture
|
||||||
from shutil import copyfile, rmtree
|
from shutil import copyfile, rmtree
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
from buildozer.libs.version import parse
|
from buildozer.libs.version import parse
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
@ -60,6 +61,7 @@ class TargetAndroid(Target):
|
||||||
p4a_directory_name = "python-for-android"
|
p4a_directory_name = "python-for-android"
|
||||||
p4a_fork = 'kivy'
|
p4a_fork = 'kivy'
|
||||||
p4a_branch = 'master'
|
p4a_branch = 'master'
|
||||||
|
p4a_commit = 'HEAD'
|
||||||
p4a_apk_cmd = "apk --debug --bootstrap="
|
p4a_apk_cmd = "apk --debug --bootstrap="
|
||||||
p4a_recommended_ndk_version = None
|
p4a_recommended_ndk_version = None
|
||||||
extra_p4a_args = ''
|
extra_p4a_args = ''
|
||||||
|
@ -98,11 +100,15 @@ class TargetAndroid(Target):
|
||||||
else:
|
else:
|
||||||
self.extra_p4a_args += ' --ignore-setup-py'
|
self.extra_p4a_args += ' --ignore-setup-py'
|
||||||
|
|
||||||
|
|
||||||
activity_class_name = self.buildozer.config.getdefault(
|
activity_class_name = self.buildozer.config.getdefault(
|
||||||
'app', 'android.activity_class_name', 'org.kivy.android.PythonActivity')
|
'app', 'android.activity_class_name', 'org.kivy.android.PythonActivity')
|
||||||
if activity_class_name != 'org.kivy.android.PythonActivity':
|
if activity_class_name != 'org.kivy.android.PythonActivity':
|
||||||
self.extra_p4a_args += ' --activity-class-name={}'.format(activity_class_name)
|
self.extra_p4a_args += ' --activity-class-name={}'.format(activity_class_name)
|
||||||
|
|
||||||
|
if self.buildozer.log_level >= 2:
|
||||||
|
self.extra_p4a_args += ' --debug'
|
||||||
|
|
||||||
self.warn_on_deprecated_tokens()
|
self.warn_on_deprecated_tokens()
|
||||||
|
|
||||||
def warn_on_deprecated_tokens(self):
|
def warn_on_deprecated_tokens(self):
|
||||||
|
@ -124,7 +130,7 @@ class TargetAndroid(Target):
|
||||||
# Default p4a dir
|
# Default p4a dir
|
||||||
p4a_dir = join(self.buildozer.platform_dir, self.p4a_directory_name)
|
p4a_dir = join(self.buildozer.platform_dir, self.p4a_directory_name)
|
||||||
|
|
||||||
# Possibly overriden by user setting
|
# Possibly overridden by user setting
|
||||||
system_p4a_dir = self.buildozer.config.getdefault('app', 'p4a.source_dir')
|
system_p4a_dir = self.buildozer.config.getdefault('app', 'p4a.source_dir')
|
||||||
if system_p4a_dir:
|
if system_p4a_dir:
|
||||||
p4a_dir = expanduser(system_p4a_dir)
|
p4a_dir = expanduser(system_p4a_dir)
|
||||||
|
@ -248,10 +254,7 @@ class TargetAndroid(Target):
|
||||||
'adb.exe')
|
'adb.exe')
|
||||||
self.javac_cmd = self._locate_java('javac.exe')
|
self.javac_cmd = self._locate_java('javac.exe')
|
||||||
self.keytool_cmd = self._locate_java('keytool.exe')
|
self.keytool_cmd = self._locate_java('keytool.exe')
|
||||||
elif platform in ('darwin', ):
|
# darwin, linux
|
||||||
self.adb_cmd = join(self.android_sdk_dir, 'platform-tools', 'adb')
|
|
||||||
self.javac_cmd = self._locate_java('javac')
|
|
||||||
self.keytool_cmd = self._locate_java('keytool')
|
|
||||||
else:
|
else:
|
||||||
self.adb_cmd = join(self.android_sdk_dir, 'platform-tools', 'adb')
|
self.adb_cmd = join(self.android_sdk_dir, 'platform-tools', 'adb')
|
||||||
self.javac_cmd = self._locate_java('javac')
|
self.javac_cmd = self._locate_java('javac')
|
||||||
|
@ -375,7 +378,7 @@ class TargetAndroid(Target):
|
||||||
|
|
||||||
self.buildozer.info('Android ANT is missing, downloading')
|
self.buildozer.info('Android ANT is missing, downloading')
|
||||||
archive = 'apache-ant-{0}-bin.tar.gz'.format(APACHE_ANT_VERSION)
|
archive = 'apache-ant-{0}-bin.tar.gz'.format(APACHE_ANT_VERSION)
|
||||||
url = 'http://archive.apache.org/dist/ant/binaries/'
|
url = 'https://archive.apache.org/dist/ant/binaries/'
|
||||||
self.buildozer.download(url,
|
self.buildozer.download(url,
|
||||||
archive,
|
archive,
|
||||||
cwd=ant_dir)
|
cwd=ant_dir)
|
||||||
|
@ -423,7 +426,7 @@ class TargetAndroid(Target):
|
||||||
return ndk_dir
|
return ndk_dir
|
||||||
|
|
||||||
import re
|
import re
|
||||||
_version = re.search('(.+?)[a-z]', self.android_ndk_version).group(1)
|
_version = int(re.search(r'(\d+)', self.android_ndk_version).group(1))
|
||||||
|
|
||||||
self.buildozer.info('Android NDK is missing, downloading')
|
self.buildozer.info('Android NDK is missing, downloading')
|
||||||
# Welcome to the NDK URL hell!
|
# Welcome to the NDK URL hell!
|
||||||
|
@ -433,28 +436,23 @@ class TargetAndroid(Target):
|
||||||
# from 10e on the URLs can be looked up at
|
# from 10e on the URLs can be looked up at
|
||||||
# https://developer.android.com/ndk/downloads/older_releases
|
# https://developer.android.com/ndk/downloads/older_releases
|
||||||
|
|
||||||
|
is_darwin = platform == 'darwin'
|
||||||
|
is_linux = platform.startswith('linux')
|
||||||
|
|
||||||
if platform in ('win32', 'cygwin'):
|
if platform in ('win32', 'cygwin'):
|
||||||
# Checking of 32/64 bits at Windows from: http://stackoverflow.com/a/1405971/798575
|
# Checking of 32/64 bits at Windows from: https://stackoverflow.com/a/1405971/798575
|
||||||
import struct
|
import struct
|
||||||
archive = 'android-ndk-r{0}-windows-{1}.zip'
|
archive = 'android-ndk-r{0}-windows-{1}.zip'
|
||||||
is_64 = (8 * struct.calcsize("P") == 64)
|
is_64 = (8 * struct.calcsize("P") == 64)
|
||||||
|
elif is_darwin or is_linux:
|
||||||
elif platform in ('darwin', ):
|
_platform = 'linux' if is_linux else 'darwin'
|
||||||
if _version >= '10e':
|
if self.android_ndk_version in ['10c', '10d', '10e']:
|
||||||
archive = 'android-ndk-r{0}-darwin-{1}.zip'
|
ext = 'bin'
|
||||||
elif _version >= '10c':
|
elif _version <= 10:
|
||||||
archive = 'android-ndk-r{0}-darwin-{1}.bin'
|
ext = 'tar.bz2'
|
||||||
else:
|
else:
|
||||||
archive = 'android-ndk-r{0}-darwin-{1}.tar.bz2'
|
ext = 'zip'
|
||||||
is_64 = (os.uname()[4] == 'x86_64')
|
archive = 'android-ndk-r{0}-' + _platform + '-{1}.' + ext
|
||||||
|
|
||||||
elif platform.startswith('linux'):
|
|
||||||
if _version >= '10e':
|
|
||||||
archive = 'android-ndk-r{0}-linux-{1}.zip'
|
|
||||||
elif _version >= '10c':
|
|
||||||
archive = 'android-ndk-r{0}-linux-{1}.bin'
|
|
||||||
else:
|
|
||||||
archive = 'android-ndk-r{0}-linux-{1}.tar.bz2'
|
|
||||||
is_64 = (os.uname()[4] == 'x86_64')
|
is_64 = (os.uname()[4] == 'x86_64')
|
||||||
else:
|
else:
|
||||||
raise SystemError('Unsupported platform: {}'.format(platform))
|
raise SystemError('Unsupported platform: {}'.format(platform))
|
||||||
|
@ -464,10 +462,10 @@ class TargetAndroid(Target):
|
||||||
archive = archive.format(self.android_ndk_version, architecture)
|
archive = archive.format(self.android_ndk_version, architecture)
|
||||||
unpacked = unpacked.format(self.android_ndk_version)
|
unpacked = unpacked.format(self.android_ndk_version)
|
||||||
|
|
||||||
if _version >= '10e':
|
if _version >= 11:
|
||||||
url = 'https://dl.google.com/android/repository/'
|
url = 'https://dl.google.com/android/repository/'
|
||||||
else:
|
else:
|
||||||
url = 'http://dl.google.com/android/ndk/'
|
url = 'https://dl.google.com/android/ndk/'
|
||||||
|
|
||||||
self.buildozer.download(url,
|
self.buildozer.download(url,
|
||||||
archive,
|
archive,
|
||||||
|
@ -666,7 +664,7 @@ class TargetAndroid(Target):
|
||||||
self.buildozer.error(
|
self.buildozer.error(
|
||||||
'You might have missed to install 32bits libs')
|
'You might have missed to install 32bits libs')
|
||||||
self.buildozer.error(
|
self.buildozer.error(
|
||||||
'Check http://buildozer.readthedocs.org/en/latest/installation.html')
|
'Check https://buildozer.readthedocs.org/en/latest/installation.html')
|
||||||
self.buildozer.error('')
|
self.buildozer.error('')
|
||||||
else:
|
else:
|
||||||
self.buildozer.error('')
|
self.buildozer.error('')
|
||||||
|
@ -699,9 +697,15 @@ class TargetAndroid(Target):
|
||||||
p4a_fork = self.buildozer.config.getdefault(
|
p4a_fork = self.buildozer.config.getdefault(
|
||||||
'app', 'p4a.fork', self.p4a_fork
|
'app', 'p4a.fork', self.p4a_fork
|
||||||
)
|
)
|
||||||
|
p4a_url = self.buildozer.config.getdefault(
|
||||||
|
'app', 'p4a.url', f'https://github.com/{p4a_fork}/python-for-android.git'
|
||||||
|
)
|
||||||
p4a_branch = self.buildozer.config.getdefault(
|
p4a_branch = self.buildozer.config.getdefault(
|
||||||
'app', 'p4a.branch', self.p4a_branch
|
'app', 'p4a.branch', self.p4a_branch
|
||||||
)
|
)
|
||||||
|
p4a_commit = self.buildozer.config.getdefault(
|
||||||
|
'app', 'p4a.commit', self.p4a_commit
|
||||||
|
)
|
||||||
|
|
||||||
p4a_dir = self.p4a_dir
|
p4a_dir = self.p4a_dir
|
||||||
system_p4a_dir = self.buildozer.config.getdefault('app',
|
system_p4a_dir = self.buildozer.config.getdefault('app',
|
||||||
|
@ -714,21 +718,19 @@ class TargetAndroid(Target):
|
||||||
self.buildozer.error('')
|
self.buildozer.error('')
|
||||||
raise BuildozerException()
|
raise BuildozerException()
|
||||||
else:
|
else:
|
||||||
# check that fork/branch has not been changed
|
# check that url/branch has not been changed
|
||||||
if self.buildozer.file_exists(p4a_dir):
|
if self.buildozer.file_exists(p4a_dir):
|
||||||
cur_fork = cmd(
|
cur_url = cmd(
|
||||||
'git config --get remote.origin.url',
|
'git config --get remote.origin.url',
|
||||||
get_stdout=True,
|
get_stdout=True,
|
||||||
cwd=p4a_dir,
|
cwd=p4a_dir,
|
||||||
)[0].split('/')[3]
|
)[0].strip()
|
||||||
cur_branch = cmd(
|
cur_branch = cmd(
|
||||||
'git branch -vv', get_stdout=True, cwd=p4a_dir
|
'git branch -vv', get_stdout=True, cwd=p4a_dir
|
||||||
)[0].split()[1]
|
)[0].split()[1]
|
||||||
if any([cur_fork != p4a_fork, cur_branch != p4a_branch]):
|
if any([cur_url != p4a_url, cur_branch != p4a_branch]):
|
||||||
self.buildozer.info(
|
self.buildozer.info(
|
||||||
"Detected old fork/branch ({}/{}), deleting...".format(
|
f"Detected old url/branch ({cur_url}/{cur_branch}), deleting..."
|
||||||
cur_fork, cur_branch
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
rmtree(p4a_dir)
|
rmtree(p4a_dir)
|
||||||
|
|
||||||
|
@ -736,11 +738,10 @@ class TargetAndroid(Target):
|
||||||
cmd(
|
cmd(
|
||||||
(
|
(
|
||||||
'git clone -b {p4a_branch} --single-branch '
|
'git clone -b {p4a_branch} --single-branch '
|
||||||
'https://github.com/{p4a_fork}/python-for-android.git '
|
'{p4a_url} {p4a_dir}'
|
||||||
'{p4a_dir}'
|
|
||||||
).format(
|
).format(
|
||||||
p4a_branch=p4a_branch,
|
p4a_branch=p4a_branch,
|
||||||
p4a_fork=p4a_fork,
|
p4a_url=p4a_url,
|
||||||
p4a_dir=self.p4a_directory_name,
|
p4a_dir=self.p4a_directory_name,
|
||||||
),
|
),
|
||||||
cwd=self.buildozer.platform_dir,
|
cwd=self.buildozer.platform_dir,
|
||||||
|
@ -755,6 +756,8 @@ class TargetAndroid(Target):
|
||||||
cmd('git fetch --tags origin {0}:{0}'.format(p4a_branch),
|
cmd('git fetch --tags origin {0}:{0}'.format(p4a_branch),
|
||||||
cwd=p4a_dir)
|
cwd=p4a_dir)
|
||||||
cmd('git checkout {}'.format(p4a_branch), cwd=p4a_dir)
|
cmd('git checkout {}'.format(p4a_branch), cwd=p4a_dir)
|
||||||
|
if p4a_commit != 'HEAD':
|
||||||
|
cmd('git reset --hard {}'.format(p4a_commit), cwd=p4a_dir)
|
||||||
|
|
||||||
# also install dependencies (currently, only setup.py knows about it)
|
# also install dependencies (currently, only setup.py knows about it)
|
||||||
# let's extract them.
|
# let's extract them.
|
||||||
|
@ -766,7 +769,7 @@ class TargetAndroid(Target):
|
||||||
except IOError:
|
except IOError:
|
||||||
self.buildozer.error('Failed to read python-for-android setup.py at {}'.format(
|
self.buildozer.error('Failed to read python-for-android setup.py at {}'.format(
|
||||||
join(self.p4a_dir, 'setup.py')))
|
join(self.p4a_dir, 'setup.py')))
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
pip_deps = []
|
pip_deps = []
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
pip_deps.append("'{}'".format(dep))
|
pip_deps.append("'{}'".format(dep))
|
||||||
|
@ -939,6 +942,11 @@ class TargetAndroid(Target):
|
||||||
cmd.append('--manifest-placeholders')
|
cmd.append('--manifest-placeholders')
|
||||||
cmd.append("{}".format(manifest_placeholders))
|
cmd.append("{}".format(manifest_placeholders))
|
||||||
|
|
||||||
|
# support disabling of compilation
|
||||||
|
compile_py = self.buildozer.config.getdefault('app', 'android.no-compile-pyo', None)
|
||||||
|
if compile_py:
|
||||||
|
cmd.append('--no-compile-pyo')
|
||||||
|
|
||||||
cmd.append('--arch')
|
cmd.append('--arch')
|
||||||
cmd.append(self._arch)
|
cmd.append(self._arch)
|
||||||
|
|
||||||
|
@ -988,6 +996,12 @@ class TargetAndroid(Target):
|
||||||
cwd=self.buildozer.global_platform_dir)
|
cwd=self.buildozer.global_platform_dir)
|
||||||
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if self._get_pid():
|
||||||
|
break
|
||||||
|
sleep(.1)
|
||||||
|
self.buildozer.info('Waiting for application to start.')
|
||||||
|
|
||||||
self.buildozer.info('Application started.')
|
self.buildozer.info('Application started.')
|
||||||
|
|
||||||
def cmd_p4a(self, *args):
|
def cmd_p4a(self, *args):
|
||||||
|
@ -1160,6 +1174,11 @@ class TargetAndroid(Target):
|
||||||
icon = config.getdefault('app', 'icon.filename', '')
|
icon = config.getdefault('app', 'icon.filename', '')
|
||||||
if icon:
|
if icon:
|
||||||
build_cmd += [("--icon", join(self.buildozer.root_dir, icon))]
|
build_cmd += [("--icon", join(self.buildozer.root_dir, icon))]
|
||||||
|
icon_fg = config.getdefault('app', 'icon.adaptive_foreground.filename', '')
|
||||||
|
icon_bg = config.getdefault('app', 'icon.adaptive_background.filename', '')
|
||||||
|
if icon_fg and icon_bg:
|
||||||
|
build_cmd += [("--icon-fg", join(self.buildozer.root_dir, icon_fg))]
|
||||||
|
build_cmd += [("--icon-bg", join(self.buildozer.root_dir, icon_bg))]
|
||||||
|
|
||||||
# OUYA Console support
|
# OUYA Console support
|
||||||
ouya_category = config.getdefault('app', 'android.ouya.category',
|
ouya_category = config.getdefault('app', 'android.ouya.category',
|
||||||
|
@ -1193,6 +1212,13 @@ class TargetAndroid(Target):
|
||||||
if wakelock:
|
if wakelock:
|
||||||
build_cmd += [("--wakelock", )]
|
build_cmd += [("--wakelock", )]
|
||||||
|
|
||||||
|
# AndroidX ?
|
||||||
|
enable_androidx = config.getbooldefault('app',
|
||||||
|
'android.enable_androidx',
|
||||||
|
False)
|
||||||
|
if enable_androidx:
|
||||||
|
build_cmd += [("--enable-androidx", )]
|
||||||
|
|
||||||
# intent filters
|
# intent filters
|
||||||
intent_filters = config.getdefault(
|
intent_filters = config.getdefault(
|
||||||
'app', 'android.manifest.intent_filters', '')
|
'app', 'android.manifest.intent_filters', '')
|
||||||
|
@ -1313,7 +1339,7 @@ class TargetAndroid(Target):
|
||||||
self.buildozer.error(
|
self.buildozer.error(
|
||||||
'Invalid library reference (path not found): {}'.format(
|
'Invalid library reference (path not found): {}'.format(
|
||||||
cref))
|
cref))
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
# get a relative path from the project file
|
# get a relative path from the project file
|
||||||
ref = relpath(ref, realpath(expanduser(dist_dir)))
|
ref = relpath(ref, realpath(expanduser(dist_dir)))
|
||||||
# ensure the reference exists
|
# ensure the reference exists
|
||||||
|
@ -1416,6 +1442,18 @@ class TargetAndroid(Target):
|
||||||
|
|
||||||
self.buildozer.info('Application pushed.')
|
self.buildozer.info('Application pushed.')
|
||||||
|
|
||||||
|
def _get_pid(self):
|
||||||
|
pid, *_ = self.buildozer.cmd(
|
||||||
|
f'{self.adb_cmd} shell pidof {self._get_package()}',
|
||||||
|
get_stdout=True,
|
||||||
|
show_output=False,
|
||||||
|
break_on_error=False,
|
||||||
|
quiet=True,
|
||||||
|
)
|
||||||
|
if pid:
|
||||||
|
return pid.strip()
|
||||||
|
return False
|
||||||
|
|
||||||
def cmd_logcat(self, *args):
|
def cmd_logcat(self, *args):
|
||||||
'''Show the log from the device
|
'''Show the log from the device
|
||||||
'''
|
'''
|
||||||
|
@ -1427,10 +1465,23 @@ class TargetAndroid(Target):
|
||||||
"app", "android.logcat_filters", "", section_sep=":", split_char=" ")
|
"app", "android.logcat_filters", "", section_sep=":", split_char=" ")
|
||||||
filters = " ".join(filters)
|
filters = " ".join(filters)
|
||||||
self.buildozer.environ['ANDROID_SERIAL'] = serial[0]
|
self.buildozer.environ['ANDROID_SERIAL'] = serial[0]
|
||||||
self.buildozer.cmd('{adb} logcat {filters}'.format(adb=self.adb_cmd,
|
extra_args = []
|
||||||
filters=filters),
|
pid = None
|
||||||
cwd=self.buildozer.global_platform_dir,
|
if self.buildozer.config.getdefault('app', 'android.logcat_pid_only'):
|
||||||
show_output=True)
|
pid = self._get_pid()
|
||||||
|
if pid:
|
||||||
|
extra_args.extend(('--pid', pid))
|
||||||
|
|
||||||
|
self.buildozer.cmd(
|
||||||
|
f"{self.adb_cmd} logcat {filters} {' '.join(extra_args)}",
|
||||||
|
cwd=self.buildozer.global_platform_dir,
|
||||||
|
show_output=True,
|
||||||
|
run_condition=self._get_pid if pid else None,
|
||||||
|
break_on_error=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.buildozer.info(f"{self._get_package()} terminated")
|
||||||
|
|
||||||
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,8 @@ class TargetIos(Target):
|
||||||
kwargs.setdefault('cwd', self.ios_dir)
|
kwargs.setdefault('cwd', self.ios_dir)
|
||||||
return self.buildozer.cmd(self._toolchain_cmd + cmd, **kwargs)
|
return self.buildozer.cmd(self._toolchain_cmd + cmd, **kwargs)
|
||||||
|
|
||||||
def xcodebuild(self, cmd='', **kwargs):
|
def xcodebuild(self, *args, **kwargs):
|
||||||
return self.buildozer.cmd(self._xcodebuild_cmd + cmd, **kwargs)
|
return self.buildozer.cmd(self._xcodebuild_cmd + ' '.join(arg for arg in args if arg is not None), **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def code_signing_allowed(self):
|
def code_signing_allowed(self):
|
||||||
|
@ -124,6 +124,11 @@ class TargetIos(Target):
|
||||||
allowed = "YES" if allowed else "NO"
|
allowed = "YES" if allowed else "NO"
|
||||||
return f"CODE_SIGNING_ALLOWED={allowed}"
|
return f"CODE_SIGNING_ALLOWED={allowed}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def code_signing_development_team(self):
|
||||||
|
team = self.buildozer.config.getdefault("app", f"ios.codesign.development_team.{self.build_mode}", None)
|
||||||
|
return f"DEVELOPMENT_TEAM={team}" if team else None
|
||||||
|
|
||||||
def get_available_packages(self):
|
def get_available_packages(self):
|
||||||
available_modules = self.toolchain("recipes --compact", get_stdout=True)[0]
|
available_modules = self.toolchain("recipes --compact", get_stdout=True)[0]
|
||||||
return available_modules.splitlines()[0].split()
|
return available_modules.splitlines()[0].split()
|
||||||
|
@ -202,7 +207,8 @@ class TargetIos(Target):
|
||||||
plist_rfn = join(self.app_project_dir, plist_fn)
|
plist_rfn = join(self.app_project_dir, plist_fn)
|
||||||
version = self.buildozer.get_version()
|
version = self.buildozer.get_version()
|
||||||
self.buildozer.info('Update Plist {}'.format(plist_fn))
|
self.buildozer.info('Update Plist {}'.format(plist_fn))
|
||||||
plist = plistlib.readPlist(plist_rfn)
|
with open(plist_rfn, 'rb') as f:
|
||||||
|
plist = plistlib.load(f)
|
||||||
plist['CFBundleIdentifier'] = self._get_package()
|
plist['CFBundleIdentifier'] = self._get_package()
|
||||||
plist['CFBundleShortVersionString'] = version
|
plist['CFBundleShortVersionString'] = version
|
||||||
plist['CFBundleVersion'] = '{}.{}'.format(version,
|
plist['CFBundleVersion'] = '{}.{}'.format(version,
|
||||||
|
@ -211,12 +217,36 @@ class TargetIos(Target):
|
||||||
# add icons
|
# add icons
|
||||||
self._create_icons()
|
self._create_icons()
|
||||||
|
|
||||||
|
# Generate OTA distribution manifest if `app_url`, `display_image_url` and `full_size_image_url` are defined.
|
||||||
|
app_url = self.buildozer.config.getdefault("app", "ios.manifest.app_url", None)
|
||||||
|
display_image_url = self.buildozer.config.getdefault("app", "ios.manifest.display_image_url", None)
|
||||||
|
full_size_image_url = self.buildozer.config.getdefault("app", "ios.manifest.full_size_image_url", None)
|
||||||
|
|
||||||
|
if any((app_url, display_image_url, full_size_image_url)):
|
||||||
|
|
||||||
|
if not all((app_url, display_image_url, full_size_image_url)):
|
||||||
|
self.buildozer.error("Options ios.manifest.app_url, ios.manifest.display_image_url"
|
||||||
|
" and ios.manifest.full_size_image_url should be defined all together")
|
||||||
|
return
|
||||||
|
|
||||||
|
plist['manifest'] = {
|
||||||
|
'appURL': app_url,
|
||||||
|
'displayImageURL': display_image_url,
|
||||||
|
'fullSizeImageURL': full_size_image_url,
|
||||||
|
}
|
||||||
|
|
||||||
# ok, write the modified plist.
|
# ok, write the modified plist.
|
||||||
plistlib.writePlist(plist, plist_rfn)
|
with open(plist_rfn, 'wb') as f:
|
||||||
|
plistlib.dump(plist, f)
|
||||||
|
|
||||||
mode = self.build_mode.capitalize()
|
mode = self.build_mode.capitalize()
|
||||||
self.xcodebuild(
|
self.xcodebuild(
|
||||||
f"-configuration {mode} ENABLE_BITCODE=NO {self.code_signing_allowed} clean build",
|
f'-configuration {mode}',
|
||||||
|
'-allowProvisioningUpdates',
|
||||||
|
'ENABLE_BITCODE=NO',
|
||||||
|
self.code_signing_allowed,
|
||||||
|
self.code_signing_development_team,
|
||||||
|
'clean build',
|
||||||
cwd=self.app_project_dir)
|
cwd=self.app_project_dir)
|
||||||
ios_app_dir = '{app_lower}-ios/build/{mode}-iphoneos/{app_lower}.app'.format(
|
ios_app_dir = '{app_lower}-ios/build/{mode}-iphoneos/{app_lower}.app'.format(
|
||||||
app_lower=app_name.lower(), mode=mode)
|
app_lower=app_name.lower(), mode=mode)
|
||||||
|
@ -242,25 +272,24 @@ class TargetIos(Target):
|
||||||
self.buildozer.rmdir(intermediate_dir)
|
self.buildozer.rmdir(intermediate_dir)
|
||||||
|
|
||||||
self.buildozer.info('Creating archive...')
|
self.buildozer.info('Creating archive...')
|
||||||
self.xcodebuild((
|
self.xcodebuild(
|
||||||
' -alltargets'
|
'-alltargets',
|
||||||
' -configuration {mode}'
|
f'-configuration {mode}',
|
||||||
' -scheme {scheme}'
|
f'-scheme {app_name.lower()}',
|
||||||
' -archivePath "{xcarchive}"'
|
f'-archivePath "{xcarchive}"',
|
||||||
' archive'
|
'archive',
|
||||||
' ENABLE_BITCODE=NO'
|
'ENABLE_BITCODE=NO',
|
||||||
).format(mode=mode, xcarchive=xcarchive, scheme=app_name.lower()),
|
self.code_signing_development_team,
|
||||||
cwd=build_dir)
|
cwd=build_dir)
|
||||||
|
|
||||||
self.buildozer.info('Creating IPA...')
|
self.buildozer.info('Creating IPA...')
|
||||||
self.xcodebuild((
|
self.xcodebuild(
|
||||||
' -exportArchive'
|
'-exportArchive',
|
||||||
' -exportFormat IPA'
|
f'-archivePath "{xcarchive}"',
|
||||||
' -archivePath "{xcarchive}"'
|
f'-exportOptionsPlist "{plist_rfn}"',
|
||||||
' -exportPath "{ipa}"'
|
f'-exportPath "{ipa_tmp}"',
|
||||||
' CODE_SIGN_IDENTITY={ioscodesign}'
|
f'CODE_SIGN_IDENTITY={ioscodesign}',
|
||||||
' ENABLE_BITCODE=NO'
|
'ENABLE_BITCODE=NO',
|
||||||
).format(xcarchive=xcarchive, ipa=ipa_tmp, ioscodesign=ioscodesign),
|
|
||||||
cwd=build_dir)
|
cwd=build_dir)
|
||||||
|
|
||||||
self.buildozer.info('Moving IPA to bin...')
|
self.buildozer.info('Moving IPA to bin...')
|
||||||
|
|
|
@ -46,16 +46,16 @@ class TargetOSX(Target):
|
||||||
self.buildozer.info('Downloading kivy...')
|
self.buildozer.info('Downloading kivy...')
|
||||||
status_code = check_output(
|
status_code = check_output(
|
||||||
('curl', '-L', '--write-out', '%{http_code}', '-o', 'Kivy{}.dmg'.format(py_branch),
|
('curl', '-L', '--write-out', '%{http_code}', '-o', 'Kivy{}.dmg'.format(py_branch),
|
||||||
'http://kivy.org/downloads/{}/Kivy-{}-osx-python{}.dmg'
|
'https://kivy.org/downloads/{}/Kivy-{}-osx-python{}.dmg'
|
||||||
.format(current_kivy_vers, current_kivy_vers, py_branch)),
|
.format(current_kivy_vers, current_kivy_vers, py_branch)),
|
||||||
cwd=cwd)
|
cwd=cwd)
|
||||||
|
|
||||||
if status_code == "404":
|
if status_code == "404":
|
||||||
self.buildozer.error(
|
self.buildozer.error(
|
||||||
"Unable to download the Kivy App. Check osx.kivy_version in your buildozer.spec, and verify "
|
"Unable to download the Kivy App. Check osx.kivy_version in your buildozer.spec, and verify "
|
||||||
"Kivy servers are accessible. http://kivy.org/downloads/")
|
"Kivy servers are accessible. https://kivy.org/downloads/")
|
||||||
check_call(("rm", "Kivy{}.dmg".format(py_branch)), cwd=cwd)
|
check_call(("rm", "Kivy{}.dmg".format(py_branch)), cwd=cwd)
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
self.buildozer.info('Extracting and installing Kivy...')
|
self.buildozer.info('Extracting and installing Kivy...')
|
||||||
check_call(('hdiutil', 'attach', cwd + '/Kivy{}.dmg'.format(py_branch)))
|
check_call(('hdiutil', 'attach', cwd + '/Kivy{}.dmg'.format(py_branch)))
|
||||||
|
@ -76,8 +76,6 @@ class TargetOSX(Target):
|
||||||
else:
|
else:
|
||||||
self.download_kivy(kivy_app_dir, py_branch)
|
self.download_kivy(kivy_app_dir, py_branch)
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def check_requirements(self):
|
def check_requirements(self):
|
||||||
self.ensure_sdk()
|
self.ensure_sdk()
|
||||||
self.ensure_kivyapp()
|
self.ensure_kivyapp()
|
||||||
|
@ -90,7 +88,7 @@ class TargetOSX(Target):
|
||||||
len(errors)))
|
len(errors)))
|
||||||
for error in errors:
|
for error in errors:
|
||||||
print(error)
|
print(error)
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
# check
|
# check
|
||||||
|
|
||||||
def build_package(self):
|
def build_package(self):
|
||||||
|
@ -177,7 +175,7 @@ class TargetOSX(Target):
|
||||||
if not args:
|
if not args:
|
||||||
self.buildozer.error('Missing target command')
|
self.buildozer.error('Missing target command')
|
||||||
self.buildozer.usage()
|
self.buildozer.usage()
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
last_command = []
|
last_command = []
|
||||||
|
@ -191,7 +189,7 @@ class TargetOSX(Target):
|
||||||
if not last_command:
|
if not last_command:
|
||||||
self.buildozer.error('Argument passed without a command')
|
self.buildozer.error('Argument passed without a command')
|
||||||
self.buildozer.usage()
|
self.buildozer.usage()
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
last_command.append(arg)
|
last_command.append(arg)
|
||||||
if last_command:
|
if last_command:
|
||||||
result.append(last_command)
|
result.append(last_command)
|
||||||
|
@ -202,7 +200,7 @@ class TargetOSX(Target):
|
||||||
command, args = item[0], item[1:]
|
command, args = item[0], item[1:]
|
||||||
if not hasattr(self, 'cmd_{0}'.format(command)):
|
if not hasattr(self, 'cmd_{0}'.format(command)):
|
||||||
self.buildozer.error('Unknown command {0}'.format(command))
|
self.buildozer.error('Unknown command {0}'.format(command))
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
func = getattr(self, 'cmd_{0}'.format(command))
|
func = getattr(self, 'cmd_{0}'.format(command))
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ torrent:
|
||||||
mktorrent \
|
mktorrent \
|
||||||
-a ${TORRENT_ANNOUNCE} \
|
-a ${TORRENT_ANNOUNCE} \
|
||||||
-o output-kivy-buildozer-vm/kivy-buildozer-vm.torrent \
|
-o output-kivy-buildozer-vm/kivy-buildozer-vm.torrent \
|
||||||
-w http://txzone.net/files/torrents/${PACKAGE_FILENAME} \
|
-w https://txzone.net/files/torrents/${PACKAGE_FILENAME} \
|
||||||
-v output-kivy-buildozer-vm/${PACKAGE_FILENAME}
|
-v output-kivy-buildozer-vm/${PACKAGE_FILENAME}
|
||||||
|
|
||||||
upload:
|
upload:
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# an error when using the android sdk:
|
# an error when using the android sdk:
|
||||||
# "Can't read cryptographic policy directory: unlimited"
|
# "Can't read cryptographic policy directory: unlimited"
|
||||||
|
|
||||||
wget http://bootstrap.pypa.io/get-pip.py
|
wget https://bootstrap.pypa.io/get-pip.py
|
||||||
python get-pip.py
|
python get-pip.py
|
||||||
rm get-pip.py
|
rm get-pip.py
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ BUILDDIR = build
|
||||||
|
|
||||||
# User-friendly check for sphinx-build
|
# User-friendly check for sphinx-build
|
||||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from https://www.sphinx-doc.org/)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Internal variables.
|
# Internal variables.
|
||||||
|
|
|
@ -56,7 +56,7 @@ if errorlevel 9009 (
|
||||||
echo.may add the Sphinx directory to PATH.
|
echo.may add the Sphinx directory to PATH.
|
||||||
echo.
|
echo.
|
||||||
echo.If you don't have Sphinx installed, grab it from
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
echo.http://sphinx-doc.org/
|
echo.https://www.sphinx-doc.org/
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@ limitation.
|
||||||
|
|
||||||
To test your own recipe via Buildozer, you need to:
|
To test your own recipe via Buildozer, you need to:
|
||||||
|
|
||||||
#. Fork `Python for Android <http://github.com/kivy/python-for-android>`_, and
|
#. Fork `Python for Android <https://github.com/kivy/python-for-android>`_, and
|
||||||
clone your own version (this will allow easy contribution later)::
|
clone your own version (this will allow easy contribution later)::
|
||||||
|
|
||||||
git clone http://github.com/YOURNAME/python-for-android
|
git clone https://github.com/YOURNAME/python-for-android
|
||||||
|
|
||||||
#. Change your `buildozer.spec` to reference your version::
|
#. Change your `buildozer.spec` to reference your version::
|
||||||
|
|
||||||
|
@ -44,6 +44,6 @@ include it in the python-for-android project, by issuing a Pull Request:
|
||||||
|
|
||||||
git push origin master
|
git push origin master
|
||||||
|
|
||||||
#. Go to `http://github.com/YOURNAME/python-for-android`, and you should see
|
#. Go to `https://github.com/YOURNAME/python-for-android`, and you should see
|
||||||
your new branch and a button "Pull Request" on it. Use it, write a
|
your new branch and a button "Pull Request" on it. Use it, write a
|
||||||
description about what you did, and Send!
|
description about what you did, and Send!
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -27,6 +28,48 @@ Android on Ubuntu 20.04 (64bit)
|
||||||
# add the following line at the end of your ~/.bashrc file
|
# add the following line at the end of your ~/.bashrc file
|
||||||
export PATH=$PATH:~/.local/bin/
|
export PATH=$PATH:~/.local/bin/
|
||||||
|
|
||||||
|
Android on Windows 10
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
To use buildozer in Windows 10 you need first to enable Windows Subsystem for Linux (WSL) and install a Linux distribution: https://docs.microsoft.com/en-us/windows/wsl/install-win10.
|
||||||
|
|
||||||
|
These instructions were tested with WSL 1 and Ubuntu 18.04 LTS.
|
||||||
|
|
||||||
|
After installing WSL and Ubuntu in your Windows 10 machine, open Ubuntu and do this:
|
||||||
|
|
||||||
|
1) Run the commands listed on the previous section (Android in Ubuntu 18.04 (64-bit).
|
||||||
|
2) Run the following commands:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# Use here the python version you need
|
||||||
|
sudo apt install -y python3.7-venv
|
||||||
|
# Create a folder for buildozer. For example: C:\buildozer
|
||||||
|
mkdir /mnt/c/buildozer
|
||||||
|
cd /mnt/c/buildozer
|
||||||
|
python3.7 -m venv venv-buildozer
|
||||||
|
source venv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install --upgrade wheel
|
||||||
|
python -m pip install --upgrade cython
|
||||||
|
python -m pip install --upgrade virtualenv
|
||||||
|
python -m pip install --upgrade buildozer
|
||||||
|
# Restart your WSL terminal to enable the path change
|
||||||
|
|
||||||
|
Windows Subsystem for Linux does not have direct access to USB. Due to this, you need to install the Windows version of ADB (Android Debug Bridge):
|
||||||
|
|
||||||
|
- Go to https://developer.android.com/studio/releases/platform-tools and click on "Download SDK Platform-Tools for Windows".
|
||||||
|
|
||||||
|
- Unzip the downloaded file to a new folder. For example, "C:\\platform-tools".
|
||||||
|
|
||||||
|
Before Using Buildozer
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you wish, clone your code to a new folder, where the build process will run.
|
||||||
|
|
||||||
|
You don't need to create a virtualenv for your code requirements. But just add these requirements to a configuration file called buildozer.spec as you will see in the following sections.
|
||||||
|
|
||||||
|
Before running buildozer in your code folder, remember to go into the buildozer folder and activate the buildozer virtualenv.
|
||||||
|
|
||||||
Android on macOS
|
Android on macOS
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -57,7 +57,7 @@ setup(
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
author='Mathieu Virbel',
|
author='Mathieu Virbel',
|
||||||
author_email='mat@kivy.org',
|
author_email='mat@kivy.org',
|
||||||
url='http://github.com/kivy/buildozer',
|
url='https://github.com/kivy/buildozer',
|
||||||
license='MIT',
|
license='MIT',
|
||||||
packages=[
|
packages=[
|
||||||
'buildozer', 'buildozer.targets', 'buildozer.libs', 'buildozer.scripts'
|
'buildozer', 'buildozer.targets', 'buildozer.libs', 'buildozer.scripts'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from six import StringIO
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -350,3 +351,44 @@ class TestTargetAndroid:
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def test_install_platform_p4a_clone_url(self):
|
||||||
|
"""The `p4a.url` config should be used for cloning p4a before the `p4a.fork` option."""
|
||||||
|
target_android = init_target(self.temp_dir, {
|
||||||
|
'p4a.url': 'https://custom-p4a-url/p4a.git',
|
||||||
|
'p4a.fork': 'myfork',
|
||||||
|
})
|
||||||
|
|
||||||
|
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||||
|
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||||
|
target_android._install_p4a()
|
||||||
|
|
||||||
|
assert mock.call(
|
||||||
|
'git clone -b master --single-branch https://custom-p4a-url/p4a.git python-for-android',
|
||||||
|
cwd=mock.ANY) in m_cmd.call_args_list
|
||||||
|
|
||||||
|
def test_install_platform_p4a_clone_fork(self):
|
||||||
|
"""The `p4a.fork` config should be used for cloning p4a."""
|
||||||
|
target_android = init_target(self.temp_dir, {
|
||||||
|
'p4a.fork': 'fork'
|
||||||
|
})
|
||||||
|
|
||||||
|
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||||
|
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||||
|
target_android._install_p4a()
|
||||||
|
|
||||||
|
assert mock.call(
|
||||||
|
'git clone -b master --single-branch https://github.com/fork/python-for-android.git python-for-android',
|
||||||
|
cwd=mock.ANY) in m_cmd.call_args_list
|
||||||
|
|
||||||
|
def test_install_platform_p4a_clone_default(self):
|
||||||
|
"""The default URL should be used for cloning p4a if no config options `p4a.url` and `p4a.fork` are set."""
|
||||||
|
target_android = init_target(self.temp_dir)
|
||||||
|
|
||||||
|
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||||
|
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||||
|
target_android._install_p4a()
|
||||||
|
|
||||||
|
assert mock.call(
|
||||||
|
'git clone -b master --single-branch https://github.com/kivy/python-for-android.git python-for-android',
|
||||||
|
cwd=mock.ANY) in m_cmd.call_args_list
|
||||||
|
|
|
@ -182,7 +182,6 @@ class TestTargetIos:
|
||||||
# fmt: off
|
# fmt: off
|
||||||
with patch_target_ios("_unlock_keychain") as m_unlock_keychain, \
|
with patch_target_ios("_unlock_keychain") as m_unlock_keychain, \
|
||||||
patch_buildozer_error() as m_error, \
|
patch_buildozer_error() as m_error, \
|
||||||
patch_target_ios("xcodebuild") as m_xcodebuild, \
|
|
||||||
mock.patch("buildozer.targets.ios.plistlib.readPlist") as m_readplist, \
|
mock.patch("buildozer.targets.ios.plistlib.readPlist") as m_readplist, \
|
||||||
mock.patch("buildozer.targets.ios.plistlib.writePlist") as m_writeplist, \
|
mock.patch("buildozer.targets.ios.plistlib.writePlist") as m_writeplist, \
|
||||||
patch_buildozer_cmd() as m_cmd:
|
patch_buildozer_cmd() as m_cmd:
|
||||||
|
@ -196,13 +195,6 @@ class TestTargetIos:
|
||||||
'You must fill the "ios.codesign.debug" token.'
|
'You must fill the "ios.codesign.debug" token.'
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
assert m_xcodebuild.call_args_list == [
|
|
||||||
mock.call(
|
|
||||||
"-configuration Debug ENABLE_BITCODE=NO "
|
|
||||||
"CODE_SIGNING_ALLOWED=NO clean build",
|
|
||||||
cwd="/ios/dir/myapp-ios",
|
|
||||||
)
|
|
||||||
]
|
|
||||||
assert m_readplist.call_args_list == [
|
assert m_readplist.call_args_list == [
|
||||||
mock.call("/ios/dir/myapp-ios/myapp-Info.plist")
|
mock.call("/ios/dir/myapp-ios/myapp-Info.plist")
|
||||||
]
|
]
|
||||||
|
@ -216,4 +208,8 @@ class TestTargetIos:
|
||||||
"/ios/dir/myapp-ios/myapp-Info.plist",
|
"/ios/dir/myapp-ios/myapp-Info.plist",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
assert m_cmd.call_args_list == [mock.call(mock.ANY, cwd=target.ios_dir)]
|
assert m_cmd.call_args_list == [mock.call(mock.ANY, cwd=target.ios_dir), mock.call(
|
||||||
|
"xcodebuild -configuration Debug -allowProvisioningUpdates ENABLE_BITCODE=NO "
|
||||||
|
"CODE_SIGNING_ALLOWED=NO clean build",
|
||||||
|
cwd="/ios/dir/myapp-ios",
|
||||||
|
)]
|
||||||
|
|
|
@ -53,7 +53,7 @@ def init_buildozer(temp_dir, target, options=None):
|
||||||
spec = []
|
spec = []
|
||||||
for line in default_spec:
|
for line in default_spec:
|
||||||
if line.strip():
|
if line.strip():
|
||||||
match = re.search(r"[#\s]?([a-z_\.]+)", line)
|
match = re.search(r"[#\s]?([0-9a-z_.]+)", line)
|
||||||
key = match and match.group(1)
|
key = match and match.group(1)
|
||||||
if key in options:
|
if key in options:
|
||||||
line = "{} = {}\n".format(key, options[key])
|
line = "{} = {}\n".format(key, options[key])
|
||||||
|
|
|
@ -61,7 +61,7 @@ class TestBuildozer(unittest.TestCase):
|
||||||
|
|
||||||
def test_buildozer_base(self):
|
def test_buildozer_base(self):
|
||||||
"""
|
"""
|
||||||
Basic test making sure the Buildozer object can be instanciated.
|
Basic test making sure the Buildozer object can be instantiated.
|
||||||
"""
|
"""
|
||||||
buildozer = Buildozer()
|
buildozer = Buildozer()
|
||||||
assert buildozer.specfilename == 'buildozer.spec'
|
assert buildozer.specfilename == 'buildozer.spec'
|
||||||
|
@ -158,7 +158,7 @@ class TestBuildozer(unittest.TestCase):
|
||||||
assert m_file_extract.call_args_list == [mock.call(mock.ANY, cwd='/my/ant/path')]
|
assert m_file_extract.call_args_list == [mock.call(mock.ANY, cwd='/my/ant/path')]
|
||||||
assert ant_path == my_ant_path
|
assert ant_path == my_ant_path
|
||||||
assert download.call_args_list == [
|
assert download.call_args_list == [
|
||||||
mock.call("http://archive.apache.org/dist/ant/binaries/", mock.ANY, cwd=my_ant_path)]
|
mock.call("https://archive.apache.org/dist/ant/binaries/", mock.ANY, cwd=my_ant_path)]
|
||||||
# Mock ant already installed
|
# Mock ant already installed
|
||||||
with mock.patch.object(Buildozer, 'file_exists', return_value=True):
|
with mock.patch.object(Buildozer, 'file_exists', return_value=True):
|
||||||
ant_path = target._install_apache_ant()
|
ant_path = target._install_apache_ant()
|
||||||
|
|
Loading…
Reference in a new issue