wip
This commit is contained in:
parent
da7c95b6ee
commit
3dc42cb627
3 changed files with 140 additions and 52 deletions
11
README.rst
11
README.rst
|
@ -28,16 +28,21 @@ buildozer.spec
|
|||
# Title of your application
|
||||
title = My Application
|
||||
|
||||
# Source code variables
|
||||
# Source code where the main.py live
|
||||
source.dir = .
|
||||
source.include_ext = py,png,jpg
|
||||
|
||||
# Source files to include (let empty to include all the files)
|
||||
source.include_exts = py,png,jpg
|
||||
|
||||
# Source files to exclude (let empty to not excluding anything)
|
||||
#source.exclude_exts = spec
|
||||
|
||||
# Application versionning
|
||||
version.regex = __version__ = '(.*)'
|
||||
version.filename = %(source.dir)s/main.py
|
||||
|
||||
# Application requirements
|
||||
requirements = twisted kivy
|
||||
requirements = twisted,kivy
|
||||
|
||||
# Android specific
|
||||
android.permissions = INTERNET
|
||||
|
|
|
@ -11,30 +11,50 @@ Layout directory for buildozer:
|
|||
'''
|
||||
|
||||
import shelve
|
||||
import zipfile
|
||||
from sys import stdout, exit
|
||||
from urllib import urlretrieve
|
||||
from re import search
|
||||
from ConfigParser import SafeConfigParser
|
||||
from os.path import join, exists, dirname, realpath
|
||||
from os.path import join, exists, dirname, realpath, splitext
|
||||
from subprocess import Popen, PIPE
|
||||
from os import environ, mkdir, unlink, rename
|
||||
from os import environ, mkdir, unlink, rename, walk, sep
|
||||
from copy import copy
|
||||
from shutil import copyfile
|
||||
|
||||
class ConfigDict(dict):
|
||||
def get(self, key, value, default):
|
||||
print 'hello'
|
||||
|
||||
|
||||
class Buildozer(object):
|
||||
|
||||
def __init__(self, filename, target):
|
||||
super(Buildozer, self).__init__()
|
||||
self.environ = copy(environ)
|
||||
self.environ = {}
|
||||
self.targetname = target
|
||||
self.specfilename = filename
|
||||
self.state = None
|
||||
self.config = SafeConfigParser()
|
||||
self.config = SafeConfigParser({}, ConfigDict, allow_no_value=True)
|
||||
self.config.getlist = self._get_config_list
|
||||
self.config.getdefault = self._get_config_default
|
||||
self.config.read(filename)
|
||||
|
||||
# resolve target
|
||||
m = __import__('buildozer.targets.%s' % target, fromlist=['buildozer'])
|
||||
self.target = m.get_target(self)
|
||||
|
||||
def _get_config_list(self, section, token, default=None):
|
||||
values = self.config.getdefault(section, token, default).split(',')
|
||||
return [x.strip() for x in values]
|
||||
|
||||
def _get_config_default(self, section, token, default=None):
|
||||
if not self.config.has_section(section):
|
||||
return default
|
||||
if not self.config.has_option(section, token):
|
||||
return default
|
||||
return self.config.get(section, token)
|
||||
|
||||
def log(self, msg):
|
||||
print '-', msg
|
||||
|
||||
|
@ -54,7 +74,11 @@ class Buildozer(object):
|
|||
raise Exception(msg + 'not found')
|
||||
|
||||
def cmd(self, command, **kwargs):
|
||||
kwargs.setdefault('env', self.environ)
|
||||
#print ' '.join(['{0}={1}'.format(*args) for args in
|
||||
# self.environ.iteritems()])
|
||||
env = copy(environ)
|
||||
env.update(self.environ)
|
||||
kwargs.setdefault('env', env)
|
||||
self.log('run %r' % command)
|
||||
c = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, **kwargs)
|
||||
ret = c.communicate()
|
||||
|
@ -70,29 +94,35 @@ class Buildozer(object):
|
|||
def run(self):
|
||||
self.log('Build started')
|
||||
|
||||
self.log('check configuration tokens')
|
||||
self.log('Check configuration tokens')
|
||||
self.do_config_requirements()
|
||||
|
||||
self.log('check requirements for %s' % self.targetname)
|
||||
self.log('Check requirements for %s' % self.targetname)
|
||||
self.target.check_requirements()
|
||||
|
||||
self.log('ensure build layout')
|
||||
self.log('Ensure build layout')
|
||||
self.ensure_build_layout()
|
||||
|
||||
self.log('install platform')
|
||||
self.log('Install platform')
|
||||
self.target.install_platform()
|
||||
|
||||
self.log('compile platform')
|
||||
self.log('Compile platform')
|
||||
self.target.compile_platform()
|
||||
|
||||
self.log('Prebuild the application')
|
||||
self.prebuild_application()
|
||||
|
||||
self.log('Package the application')
|
||||
self.target.build_package()
|
||||
|
||||
def do_config_requirements(self):
|
||||
pass
|
||||
|
||||
def ensure_build_layout(self):
|
||||
specdir = dirname(self.specfilename)
|
||||
self.mkdir(join(specdir, self.targetname))
|
||||
self.mkdir(join(specdir, self.targetname, 'platform'))
|
||||
self.mkdir(join(specdir, self.targetname, 'app'))
|
||||
self.mkdir(join(specdir, '.buildozer', self.targetname))
|
||||
self.mkdir(join(specdir, '.buildozer', self.targetname, 'platform'))
|
||||
self.mkdir(join(specdir, '.buildozer', self.targetname, 'app'))
|
||||
self.state = shelve.open(join(self.platform_dir, 'state.db'))
|
||||
|
||||
def mkdir(self, dn):
|
||||
|
@ -109,6 +139,28 @@ class Buildozer(object):
|
|||
target = join(cwd, target)
|
||||
rename(source, target)
|
||||
|
||||
def file_extract(self, archive, cwd=None):
|
||||
if archive.endswith('.tgz') or archive.endswith('.tar.gz'):
|
||||
# XXX tarfile doesn't work for NDK-r8c :(
|
||||
#tf = tarfile.open(archive, 'r:*')
|
||||
#tf.extractall(path=cwd)
|
||||
#tf.close()
|
||||
self.cmd('tar xzf {0}'.format(archive), cwd=cwd)
|
||||
return
|
||||
|
||||
if archive.endswith('.tbz2') or archive.endswith('.tar.bz2'):
|
||||
# XXX same as before
|
||||
self.cmd('tar xjf {0}'.format(archive), cwd=cwd)
|
||||
return
|
||||
|
||||
if archive.endswith('.zip'):
|
||||
zf = zipfile.ZipFile(archive)
|
||||
zf.extractall(path=cwd)
|
||||
zf.close()
|
||||
return
|
||||
|
||||
raise Exception('Unhandled extraction for type {0}'.format(archive))
|
||||
|
||||
def download(self, url, filename, cwd=None):
|
||||
def report_hook(index, blksize, size):
|
||||
if size <= 0:
|
||||
|
@ -161,13 +213,52 @@ class Buildozer(object):
|
|||
|
||||
raise Exception('Missing version or version.regex + version.filename')
|
||||
|
||||
def prebuild_application(self):
|
||||
source_dir = realpath(self.config.getdefault('app', 'source.dir', '.'))
|
||||
include_exts = self.config.getlist('app', 'source.include_exts', '')
|
||||
exclude_exts = self.config.getlist('app', 'source.exclude_exts', '')
|
||||
app_dir = self.app_dir
|
||||
|
||||
for root, dirs, files in walk(source_dir):
|
||||
# avoid hidden directory
|
||||
if True in [x.startswith('.') for x in root.split(sep)]:
|
||||
continue
|
||||
|
||||
for fn in files:
|
||||
# avoid hidden files
|
||||
if fn.startswith('.'):
|
||||
continue
|
||||
|
||||
# filter based on the extension
|
||||
# TODO more filters
|
||||
basename, ext = splitext(fn)
|
||||
if ext:
|
||||
ext = ext[1:]
|
||||
if include_exts and ext not in include_exts:
|
||||
continue
|
||||
if exclude_exts and ext in exclude_exts:
|
||||
continue
|
||||
|
||||
sfn = join(root, fn)
|
||||
rfn = realpath(join(app_dir, root[len(source_dir):], fn))
|
||||
|
||||
# ensure the directory exists
|
||||
dfn = dirname(rfn)
|
||||
self.mkdir(dfn)
|
||||
|
||||
# copy!
|
||||
self.log('Copy {0}'.format(sfn))
|
||||
copyfile(sfn, rfn)
|
||||
|
||||
@property
|
||||
def platform_dir(self):
|
||||
return join(dirname(self.specfilename), self.targetname, 'platform')
|
||||
return join(dirname(self.specfilename), '.buildozer',
|
||||
self.targetname, 'platform')
|
||||
|
||||
@property
|
||||
def app_dir(self):
|
||||
return join(dirname(self.specfilename), self.targetname, 'app')
|
||||
return join(dirname(self.specfilename), '.buildozer',
|
||||
self.targetname, 'app')
|
||||
|
||||
def run():
|
||||
from optparse import OptionParser
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
ANDROID_API = '16'
|
||||
#
|
||||
# Android target
|
||||
# Thanks for Renpy (again) for its install_sdk.py and plat.py in the PGS4A
|
||||
# project!
|
||||
#
|
||||
|
||||
|
||||
ANDROID_API = '14'
|
||||
ANDROID_SDK_VERSION = '21'
|
||||
ANDROID_NDK_VERSION = '8c'
|
||||
APACHE_ANT_VERSION = '1.8.4'
|
||||
|
||||
import tarfile
|
||||
import zipfile
|
||||
|
||||
import traceback
|
||||
from sys import platform
|
||||
from buildozer.target import Target
|
||||
|
@ -72,13 +78,10 @@ class TargetAndroid(Target):
|
|||
archive = 'apache-ant-{0}-bin.tar.gz'.format(APACHE_ANT_VERSION)
|
||||
unpacked = 'apache-ant-{0}'.format(APACHE_ANT_VERSION)
|
||||
url = 'http://archive.apache.org/dist/ant/binaries/'
|
||||
archive = self.buildozer.download(url, archive,
|
||||
self.buildozer.download(url, archive,
|
||||
cwd=self.buildozer.platform_dir)
|
||||
|
||||
tf = tarfile.open(archive, 'r:*')
|
||||
tf.extractall(path=self.buildozer.platform_dir)
|
||||
tf.close()
|
||||
|
||||
self.buildozer.file_extract(archive, cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.file_rename(unpacked, 'apache-ant',
|
||||
cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.log('Apache ANT installation done.')
|
||||
|
@ -105,19 +108,11 @@ class TargetAndroid(Target):
|
|||
|
||||
archive = archive.format(ANDROID_SDK_VERSION)
|
||||
url = 'http://dl.google.com/android/'
|
||||
archive = self.buildozer.download(url, archive,
|
||||
self.buildozer.download(url, archive,
|
||||
cwd=self.buildozer.platform_dir)
|
||||
|
||||
self.buildozer.log('Unpacking Android SDK')
|
||||
if archive.endswith('.tgz'):
|
||||
tf = tarfile.open(archive, 'r:*')
|
||||
tf.extractall(path=self.buildozer.platform_dir)
|
||||
tf.close()
|
||||
else:
|
||||
zf = zipfile.ZipFile(archive)
|
||||
zf.extractall(path=self.buildozer.platform_dir)
|
||||
zf.close()
|
||||
|
||||
self.buildozer.file_extract(archive, cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.file_rename(unpacked, 'android-sdk',
|
||||
cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.log('Android SDK installation done.')
|
||||
|
@ -143,19 +138,11 @@ class TargetAndroid(Target):
|
|||
archive = archive.format(ANDROID_NDK_VERSION)
|
||||
unpacked = unpacked.format(ANDROID_NDK_VERSION)
|
||||
url = 'http://dl.google.com/android/ndk/'
|
||||
archive = self.buildozer.download(url, archive,
|
||||
self.buildozer.download(url, archive,
|
||||
cwd=self.buildozer.platform_dir)
|
||||
|
||||
self.buildozer.log('Unpacking Android NDK')
|
||||
if archive.endswith('.tar.bz2'):
|
||||
tf = tarfile.open(archive, 'r:*')
|
||||
tf.extractall(path=self.buildozer.platform_dir)
|
||||
tf.close()
|
||||
else:
|
||||
zf = zipfile.ZipFile(archive)
|
||||
zf.extractall(path=self.buildozer.platform_dir)
|
||||
zf.close()
|
||||
|
||||
self.buildozer.file_extract(archive, cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.file_rename(unpacked, 'android-ndk',
|
||||
cwd=self.buildozer.platform_dir)
|
||||
self.buildozer.log('Android NDK installation done.')
|
||||
|
@ -172,11 +159,9 @@ class TargetAndroid(Target):
|
|||
if not packages:
|
||||
self.buildozer.log('Android packages already installed.')
|
||||
return
|
||||
ret = self.buildozer.cmd('{0} update sdk -u -a -t {1}'.format(
|
||||
self.buildozer.cmd('{0} update sdk -u -a -t {1}'.format(
|
||||
self.android_cmd, ','.join(packages)),
|
||||
cwd=self.buildozer.platform_dir)
|
||||
print ret[0]
|
||||
print ret[1]
|
||||
self.buildozer.log('Android packages installation done.')
|
||||
|
||||
def install_platform(self):
|
||||
|
@ -192,7 +177,7 @@ class TargetAndroid(Target):
|
|||
cmd('git pull origin master', cwd=pa_dir)
|
||||
'''
|
||||
|
||||
self.ant_dir = ant_dir = self._install_apache_ant()
|
||||
self._install_apache_ant()
|
||||
self.sdk_dir = sdk_dir = self._install_android_sdk()
|
||||
self.ndk_dir = ndk_dir = self._install_android_ndk()
|
||||
self._install_android_packages()
|
||||
|
@ -206,8 +191,8 @@ class TargetAndroid(Target):
|
|||
# for android, the compilation depends really on the app requirements.
|
||||
# compile the distribution only if the requirements changed.
|
||||
last_requirements = self.buildozer.state.get('android.requirements', '')
|
||||
app_requirements = self.buildozer.config.get('app',
|
||||
'requirements', '').split()
|
||||
app_requirements = self.buildozer.config.getlist('app',
|
||||
'requirements', '')
|
||||
|
||||
# we need to extract the requirements that python-for-android knows
|
||||
# about
|
||||
|
@ -244,7 +229,14 @@ class TargetAndroid(Target):
|
|||
cmd('./distribute.sh -m "{0}"'.format(modules_str), cwd=self.pa_dir)
|
||||
self.buildozer.log('Distribution compiled.')
|
||||
|
||||
# ensure we will not compile again
|
||||
self.buildozer.state['android.requirements'] = android_requirements
|
||||
self.buildozer.state.sync()
|
||||
|
||||
def build_package(self):
|
||||
dist_dir = join(self.pa_dir, 'dist', 'default')
|
||||
#cmd('./build.py --name {0} --private {1} '
|
||||
# '--version {2}
|
||||
|
||||
|
||||
def get_target(buildozer):
|
||||
|
|
Loading…
Reference in a new issue