From 230286786f580a21681c9ac1addfef3e33055bb6 Mon Sep 17 00:00:00 2001 From: "lb@lb520" Date: Tue, 20 Jun 2017 14:16:31 +0200 Subject: [PATCH] Added a method to build python/kivy projects using buildozer. --- fdroidserver/build.py | 91 ++++++++++++++++++++++++++++++++++++++++ fdroidserver/metadata.py | 6 ++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/fdroidserver/build.py b/fdroidserver/build.py index f2fbad04..59c25eaa 100644 --- a/fdroidserver/build.py +++ b/fdroidserver/build.py @@ -451,6 +451,9 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext elif bmethod == 'kivy': pass + elif bmethod == 'buildozer': + pass + elif bmethod == 'ant': logging.info("Cleaning Ant project...") p = FDroidPopen(['ant', 'clean'], cwd=root_dir) @@ -645,6 +648,73 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext cmd.append('release') p = FDroidPopen(cmd, cwd=distdir) + elif bmethod == 'buildozer': + logging.info("Building Kivy project using buildozer...") + + # parse buildozer.spez + spec = os.path.join(root_dir, 'buildozer.spec') + if not os.path.exists(spec): + raise BuildException("Expected to find buildozer-compatible spec at {0}" + .format(spec)) + defaults = {'orientation': 'landscape', 'icon': '', + 'permissions': '', 'android.api': "19" } + bconfig = ConfigParser(defaults, allow_no_value=True) + bconfig.read(spec) + + # update spec with sdk and ndk locations to prevent buildozer from + # downloading. + loc_ndk = common.env['ANDROID_NDK'] + loc_sdk = common.env['ANDROID_SDK'] + if loc_ndk == '$ANDROID_NDK': + loc_ndk = loc_sdk+'/ndk-bundle' + + bc_ndk = None + bc_sdk = None + try: + bc_ndk = bconfig.get('app','android.sdk_path') + except: + pass + try: + bc_sdk = bconfig.get('app','android.ndk_path') + except: + pass + + if bc_sdk is None: + bconfig.set('app','android.sdk_path',loc_sdk) + if bc_ndk is None: + bconfig.set('app','android.ndk_path',loc_ndk) + + fspec = open(spec,'w') + bconfig.write(fspec) + fspec.close() + + logging.info("sdk_path = %s" % loc_sdk) + logging.info("ndk_path = %s" % loc_ndk) + + p = None + # execute buildozer + cmd = ['buildozer','android','release'] + try: + p = FDroidPopen(cmd, cwd=root_dir) + except: + pass + + # buidozer not installed ? clone repo and run + if (p is None or p.returncode!=0): + cmd = ['git','clone','https://github.com/kivy/buildozer.git'] + p = subprocess.Popen(cmd, cwd=root_dir, shell=False) + p.wait() + if p.returncode != 0: + raise BuildException("Distribute build failed") + + cmd = ['python','buildozer/buildozer/scripts/client.py','android','release'] + p = FDroidPopen(cmd, cwd=root_dir) + + # expected to fail. + # Signing will fail if not set by environnment vars (cf. p4a docs). + # But the unsigned apk will be ok. + p.returncode = 0 + elif bmethod == 'gradle': logging.info("Building Gradle project...") @@ -697,6 +767,27 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext '{0}-{1}-release.apk'.format( bconfig.get('app', 'title'), bconfig.get('app', 'version'))) + + elif omethod == 'buildozer': + src = None + for apks_dir in [ + os.path.join(root_dir, '.buildozer', 'android', 'platform', 'build', 'dists', bconfig.get('app', 'title'), 'bin'), + ]: + for apkglob in ['*-release-unsigned.apk', '*-unsigned.apk', '*.apk']: + apks = glob.glob(os.path.join(apks_dir, apkglob)) + + if len(apks) > 1: + raise BuildException('More than one resulting apks found in %s' % apks_dir, + '\n'.join(apks)) + if len(apks) == 1: + src = apks[0] + break + if src is not None: + break + + if src is None: + raise BuildException('Failed to find any output apks') + elif omethod == 'gradle': src = None for apks_dir in [ diff --git a/fdroidserver/metadata.py b/fdroidserver/metadata.py index 6ca9aace..0c9d4831 100644 --- a/fdroidserver/metadata.py +++ b/fdroidserver/metadata.py @@ -209,6 +209,7 @@ build_flags_order = [ 'gradle', 'maven', 'kivy', + 'buildozer', 'output', 'srclibs', 'oldsdkloc', @@ -249,6 +250,7 @@ class Build(dict): self.gradle = [] self.maven = False self.kivy = False + self.buildozer = False self.output = None self.srclibs = [] self.oldsdkloc = False @@ -289,7 +291,7 @@ class Build(dict): raise AttributeError("No such attribute: " + name) def build_method(self): - for f in ['maven', 'gradle', 'kivy']: + for f in ['maven', 'gradle', 'kivy', 'buildozer']: if self.get(f): return f if self.output: @@ -300,7 +302,7 @@ class Build(dict): def output_method(self): if self.output: return 'raw' - for f in ['maven', 'gradle', 'kivy']: + for f in ['maven', 'gradle', 'kivy', 'buildozer']: if self.get(f): return f return 'ant'