Do not use a pre-defined list of Dependency but resolve a dependency graph.
By resolving a dependency graph, we avoid us to have a fixed list of dependencies. This is even more usefull because now, we don't have to track different dependencies lists dependending of the build_target.
This commit is contained in:
parent
0c046e88fb
commit
f5dff05a55
110
kiwix-build.py
110
kiwix-build.py
|
@ -9,7 +9,7 @@ import hashlib
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import configparser
|
import configparser
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple, OrderedDict
|
||||||
|
|
||||||
|
|
||||||
pj = os.path.join
|
pj = os.path.join
|
||||||
|
@ -23,6 +23,14 @@ class Defaultdict(defaultdict):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return self[name]
|
return self[name]
|
||||||
|
|
||||||
|
def remove_duplicates(iterable):
|
||||||
|
seen = set()
|
||||||
|
for elem in iterable:
|
||||||
|
if elem in seen:
|
||||||
|
continue
|
||||||
|
seen.add(elem)
|
||||||
|
yield elem
|
||||||
|
|
||||||
def get_sha256(path):
|
def get_sha256(path):
|
||||||
sha256 = hashlib.sha256()
|
sha256 = hashlib.sha256()
|
||||||
with open(path, 'br') as f:
|
with open(path, 'br') as f:
|
||||||
|
@ -92,7 +100,7 @@ class BuildEnv:
|
||||||
'win32' : {'wrapper': 'mingw32-env'}
|
'win32' : {'wrapper': 'mingw32-env'}
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options, targetsDict):
|
||||||
self.source_dir = pj(options.working_dir, "SOURCE")
|
self.source_dir = pj(options.working_dir, "SOURCE")
|
||||||
build_dir = "BUILD_{target}_{libmod}".format(
|
build_dir = "BUILD_{target}_{libmod}".format(
|
||||||
target=options.build_target,
|
target=options.build_target,
|
||||||
|
@ -112,6 +120,7 @@ class BuildEnv:
|
||||||
self.meson_command = self._detect_meson()
|
self.meson_command = self._detect_meson()
|
||||||
self.options = options
|
self.options = options
|
||||||
self.libprefix = options.libprefix or self._detect_libdir()
|
self.libprefix = options.libprefix or self._detect_libdir()
|
||||||
|
self.targetsDict = targetsDict
|
||||||
|
|
||||||
def setup_build_target(self, build_target):
|
def setup_build_target(self, build_target):
|
||||||
self.build_target = build_target
|
self.build_target = build_target
|
||||||
|
@ -257,7 +266,17 @@ class BuildEnv:
|
||||||
################################################################################
|
################################################################################
|
||||||
##### PROJECT
|
##### PROJECT
|
||||||
################################################################################
|
################################################################################
|
||||||
class Dependency:
|
class _MetaDependency(type):
|
||||||
|
def __new__(cls, name, bases, dct):
|
||||||
|
_class = type.__new__(cls, name, bases, dct)
|
||||||
|
if name != 'Dependency':
|
||||||
|
Dependency.all_deps[name] = _class
|
||||||
|
return _class
|
||||||
|
|
||||||
|
|
||||||
|
class Dependency(metaclass=_MetaDependency):
|
||||||
|
all_deps = {}
|
||||||
|
dependencies = []
|
||||||
force_native_build = False
|
force_native_build = False
|
||||||
version = None
|
version = None
|
||||||
def __init__(self, buildEnv):
|
def __init__(self, buildEnv):
|
||||||
|
@ -571,6 +590,12 @@ class Xapian(Dependency):
|
||||||
configure_env = {'_format_LDFLAGS' : "-L{buildEnv.install_dir}/{buildEnv.libprefix}",
|
configure_env = {'_format_LDFLAGS' : "-L{buildEnv.install_dir}/{buildEnv.libprefix}",
|
||||||
'_format_CXXFLAGS' : "-I{buildEnv.install_dir}/include"}
|
'_format_CXXFLAGS' : "-I{buildEnv.install_dir}/include"}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dependencies(self):
|
||||||
|
if self.buildEnv.build_target == 'win32':
|
||||||
|
return []
|
||||||
|
return ['UUID']
|
||||||
|
|
||||||
|
|
||||||
class CTPP2(Dependency):
|
class CTPP2(Dependency):
|
||||||
name = "ctpp2"
|
name = "ctpp2"
|
||||||
|
@ -689,6 +714,11 @@ class Zimlib(Dependency):
|
||||||
|
|
||||||
class Kiwixlib(Dependency):
|
class Kiwixlib(Dependency):
|
||||||
name = "kiwix-lib"
|
name = "kiwix-lib"
|
||||||
|
@property
|
||||||
|
def dependencies(self):
|
||||||
|
if self.buildEnv.build_target == 'win32':
|
||||||
|
return ["Xapian", "CTPP2", "Pugixml", "Icu_cross_compile", "Zimlib"]
|
||||||
|
return ["Xapian", "CTPP2", "Pugixml", "Icu", "Zimlib"]
|
||||||
|
|
||||||
class Source(GitClone):
|
class Source(GitClone):
|
||||||
git_remote = "https://github.com/kiwix/kiwix-lib.git"
|
git_remote = "https://github.com/kiwix/kiwix-lib.git"
|
||||||
|
@ -700,6 +730,7 @@ class Kiwixlib(Dependency):
|
||||||
|
|
||||||
class KiwixTools(Dependency):
|
class KiwixTools(Dependency):
|
||||||
name = "kiwix-tools"
|
name = "kiwix-tools"
|
||||||
|
dependencies = ["Kiwixlib", "MicroHttpd"]
|
||||||
|
|
||||||
class Source(GitClone):
|
class Source(GitClone):
|
||||||
git_remote = "https://github.com/kiwix/kiwix-tools.git"
|
git_remote = "https://github.com/kiwix/kiwix-tools.git"
|
||||||
|
@ -710,44 +741,52 @@ class KiwixTools(Dependency):
|
||||||
|
|
||||||
|
|
||||||
class Builder:
|
class Builder:
|
||||||
def __init__(self, buildEnv):
|
def __init__(self, options, targetDef='KiwixTools'):
|
||||||
self.buildEnv = buildEnv
|
self.targets = OrderedDict()
|
||||||
|
self.buildEnv = buildEnv = BuildEnv(options, self.targets)
|
||||||
if buildEnv.build_target != 'native':
|
if buildEnv.build_target != 'native':
|
||||||
subBuildEnv = BuildEnv(buildEnv.options)
|
self.nativeBuildEnv = BuildEnv(options, self.targets)
|
||||||
subBuildEnv.setup_build_target('native')
|
self.nativeBuildEnv.setup_build_target('native')
|
||||||
nativeICU = Icu_native(subBuildEnv)
|
|
||||||
self.dependencies = [
|
|
||||||
Xapian(buildEnv),
|
|
||||||
CTPP2(buildEnv),
|
|
||||||
Pugixml(buildEnv),
|
|
||||||
Zimlib(buildEnv),
|
|
||||||
MicroHttpd(buildEnv),
|
|
||||||
nativeICU,
|
|
||||||
Icu_cross_compile(buildEnv, True, nativeICU),
|
|
||||||
Kiwixlib(buildEnv),
|
|
||||||
KiwixTools(buildEnv)
|
|
||||||
]
|
|
||||||
else:
|
else:
|
||||||
self.dependencies = [UUID(buildEnv),
|
self.nativeBuildEnv = buildEnv
|
||||||
Xapian(buildEnv),
|
|
||||||
CTPP2(buildEnv),
|
_targets = {}
|
||||||
Pugixml(buildEnv),
|
self.add_targets(targetDef, _targets)
|
||||||
Zimlib(buildEnv),
|
|
||||||
MicroHttpd(buildEnv),
|
dependencies_order = list(remove_duplicates(self.order_dependencies(_targets, targetDef)))
|
||||||
Icu(buildEnv),
|
dependencies_order.append(targetDef)
|
||||||
Kiwixlib(buildEnv),
|
|
||||||
KiwixTools(buildEnv)
|
for dep in dependencies_order:
|
||||||
]
|
self.targets[dep] = _targets[dep]
|
||||||
|
|
||||||
|
self.sources = remove_duplicates(dep.source for dep in self.targets.values())
|
||||||
|
self.builders = (dep.builder for dep in self.targets.values())
|
||||||
|
|
||||||
|
def add_targets(self, targetName, targets):
|
||||||
|
if targetName in targets:
|
||||||
|
return
|
||||||
|
targetClass = Dependency.all_deps[targetName]
|
||||||
|
if targetClass.force_native_build:
|
||||||
|
target = targetClass(self.nativeBuildEnv)
|
||||||
|
else:
|
||||||
|
target = targetClass(self.buildEnv)
|
||||||
|
targets[targetName] = target
|
||||||
|
for dep in target.dependencies:
|
||||||
|
self.add_targets(dep, targets)
|
||||||
|
|
||||||
|
def order_dependencies(self, _targets, targetName):
|
||||||
|
target = _targets[targetName]
|
||||||
|
for depName in target.dependencies:
|
||||||
|
yield from self.order_dependencies(_targets, depName)
|
||||||
|
yield targetName
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
for dependency in self.dependencies:
|
for source in self.sources:
|
||||||
source = dependency.source
|
print("prepare sources {} :".format(source.name))
|
||||||
print("prepare {} :".format(source.name))
|
|
||||||
source.prepare()
|
source.prepare()
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
for dependency in self.dependencies:
|
for builder in self.builders:
|
||||||
builder = dependency.builder
|
|
||||||
print("build {} :".format(builder.name))
|
print("build {} :".format(builder.name))
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
||||||
|
@ -765,8 +804,7 @@ def parse_args():
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
options = parse_args()
|
options = parse_args()
|
||||||
options.working_dir = os.path.abspath(options.working_dir)
|
options.working_dir = os.path.abspath(options.working_dir)
|
||||||
buildEnv = BuildEnv(options)
|
builder = Builder(options)
|
||||||
builder = Builder(buildEnv)
|
|
||||||
try:
|
try:
|
||||||
print("[PREPARE]")
|
print("[PREPARE]")
|
||||||
builder.prepare()
|
builder.prepare()
|
||||||
|
|
Loading…
Reference in New Issue