ios: update the plist to include correct package domain+name, version, build id, and resample the icon if the dimensions are not ok.
This commit is contained in:
parent
fb0741a21f
commit
5f203cf3bb
3 changed files with 94 additions and 3 deletions
|
@ -53,6 +53,7 @@ class Buildozer(object):
|
||||||
self.environ = {}
|
self.environ = {}
|
||||||
self.specfilename = filename
|
self.specfilename = filename
|
||||||
self.state = None
|
self.state = None
|
||||||
|
self.build_id = None
|
||||||
self.config = SafeConfigParser()
|
self.config = SafeConfigParser()
|
||||||
self.config.getlist = self._get_config_list
|
self.config.getlist = self._get_config_list
|
||||||
self.config.getdefault = self._get_config_default
|
self.config.getdefault = self._get_config_default
|
||||||
|
@ -122,7 +123,15 @@ class Buildozer(object):
|
||||||
if hasattr(self.target, '_build_done'):
|
if hasattr(self.target, '_build_done'):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.info('Build the application')
|
# increment the build number
|
||||||
|
self.build_id = int(self.state.get('cache.build_id', '0')) + 1
|
||||||
|
self.state['cache.build_id'] = str(self.build_id)
|
||||||
|
# FIXME WHY the hell we need to close/reopen the state to sync the build
|
||||||
|
# id ???
|
||||||
|
self.state.close()
|
||||||
|
self.state = shelve.open(join(self.buildozer_dir, 'state.db'))
|
||||||
|
|
||||||
|
self.info('Build the application #{}'.format(self.build_id))
|
||||||
self.build_application()
|
self.build_application()
|
||||||
|
|
||||||
self.info('Package the application')
|
self.info('Package the application')
|
||||||
|
@ -384,6 +393,13 @@ class Buildozer(object):
|
||||||
self.debug('Rename {0} to {1}'.format(source, target))
|
self.debug('Rename {0} to {1}'.format(source, target))
|
||||||
rename(source, target)
|
rename(source, target)
|
||||||
|
|
||||||
|
def file_copy(self, source, target, cwd=None):
|
||||||
|
if cwd:
|
||||||
|
source = join(cwd, source)
|
||||||
|
target = join(cwd, target)
|
||||||
|
self.debug('Copy {0} to {1}'.format(source, target))
|
||||||
|
copyfile(source, target)
|
||||||
|
|
||||||
def file_extract(self, archive, cwd=None):
|
def file_extract(self, archive, cwd=None):
|
||||||
if archive.endswith('.tgz') or archive.endswith('.tar.gz'):
|
if archive.endswith('.tgz') or archive.endswith('.tar.gz'):
|
||||||
# XXX tarfile doesn't work for NDK-r8c :(
|
# XXX tarfile doesn't work for NDK-r8c :(
|
||||||
|
|
|
@ -338,7 +338,7 @@ class TargetAndroid(Target):
|
||||||
package = config.get('app', 'package.name')
|
package = config.get('app', 'package.name')
|
||||||
if package_domain:
|
if package_domain:
|
||||||
package = package_domain + '.' + package
|
package = package_domain + '.' + package
|
||||||
return package
|
return package.lower()
|
||||||
|
|
||||||
def build_package(self):
|
def build_package(self):
|
||||||
dist_dir = join(self.pa_dir, 'dist', 'default')
|
dist_dir = join(self.pa_dir, 'dist', 'default')
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
iOS target, based on kivy-ios project. (not working yet.)
|
iOS target, based on kivy-ios project. (not working yet.)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import plistlib
|
||||||
from buildozer.target import Target
|
from buildozer.target import Target
|
||||||
from os.path import join, basename
|
from os.path import join, basename
|
||||||
|
|
||||||
|
@ -57,6 +58,14 @@ class TargetIos(Target):
|
||||||
if not self.buildozer.file_exists(self.fruitstrap_dir, 'fruitstrap'):
|
if not self.buildozer.file_exists(self.fruitstrap_dir, 'fruitstrap'):
|
||||||
self.buildozer.cmd('make fruitstrap', cwd=self.fruitstrap_dir)
|
self.buildozer.cmd('make fruitstrap', cwd=self.fruitstrap_dir)
|
||||||
|
|
||||||
|
def _get_package(self):
|
||||||
|
config = self.buildozer.config
|
||||||
|
package_domain = config.getdefault('app', 'package.domain', '')
|
||||||
|
package = config.get('app', 'package.name')
|
||||||
|
if package_domain:
|
||||||
|
package = package_domain + '.' + package
|
||||||
|
return package.lower()
|
||||||
|
|
||||||
def build_package(self):
|
def build_package(self):
|
||||||
# create the project
|
# create the project
|
||||||
app_name = self.buildozer.namify(self.buildozer.config.get('app', 'title'))
|
app_name = self.buildozer.namify(self.buildozer.config.get('app', 'title'))
|
||||||
|
@ -71,6 +80,27 @@ class TargetIos(Target):
|
||||||
app_name, self.buildozer.app_dir),
|
app_name, self.buildozer.app_dir),
|
||||||
cwd=self.ios_dir)
|
cwd=self.ios_dir)
|
||||||
|
|
||||||
|
# fix the plist
|
||||||
|
plist_fn = '{}-Info.plist'.format(app_name.lower())
|
||||||
|
plist_rfn = join(self.app_project_dir, plist_fn)
|
||||||
|
version = self.buildozer.get_version()
|
||||||
|
self.buildozer.info('Update Plist {}'.format(plist_fn))
|
||||||
|
plist = plistlib.readPlist(plist_rfn)
|
||||||
|
plist['CFBundleIdentifier'] = self._get_package()
|
||||||
|
plist['CFBundleShortVersionString'] = version
|
||||||
|
plist['CFBundleVersion'] = '{}.{}'.format(version,
|
||||||
|
self.buildozer.build_id)
|
||||||
|
|
||||||
|
# add icon
|
||||||
|
icon = self._get_icon()
|
||||||
|
if icon:
|
||||||
|
plist['CFBundleIconFiles'] = [icon]
|
||||||
|
plist['CFBundleIcons'] = {'CFBundlePrimaryIcon': {
|
||||||
|
'UIPrerenderedIcon': False, 'CFBundleIconFiles': [icon]}}
|
||||||
|
|
||||||
|
# ok, write the modified plist.
|
||||||
|
plistlib.writePlist(plist, plist_rfn)
|
||||||
|
|
||||||
mode = 'Debug' if self.build_mode == 'debug' else 'Release'
|
mode = 'Debug' if self.build_mode == 'debug' else 'Release'
|
||||||
self.buildozer.cmd('xcodebuild -configuration {}'.format(mode),
|
self.buildozer.cmd('xcodebuild -configuration {}'.format(mode),
|
||||||
cwd=self.app_project_dir)
|
cwd=self.app_project_dir)
|
||||||
|
@ -83,10 +113,10 @@ class TargetIos(Target):
|
||||||
if not ioscodesign:
|
if not ioscodesign:
|
||||||
self.buildozer.error('Cannot create the IPA package without'
|
self.buildozer.error('Cannot create the IPA package without'
|
||||||
' signature. You must fill the "{}" token.'.format(key))
|
' signature. You must fill the "{}" token.'.format(key))
|
||||||
|
return
|
||||||
elif ioscodesign[0] not in ('"', "'"):
|
elif ioscodesign[0] not in ('"', "'"):
|
||||||
ioscodesign = '"{}"'.format(ioscodesign)
|
ioscodesign = '"{}"'.format(ioscodesign)
|
||||||
|
|
||||||
version = self.buildozer.get_version()
|
|
||||||
ipa = join(self.buildozer.bin_dir, '{}-{}.ipa'.format(
|
ipa = join(self.buildozer.bin_dir, '{}-{}.ipa'.format(
|
||||||
app_name, version))
|
app_name, version))
|
||||||
self.buildozer.cmd((
|
self.buildozer.cmd((
|
||||||
|
@ -117,6 +147,7 @@ class TargetIos(Target):
|
||||||
if 'ios:latestappdir' not in state:
|
if 'ios:latestappdir' not in state:
|
||||||
self.buildozer.error(
|
self.buildozer.error(
|
||||||
'App not built yet. Run "debug" or "release" first.')
|
'App not built yet. Run "debug" or "release" first.')
|
||||||
|
return
|
||||||
ios_app_dir = state.get('ios:latestappdir')
|
ios_app_dir = state.get('ios:latestappdir')
|
||||||
|
|
||||||
if gdb:
|
if gdb:
|
||||||
|
@ -131,6 +162,50 @@ class TargetIos(Target):
|
||||||
gdb=gdb_mode, app_dir=ios_app_dir),
|
gdb=gdb_mode, app_dir=ios_app_dir),
|
||||||
cwd=self.ios_dir, show_output=True)
|
cwd=self.ios_dir, show_output=True)
|
||||||
|
|
||||||
|
def _get_icon(self):
|
||||||
|
# check the icon size, must be 72x72 or 144x144
|
||||||
|
icon = self.buildozer.config.getdefault('app', 'icon.filename', '')
|
||||||
|
if not icon:
|
||||||
|
return
|
||||||
|
icon_fn = join(self.buildozer.app_dir, icon)
|
||||||
|
if not self.buildozer.file_exists(icon_fn):
|
||||||
|
self.buildozer.error('Icon {} does not exists'.format(icon_fn))
|
||||||
|
return
|
||||||
|
output = self.buildozer.cmd('file {}'.format(icon),
|
||||||
|
cwd=self.buildozer.app_dir, get_stdout=True)[0]
|
||||||
|
if not output:
|
||||||
|
self.buildozer.error('Unable to read icon {}'.format(icon_fn))
|
||||||
|
return
|
||||||
|
# output is something like:
|
||||||
|
# "data/cancel.png: PNG image data, 50 x 50, 8-bit/color RGBA,
|
||||||
|
# non-interlaced"
|
||||||
|
info = output.splitlines()[0].split(',')
|
||||||
|
fmt = info[0].split(':')[-1].strip()
|
||||||
|
if fmt != 'PNG image data':
|
||||||
|
self.buildozer.error('Only PNG icon are accepted, {} invalid'.format(icon_fn))
|
||||||
|
return
|
||||||
|
size = [int(x.strip()) for x in info[1].split('x')]
|
||||||
|
if size != [72, 72] and size != [144, 144]:
|
||||||
|
# icon cannot be used like that, it need a resize.
|
||||||
|
self.buildozer.error('Invalid PNG size, must be 72x72 or 144x144. Resampling.')
|
||||||
|
nearest_size = 144
|
||||||
|
if size[0] < 144:
|
||||||
|
nearest_size = 72
|
||||||
|
|
||||||
|
icon_basename = 'icon-{}.png'.format(nearest_size)
|
||||||
|
self.buildozer.file_copy(icon_fn, join(self.app_project_dir,
|
||||||
|
icon_basename))
|
||||||
|
self.buildozer.cmd('sips -z {0} {0} {1}'.format(nearest_size,
|
||||||
|
icon_basename), cwd=self.app_project_dir)
|
||||||
|
else:
|
||||||
|
# icon ok, use it as it.
|
||||||
|
icon_basename = 'icon-{}.png'.format(size[0])
|
||||||
|
self.buildozer.file_copy(icon_fn, join(self.app_project_dir,
|
||||||
|
icon_basename))
|
||||||
|
|
||||||
|
icon_fn = join(self.app_project_dir, icon_basename)
|
||||||
|
return icon_fn
|
||||||
|
|
||||||
def check_configuration_tokens(self):
|
def check_configuration_tokens(self):
|
||||||
errors = []
|
errors = []
|
||||||
if not self.buildozer.config.getdefault('app', 'ios.codesign.debug'):
|
if not self.buildozer.config.getdefault('app', 'ios.codesign.debug'):
|
||||||
|
|
Loading…
Reference in a new issue