Merge pull request #43 from kiwix/android_custom_apk
Android custom apk
This commit is contained in:
commit
4a980a3192
|
@ -1,4 +1,5 @@
|
||||||
import shutil,os
|
import shutil, os, json
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from dependency_utils import (
|
from dependency_utils import (
|
||||||
Dependency,
|
Dependency,
|
||||||
|
@ -357,5 +358,83 @@ class KiwixAndroid(Dependency):
|
||||||
def _configure(self, context):
|
def _configure(self, context):
|
||||||
if not os.path.exists(self.build_path):
|
if not os.path.exists(self.build_path):
|
||||||
shutil.copytree(self.source_path, self.build_path)
|
shutil.copytree(self.source_path, self.build_path)
|
||||||
shutil.rmtree(pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
try:
|
||||||
|
shutil.rmtree(pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
shutil.copytree(pj(self.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
shutil.copytree(pj(self.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
||||||
|
|
||||||
|
|
||||||
|
class KiwixCustomApp(Dependency):
|
||||||
|
name = "kiwix-android-custom"
|
||||||
|
dependencies = ["kiwix-android", "kiwix-lib"]
|
||||||
|
|
||||||
|
def __init__(self, buildEnv):
|
||||||
|
super().__init__(buildEnv)
|
||||||
|
self.custom_name = buildEnv.options.android_custom_app
|
||||||
|
|
||||||
|
class Source(GitClone):
|
||||||
|
git_remote = "https://github.com/kiwix/kiwix-android-custom"
|
||||||
|
git_dir = "kiwix-android-custom"
|
||||||
|
|
||||||
|
class Builder(GradleBuilder):
|
||||||
|
@property
|
||||||
|
def gradle_target(self):
|
||||||
|
return "assemble{}".format(self.target.custom_name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gradle_option(self):
|
||||||
|
return "-i -P customDir={}".format(pj(self.build_path, 'custom'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def build_path(self):
|
||||||
|
return pj(self.buildEnv.build_dir, "{}_{}".format(self.target.full_name, self.target.custom_name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def custom_build_path(self):
|
||||||
|
return pj(self.build_path, 'custom', self.target.custom_name)
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
self.command('configure', self._configure)
|
||||||
|
self.command('download_zim', self._download_zim)
|
||||||
|
self.command('compile', self._compile)
|
||||||
|
|
||||||
|
def _download_zim(self, context):
|
||||||
|
zim_url = self.buildEnv.options.zim_file_url
|
||||||
|
if zim_url is None:
|
||||||
|
raise SkipCommand()
|
||||||
|
with open(pj(self.source_path, self.target.custom_name, 'info.json')) as f:
|
||||||
|
app_info = json.load(f)
|
||||||
|
zim_url = app_info.get('zim_url', zim_url)
|
||||||
|
out_filename = urlparse(zim_url).path
|
||||||
|
out_filename = os.path.basename(out_filename)
|
||||||
|
zim_file = Remotefile(out_filename, '', zim_url)
|
||||||
|
self.buildEnv.download(zim_file)
|
||||||
|
shutil.copy(pj(self.buildEnv.archive_dir, out_filename),
|
||||||
|
pj(self.custom_build_path, app_info['zim_file']))
|
||||||
|
|
||||||
|
def _configure(self, context):
|
||||||
|
# Copy kiwix-android in build dir.
|
||||||
|
kiwix_android_dep = self.buildEnv.targetsDict['kiwix-android']
|
||||||
|
if not os.path.exists(self.build_path):
|
||||||
|
shutil.copytree(kiwix_android_dep.source_path, self.build_path)
|
||||||
|
|
||||||
|
# Copy kiwix-lib application in build dir
|
||||||
|
try:
|
||||||
|
shutil.rmtree(pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
shutil.copytree(pj(self.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main'))
|
||||||
|
|
||||||
|
# Generate custom directory
|
||||||
|
try:
|
||||||
|
shutil.rmtree(pj(self.build_path, 'custom'))
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
os.makedirs(pj(self.build_path, 'custom'))
|
||||||
|
command = "./gen-custom-android-directory.py {custom_name} --output-dir {custom_dir}"
|
||||||
|
command = command.format(
|
||||||
|
custom_name=self.target.custom_name,
|
||||||
|
custom_dir=pj(self.build_path, 'custom', self.target.custom_name)
|
||||||
|
)
|
||||||
|
self.buildEnv.run_command(command, self.source_path, context)
|
||||||
|
|
|
@ -308,12 +308,14 @@ class MesonBuilder(Builder):
|
||||||
|
|
||||||
|
|
||||||
class GradleBuilder(Builder):
|
class GradleBuilder(Builder):
|
||||||
|
gradle_target = "build"
|
||||||
|
gradle_option = "-i"
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.command('configure', self._configure)
|
self.command('configure', self._configure)
|
||||||
if hasattr(self, '_pre_compile_script'):
|
if hasattr(self, '_pre_compile_script'):
|
||||||
self.command('pre_compile_script', self._pre_compile_script)
|
self.command('pre_compile_script', self._pre_compile_script)
|
||||||
self.command('compile', self._compile)
|
self.command('compile', self._compile)
|
||||||
self.command('install', self._install)
|
|
||||||
|
|
||||||
def _configure(self, context):
|
def _configure(self, context):
|
||||||
# We don't have a lot to configure by itself
|
# We don't have a lot to configure by itself
|
||||||
|
@ -323,10 +325,8 @@ class GradleBuilder(Builder):
|
||||||
shutil.copytree(self.source_path, self.build_path)
|
shutil.copytree(self.source_path, self.build_path)
|
||||||
|
|
||||||
def _compile(self, context):
|
def _compile(self, context):
|
||||||
command = "gradle clean assemble --info"
|
command = "gradle {gradle_target} {gradle_option}"
|
||||||
|
command = command.format(
|
||||||
|
gradle_target=self.gradle_target,
|
||||||
|
gradle_option=self.gradle_option)
|
||||||
self.buildEnv.run_command(command, self.build_path, context)
|
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
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ from utils import (
|
||||||
remove_duplicates,
|
remove_duplicates,
|
||||||
add_execution_right,
|
add_execution_right,
|
||||||
get_sha256,
|
get_sha256,
|
||||||
|
print_status,
|
||||||
StopBuild,
|
StopBuild,
|
||||||
SkipCommand,
|
SkipCommand,
|
||||||
Defaultdict,
|
Defaultdict,
|
||||||
|
@ -440,11 +441,22 @@ class BuildEnv:
|
||||||
context = None
|
context = None
|
||||||
batch_size = 1024 * 8
|
batch_size = 1024 * 8
|
||||||
extra_args = {'context':context} if sys.version_info >= (3, 4, 3) else {}
|
extra_args = {'context':context} if sys.version_info >= (3, 4, 3) else {}
|
||||||
|
progress_chars = "/-\|"
|
||||||
with urllib.request.urlopen(file_url, **extra_args) as resource, open(file_path, 'wb') as file:
|
with urllib.request.urlopen(file_url, **extra_args) as resource, open(file_path, 'wb') as file:
|
||||||
|
tsize = resource.getheader('Content-Length', None)
|
||||||
|
if tsize is not None:
|
||||||
|
tsize = int(tsize)
|
||||||
|
current = 0
|
||||||
while True:
|
while True:
|
||||||
batch = resource.read(batch_size)
|
batch = resource.read(batch_size)
|
||||||
if not batch:
|
if not batch:
|
||||||
break
|
break
|
||||||
|
if tsize:
|
||||||
|
current += batch_size
|
||||||
|
print_status("{:.2%}".format(current/tsize))
|
||||||
|
else:
|
||||||
|
print_status(progress_chars[current])
|
||||||
|
current = (current+1)%4
|
||||||
file.write(batch)
|
file.write(batch)
|
||||||
|
|
||||||
if not what.sha256:
|
if not what.sha256:
|
||||||
|
@ -921,7 +933,20 @@ def parse_args():
|
||||||
parser.add_argument('--clean-at-end', action='store_true',
|
parser.add_argument('--clean-at-end', action='store_true',
|
||||||
help="Clean all intermediate files after the (successfull) build")
|
help="Clean all intermediate files after the (successfull) build")
|
||||||
|
|
||||||
return parser.parse_args()
|
subgroup = parser.add_argument_group('custom app',
|
||||||
|
description="Android custom app specific options")
|
||||||
|
subgroup.add_argument('--android-custom-app',
|
||||||
|
help="The custom android app to build")
|
||||||
|
subgroup.add_argument('--zim-file-url',
|
||||||
|
help="The url of the zim file to download")
|
||||||
|
options = parser.parse_args()
|
||||||
|
|
||||||
|
if options.targets == 'kiwix-android-custom':
|
||||||
|
if not options.android_custom_app or not options.zim_file_url:
|
||||||
|
print("You need to specify ANDROID_CUSTOM_APP and ZIM_FILE_URL if "
|
||||||
|
"want to build a kiwix-android-custom target")
|
||||||
|
sys.exit(1)
|
||||||
|
return options
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
14
utils.py
14
utils.py
|
@ -27,11 +27,23 @@ def remove_duplicates(iterable, key_function=None):
|
||||||
|
|
||||||
|
|
||||||
def get_sha256(path):
|
def get_sha256(path):
|
||||||
|
progress_chars = "/-\|"
|
||||||
|
current = 0
|
||||||
|
batch_size = 1024 * 8
|
||||||
sha256 = hashlib.sha256()
|
sha256 = hashlib.sha256()
|
||||||
with open(path, 'br') as f:
|
with open(path, 'br') as f:
|
||||||
sha256.update(f.read())
|
while True:
|
||||||
|
batch = f.read(batch_size)
|
||||||
|
if not batch:
|
||||||
|
break
|
||||||
|
sha256.update(batch)
|
||||||
|
print_status(progress_chars[current])
|
||||||
|
current = (current+1)%4
|
||||||
return sha256.hexdigest()
|
return sha256.hexdigest()
|
||||||
|
|
||||||
|
def print_status(status):
|
||||||
|
text = "{}\033[{}D".format(status, len(status))
|
||||||
|
print(text, end="")
|
||||||
|
|
||||||
def add_execution_right(file_path):
|
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)
|
||||||
|
|
Loading…
Reference in New Issue