149 lines
5.3 KiB
Python
149 lines
5.3 KiB
Python
|
from __future__ import print_function
|
||
|
from setuptools import Command
|
||
|
from pythonforandroid import toolchain
|
||
|
|
||
|
import sys
|
||
|
from os.path import realpath, join, exists, dirname, curdir, basename, split
|
||
|
from os import makedirs
|
||
|
from glob import glob
|
||
|
from shutil import rmtree, copyfile
|
||
|
|
||
|
|
||
|
def argv_contains(t):
|
||
|
for arg in sys.argv:
|
||
|
if arg.startswith(t):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
class BdistAPK(Command):
|
||
|
description = 'Create an APK with python-for-android'
|
||
|
|
||
|
user_options = []
|
||
|
|
||
|
def initialize_options(self):
|
||
|
for option in self.user_options:
|
||
|
setattr(self, option[0].strip('=').replace('-', '_'), None)
|
||
|
|
||
|
option_dict = self.distribution.get_option_dict('apk')
|
||
|
|
||
|
# This is a hack, we probably aren't supposed to loop through
|
||
|
# the option_dict so early because distutils does exactly the
|
||
|
# same thing later to check that we support the
|
||
|
# options. However, it works...
|
||
|
for (option, (source, value)) in option_dict.items():
|
||
|
setattr(self, option, str(value))
|
||
|
|
||
|
|
||
|
def finalize_options(self):
|
||
|
|
||
|
setup_options = self.distribution.get_option_dict('apk')
|
||
|
for (option, (source, value)) in setup_options.items():
|
||
|
if source == 'command line':
|
||
|
continue
|
||
|
if not argv_contains('--' + option):
|
||
|
# allow 'permissions': ['permission', 'permission] in apk
|
||
|
if option == 'permissions':
|
||
|
for perm in value:
|
||
|
sys.argv.append('--permission={}'.format(perm))
|
||
|
elif value in (None, 'None'):
|
||
|
sys.argv.append('--{}'.format(option))
|
||
|
else:
|
||
|
sys.argv.append('--{}={}'.format(option, value))
|
||
|
|
||
|
# Inject some argv options from setup.py if the user did not
|
||
|
# provide them
|
||
|
if not argv_contains('--name'):
|
||
|
name = self.distribution.get_name()
|
||
|
sys.argv.append('--name="{}"'.format(name))
|
||
|
self.name = name
|
||
|
|
||
|
if not argv_contains('--package'):
|
||
|
package = 'org.test.{}'.format(self.name.lower().replace(' ', ''))
|
||
|
print('WARNING: You did not supply an Android package '
|
||
|
'identifier, trying {} instead.'.format(package))
|
||
|
print(' This may fail if this is not a valid identifier')
|
||
|
sys.argv.append('--package={}'.format(package))
|
||
|
|
||
|
if not argv_contains('--version'):
|
||
|
version = self.distribution.get_version()
|
||
|
sys.argv.append('--version={}'.format(version))
|
||
|
|
||
|
if not argv_contains('--arch'):
|
||
|
arch = 'arm64-v8a'
|
||
|
self.arch = arch
|
||
|
sys.argv.append('--arch={}'.format(arch))
|
||
|
|
||
|
def run(self):
|
||
|
|
||
|
self.prepare_build_dir()
|
||
|
|
||
|
from pythonforandroid.toolchain import main
|
||
|
sys.argv[1] = 'apk'
|
||
|
main()
|
||
|
|
||
|
def prepare_build_dir(self):
|
||
|
|
||
|
if argv_contains('--private') and not argv_contains('--launcher'):
|
||
|
print('WARNING: Received --private argument when this would '
|
||
|
'normally be generated automatically.')
|
||
|
print(' This is probably bad unless you meant to do '
|
||
|
'that.')
|
||
|
|
||
|
bdist_dir = 'build/bdist.android-{}'.format(self.arch)
|
||
|
if exists(bdist_dir):
|
||
|
rmtree(bdist_dir)
|
||
|
makedirs(bdist_dir)
|
||
|
|
||
|
globs = []
|
||
|
for directory, patterns in self.distribution.package_data.items():
|
||
|
for pattern in patterns:
|
||
|
globs.append(join(directory, pattern))
|
||
|
|
||
|
filens = []
|
||
|
for pattern in globs:
|
||
|
filens.extend(glob(pattern))
|
||
|
|
||
|
main_py_dirs = []
|
||
|
if not argv_contains('--launcher'):
|
||
|
for filen in filens:
|
||
|
new_dir = join(bdist_dir, dirname(filen))
|
||
|
if not exists(new_dir):
|
||
|
makedirs(new_dir)
|
||
|
print('Including {}'.format(filen))
|
||
|
copyfile(filen, join(bdist_dir, filen))
|
||
|
if basename(filen) in ('main.py', 'main.pyo'):
|
||
|
main_py_dirs.append(filen)
|
||
|
|
||
|
# This feels ridiculous, but how else to define the main.py dir?
|
||
|
# Maybe should just fail?
|
||
|
if not main_py_dirs and not argv_contains('--launcher'):
|
||
|
print('ERROR: Could not find main.py, so no app build dir defined')
|
||
|
print('You should name your app entry point main.py')
|
||
|
exit(1)
|
||
|
if len(main_py_dirs) > 1:
|
||
|
print('WARNING: Multiple main.py dirs found, using the shortest path')
|
||
|
main_py_dirs.sort(key=lambda j: len(split(j)))
|
||
|
|
||
|
if not argv_contains('--launcher'):
|
||
|
sys.argv.append('--private={}'.format(
|
||
|
join(realpath(curdir), bdist_dir, dirname(main_py_dirs[0])))
|
||
|
)
|
||
|
|
||
|
|
||
|
def _set_user_options():
|
||
|
# This seems like a silly way to do things, but not sure if there's a
|
||
|
# better way to pass arbitrary options onwards to p4a
|
||
|
user_options = [('requirements=', None, None),]
|
||
|
for i, arg in enumerate(sys.argv):
|
||
|
if arg.startswith('--'):
|
||
|
if ('=' in arg or
|
||
|
(i < (len(sys.argv) - 1) and not sys.argv[i+1].startswith('-'))):
|
||
|
user_options.append((arg[2:].split('=')[0] + '=', None, None))
|
||
|
else:
|
||
|
user_options.append((arg[2:], None, None))
|
||
|
|
||
|
BdistAPK.user_options = user_options
|
||
|
|
||
|
_set_user_options()
|