chiark / gitweb /
Added a method to build python/kivy projects using buildozer.
authorlb@lb520 <lb@lb520>
Tue, 20 Jun 2017 12:16:31 +0000 (14:16 +0200)
committerlb@lb520 <lb@lb520>
Tue, 20 Jun 2017 12:16:31 +0000 (14:16 +0200)
fdroidserver/build.py
fdroidserver/metadata.py

index f2fbad046e68e64216b657803a1d1c3f87cf07e0..59c25eaa06aa1bdbae4f62a2544e7585a5910c9e 100644 (file)
@@ -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 [
index 6ca9aace4ab13797592332b56bb5163ba65da162..0c9d4831c596078ba24aee2fe1061d60a416ad6c 100644 (file)
@@ -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'