def _configure(self, context): if not os.path.exists(self.build_path): shutil.copytree(self.source_path, self.build_path, symlinks=True) try: shutil.rmtree(pj(self.build_path, 'kiwixlib', 'src', 'main')) except FileNotFoundError: pass for arch in option('android_arch'): try: kiwix_builder = get_target_step('kiwix-lib', 'android_{}'.format(arch)) except KeyError: pass else: copy_tree( pj(kiwix_builder.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main')) os.makedirs(pj(self.build_path, 'app', 'src', 'main', 'assets', 'icu'), exist_ok=True) for arch in option('android_arch'): try: kiwix_builder = get_target_step('kiwix-lib', 'android_{}'.format(arch)) except KeyError: pass else: shutil.copy2( pj(kiwix_builder.buildEnv.install_dir, 'share', 'icu', '58.2', 'icudt58l.dat'), pj(self.build_path, 'app', 'src', 'main', 'assets', 'icu', 'icudt58l.dat')) break
def _get_zim_size(self): try: zim_size = option('zim_file_size') except AttributeError: with open(pj(self.source_path, option('android_custom_app'), 'info.json')) as f: app_info = json.load(f) zim_size = os.path.getsize(pj(self.custom_build_path, app_info['zim_file'])) return zim_size
def _download_zim(self, context): zim_url = option('zim_file_url') if zim_url is None: raise SkipCommand() with open(pj(self.source_path, option('android_custom_app'), '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 add_targets(self, targetName, targets): print(targetName) if option('target') == targetName: return super().add_targets(targetName, targets) else: static_platform = self.get_platform('native_static', targets) return static_platform.add_targets(targetName, targets)
def get_dependencies(cls, platformInfo, allDeps): if not allDeps: return super().get_dependencies(platformInfo, allDeps) else: deps = [('android_{}'.format(arch), 'kiwix-lib') for arch in option('android_arch')] return deps
def _configure(self, context): # Copy kiwix-android in build dir. kiwix_android_source = get_target_step('kiwix-android', 'source') if not os.path.exists(self.build_path): shutil.copytree(kiwix_android_source.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 for arch in option('android_arch'): try: kiwix_builder = get_target_step('kiwix-lib', 'android_{}'.format(arch)) except KeyError: pass else: copy_tree(pj(kiwix_builder.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixlib', 'src', 'main')) os.makedirs( pj(self.build_path, 'app', 'src', 'main', 'assets', 'icu'), exist_ok=True) for arch in option('android_arch'): try: kiwix_builder = get_target_step('kiwix-lib', 'android_{}'.format(arch)) except KeyError: pass else: shutil.copy2(pj(kiwix_builder.buildEnv.install_dir, 'share', 'icu', '58.2', 'icudt58l.dat'), pj(self.build_path, 'app', 'src', 'main', 'assets', 'icu', 'icudt58l.dat')) break # 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=option('android_custom_app'), custom_dir=pj(self.build_path, 'custom', option('android_custom_app')) ) run_command(command, self.source_path, context, buildEnv=self.buildEnv)
def configure_option(self): platformInfo = self.buildEnv.platformInfo if platformInfo.build == 'android': return "-DUSE_BUFFER_HEADER=false" if platformInfo.build == 'iOS': return "-Db_bitcode=true" if platformInfo.name == 'native_mixed' and option('target') == 'libzim': return "-Dstatic-linkage=true" return ""
def _git_init(self, context): if option('fast_clone') and self.force_full_clone == False: command = "git clone --depth=1 --branch {} {} {}".format( self.git_ref, self.git_remote, self.source_dir) run_command(command, neutralEnv('source_dir'), context) else: command = "git clone {} {}".format(self.git_remote, self.source_dir) run_command(command, neutralEnv('source_dir'), context) command = "git checkout {}".format(self.git_ref) run_command(command, self.git_path, context)
def _configure(self, context): try: shutil.rmtree(self.build_path) except FileNotFoundError: pass if not os.path.exists(self.build_path): shutil.copytree(pj(self.source_path, 'android-kiwix-lib-publisher'), self.build_path, symlinks=True) for arch in option('android_arch'): try: kiwix_builder = get_target_step('kiwix-lib', 'android_{}'.format(arch)) except KeyError: pass else: copy_tree(pj(kiwix_builder.buildEnv.install_dir, 'kiwix-lib'), pj(self.build_path, 'kiwixLibAndroid', 'src', 'main'))
def run_command(command, cwd, context, *, env=None, input=None): os.makedirs(cwd, exist_ok=True) if env is None: env = Defaultdict(str, os.environ) log = None try: if not option('verbose'): log = open(context.log_file, 'w') print("run command '{}'".format(command), file=log) print("current directory is '{}'".format(cwd), file=log) print("env is :", file=log) for k, v in env.items(): print(" {} : {!r}".format(k, v), file=log) if log: log.flush() kwargs = dict() if input: kwargs['stdin'] = subprocess.PIPE process = subprocess.Popen(command, shell=True, cwd=cwd, env=env, stdout=log or sys.stdout, stderr=subprocess.STDOUT, **kwargs) if input: input = input.encode() while True: try: if input is None: process.wait(timeout=30) else: process.communicate(input, timeout=30) except subprocess.TimeoutExpired: # Either `wait` timeout (and `input` is None) or # `communicate` timeout (and we must set `input` to None # to not communicate again). input = None print('.', end='', flush=True) else: break if process.returncode: raise subprocess.CalledProcessError(process.returncode, command) finally: if log: log.close()
def _merge_libs(self, context): lib_dirs = [] for arch in option('ios_arch'): plt = PlatformInfo.get_platform('iOS_{}'.format(arch)) lib_dirs.append(pj(plt.buildEnv.install_dir, 'lib')) libs = [] for f in os.listdir(lib_dirs[0]): if os.path.islink(pj(lib_dirs[0], f)): continue if f.endswith('.a') or f.endswith('.dylib'): libs.append(f) os.makedirs(pj(self.buildEnv.install_dir, 'lib'), exist_ok=True) command_tmp = "lipo -create {input} -output {output}" for l in libs: command = command_tmp.format( input=" ".join(pj(d, l) for d in lib_dirs), output=pj(self.buildEnv.install_dir, 'lib', l)) run_command(command, self.buildEnv.install_dir, context)
def download_remote(what, where): file_path = pj(where, what.name) file_url = what.url or (REMOTE_PREFIX + what.name) if os.path.exists(file_path): if what.sha256 == get_sha256(file_path): raise SkipCommand() os.remove(file_path) if option('no_cert_check'): context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE else: context = None batch_size = 1024 * 8 extra_args = {'context': context} if sys.version_info >= (3, 4, 3) else {} progress_chars = "/-\|" try: with urllib.request.urlopen(file_url, **extra_args) as resource, open( file_path, 'wb') as file: tsize = resource.info().get('Content-Length', None) if tsize is not None: tsize = int(tsize) current = 0 while True: batch = resource.read(batch_size) if not batch: break if tsize: current += batch_size print_progress("{:.2%}".format(current / tsize)) else: print_progress(progress_chars[current]) current = (current + 1) % 4 file.write(batch) except urllib.error.URLError as e: print("Cannot download url {}:\n{}".format(file_url, e.reason)) raise StopBuild() if not what.sha256: print('Sha256 for {} not set, do no verify download'.format(what.name)) elif what.sha256 != get_sha256(file_path): os.remove(file_path) raise StopBuild()
def run_command(command, cwd, context, buildEnv=None, env=None, input=None, cross_env_only=False): os.makedirs(cwd, exist_ok=True) if env is None: env = Defaultdict(str, os.environ) if buildEnv is not None: cross_compile_env = True cross_compile_compiler = True cross_compile_path = True if context.force_native_build: cross_compile_env = False cross_compile_compiler = False cross_compile_path = False if cross_env_only: cross_compile_compiler = False env = buildEnv._set_env(env, cross_compile_env, cross_compile_compiler, cross_compile_path) log = None try: if not option('verbose'): log = open(context.log_file, 'w') print("run command '{}'".format(command), file=log) print("current directory is '{}'".format(cwd), file=log) print("env is :", file=log) for k, v in env.items(): print(" {} : {!r}".format(k, v), file=log) kwargs = dict() if input: kwargs['stdin'] = subprocess.PIPE process = subprocess.Popen(command, shell=True, cwd=cwd, env=env, stdout=log or sys.stdout, stderr=subprocess.STDOUT, **kwargs) if input: process.communicate(input.encode()) retcode = process.wait() if retcode: raise subprocess.CalledProcessError(retcode, command) finally: if log: log.close()
def source_dir(self): if option('make_release'): return "{}_release".format(self.git_dir) else: return self.git_dir
def subPlatformNames(self): return ['android_{}'.format(arch) for arch in option('android_arch')]
def build_path(self): return pj(self.buildEnv.build_dir, "{}_{}".format(self.target.full_name(), option('android_custom_app')))
def custom_build_path(self): return pj(self.build_path, 'custom', option('android_custom_app'))
def subPlatformNames(self): return ['iOS_{}'.format(arch) for arch in option('ios_arch')]
def print_progress(progress): if option('show_progress'): text = "{}\033[{}D".format(progress, len(progress)) print(text, end="")
def get_fully_qualified_dep(self, dep): if isinstance(dep, tuple): return dep if option('target') == dep: return 'native_mixed', dep return 'native_static', dep
def get_dependencies(self, platfomInfo, alldeps): base_target = option('target') return [('iOS_{}'.format(arch), base_target) for arch in option('ios_arch')]
def _copy_headers(self, context): plt = PlatformInfo.get_platform('iOS_{}'.format( option('ios_arch')[0])) include_src = pj(plt.buildEnv.install_dir, 'include') include_dst = pj(self.buildEnv.install_dir, 'include') copy_tree(include_src, include_dst)
def gradle_target(self): return "assemble{}".format(option('android_custom_app'))
def build_type(self): return 'release' if option('make_release') else 'debug'
def git_ref(self): if option('make_release'): return self.release_git_ref else: return self.base_git_ref
def version(cls): if cls.name in base_deps_versions: return base_deps_versions[cls.name] elif option('make_release'): return main_project_versions.get(cls.name, None) return None
def build(self): if option('target') == 'kiwix-android-custom': print("SKIP") else: super().build()
def strip_option(self): return '--strip' if option('make_release') else ''
def __init__(self, buildEnv): super().__init__(buildEnv) self.custom_name = option('android_custom_app')