Allow kiwix-build to build android APK.

Previous script (from kiwix repository) created a APK with all architecture embeded.
Now, we generated a APK per architecture. It simplify the build process and
generate smaller APKs.
This commit is contained in:
Matthieu Gautier 2017-03-08 10:31:00 +01:00
parent 56862b09d6
commit 86c1547f88
6 changed files with 140 additions and 8 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ ARCHIVE
BUILD_* BUILD_*
LOGS LOGS
SOURCE SOURCE
TOOLCHAINS

View File

@ -1,4 +1,4 @@
import shutil import shutil,os
from dependency_utils import ( from dependency_utils import (
Dependency, Dependency,
@ -6,9 +6,11 @@ from dependency_utils import (
GitClone, GitClone,
MakeBuilder, MakeBuilder,
CMakeBuilder, CMakeBuilder,
MesonBuilder) MesonBuilder,
GradleBuilder,
Builder as BaseBuilder)
from utils import Remotefile, pj, SkipCommand from utils import Remotefile, pj, SkipCommand, copy_tree, add_execution_right
# ************************************* # *************************************
# Missing dependencies # Missing dependencies
@ -318,3 +320,42 @@ class KiwixTools(Dependency):
if self.buildEnv.platform_info.static: if self.buildEnv.platform_info.static:
return "-Dstatic-linkage=true" return "-Dstatic-linkage=true"
return "" return ""
class Gradle(Dependency):
name = "Gradle"
version = "3.4"
class Source(ReleaseDownload):
archive = Remotefile('gradle-3.4-bin.zip',
'72d0cd4dcdd5e3be165eb7cd7bbd25cf8968baf400323d9ab1bba622c3f72205',
'https://services.gradle.org/distributions/gradle-3.4-bin.zip')
class Builder(BaseBuilder):
def build(self):
self.command('install', self._install)
def _install(self, context):
copy_tree(
pj(self.source_path, "bin"),
pj(self.buildEnv.install_dir, "bin"),
post_copy_function = add_execution_right)
copy_tree(
pj(self.source_path, "lib"),
pj(self.buildEnv.install_dir, "lib"))
class KiwixAndroid(Dependency):
name = "kiwix-android"
dependencies = ["Gradle", "kiwix-lib"]
class Source(GitClone):
git_remote = "https://github.com/kiwix/kiwix-android"
git_dir = "kiwix-android"
class Builder(GradleBuilder):
def _configure(self, context):
if not os.path.exists(self.build_path):
shutil.copytree(self.source_path, self.build_path)
shutil.rmtree(pj(self.build_path, 'kiwixlib', 'src', 'main'))
shutil.copytree(pj(self.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main'))

View File

@ -305,3 +305,28 @@ class MesonBuilder(Builder):
def _install(self, context): def _install(self, context):
command = "{} -v install".format(self.buildEnv.ninja_command) command = "{} -v install".format(self.buildEnv.ninja_command)
self.buildEnv.run_command(command, self.build_path, context) self.buildEnv.run_command(command, self.build_path, context)
class GradleBuilder(Builder):
def build(self):
self.command('configure', self._configure)
if hasattr(self, '_pre_compile_script'):
self.command('pre_compile_script', self._pre_compile_script)
self.command('compile', self._compile)
self.command('install', self._install)
def _configure(self, context):
# We don't have a lot to configure by itself
context.try_skip(self.build_path)
if os.path.exists(self.build_path):
shutil.rmtree(self.build_path)
shutil.copytree(self.source_path, self.build_path)
def _compile(self, context):
command = "gradle clean assemble --info"
self.buildEnv.run_command(command, self.build_path, context)
command = "gradle build --info"
self.buildEnv.run_command(command, self.build_path, context)
def _install(self, context):
pass

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os, sys import os, sys, shutil
import argparse import argparse
import ssl import ssl
import urllib.request import urllib.request
@ -39,7 +39,7 @@ CROSS_ENV = {
} }
}, },
'fedora_android': { 'fedora_android': {
'toolchain_names': ['android_ndk'], 'toolchain_names': ['android_ndk', 'android_sdk'],
'extra_libs': [], 'extra_libs': [],
'extra_cflags': [], 'extra_cflags': [],
'host_machine': { 'host_machine': {
@ -62,7 +62,7 @@ CROSS_ENV = {
} }
}, },
'debian_android': { 'debian_android': {
'toolchain_names': ['android_ndk'], 'toolchain_names': ['android_ndk', 'android_sdk'],
'extra_libs': [], 'extra_libs': [],
'extra_cflags': [], 'extra_cflags': [],
'host_machine': { 'host_machine': {
@ -190,11 +190,13 @@ class BuildEnv:
build_dir = "BUILD_{}".format(options.target_platform) build_dir = "BUILD_{}".format(options.target_platform)
self.build_dir = pj(options.working_dir, build_dir) self.build_dir = pj(options.working_dir, build_dir)
self.archive_dir = pj(options.working_dir, "ARCHIVE") self.archive_dir = pj(options.working_dir, "ARCHIVE")
self.toolchain_dir = pj(options.working_dir, "TOOLCHAINS")
self.log_dir = pj(self.build_dir, 'LOGS') self.log_dir = pj(self.build_dir, 'LOGS')
self.install_dir = pj(self.build_dir, "INSTALL") self.install_dir = pj(self.build_dir, "INSTALL")
for d in (self.source_dir, for d in (self.source_dir,
self.build_dir, self.build_dir,
self.archive_dir, self.archive_dir,
self.toolchain_dir,
self.log_dir, self.log_dir,
self.install_dir): self.install_dir):
os.makedirs(d, exist_ok=True) os.makedirs(d, exist_ok=True)
@ -717,6 +719,56 @@ class android_ndk(Toolchain):
env['NDK_DEBUG'] = '0' env['NDK_DEBUG'] = '0'
class android_sdk(Toolchain):
name = 'android-sdk'
version = 'r25.2.3'
class Source(ReleaseDownload):
archive = Remotefile('tools_r25.2.3-linux.zip',
'1b35bcb94e9a686dff6460c8bca903aa0281c6696001067f34ec00093145b560',
'https://dl.google.com/android/repository/tools_r25.2.3-linux.zip')
class Builder(Builder):
@property
def install_path(self):
return pj(self.buildEnv.toolchain_dir, self.target.full_name)
def _build_platform(self, context):
context.try_skip(self.install_path)
tools_dir = pj(self.install_path, 'tools')
shutil.copytree(self.source_path, tools_dir)
script = pj(tools_dir, 'android')
command = '{script} --verbose update sdk -a --no-ui --filter {packages}'
command = command.format(
script=script,
packages = ','.join(str(i) for i in [1,2,8,34,162])
)
# packages correspond to :
# - 1 : Android SDK Tools, revision 25.2.5
# - 2 : Android SDK Platform-tools, revision 25.0.3
# - 8 : Android SDK Build-tools, revision 24.0.1
# - 34 : SDK Platform Android 7.0, API 24, revision 2
# - 162 : Android Support Repository, revision 44
self.buildEnv.run_command(command, self.install_path, context, input="y\n")
def _fix_licenses(self, context):
context.try_skip(self.install_path)
os.makedirs(pj(self.install_path, 'licenses'), exist_ok=True)
with open(pj(self.install_path, 'licenses', 'android-sdk-license'), 'w') as f:
f.write("\n8933bad161af4178b1185d1a37fbf41ea5269c55")
def build(self):
self.command('build_platform', self._build_platform)
self.command('fix_licenses', self._fix_licenses)
def get_bin_dir(self):
return []
def set_env(self, env):
env['ANDROID_HOME'] = self.builder.install_path
class Builder: class Builder:
def __init__(self, options): def __init__(self, options):
self.options = options self.options = options

View File

@ -14,7 +14,7 @@ if [[ "$TRAVIS_EVENT_TYPE" = "cron" ]]
then then
if [[ ${PLATFORM} = android* ]] if [[ ${PLATFORM} = android* ]]
then then
TARGETS="libzim kiwix-lib" TARGETS="libzim kiwix-lib kiwix-android"
else else
TARGETS="libzim kiwix-lib kiwix-tools" TARGETS="libzim kiwix-lib kiwix-tools"
fi fi
@ -77,7 +77,7 @@ else
# No a cron job, we just have to build to be sure nothing is broken. # No a cron job, we just have to build to be sure nothing is broken.
if [[ ${PLATFORM} = android* ]] if [[ ${PLATFORM} = android* ]]
then then
TARGET=kiwix-lib TARGET=kiwix-android
else else
TARGET=kiwix-tools TARGET=kiwix-tools
fi fi

View File

@ -2,6 +2,7 @@ import os.path
import hashlib import hashlib
import tarfile, zipfile import tarfile, zipfile
import tempfile import tempfile
import shutil
import os, stat import os, stat
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
@ -36,6 +37,18 @@ def add_execution_right(file_path):
current_permissions = stat.S_IMODE(os.lstat(file_path).st_mode) current_permissions = stat.S_IMODE(os.lstat(file_path).st_mode)
os.chmod(file_path, current_permissions | stat.S_IXUSR) os.chmod(file_path, current_permissions | stat.S_IXUSR)
def copy_tree(src, dst, post_copy_function=None):
os.makedirs(dst, exist_ok=True)
for root, dirs, files in os.walk(src):
r = os.path.relpath(root, src)
dstdir = pj(dst, r)
os.makedirs(dstdir, exist_ok=True)
for f in files:
dstfile = pj(dstdir, f)
shutil.copy2(pj(root, f), dstfile)
if post_copy_function is not None:
post_copy_function(dstfile)
class SkipCommand(Exception): class SkipCommand(Exception):
pass pass