This commit is contained in:
Robert Niederreiter 2017-04-20 20:23:15 +02:00
commit fca0848f94
7 changed files with 200 additions and 64 deletions

View file

@ -1,8 +1,6 @@
Buildozer
=========
This tool is currently in alpha.
Buildozer is a tool for creating application packages easily.
The goal is to have one "buildozer.spec" file in your app directory, describing
@ -18,10 +16,10 @@ is intended in the future.
Note that this tool has nothing to do with the eponymous online build service
`buildozer.io <http://buildozer.io />`_.
Usage example
-------------
Installing Buildozer with python2 support:
------------------------------------------
#. Install buildozer::
#. Install buildozer::
# via pip (latest stable, recommended)
sudo pip install buildozer
@ -35,13 +33,49 @@ Usage example
python setup.py build
sudo pip install -e .
#. Go into your application directory and do::
#. Go into your application directory and run::
buildozer init
# edit the buildozer.spec, then
buildozer android_new debug deploy run
Example of commands::
Installing Buildozer with python3 support:
------------------------------------------
The pip package does not yet support python3.
#. Install buildozer from source::
git clone https://github.com/kivy/buildozer
cd buildozer
python setup.py build
sudo pip install -e
#. Download and extract the Crystax NDK somewhere (~/.buildozer/crystax-ndk is one option): https://www.crystax.net/en/download
#. Go into your application directory and execute::
buildozer init
#. Make sure the following lines are in your buildozer.spec file.::
# Require python3crystax:
requirements = python3crystax,kivy
# Point to the directory where you extracted the crystax-ndk:
android.ndk_path = <Your install path here. Use ~ for home DIR>
#. Finally, build, deploy and run the app on your phone::
buildozer android_new debug deploy run
#. Please note the "android_new" buildozer target, and use that for any and all buildozer commands you run (even if the docs just say "android"). Python3 only works with the **android_new** toolchain.
Examples of Buildozer commands:
--------------------------------
::
# buildozer target command
buildozer android_new clean
@ -128,6 +162,68 @@ config, along with the environment variables that would override them.
- ``package.name`` -> ``$APP_PACKAGE_NAME``
- ``android.p4a_dir`` -> ``$APP_ANDROID_P4A_DIR``
Buildozer Virtual Machine
-------------------------
The current virtual machine (available via https://kivy.org/downloads/) allow
you to have a ready to use vm for building android application. But
the current one have many flaw.
We're in the process to deliver a new VM that fixes most of them.
Using shared folders
++++++++++++++++++++
The Virtualbox Guest tools are outdated, install the latest one:
- in the Virtualbox: `Devices` -> `Install Guest Additions CD images`
- in the guest/linux: Go to the cdrom and run the installer
The `kivy` user is not in the `vboxsf` groups, so in a terminal:
- `sudo adduser kivy vboxsf`
- reboot the vm
VirtualBox filesystem doesn't support symlink anymore (don't
try the setextradata solution, it doesn't work.). So you must
do the build outside the shared folder. One solution:
- `sudo mkdir /build`
- `sudo chown kivy /build`
- In your buildozer.spec, section `[buildozer]`, set `build_dir = /build/buildozer-myapp`
No space left
+++++++++++++
If you build on the current VM, you'll hit the no space left on device:
- Stop your VM
- Adjust the disk size to 20GB: `VBoxManage modifyhd ~/Downloads/Buildozer/Buildozer.vdi --resize 20000`
- Download the http://www.slitaz.org/en/get/#stable
- In the virtualbox, `Devices` -> `Optical Drive` -> Select the slitaz iso
- Reboot the VM
- In slitaz, open a terminal, and unmount the swap: `swapoff -a`
- Open gparted
- delete sda2
- extend sda1 to 18000
- add a primary partition, set the format to linux-swap
- you should have a sda2 partition
- save
- Unmount the slitaz iso `Devices` -> `Optical Drive` -> `Eject`
- Reset/Restart the VM
- Check your disk is 20GB: `df -h`
Using your devices via the VM
+++++++++++++++++++++++++++++
There is a little icon on the bottom left that represent an USB plug.
Select it, and select your android device on it. Then you can check:
- `buildozer android_new adb -- devices`
If it doesn't, use Google. They are so many differents way / issues
depending your phone that Google will be your only source of
information, not us :)
Support
-------

View file

@ -582,8 +582,6 @@ class Buildozer(object):
result = []
for pattern in patterns:
matches = glob(expanduser(pattern.strip()))
if not matches:
return
result.extend(matches)
return result

View file

@ -52,7 +52,7 @@ requirements = kivy
#icon.filename = %(source.dir)s/data/icon.png
# (str) Supported orientation (one of landscape, portrait or all)
orientation = landscape
orientation = portrait
# (list) List of service to declare
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
@ -64,12 +64,25 @@ orientation = landscape
#
# author = © Copyright Info
# change the major version of python used by the app
osx.python_version = 3
# Kivy version to use
osx.kivy_version = 1.9.1
#
# Android specific
#
# (bool) Indicate if the application should be fullscreen or not
fullscreen = 1
fullscreen = 0
# (string) Presplash background color (for new android toolchain)
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
# olive, purple, silver, teal.
#android.presplash_color = #FFFFFF
# (string) Presplash background color (for new android toolchain)
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:

View file

@ -27,6 +27,7 @@ from buildozer import IS_PY3
from buildozer.target import Target
from os import environ
from os.path import exists, join, realpath, expanduser, basename, relpath
from platform import architecture
from shutil import copyfile
from glob import glob
@ -415,19 +416,17 @@ class TargetAndroid(Target):
'build-tools')
packages = self._android_list_sdk(include_all=True)
ver = self._find_latest_package(packages, 'build-tools-')
if ver and ver > v_build_tools:
self._android_update_sdk(self._build_package_string('build-tools',
ver))
if ver and ver > v_build_tools and not skip_upd:
self._android_update_sdk(self._build_package_string('build-tools', ver))
# 2.bis check aidl can be runned
self._check_aidl(v_build_tools)
# 3. finally, install the android for the current api
android_platform = join(self.android_sdk_dir, 'platforms',
'android-{0}'.format(self.android_api))
android_platform = join(self.android_sdk_dir, 'platforms', 'android-{0}'.format(self.android_api))
if not self.buildozer.file_exists(android_platform):
packages = self._android_list_sdk()
android_package = 'android-{}'.format(self.android_api)
if android_package in packages:
if android_package in packages and not skip_upd:
self._android_update_sdk(android_package)
self.buildozer.info('Android packages installation done.')
@ -447,7 +446,7 @@ class TargetAndroid(Target):
show_output=False)
if returncode != 1:
self.buildozer.error('Aidl cannot be executed')
if sys.maxint > 2**32:
if architecture()[0] == '64bit':
self.buildozer.error('')
self.buildozer.error(
'You might have missed to install 32bits libs')

View file

@ -20,7 +20,8 @@ class TargetAndroidNew(TargetAndroid):
def __init__(self, buildozer):
super(TargetAndroidNew, self).__init__(buildozer)
self._build_dir = join(self.buildozer.platform_dir, 'build')
self._p4a_cmd = 'python -m pythonforandroid.toolchain '
executable = sys.executable or 'python'
self._p4a_cmd = '{} -m pythonforandroid.toolchain '.format(executable)
self._p4a_bootstrap = self.buildozer.config.getdefault(
'app', 'android.bootstrap', 'sdl2')
self.p4a_apk_cmd += self._p4a_bootstrap

View file

@ -222,16 +222,42 @@ class TargetIos(Target):
elif ioscodesign[0] not in ('"', "'"):
ioscodesign = '"{}"'.format(ioscodesign)
ipa = join(self.buildozer.bin_dir, '{}-{}.ipa'.format(
intermediate_dir = join(self.ios_dir, '{}-{}.intermediates'.format(app_name, version))
xcarchive = join(intermediate_dir, '{}-{}.xcarchive'.format(
app_name, version))
ipa_name = '{}-{}.ipa'.format(app_name, version)
ipa_tmp = join(intermediate_dir, ipa_name)
ipa = join(self.buildozer.bin_dir, ipa_name)
build_dir = join(self.ios_dir, '{}-ios'.format(app_name.lower()))
self.buildozer.rmdir(intermediate_dir)
self.buildozer.info('Creating archive...')
self.buildozer.cmd((
'/usr/bin/xcrun '
'-sdk iphoneos PackageApplication {ios_app_dir} '
'-o {ipa} --sign {ioscodesign} --embed '
'{ios_app_dir}/embedded.mobileprovision').format(
ioscodesign=ioscodesign, ios_app_dir=ios_app_dir,
mode=mode, ipa=ipa),
cwd=self.ios_dir)
'/usr/bin/xcodebuild'
' -alltargets'
' -configuration {mode}'
' -scheme {scheme}'
' -archivePath "{xcarchive}"'
' archive'
' ENABLE_BITCODE=NO'
).format(mode=mode, xcarchive=xcarchive, scheme=app_name.lower()),
cwd=build_dir)
self.buildozer.info('Creating IPA...')
self.buildozer.cmd((
'/usr/bin/xcodebuild'
' -exportArchive'
' -exportFormat IPA'
' -archivePath "{xcarchive}"'
' -exportPath "{ipa}"'
' CODE_SIGN_IDENTITY={ioscodesign}'
' ENABLE_BITCODE=NO'
).format(xcarchive=xcarchive, ipa=ipa_tmp, ioscodesign=ioscodesign),
cwd=build_dir)
self.buildozer.info('Moving IPA to bin...')
self.buildozer.file_rename(ipa_tmp, ipa)
self.buildozer.info('iOS packaging done!')
self.buildozer.info('IPA {0} available in the bin directory'.format(

View file

@ -47,53 +47,56 @@ class TargetOSX(Target):
check_call(('unzip', 'master.zip'), cwd=platdir)
check_call(('rm', 'master.zip'), cwd=platdir)
def download_kivy(self, cwd, kivy='Kivy2'):
self.buildozer.info('Downloading kivy...')
if not exists(cwd+'/'+kivy+'.7z'):
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(
('curl', '-O', '-L',
'http://kivy.org/downloads/tests/{}.7z'.format(kivy)),
cwd=cwd)
if not exists(cwd+'/Keka.app'):
if exists('/Applications/Keka.app'):
('cp', '-a', '/Applications/Kivy{}.app'.format(py_branch),
'Kivy.app'), cwd=cwd)
else:
if not exists(join(cwd, 'Kivy{}.7z'.format(py_branch))):
self.buildozer.info('Downloading kivy...')
check_call(
('cp', '-a', '/Applications/Keka.app', './Keka.app'),
cwd=cwd)
else:
check_call(('curl', '-o',
'http://www.kekaosx.com/release/Keka-1.0.4-intel.dmg'),
('curl', '-L', '-o', 'Kivy{}.7z'.format(py_branch),
'http://kivy.org/downloads/{}/Kivy-{}-osx-python{}.7z'\
.format(current_kivy_vers, current_kivy_vers, py_branch)),
cwd=cwd)
if not exists(join(cwd, 'Keka.app')):
self.buildozer.info(
'Downloading Keka as dependency (to install Kivy)')
check_call(
('hdiutil', 'attach', 'Keka-1.0.4-intel.dmg'),
('curl', '-O', 'http://www.kekaosx.com/release/Keka-1.0.4-intel.dmg'),
cwd=cwd)
check_call(
('cp', '-a','/Volumes/Keka/Keka.app',
'./Keka.app'), cwd=cwd)
check_call(('hdutil', 'detach', '/Volumes/Keka'))
check_call(
('Keka.app/Contents/Resources/keka7z',
'x', '{}.7z'.format(kivy)), cwd=cwd)
check_call(('rm', '-rf', '{}.7z'.format('Kivy2')), cwd=cwd)
check_call(('mv', '{}.app'.format(kivy), 'Kivy.app'),cwd=cwd)
check_call(('hdiutil', 'attach', 'Keka-1.0.4-intel.dmg'), cwd=cwd)
check_call(('cp', '-a','/Volumes/Keka/Keka.app', './Keka.app'), cwd=cwd)
check_call(('hdiutil', 'detach', '/Volumes/Keka'))
self.buildozer.info('Extracting and installing Kivy...')
check_call(
(join(cwd, 'Keka.app/Contents/MacOS/Keka'),
join(cwd, 'Kivy{}.7z').format(py_branch)), cwd=cwd)
check_call(('rm', 'Kivy{}.7z'.format(py_branch)), cwd=cwd)
check_call(('mv', 'Kivy{}.app'.format(py_branch), 'Kivy.app'),cwd=cwd)
def ensure_kivyapp(self):
self.buildozer.info('check if Kivy.app exists in local dir')
kivy_app_dir = join(
self.buildozer.platform_dir,
'kivy-sdk-packager-master', 'osx')
kivy_app_dir = join(self.buildozer.platform_dir, 'kivy-sdk-packager-master', 'osx')
py_branch = self.buildozer.config.get('app', 'osx.python_version')
if not int(py_branch) in (2, 3):
self.buildozer.error('incompatible python version... aborting')
sys.exit(1)
if exists(join(kivy_app_dir, 'Kivy.app')):
self.buildozer.info('Kivy.app found at ' + kivy_app_dir)
return
# check if Kivy.app exists in /Applications
if not exists('/Applications/Kivy.app'):
self.download_kivy(kivy_app_dir)
return
self.buildozer.info('Kivy.app found at ' + kivy_app_dir)
else:
self.buildozer.info('Kivy.app found at /Applications/Kivy.app')
self.buildozer.info('copying it to platform dir')
check_call(
('cp', '-a', '/Applications/Kivy.app',
join(kivy_app_dir, 'Kivy.app')))
self.download_kivy(kivy_app_dir, py_branch)
return
def check_requirements(self):