Skip to content
Open
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Usage:
Available targets:
android Android target, based on python-for-android project
ios iOS target, based on kivy-ios project
osx MacOs X target, based on kivy-sdk-packager project

Global commands (without target):
distclean Clean the whole Buildozer environment
Expand Down
8 changes: 7 additions & 1 deletion buildozer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,14 @@ def check_application_requirements(self):
self.state['cache.applibs'] = requirements

def _install_application_requirement(self, module):
# ignore *.spec requirements for osx target, uses requirements.txt section of target
if 'osx' in f'{self.target}':
return

# if you get obsolete files style =x.x.x maybe need uncomment next line
# module = str(module).replace('>', '=')
self._ensure_virtualenv()
self.debug('Install requirement {} in virtualenv'.format(module))
self.debug(f'Install requirement {module} in virtualenv')
self.cmd(
["pip", "install", f"--target={self.applibs_dir}", module],
env=self.env_venv,
Expand Down
4 changes: 2 additions & 2 deletions buildozer/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,12 @@ def install_or_update_repo(self, repo, **kwargs):
if not self.buildozer.file_exists(install_dir):
if custom_dir:
cmd(["mkdir", "-p", install_dir])
cmd(["cp", "-a", f"{custom_dir}/*", f"{install_dir}/"])
cmd(["cp", "-a", f"{custom_dir}/.", f"{install_dir}/"])
else:
cmd(["git", "clone", "--branch", clone_branch, clone_url], cwd=self.buildozer.platform_dir)
elif self.platform_update:
if custom_dir:
cmd(["cp", "-a", f"{custom_dir}/*", f"{install_dir}/"])
cmd(["cp", "-a", f"{custom_dir}/.", f"{install_dir}/"])
else:
cmd(["git", "clean", "-dxf"], cwd=install_dir)
cmd(["git", "pull", "origin", clone_branch], cwd=install_dir)
Expand Down
25 changes: 21 additions & 4 deletions buildozer/targets/ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from buildozer.target import Target, no_config
from os.path import join, basename, expanduser, realpath
from getpass import getpass
from PIL import Image


PHP_TEMPLATE = '''
Expand Down Expand Up @@ -299,14 +300,19 @@ def build_package(self):
self.buildozer.info('Creating IPA...')
self.xcodebuild(
'-exportArchive',
f'-archivePath "{xcarchive}"',
f'-exportOptionsPlist "{plist_rfn}"',
f'-exportPath "{ipa_tmp}"',
'-archivePath',
xcarchive,
'-exportOptionsPlist',
plist_rfn,
'-exportPath',
ipa_tmp,
f'CODE_SIGN_IDENTITY={ioscodesign}',
'ENABLE_BITCODE=NO',
cwd=build_dir)

self.buildozer.info('Moving IPA to bin...')
# clean out dir
self.buildozer.rmdir(ipa)
self.buildozer.file_rename(ipa_tmp, ipa)

self.buildozer.info('iOS packaging done!')
Expand Down Expand Up @@ -360,7 +366,18 @@ def _create_icons(self):
icon = self.buildozer.config.getdefault('app', 'icon.filename', '')
if not icon:
return
icon_fn = join(self.buildozer.app_dir, icon)

# get icon size and make it for god for not get err
img = Image.open(icon)
if img.height != 72 or img.width != 72 or not str(icon).endswith('.png'):
self.buildozer.debug('Icon size as bad format try to make a new format: {}/{} to 72/72.'.format(img.height, img.width))
size = 72, 72
img = img.resize(size, Image.ANTIALIAS)
img.save(join(self.app_project_dir, 'icon.png'), "PNG")
else:
self.buildozer.cmd(['cp', icon, f'{self.app_project_dir}/icon.png'])

icon_fn = join(self.app_project_dir, 'icon.png')
if not self.buildozer.file_exists(icon_fn):
self.buildozer.error('Icon {} does not exists'.format(icon_fn))
return
Expand Down
88 changes: 51 additions & 37 deletions buildozer/targets/osx.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
'''

import sys

if sys.platform != 'darwin':
raise NotImplementedError('This will only work on osx')

from buildozer.target import Target
from os.path import exists, join, abspath, dirname
from subprocess import check_call, check_output


class TargetOSX(Target):
Expand All @@ -19,47 +19,47 @@ def ensure_sdk(self):
if exists(
join(self.buildozer.platform_dir, 'kivy-sdk-packager-master')):
self.buildozer.info(
'kivy-sdk-packager found at '
'kivy-sdk-packager found at '
'{}'.format(self.buildozer.platform_dir))
return

self.buildozer.info('kivy-sdk-packager does not exist, clone it')
platdir = self.buildozer.platform_dir
check_call(
('curl', '-O', '-L',
'https://github.com/kivy/kivy-sdk-packager/archive/master.zip'),
self.buildozer.cmd(
['curl', '-O', '-L',
'https://github.com/kivy/kivy-sdk-packager/archive/master.zip'],
cwd=platdir)
check_call(('unzip', 'master.zip'), cwd=platdir)
check_call(('rm', 'master.zip'), cwd=platdir)
self.buildozer.cmd(['unzip', 'master.zip'], cwd=platdir)
self.buildozer.cmd(['rm', 'master.zip'], cwd=platdir)

def download_kivy(self, cwd, py_branch=2):
current_kivy_vers = self.buildozer.config.get('app', 'osx.kivy_version')

if exists('/Applications/Kivy{}.app'.format(py_branch)):
self.buildozer.info('Kivy found in Applications dir...')
check_call(
('cp', '-a', '/Applications/Kivy{}.app'.format(py_branch),
'Kivy.app'), cwd=cwd)
self.buildozer.cmd(
['cp', '-a', '/Applications/Kivy{}.app'.format(py_branch),
'Kivy.app'], cwd=cwd)

else:
if not exists(join(cwd, 'Kivy{}.dmg'.format(py_branch))):
self.buildozer.info('Downloading kivy...')
status_code = check_output(
('curl', '-L', '--write-out', '%{http_code}', '-o', 'Kivy{}.dmg'.format(py_branch),
'https://kivy.org/downloads/{}/Kivy-{}-osx-python{}.dmg'
.format(current_kivy_vers, current_kivy_vers, py_branch)),
status_code = self.buildozer.cmd(
['curl', '-L', '--write-out', '%{http_code}', '-o', 'Kivy{}.dmg'.format(py_branch),
'https://kivy.org/downloads/{}/Kivy.dmg' # -{}-osx-python{}.dmg'
.format(current_kivy_vers)], # , current_kivy_vers, py_branch)),
cwd=cwd)

if status_code == "404":
self.buildozer.error(
"Unable to download the Kivy App. Check osx.kivy_version in your buildozer.spec, and verify "
"Kivy servers are accessible. https://kivy.org/downloads/")
check_call(("rm", "Kivy{}.dmg".format(py_branch)), cwd=cwd)
self.buildozer.cmd(["rm", "Kivy{}.dmg".format(py_branch)], cwd=cwd)
sys.exit(1)

self.buildozer.info('Extracting and installing Kivy...')
check_call(('hdiutil', 'attach', cwd + '/Kivy{}.dmg'.format(py_branch)))
check_call(('cp', '-a', '/Volumes/Kivy/Kivy.app', './Kivy.app'), cwd=cwd)
self.buildozer.cmd(['hdiutil', 'attach', cwd + '/Kivy{}.dmg'.format(py_branch)])
self.buildozer.cmd(['cp', '-a', '/Volumes/Kivy/Kivy.app', './Kivy.app'], cwd=cwd)

def ensure_kivyapp(self):
self.buildozer.info('check if Kivy.app exists in local dir')
Expand All @@ -85,12 +85,23 @@ def check_configuration_tokens(self, errors=None):
self.buildozer.info('Check target configuration tokens')
self.buildozer.error(
'{0} error(s) found in the buildozer.spec'.format(
len(errors)))
len(errors)))
for error in errors:
print(error)
sys.exit(1)
# check

def _install_application_requirement(self, module):
self.buildozer._ensure_virtualenv()
if 'kivy' in '{}'.format(module) or 'buildozer' in '{}'.format(module):
self.buildozer.debug('Install requirement {} in virtualenv ignored for target: osx'.format(module))
return

self.buildozer.debug('Install requirement {} in virtualenv'.format(module))
cwd = join(self.buildozer.platform_dir, 'kivy-sdk-packager-master', 'osx')
self.buildozer.cmd(['Kivy.app/Contents/Resources/script', '-m', 'pip', 'install', '--upgrade', '--force-reinstall', '--target={}/_applibs'.format(self.buildozer.app_dir), '{}'.format(module)],
cwd=cwd)

def build_package(self):
self.buildozer.info('Building package')

Expand All @@ -99,50 +110,53 @@ def build_package(self):
package_name = bcg('app', 'package.name')
domain = bcg('app', 'package.domain')
title = bcg('app', 'title')
app_deps = open('requirements.txt').read()
source = bcg('app', 'source.dir')
app_deps = None
if exists('{}/requirements.txt'.format(source)):
app_deps = open('{}/requirements.txt'.format(source)).read()
# remove # from app_deps
app_deps = [a for a in app_deps.split('\n') if not a.startswith('#')]
icon = bc.getdefault('app', 'icon.filename', '')
if source in icon:
icon = '{}'.format(icon).replace('{}'.format(source), '{}'.format(self.buildozer.app_dir))
version = self.buildozer.get_version()
author = bc.getdefault('app', 'author', '')

self.buildozer.info('Create {}.app'.format(package_name))
self.buildozer.mkdir('{}/_applibs'.format(self.buildozer.app_dir))
cwd = join(self.buildozer.platform_dir, 'kivy-sdk-packager-master', 'osx')
# remove kivy from app_deps
app_deps = [a for a in app_deps.split('\n') if not a.startswith('#') and a not in ['kivy', '']]

cmd = [
'Kivy.app/Contents/Resources/script',
'-m', 'pip', 'install',
]
cmd.extend(app_deps)
check_output(cmd, cwd=cwd)
if app_deps is not None:
for dep in app_deps:
self._install_application_requirement(dep.replace('>', '='))

cmd = [
'python', 'package_app.py', self.buildozer.app_dir,
'--appname={}'.format(package_name),
'--bundlename={}'.format(title),
'--bundleid={}'.format(domain),
'--bundleversion={}'.format(version),
'--displayname={}'.format(title)
]
'--bundlename={}'.format(title),
'--bundleid={}'.format(domain),
'--bundleversion={}'.format(version),
'--displayname={}'.format(title)
]
if icon:
cmd.append('--icon={}'.format(icon))
if author:
cmd.append('--author={}'.format(author))

check_output(cmd, cwd=cwd)
self.buildozer.cmd(cmd, cwd=cwd)

self.buildozer.info('{}.app created.'.format(package_name))
self.buildozer.info('Creating {}.dmg'.format(package_name))
check_output(
('sh', '-x', 'create-osx-dmg.sh', package_name + '.app'),
self.buildozer.cmd(
['sh', '-x', 'create-osx-dmg.sh', package_name + '.app', package_name],
cwd=cwd)
self.buildozer.info('{}.dmg created'.format(package_name))
self.buildozer.info('moving {}.dmg to bin.'.format(package_name))
binpath = join(
self.buildozer.user_build_dir or
dirname(abspath(self.buildozer.specfilename)), 'bin')
check_output(
('cp', '-a', package_name + '.dmg', binpath),
self.buildozer.cmd(
['cp', '-a', package_name + '.dmg', binpath],
cwd=cwd)
self.buildozer.info('All Done!')

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def find_version(*file_paths):
],
package_data={'buildozer': ['default.spec']},
include_package_data=True,
install_requires=['pexpect', 'virtualenv', 'sh'],
install_requires=['pexpect', 'virtualenv', 'sh', 'pillow'],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
Expand Down