Move from target logic to steps logic.

This is the big change !!!!

Instead of handling target as primary object and prepare/build targets,
we are handling build steps.

A build step may be a source (preparation) or a build (of the source).
Actualy, a step is a tuple (context, Builder or Source).

The context define the context of the step. It can be :
- 'source', for a Source step
- 'neutral' or the name of a platform for Build step.

Target becomes a "Class only" class.
This commit is contained in:
Matthieu Gautier 2018-05-28 15:42:30 +02:00
parent 754df8df1d
commit 041826d0e8
17 changed files with 393 additions and 233 deletions

View File

@ -1,4 +1,8 @@
from collections import OrderedDict as _OrderedDict
_neutralEnv = None
_target_steps = _OrderedDict()
_plt_steps = _OrderedDict()
def set_neutralEnv(env):
global _neutralEnv
@ -6,3 +10,29 @@ def set_neutralEnv(env):
def neutralEnv(what):
return getattr(_neutralEnv, what)
def add_target_step(key, what):
_target_steps[key] = what
def get_target_step(key, default_context=None):
try:
context, target = key
except ValueError:
context, target = default_context, key
return _target_steps[(context, target)]
def target_steps():
return _target_steps
def add_plt_step(key, what):
_plt_steps[key] = what
def get_plt_step(key, default_context=None):
try:
context, target = key
except ValueError:
context, target = default_context, key
return _plt_steps[(context, target)]
def plt_steps():
return _plt_steps

View File

@ -76,17 +76,18 @@ class PlatformNeutralEnv:
class BuildEnv:
def __init__(self, platformInfo, targetsDict):
def __init__(self, platformInfo):
build_dir = "BUILD_{}".format(platformInfo.name)
self.platformInfo = platformInfo
self.build_dir = pj(neutralEnv('working_dir'), build_dir)
self.install_dir = pj(self.build_dir, "INSTALL")
self.log_dir = pj(self.build_dir, 'LOGS')
for d in (self.build_dir,
self.install_dir):
self.install_dir,
self.log_dir):
os.makedirs(d, exist_ok=True)
self.libprefix = neutralEnv('libprefix') or self._detect_libdir()
self.targetsDict = targetsDict
def clean_intermediate_directories(self):
for subdir in os.listdir(self.build_dir):

View File

@ -3,8 +3,14 @@ import sys
from collections import OrderedDict
from .buildenv import *
from .platforms import PlatformInfo
from .utils import remove_duplicates, StopBuild
from .dependencies import Dependency
from ._global import (
neutralEnv,
add_target_step, get_target_step, target_steps,
add_plt_step, get_plt_step, plt_steps)
from . import _global
class Builder:
def __init__(self, options):
@ -15,78 +21,115 @@ class Builder:
'Select another target platform, or change your host system.'
).format(options.target_platform, self.distname))
sys.exit(-1)
self.targets = OrderedDict()
self.platform = platform = platformClass(self.targets)
self.platform = platform = platformClass()
_targets = {}
targetDef = options.targets
targetDef = (options.target_platform, options.targets)
self.add_targets(targetDef, _targets)
dependencies = self.order_dependencies(_targets, targetDef)
dependencies = list(remove_duplicates(dependencies))
if options.build_nodeps:
self.targets[targetDef] = _targets[targetDef]
add_target_step(targetDef, _targets[targetDef])
else:
for dep in dependencies:
if self.options.build_deps_only and dep == targetDef:
continue
self.targets[dep] = _targets[dep]
add_target_step(dep, _targets[dep])
def add_targets(self, targetName, targets):
if targetName in targets:
def add_targets(self, targetDef, targets):
if targetDef in targets:
return
targetPlatformName, targetName = targetDef
targetPlatform = PlatformInfo.all_platforms[targetPlatformName]
targetClass = Dependency.all_deps[targetName]
target = targetClass(self.platform.buildEnv)
targets[targetName] = target
for dep in target.builder.get_dependencies(self.platform):
self.add_targets(dep, targets)
targets[('source', targetName)] = targetClass.Source
targets[targetDef] = targetClass.Builder
for dep in targetClass.Builder.get_dependencies(targetPlatform):
try:
depPlatform, depName = dep
except ValueError:
depPlatform, depName = targetPlatformName, dep
self.add_targets((depPlatform, depName), targets)
def order_dependencies(self, _targets, targetName):
target = _targets[targetName]
for depName in target.builder.dependencies(self.platform):
yield from self.order_dependencies(_targets, depName)
yield targetName
def order_dependencies(self, _targets, targetDef):
targetPlatformName, targetName = targetDef
if targetPlatformName == 'source':
# Do not try to order sources, they will be added as dep by the
# build step two lines later.
return
target = _targets[targetDef]
targetPlatform = PlatformInfo.all_platforms[targetPlatformName]
yield ('source', targetName)
for dep in target.get_dependencies(targetPlatform):
try:
depPlatform, depName = dep
except ValueError:
depPlatform, depName = targetPlatformName, dep
yield from self.order_dependencies(_targets, (depPlatform, depName))
yield targetDef
def prepare_toolchain_sources(self):
tlsourceDefs = (tlDef for tlDef in plt_steps() if tlDef[0]=='source')
for tlsourceDef in tlsourceDefs:
print("prepare sources for toolchain {} :".format(tlsourceDef[1]))
toolchainClass = Toolchain.all_toolchains[tlsourceDef[1]]
source = get_plt_step(tlsourceDef)(toolchainClass)
add_plt_step(tlsourceDef, source)
source.prepare()
def prepare_sources(self):
if self.options.skip_source_prepare:
print("SKIP")
return
toolchain_sources = (tlc.source for tlc in self.platform.buildEnv.toolchains if tlc.source)
for toolchain_source in toolchain_sources:
print("prepare sources for toolchain {} :".format(toolchain_source.name))
toolchain_source.prepare()
sourceDefs = remove_duplicates(tDef for tDef in target_steps() if tDef[0]=='source')
for sourceDef in sourceDefs:
sources = (dep.source for dep in self.targets.values() if not dep.skip)
sources = remove_duplicates(sources, lambda s: s.__class__)
for source in sources:
print("prepare sources {} :".format(source.name))
print("prepare sources {} :".format(sourceDef[1]))
depClass = Dependency.all_deps[sourceDef[1]]
source = get_target_step(sourceDef)(depClass)
add_target_step(sourceDef, source)
source.prepare()
def build(self):
toolchain_builders = (tlc.builder for tlc in self.platform.buildEnv.toolchains if tlc.builder)
for toolchain_builder in toolchain_builders:
print("build toolchain {} :".format(toolchain_builder.name))
toolchain_builder.build()
builders = (dep.builder for dep in self.targets.values() if (dep.builder and not dep.skip))
for builder in builders:
if self.options.make_dist and builder.name == self.options.targets:
continue
print("build {} :".format(builder.name))
def build_toolchains(self):
tlbuilderDefs = (tlDef for tlDef in plt_steps() if tlDef[0] != 'source')
for tlbuilderDef in tlbuilderDefs:
print("build toolchain {} :".format(tlbuilderDef[1]))
toolchainClass = Toolchain.all_toolchains[tlbuilderDef[1]]
source = get_plt_step(tlbuilderDef[1], 'source')
if tlbuilderDef[0] == 'neutral':
env = _global._neutralEnv
else:
env = PlatformInfo.all_running_platforms[tlbuilderDef[0]].buildEnv
builder = get_plt_step(tlbuilderDef)(toolchainClass, source, env)
add_plt_step(tlbuilderDef, builder)
builder.build()
def build(self):
builderDefs = (tDef for tDef in target_steps() if tDef[0] != 'source')
for builderDef in builderDefs:
depClass = Dependency.all_deps[builderDef[1]]
source = get_target_step(builderDef[1], 'source')
env = PlatformInfo.all_running_platforms[builderDef[0]].buildEnv
builder = get_target_step(builderDef)(depClass, source, env)
if self.options.make_dist and builderDef[1] == self.options.targets:
print("make dist {}:".format(builder.name))
builder.make_dist()
continue
print("build {} ({}):".format(builder.name, builderDef[0]))
add_target_step(builderDef, builder)
builder.build()
if self.options.make_dist:
dep = self.targets[self.options.targets]
builder = dep.builder
print("make dist {}:".format(builder.name))
builder.make_dist()
def run(self):
try:
print("[SETUP PLATFORMS]")
self.prepare_toolchain_sources()
self.build_toolchains()
self.platform.finalize_setup()
print("[INSTALL PACKAGES]")
self.platform.install_packages()
self.platform.finalize_setup()
print("[PREPARE]")
self.prepare_sources()
print("[BUILD]")

View File

@ -22,34 +22,51 @@ class Dependency(metaclass=_MetaDependency):
all_deps = {}
force_native_build = False
def __init__(self, buildEnv):
self.buildEnv = buildEnv
self.source = self.Source(self)
self.builder = self.Builder(self)
self.skip = False
@classmethod
def version(cls):
return base_deps_versions.get(cls.name, None)
@classmethod
def full_name(cls):
if cls.version():
return "{}-{}".format(cls.name, cls.version())
return cls.name
class Source:
"""Base Class to the real preparator
A source preparator must install source in the self.source_dir attribute
inside the neutralEnv.source_dir."""
def __init__(self, target):
self.target = target
@property
def version(self):
return base_deps_versions.get(self.name, None)
def name(self):
return self.target.name
@property
def full_name(self):
if self.version:
return "{}-{}".format(self.name, self.version)
return self.name
def source_dir(self):
return self.target.full_name()
@property
def source_path(self):
return pj(neutralEnv('source_dir'), self.source.source_dir)
return pj(neutralEnv('source_dir'), self.source_dir)
@property
def _log_dir(self):
return self.buildEnv.log_dir
return neutralEnv('log_dir')
def _patch(self, context):
context.try_skip(self.source_path)
context.force_native_build = True
for p in self.patches:
with open(pj(SCRIPT_DIR, 'patches', p), 'r') as patch_input:
run_command("patch -p1", self.source_path, context, input=patch_input.read())
def command(self, name, function, *args):
print(" {} {} : ".format(name, self.name), end="", flush=True)
log = pj(self._log_dir, 'cmd_{}_{}.log'.format(name, self.name))
context = Context(name, log, self.force_native_build)
context = Context(name, log, True)
try:
ret = function(*args, context=context)
context._finalise()
@ -70,33 +87,6 @@ class Dependency(metaclass=_MetaDependency):
raise
class Source:
"""Base Class to the real preparator
A source preparator must install source in the self.source_dir attribute
inside the neutralEnv.source_dir."""
def __init__(self, target):
self.target = target
@property
def name(self):
return self.target.name
@property
def source_dir(self):
return self.target.full_name
def _patch(self, context):
source_path = pj(neutralEnv('source_dir'), self.source_dir)
context.try_skip(source_path)
context.force_native_build = True
for p in self.patches:
with open(pj(SCRIPT_DIR, 'patches', p), 'r') as patch_input:
neutralEnv('run_command')("patch -p1", source_path, context, input=patch_input.read())
def command(self, *args, **kwargs):
return self.target.command(*args, **kwargs)
class NoopSource(Source):
def prepare(self):
pass
@ -206,9 +196,10 @@ class Builder:
subsource_dir = None
dependencies = []
def __init__(self, target):
def __init__(self, target, source, buildEnv):
self.target = target
self.buildEnv = target.buildEnv
self.source = source
self.buildEnv = buildEnv
@classmethod
def get_dependencies(cls, platformInfo):
@ -220,17 +211,41 @@ class Builder:
@property
def source_path(self):
base_source_path = self.target.source_path
base_source_path = self.source.source_path
if self.subsource_dir:
return pj(base_source_path, self.subsource_dir)
return base_source_path
@property
def build_path(self):
return pj(self.buildEnv.build_dir, self.target.full_name)
return pj(self.buildEnv.build_dir, self.target.full_name())
def command(self, *args, **kwargs):
return self.target.command(*args, **kwargs)
@property
def _log_dir(self):
return self.buildEnv.log_dir
def command(self, name, function, *args):
print(" {} {} : ".format(name, self.name), end="", flush=True)
log = pj(self._log_dir, 'cmd_{}_{}.log'.format(name, self.name))
context = Context(name, log, self.target.force_native_build)
try:
ret = function(*args, context=context)
context._finalise()
print("OK")
return ret
except SkipCommand:
print("SKIP")
except subprocess.CalledProcessError:
print("ERROR")
try:
with open(log, 'r') as f:
print(f.read())
except:
pass
raise StopBuild()
except:
print("ERROR")
raise
def build(self):
if hasattr(self, '_pre_build_script'):
@ -274,8 +289,8 @@ class MakeBuilder(Builder):
def all_configure_option(self):
option = self.configure_option_template.format(
dep_options=self.configure_option,
static_option=self.static_configure_option if self.buildEnv.platform_info.static else self.dynamic_configure_option,
env_option=self.buildEnv.configure_option if not self.target.force_native_build else "",
static_option=self.static_configure_option if self.buildEnv.platformInfo.static else self.dynamic_configure_option,
env_option=self.buildEnv.platformInfo.configure_option if not self.target.force_native_build else "",
install_dir=self.buildEnv.install_dir,
libdir=pj(self.buildEnv.install_dir, self.buildEnv.libprefix)
)
@ -289,7 +304,7 @@ class MakeBuilder(Builder):
configure_option=self.all_configure_option
)
env = Defaultdict(str, os.environ)
if self.buildEnv.platform_info.static:
if self.buildEnv.platformInfo.static:
env['CFLAGS'] = env['CFLAGS'] + ' -fPIC'
if self.configure_env:
for k in self.configure_env:
@ -342,7 +357,7 @@ class CMakeBuilder(MakeBuilder):
cross_option=cross_option
)
env = Defaultdict(str, os.environ)
if self.buildEnv.platform_info.static:
if self.buildEnv.platformInfo.static:
env['CFLAGS'] = env['CFLAGS'] + ' -fPIC'
if self.configure_env:
for k in self.configure_env:
@ -360,7 +375,7 @@ class MesonBuilder(Builder):
@property
def library_type(self):
return 'static' if self.buildEnv.platform_info.static else 'shared'
return 'static' if self.buildEnv.platformInfo.static else 'shared'
def _configure(self, context):
context.try_skip(self.build_path)
@ -393,9 +408,9 @@ class MesonBuilder(Builder):
run_command(command, self.build_path, context, buildEnv=self.buildEnv)
def _test(self, context):
if ( self.buildEnv.platform_info.build == 'android'
or (self.buildEnv.platform_info.build != 'native'
and not self.buildEnv.platform_info.static)
if ( self.buildEnv.platformInfo.build == 'android'
or (self.buildEnv.platformInfo.build != 'native'
and not self.buildEnv.platformInfo.static)
):
raise SkipCommand()
command = "{} --verbose {}".format(neutralEnv('mesontest_command'), self.test_option)

View File

@ -5,7 +5,7 @@ from .base import (
)
from kiwixbuild.utils import SkipCommand
from kiwixbuild._global import get_target_step
class Icu(Dependency):
name = "icu4c"
@ -54,5 +54,7 @@ class Icu_cross_compile(Icu):
@property
def configure_option(self):
icu_native_dep = self.buildEnv.targetsDict['icu4c_native']
return super().configure_option + " --with-cross-build={} --disable-tools".format(icu_native_dep.builder.build_path)
icu_native_builder = get_target_step('icu4c_native', self.buildEnv.platformInfo.name)
return (super().configure_option
+ " --with-cross-build={} --disable-tools"
).format(icu_native_builder.build_path)

View File

@ -7,6 +7,7 @@ from .base import (
GradleBuilder)
from kiwixbuild.utils import Remotefile, pj, SkipCommand
from kiwixbuild._global import get_target_step
class KiwixCustomApp(Dependency):
name = "kiwix-android-custom"
@ -78,9 +79,9 @@ class KiwixCustomApp(Dependency):
def _configure(self, context):
# Copy kiwix-android in build dir.
kiwix_android_dep = self.buildEnv.targetsDict['kiwix-android']
kiwix_android_source = get_target_step('kiwix-android', 'source')
if not os.path.exists(self.build_path):
shutil.copytree(kiwix_android_dep.source_path, self.build_path)
shutil.copytree(kiwix_android_source.source_path, self.build_path)
# Copy kiwix-lib application in build dir
try:

View File

@ -7,6 +7,7 @@ from .base import (
)
from kiwixbuild.utils import Remotefile, pj, Defaultdict, SkipCommand
from kiwixbuild._global import get_target_step
class LibMagicBase(Dependency):
name = "libmagic"
@ -48,7 +49,7 @@ class LibMagic_cross_compile(LibMagicBase):
make_target=self.make_target,
make_option=self.make_option
)
libmagic_native_dep = self.buildEnv.targetsDict['libmagic_native']
libmagic_native_builder = get_target_step('libmagic_native', self.buildEnv.platformInfo.name)
env = Defaultdict(str, os.environ)
env['PATH'] = ':'.join([pj(libmagic_native_dep.builder.build_path, 'src'), env['PATH']])
env['PATH'] = ':'.join([pj(libmagic_native_builder.build_path, 'src'), env['PATH']])
self.buildEnv.run_command(command, self.build_path, context, env=env)

View File

@ -1,21 +1,13 @@
from .base import PlatformInfo
from kiwixbuild.utils import pj
from kiwixbuild._global import get_plt_step
class AndroidPlatformInfo(PlatformInfo):
__arch_infos = {
'arm' : ('arm-linux-androideabi', 'arm', 'armeabi'),
'arm64': ('aarch64-linux-android', 'aarch64', 'arm64-v8a'),
'mips': ('mipsel-linux-android', 'mipsel', 'mips'),
'mips64': ('mips64el-linux-android', 'mips64el', 'mips64'),
'x86': ('i686-linux-android', 'i686', 'x86'),
'x86_64': ('x86_64-linux-android', 'x86_64', 'x86_64'),
}
def __init__(self, name, arch):
super().__init__(name, 'android', True, ['android_ndk', 'android_sdk'],
hosts=['fedora', 'debian'])
self.arch = arch
self.arch_full, self.cpu, self.abi = self.__arch_infos[arch]
build = 'android'
static = True
toolchain_names = ['android-ndk', 'android-sdk']
compatible_hosts = ['fedora', 'debian']
def __str__(self):
return "android"
@ -35,11 +27,11 @@ class AndroidPlatformInfo(PlatformInfo):
@property
def ndk_builder(self):
return self.toolchains[0].builder
return get_plt_step('android_ndk', self.name)
@property
def sdk_builder(self):
return self.toolchains[1].builder
return get_plt_step('android_sdk', 'neutral')
def get_cross_config(self):
install_path = self.ndk_builder.install_path
@ -77,9 +69,53 @@ class AndroidPlatformInfo(PlatformInfo):
env['NDK_DEBUG'] = '0'
env['ANDROID_HOME'] = self.sdk_builder.install_path
AndroidPlatformInfo('android_arm', 'arm')
AndroidPlatformInfo('android_arm64', 'arm64')
AndroidPlatformInfo('android_mips', 'mips')
AndroidPlatformInfo('android_mips64', 'mips64')
AndroidPlatformInfo('android_x86', 'x86')
AndroidPlatformInfo('android_x86_64', 'x86_64')
def set_compiler(self, env):
binaries = self.binaries(self.ndk_builder.install_path)
env['CC'] = binaries['CC']
env['CXX'] = binaries['CXX']
@property
def configure_option(self):
return '--host={}'.format(self.arch_full)
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile('cmake_android_cross_file.txt')
self.buildEnv.meson_crossfile = self._gen_crossfile('meson_cross_file.txt')
class AndroidArm(AndroidPlatformInfo):
name = 'android_arm'
arch = cpu = 'arm'
arch_full = 'arm-linux-androideabi'
abi = 'armeabi'
class AndroidArm(AndroidPlatformInfo):
name = 'android_arm64'
arch = 'arm64'
arch_full = 'aarch64-linux-android'
cpu = 'aarch64'
abi = 'arm64-v8a'
class AndroidArm(AndroidPlatformInfo):
name = 'android_mips'
arch = abi = 'mips'
arch_full = 'mipsel-linux-android'
cpu = 'mipsel'
class AndroidArm(AndroidPlatformInfo):
name = 'android_mips64'
arch = abi = 'mips64'
arch_full = 'mips64el-linux-android'
cpu = 'mips64el'
class AndroidArm(AndroidPlatformInfo):
name = 'android_x86'
arch = abi = 'x86'
arch_full = 'i686-linux-android'
cpu = 'i686'
class AndroidArm(AndroidPlatformInfo):
name = 'android_x86_64'
arch = cpu = abi = 'x86_64'
arch_full = 'x86_64-linux-android'

View File

@ -1,10 +1,14 @@
from .base import PlatformInfo
from kiwixbuild.utils import pj
from kiwixbuild._global import get_plt_step
class ArmhfPlatformInfo(PlatformInfo):
build = 'armhf'
arch_full = 'arm-linux-gnueabihf'
def __init__(self, name, static):
super().__init__(name, 'armhf', static, ['armhf_toolchain'], ['fedora', 'debian'])
toolchain_names = ['armhf']
compatible_hosts = ['fedora', 'debian']
def get_cross_config(self):
return {
@ -25,7 +29,7 @@ class ArmhfPlatformInfo(PlatformInfo):
@property
def tlc_source(self):
return self.toolchains[0].source
return get_plt_step('armhf', 'source')
@property
def root_path(self):
@ -83,5 +87,10 @@ class ArmhfPlatformInfo(PlatformInfo):
self.buildEnv.cmake_crossfile = self._gen_crossfile('cmake_cross_file.txt')
self.buildEnv.meson_crossfile = self._gen_crossfile('meson_cross_file.txt')
ArmhfPlatformInfo('armhf_dyn', False)
ArmhfPlatformInfo('armhf_static', True)
class ArmhfDyn(ArmhfPlatformInfo):
name = 'armhf_dyn'
static = False
class ArmhfStatic(ArmhfPlatformInfo):
name = 'armhf_static'
static = True

View File

@ -6,20 +6,28 @@ from kiwixbuild.toolchains import Toolchain
from kiwixbuild.packages import PACKAGE_NAME_MAPPERS
from kiwixbuild.utils import pj, remove_duplicates
from kiwixbuild.buildenv import BuildEnv
from kiwixbuild._global import neutralEnv
from kiwixbuild._global import neutralEnv, add_plt_step, target_steps
_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
TEMPLATES_DIR = pj(os.path.dirname(_SCRIPT_DIR), 'templates')
class PlatformInfo:
all_platforms = {}
class _MetaPlatform(type):
def __new__(cls, name, bases, dct):
_class = type.__new__(cls, name, bases, dct)
if name not in ('PlatformInfo', 'MetaPlatformInfo') and 'name' in dct:
dep_name = dct['name']
PlatformInfo.all_platforms[dep_name] = _class
return _class
def __init__(self, name, build, static, toolchains, hosts=None):
self.all_platforms[name] = self
self.build = build
self.static = static
self.toolchains = toolchains
self.compatible_hosts = hosts
class PlatformInfo(metaclass=_MetaPlatform):
all_platforms = {}
all_running_platforms = {}
toolchain_names = []
configure_option = ""
def __init__(self):
self.all_running_platforms[self.name] = self
self.buildEnv = BuildEnv(self)
self.setup_toolchains()
@ -28,9 +36,14 @@ class PlatformInfo:
def setup_toolchains(self):
self.toolchains = {}
for tlc_name in self.toolchains:
for tlc_name in self.toolchain_names:
ToolchainClass = Toolchain.all_toolchains[tlc_name]
self.toolchains[tlc_name] = ToolchainClass()
if ToolchainClass.Source is not None:
add_plt_step(('source', tlc_name), ToolchainClass.Source)
if ToolchainClass.Builder is not None:
plt_name = 'neutral' if ToolchainClass.neutral else self.name
add_plt_step((plt_name, tlc_name), ToolchainClass.Builder)
def get_cross_config(self):
return {}

View File

@ -1,11 +1,13 @@
import os
from .base import PlatformInfo
from kiwixbuild.utils import which
class I586PlatformInfo(PlatformInfo):
build = 'i586'
arch_full = 'i586-linux-gnu'
def __init__(self, name, static):
super().__init__(name, 'i586', static, [], ['fedora', 'debian'])
compatible_hosts = ['fedora', 'debian']
def get_cross_config(self):
return {
@ -52,5 +54,10 @@ class I586PlatformInfo(PlatformInfo):
self.buildEnv.cmake_crossfile = self._gen_crossfile('cmake_i586_cross_file.txt')
self.buildEnv.meson_crossfile = self._gen_crossfile('meson_cross_file.txt')
I586PlatformInfo('i586_dyn', False)
I586PlatformInfo('i586_static', True)
class I586Dyn(I586PlatformInfo):
name = 'i586_dyn'
static = False
class I586Static(I586PlatformInfo):
name = 'i586_static'
static = True

View File

@ -6,18 +6,12 @@ from kiwixbuild.utils import pj, xrun_find
class iOSPlatformInfo(PlatformInfo):
__arch_infos = {
'armv7': ('arm-apple-darwin', 'armv7', 'iphoneos'),
'arm64': ('arm-apple-darwin', 'arm64', 'iphoneos'),
'i386': ('', 'i386', 'iphonesimulator'),
'x86_64': ('', 'x86_64', 'iphonesimulator'),
}
build = 'iOS'
static = True
compatible_hosts = ['Darwin']
def __init__(self, name, arch):
super().__init__(name, 'iOS', True, [],
hosts=['Darwin'])
self.arch = arch
self.arch_full, self.cpu, self.sdk_name = self.__arch_infos[arch]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._root_path = None
@property
@ -81,7 +75,26 @@ class iOSPlatformInfo(PlatformInfo):
env['CXX'] = self.binaries['CXX']
iOSPlatformInfo('iOS_armv7', 'armv7')
iOSPlatformInfo('iOS_arm64', 'arm64')
iOSPlatformInfo('iOS_i386', 'i386')
iOSPlatformInfo('iOS_x86_64', 'x86_64')
class iOSArmv7(iOSPlatformInfo):
name = 'iOS_armv7'
arch = cpu = 'armv7'
arch_full = 'arm-apple-darwin'
sdk_name = 'iphoneos'
class iOSArm64(iOSPlatformInfo):
name = 'iOS_arm64'
arch = cpu = 'arm64'
arch_full = 'arm-apple-darwin'
sdk_name = 'iphoneos'
class iOSi386(iOSPlatformInfo):
name = 'iOS_i386'
arch = cpu = 'i386'
arch_full = ''
sdk_name = 'iphonesimulator'
class iOSx64(iOSPlatformInfo):
name = 'iOS_x86_64'
arch = cpu = 'x86_64'
arch_full = ''
sdk_name = 'iphonesimulator'

View File

@ -2,9 +2,15 @@ from .base import PlatformInfo
class NativePlatformInfo(PlatformInfo):
def __init__(self, name, static, hosts):
super().__init__(name, 'native', static, [], hosts)
build = 'native'
NativePlatformInfo('native_dyn', False, ['fedora', 'debian', 'Darwin'])
NativePlatformInfo('native_static', True, ['fedora', 'debian'])
class NativeDyn(NativePlatformInfo):
name = 'native_dyn'
static = False
compatible_hosts = ['fedora', 'debian', 'Darwin']
class NativeStatic(NativePlatformInfo):
name = 'native_static'
static = True
compatible_hosts = ['fedora', 'debian']

View File

@ -7,9 +7,9 @@ from kiwixbuild._global import neutralEnv
class Win32PlatformInfo(PlatformInfo):
extra_libs = ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4', '-lmsvcr90', '-liphlpapi']
build = 'win32'
compatible_hosts = ['fedora', 'debian']
arch_full = 'i686-w64-mingw32'
def __init__(self, name, static):
super().__init__(name, 'win32', static, [], ['fedora', 'debian'])
def get_cross_config(self):
return {
@ -76,5 +76,10 @@ class Win32PlatformInfo(PlatformInfo):
env['PKG_CONFIG_LIBDIR'] = pj(self.root_path, 'lib', 'pkgconfig')
env['LIBS'] = " ".join(self.extra_libs) + " " +env['LIBS']
Win32PlatformInfo('win32_dyn', False)
Win32PlatformInfo('win32_static', True)
class Win32Dyn(Win32PlatformInfo):
name = 'win32_dyn'
static = False
class Win32Static(Win32PlatformInfo):
name = 'win32_static'
static = True

View File

@ -12,55 +12,11 @@ class android_ndk(Toolchain):
version = 'r13b'
gccver = '4.9.x'
@property
def api(self):
return '21' if self.arch in ('arm64', 'mips64', 'x86_64') else '14'
@property
def platform(self):
return 'android-'+self.api
@property
def arch(self):
return self.buildEnv.platform_info.arch
@property
def arch_full(self):
return self.buildEnv.platform_info.arch_full
@property
def toolchain(self):
return self.arch_full+"-4.9"
@property
def root_path(self):
return pj(self.builder.install_path, 'sysroot')
@property
def binaries(self):
binaries = ((k,'{}-{}'.format(self.arch_full, v))
for k, v in (('CC', 'gcc'),
('CXX', 'g++'),
('AR', 'ar'),
('STRIP', 'strip'),
('WINDRES', 'windres'),
('RANLIB', 'ranlib'),
('LD', 'ld'))
)
return {k:pj(self.builder.install_path, 'bin', v)
for k,v in binaries}
@property
def configure_option(self):
return '--host={}'.format(self.arch_full)
@property
def full_name(self):
return "{name}-{version}-{arch}-{api}".format(
name = self.name,
version = self.version,
arch = self.arch,
api = self.api)
@classmethod
def full_name(cls):
return "{name}-{version}".format(
name = cls.name,
version = cls.version)
class Source(ReleaseDownload):
archive = Remotefile('android-ndk-r13b-linux-x86_64.zip',
@ -75,11 +31,34 @@ class android_ndk(Toolchain):
class Builder(Builder):
@property
def install_path(self):
return self.build_path
@property
def api(self):
return '21' if self.arch in ('arm64', 'mips64', 'x86_64') else '14'
@property
def platform(self):
return 'android-'+self.api
@property
def arch(self):
return self.buildEnv.platformInfo.arch
@property
def arch_full(self):
return self.buildEnv.platformInfo.arch_full
@property
def toolchain(self):
return self.arch_full+"-4.9"
@property
def configure_option(self):
return '--host={}'.format(self.arch_full)
def _build_platform(self, context):
context.try_skip(self.build_path)
script = pj(self.source_path, 'build/tools/make_standalone_toolchain.py')
@ -87,17 +66,18 @@ class android_ndk(Toolchain):
command = '{script} --arch={arch} --api={api} --install-dir={install_dir} --force'
command = command.format(
script=script,
arch=self.target.arch,
api=self.target.api,
arch=self.arch,
api=self.api,
install_dir=self.install_path
)
context.force_native_build = True
run_command(command, self.build_path, context, buildEnv=self.buildEnv)
def _fix_permission_right(self, context):
context.try_skip(self.build_path)
bin_dirs = [pj(self.install_path, 'bin'),
pj(self.install_path, self.target.arch_full, 'bin'),
pj(self.install_path, 'libexec', 'gcc', self.target.arch_full, self.target.gccver)
pj(self.install_path, self.arch_full, 'bin'),
pj(self.install_path, 'libexec', 'gcc', self.arch_full, self.target.gccver)
]
for root, dirs, files in os.walk(self.install_path):
if not root in bin_dirs:

View File

@ -20,7 +20,7 @@ class android_sdk(Toolchain):
@property
def install_path(self):
return pj(self.buildEnv.toolchain_dir, self.target.full_name)
return pj(self.buildEnv.toolchain_dir, self.target.full_name())
def _build_platform(self, context):
context.try_skip(self.install_path)

View File

@ -10,11 +10,12 @@ class _MetaToolchain(type):
def __new__(cls, name, bases, dct):
_class = type.__new__(cls, name, bases, dct)
if name != 'Toolchain':
Toolchain.all_toolchains[name] = _class
Toolchain.all_toolchains[dct['name']] = _class
return _class
class Toolchain(metaclass=_MetaToolchain):
force_native_build = False
neutral = True
all_toolchains = {}
configure_option = ""
@ -23,15 +24,12 @@ class Toolchain(metaclass=_MetaToolchain):
Builder = None
Source = None
def __init__(self):
self.source = self.Source(self) if self.Source else None
self.builder = self.Builder(self) if self.Builder else None
@property
def full_name(self):
@classmethod
def full_name(cls):
return "{name}-{version}".format(
name = self.name,
version = self.version)
name = cls.name,
version = cls.version)
@property
def source_path(self):