Merge branch 'master' of https://github.com/kivy/buildozer
Conflicts: buildozer/__init__.py buildozer/targets/android.py
This commit is contained in:
commit
4ccdf18ec3
6 changed files with 164 additions and 30 deletions
|
@ -1,4 +0,0 @@
|
|||
buildozer
|
||||
=========
|
||||
|
||||
Generic Python packager for Android / iOS and Desktop
|
|
@ -1,7 +1,7 @@
|
|||
Buildozer
|
||||
=========
|
||||
|
||||
THIS IS A WORK IN PROGRESS, DO NOT USE.
|
||||
This tool is currently in alpha.
|
||||
|
||||
Buildozer is a tool for creating application packages easily.
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class Buildozer(object):
|
|||
self.config = SafeConfigParser()
|
||||
self.config.getlist = self._get_config_list
|
||||
self.config.getdefault = self._get_config_default
|
||||
self.config.getbooldefault = self._get_config_bool
|
||||
|
||||
if exists(filename):
|
||||
self.config.read(filename)
|
||||
|
@ -289,6 +290,10 @@ class Buildozer(object):
|
|||
adderror('[app] "version.filename" is missing'
|
||||
', required by "version.regex"')
|
||||
|
||||
orientation = get('app', 'orientation', 'landscape')
|
||||
if orientation not in ('landscape', 'portrait', 'all'):
|
||||
adderror('[app] "orientation" have an invalid value')
|
||||
|
||||
if errors:
|
||||
self.error('{0} error(s) found in the buildozer.spec'.format(
|
||||
len(errors)))
|
||||
|
@ -572,10 +577,17 @@ class Buildozer(object):
|
|||
'''
|
||||
return re.sub('[^a-zA-Z0-9_\-]', '_', name)
|
||||
|
||||
@property
|
||||
def root_dir(self):
|
||||
return realpath(join(dirname(self.specfilename)))
|
||||
|
||||
@property
|
||||
def buildozer_dir(self):
|
||||
return realpath(join(
|
||||
dirname(self.specfilename), '.buildozer'))
|
||||
return join(self.root_dir, '.buildozer')
|
||||
|
||||
@property
|
||||
def bin_dir(self):
|
||||
return join(self.root_dir, 'bin')
|
||||
|
||||
@property
|
||||
def platform_dir(self):
|
||||
|
@ -585,11 +597,6 @@ class Buildozer(object):
|
|||
def app_dir(self):
|
||||
return join(self.buildozer_dir, self.targetname, 'app')
|
||||
|
||||
@property
|
||||
def bin_dir(self):
|
||||
return realpath(join(
|
||||
dirname(self.specfilename), 'bin'))
|
||||
|
||||
@property
|
||||
def applibs_dir(self):
|
||||
return join(self.buildozer_dir, 'applibs')
|
||||
|
@ -762,10 +769,10 @@ class Buildozer(object):
|
|||
def _get_config_list(self, section, token, default=None):
|
||||
# monkey-patch method for ConfigParser
|
||||
# get a key as a list of string, seperated from the comma
|
||||
strvalue = self.config.getdefault(section, token, '')
|
||||
if not strvalue:
|
||||
return []
|
||||
values = strvalue.split(',')
|
||||
values = self.config.getdefault(section, token, '')
|
||||
if not values:
|
||||
return default
|
||||
values = values.split(',')
|
||||
if not values:
|
||||
return default
|
||||
return [x.strip() for x in values]
|
||||
|
@ -779,6 +786,14 @@ class Buildozer(object):
|
|||
return default
|
||||
return self.config.get(section, token)
|
||||
|
||||
def _get_config_bool(self, section, token, default=False):
|
||||
# monkey-patch method for ConfigParser
|
||||
# get a key in a section, or the default
|
||||
if not self.config.has_section(section):
|
||||
return default
|
||||
if not self.config.has_option(section, token):
|
||||
return default
|
||||
return self.config.getboolean(section, token)
|
||||
|
||||
class BuildozerRemote(Buildozer):
|
||||
def run_command(self, args):
|
||||
|
|
|
@ -26,7 +26,7 @@ version.filename = %(source.dir)s/main.py
|
|||
# version = 1.2.0
|
||||
|
||||
# (list) Application requirements
|
||||
requirements = twisted,kivy
|
||||
requirements = kivy
|
||||
|
||||
# (str) Presplash of the application
|
||||
#presplash.filename = %(source.dir)s/data/presplash.png
|
||||
|
@ -34,6 +34,13 @@ requirements = twisted,kivy
|
|||
# (str) Icon of the application
|
||||
#icon.filename = %(source.dir)s/data/icon.png
|
||||
|
||||
# (str) Supported orientation (one of landscape, portrait or all)
|
||||
orientation = landscape
|
||||
|
||||
# (bool) Indicate if the application should be fullscreen or not
|
||||
fullscreen = 1
|
||||
|
||||
|
||||
#
|
||||
# Android specific
|
||||
#
|
||||
|
@ -62,6 +69,9 @@ requirements = twisted,kivy
|
|||
# (str) Android entry point, default is ok for Kivy-based app
|
||||
#android.entrypoint = org.renpy.android.PythonActivity
|
||||
|
||||
# (str) python-for-android branch to use, if not master, useful to try
|
||||
# not yet merged features.
|
||||
#android.branch = master
|
||||
|
||||
#
|
||||
# iOS specific
|
||||
|
|
|
@ -19,6 +19,7 @@ import traceback
|
|||
from pipes import quote
|
||||
from sys import platform, executable
|
||||
from buildozer.target import Target
|
||||
from os import environ
|
||||
from os.path import join, realpath, expanduser
|
||||
from shutil import copyfile
|
||||
|
||||
|
@ -277,7 +278,7 @@ class TargetAndroid(Target):
|
|||
cmd('git clean -dxf', cwd=pa_dir)
|
||||
cmd('git pull origin master', cwd=pa_dir)
|
||||
|
||||
source = self.buildozer.config.get('app', 'android.branch')
|
||||
source = self.buildozer.config.getdefault('app', 'android.branch')
|
||||
if source:
|
||||
cmd('git checkout --track -b %s origin/%s' % (source, source),
|
||||
cwd=pa_dir)
|
||||
|
@ -377,12 +378,24 @@ class TargetAndroid(Target):
|
|||
# add presplash
|
||||
presplash = config.getdefault('app', 'presplash.filename', '')
|
||||
if presplash:
|
||||
build_cmd += ' --presplash {}'.format(join(self.buildozer.app_dir, '..', '..', '..', presplash))
|
||||
build_cmd += ' --presplash {}'.format(join(self.buildozer.root_dir,
|
||||
presplash))
|
||||
|
||||
# add icon
|
||||
icon = config.getdefault('app', 'icon.filename', '')
|
||||
if icon:
|
||||
build_cmd += ' --icon {}'.format(join(self.buildozer.app_dir, '..', '..', '..', icon))
|
||||
build_cmd += ' --icon {}'.format(join(self.buildozer.root_dir, icon))
|
||||
|
||||
# add orientation
|
||||
orientation = config.getdefault('app', 'orientation', 'landscape')
|
||||
if orientation == 'all':
|
||||
orientation = 'sensor'
|
||||
build_cmd += ' --orientation {}'.format(orientation)
|
||||
|
||||
# fullscreen ?
|
||||
fullscreen = config.getbooldefault('app', 'fullscreen', True)
|
||||
if not fullscreen:
|
||||
build_cmd += ' --window'
|
||||
|
||||
# build only in debug right now.
|
||||
if self.build_mode == 'debug':
|
||||
|
@ -409,6 +422,21 @@ class TargetAndroid(Target):
|
|||
self.buildozer.state['android:latestapk'] = apk
|
||||
self.buildozer.state['android:latestmode'] = self.build_mode
|
||||
|
||||
@property
|
||||
def serials(self):
|
||||
if hasattr(self, '_serials'):
|
||||
return self._serials
|
||||
serial = environ.get('ANDROID_SERIAL')
|
||||
if serial:
|
||||
return [serial]
|
||||
l = self.buildozer.cmd('adb devices',
|
||||
get_stdout=True)[0].splitlines()[1:-1]
|
||||
serials = []
|
||||
for serial in l:
|
||||
serials.append(serial.split()[0])
|
||||
self._serials = serials
|
||||
return serials
|
||||
|
||||
def cmd_deploy(self, *args):
|
||||
super(TargetAndroid, self).cmd_deploy(*args)
|
||||
state = self.buildozer.state
|
||||
|
@ -428,10 +456,14 @@ class TargetAndroid(Target):
|
|||
'Unable to found the latest APK. Please run "debug" again.')
|
||||
|
||||
# push on the device
|
||||
for serial in self.serials:
|
||||
self.buildozer.environ['ANDROID_SERIAL'] = serial
|
||||
self.buildozer.info('Deploy on {}'.format(serial))
|
||||
self.buildozer.cmd('{0} install -r {1}'.format(
|
||||
self.adb_cmd, full_apk), cwd=self.buildozer.global_platform_dir)
|
||||
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
||||
|
||||
self.buildozer.info('Application pushed on the device.')
|
||||
self.buildozer.info('Application pushed.')
|
||||
|
||||
def cmd_run(self, *args):
|
||||
super(TargetAndroid, self).cmd_run(*args)
|
||||
|
@ -440,20 +472,30 @@ class TargetAndroid(Target):
|
|||
'app', 'android.entrypoint', 'org.renpy.android.PythonActivity')
|
||||
package = self._get_package()
|
||||
|
||||
# push on the device
|
||||
for serial in self.serials:
|
||||
self.buildozer.environ['ANDROID_SERIAL'] = serial
|
||||
self.buildozer.info('Run on {}'.format(serial))
|
||||
self.buildozer.cmd(
|
||||
'{adb} shell am start -n {package}/{entry} -a {entry}'.format(
|
||||
adb=self.adb_cmd, package=package, entry=entrypoint),
|
||||
cwd=self.buildozer.global_platform_dir)
|
||||
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
||||
|
||||
self.buildozer.info('Application started on the device.')
|
||||
self.buildozer.info('Application started.')
|
||||
|
||||
def cmd_logcat(self, *args):
|
||||
'''Show the log from the device
|
||||
'''
|
||||
self.check_requirements()
|
||||
serial = self.serials[0:]
|
||||
if not serial:
|
||||
return
|
||||
self.buildozer.environ['ANDROID_SERIAL'] = serial[0]
|
||||
self.buildozer.cmd('{adb} logcat'.format(adb=self.adb_cmd),
|
||||
cwd=self.buildozer.global_platform_dir,
|
||||
show_output=True)
|
||||
self.buildozer.environ.pop('ANDROID_SERIAL', None)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,52 @@ from buildozer.target import Target
|
|||
from os.path import join, basename
|
||||
from getpass import getpass
|
||||
|
||||
PHP_TEMPLATE = '''
|
||||
<?php
|
||||
// credits goes to http://jeffreysambells.com/2010/06/22/ios-wireless-app-distribution
|
||||
|
||||
$ipas = glob('*.ipa');
|
||||
$provisioningProfiles = glob('*.mobileprovision');
|
||||
$plists = glob('*.plist');
|
||||
|
||||
$sr = stristr( $_SERVER['SCRIPT_URI'], '.php' ) === false ?
|
||||
$_SERVER['SCRIPT_URI'] : dirname($_SERVER['SCRIPT_URI']) . '/';
|
||||
$provisioningProfile = $sr . $provisioningProfiles[0];
|
||||
$ipa = $sr . $ipas[0];
|
||||
$itmsUrl = urlencode( $sr . 'index.php?plist=' . str_replace( '.plist', '', $plists[0] ) );
|
||||
|
||||
|
||||
if ($_GET['plist']) {
|
||||
$plist = file_get_contents( dirname(__FILE__)
|
||||
. DIRECTORY_SEPARATOR
|
||||
. preg_replace( '/![A-Za-z0-9-_]/i', '', $_GET['plist']) . '.plist' );
|
||||
$plist = str_replace('_URL_', $ipa, $plist);
|
||||
header('content-type: application/xml');
|
||||
echo $plist;
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Install {appname}</title>
|
||||
<style type="text/css">
|
||||
li { padding: 1em; }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li><a href="<? echo $provisioningProfile; ?>">Install Team Provisioning File</a></li>
|
||||
<li><a href="itms-services://?action=download-manifest&url=<? echo $itmsUrl; ?>">
|
||||
Install Application</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
class TargetIos(Target):
|
||||
|
||||
def check_requirements(self):
|
||||
|
@ -17,6 +63,13 @@ class TargetIos(Target):
|
|||
checkbin('Xcode xcodebuild', 'xcodebuild')
|
||||
checkbin('Xcode xcode-select', 'xcode-select')
|
||||
checkbin('Git git', 'git')
|
||||
checkbin('Cython', 'cython')
|
||||
checkbin('Mercurial', 'hg')
|
||||
checkbin('Cython cython', 'cython')
|
||||
checkbin('pkg-config', 'pkg-config')
|
||||
checkbin('autoconf', 'autoconf')
|
||||
checkbin('automake', 'automake')
|
||||
checkbin('libtool', 'libtool')
|
||||
|
||||
self.buildozer.debug('Check availability of a iPhone SDK')
|
||||
sdk = cmd('xcodebuild -showsdks | fgrep "iphoneos" |'
|
||||
|
@ -72,7 +125,8 @@ class TargetIos(Target):
|
|||
self._unlock_keychain()
|
||||
|
||||
# create the project
|
||||
app_name = self.buildozer.namify(self.buildozer.config.get('app', 'title'))
|
||||
app_name = self.buildozer.namify(self.buildozer.config.get('app',
|
||||
'package.name'))
|
||||
|
||||
self.app_project_dir = join(self.ios_dir, 'app-{0}'.format(app_name.lower()))
|
||||
if not self.buildozer.file_exists(self.app_project_dir):
|
||||
|
@ -106,7 +160,7 @@ class TargetIos(Target):
|
|||
plistlib.writePlist(plist, plist_rfn)
|
||||
|
||||
mode = 'Debug' if self.build_mode == 'debug' else 'Release'
|
||||
self.buildozer.cmd('xcodebuild -configuration {}'.format(mode),
|
||||
self.buildozer.cmd('xcodebuild -configuration {} clean build'.format(mode),
|
||||
cwd=self.app_project_dir)
|
||||
ios_app_dir = 'app-{app_lower}/build/{mode}-iphoneos/{app_lower}.app'.format(
|
||||
app_lower=app_name.lower(), mode=mode)
|
||||
|
@ -138,6 +192,8 @@ class TargetIos(Target):
|
|||
self.buildozer.state['ios:latestipa'] = ipa
|
||||
self.buildozer.state['ios:latestmode'] = self.build_mode
|
||||
|
||||
self._create_index()
|
||||
|
||||
def cmd_deploy(self, *args):
|
||||
super(TargetIos, self).cmd_deploy(*args)
|
||||
self._run_fruitstrap(gdb=False)
|
||||
|
@ -146,6 +202,17 @@ class TargetIos(Target):
|
|||
super(TargetIos, self).cmd_run(*args)
|
||||
self._run_fruitstrap(gdb=True)
|
||||
|
||||
def cmd_xcode(self, *args):
|
||||
'''Open the xcode project.
|
||||
'''
|
||||
app_name = self.buildozer.namify(self.buildozer.config.get('app',
|
||||
'package.name'))
|
||||
app_name = app_name.lower()
|
||||
|
||||
ios_dir = ios_dir = join(self.buildozer.platform_dir, 'kivy-ios')
|
||||
self.buildozer.cmd('open {}.xcodeproj'.format(
|
||||
app_name), cwd=join(ios_dir, 'app-{}'.format(app_name)))
|
||||
|
||||
def _run_fruitstrap(self, gdb=False):
|
||||
state = self.buildozer.state
|
||||
if 'ios:latestappdir' not in state:
|
||||
|
@ -210,6 +277,10 @@ class TargetIos(Target):
|
|||
icon_fn = join(self.app_project_dir, icon_basename)
|
||||
return icon_fn
|
||||
|
||||
def _create_index(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def check_configuration_tokens(self):
|
||||
errors = []
|
||||
config = self.buildozer.config
|
||||
|
|
Loading…
Reference in a new issue