Compare commits

..

No commits in common. "main" and "35" have entirely different histories.
main ... 35

135 changed files with 6812 additions and 35837 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: kiwix # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # https://kiwix.org/support-us/

View File

@ -1,46 +0,0 @@
[DEFAULTS]
[aqt]
concurrency: 4
baseurl: https://qt.mirror.constant.com/
7zcmd: 7z
print_stacktrace_on_error: False
always_keep_archives: False
archive_download_location: .
min_module_size: 41
[requests]
connection_timeout: 3.5
response_timeout: 30
max_retries_on_connection_error: 5
retry_backoff: 0.1
max_retries_on_checksum_error: 5
max_retries_to_retrieve_hash: 5
hash_algorithm: sha256
INSECURE_NOT_FOR_PRODUCTION_ignore_hash: False
[mirrors]
trusted_mirrors:
https://download.qt.io
https://qt.mirror.constant.com/
https://ftp.fau.de/qtproject/
blacklist:
http://mirrors.ocf.berkeley.edu
http://mirrors.tuna.tsinghua.edu.cn
http://mirrors.geekpie.club
fallbacks:
https://qtproject.mirror.liquidtelecom.com/
https://mirrors.aliyun.com/qt/
https://mirrors.ustc.edu.cn/qtproject/
https://ftp.jaist.ac.jp/pub/qtproject/
https://ftp.yz.yamagata-u.ac.jp/pub/qtproject/
https://qt-mirror.dannhauer.de/
https://ftp.fau.de/qtproject/
https://mirror.netcologne.de/qtproject/
https://mirrors.dotsrc.org/qtproject/
https://www.nic.funet.fi/pub/mirrors/download.qt-project.org/
https://master.qt.io/
https://mirrors.ukfast.co.uk/sites/qt.io/
https://ftp2.nluug.nl/languages/qt/
https://ftp1.nluug.nl/languages/qt/
https://qt.mirror.constant.com/

View File

@ -1,161 +0,0 @@
from typing import NamedTuple
import csv, io, re
# Definition of what to build.
# Array is read line by line.
# Empty cells under (OS_NAME, COMPILE_CONFIG) mean "always match" (catch all, or `.*` regex)
# Once a cell doesn't match, skip to the next line.
# Once a line matches, other lines are not read, so put more specific combination first.
# Lines composed of `-` , or `=`, or starting by `#` are ignored.
# 'B' letter means that the project is build in the CI
# 'd' letter means that the project's dependencies are build and published to be used by the project's CI.
# 'P' letter means that (build) project must be publish when we do a release.
# (This is used to avoid two publication of the same archive)
# 'S' letter means that source code must be publish (almost by definition, S should be put only with a P)
# 'D' letter means we trigger the docker forkflow to build the docker image.
# If a cell contains several letters, all are done.
BUILD_DEF = """
| OS_NAME | COMPILE_CONFIG | libzim | libkiwix | zim-tools | kiwix-tools | kiwix-desktop | platform_name | dependency_name |
==============================================================================================================================================
# manylinux is a special case as we need to compile libzim on old arch for python
| manylinux | native_mixed | BP | | | | | linux-x86_64-manylinux | |
| manylinux | aarch64_mixed | BP | | | | | linux-aarch64-manylinux | |
----------------------------------------------------------------------------------------------------------------------------------------------
# On Windows, we build only libzim for now. And only native_mixed as xapian doesn't compile as dll
| windows | native_static | Bd | d | BPd | BPd | | win-x86_64 | win-x86_64-static |
| windows | native_dyn | Bd | | | | | win-x86_64 | win-x86_64-dyn |
| windows | native_mixed | BPd | d | | | BPd | win-x86_64 | win-x86_64-mixed |
----------------------------------------------------------------------------------------------------------------------------------------------
# Osx builds, build binaries on native_dyn and native_static. On anyother things, build only the libraries
| macos | native_dyn | d | d | dB | B | | | macos-x86_64-dyn |
| macos | native_static | | | BP | BP | | macos-x86_64 | |
| macos | native_mixed | BP | BP | | | | macos-x86_64 | |
| macos | iOS_arm64 | dB | dB | | | | | ios-arm64-dyn |
| macos | iOSSimulator_x86_64| dB | dB | | | | | ios-x86_64-dyn |
| macos | iOSSimulator_arm64 | B | B | | | | | |
| macos | macOS_arm64_static | | | BP | BP | | macos-arm64 | |
| macos | macOS_arm64_mixed | dBP | dBP | d | | | macos-arm64 | macos-aarch64-dyn |
| macos | macOS_x86_64 | B | B | | | | | |
| macos | apple_all_static | | BP | | | | xcframework | |
----------------------------------------------------------------------------------------------------------------------------------------------
| focal | flatpak | | | | | BP | | |
| focal | native_static | d | d | dBPSD | dBPSD | | linux-x86_64 | linux-x86_64-static |
| focal | native_mixed | BPS | BPS | | | | linux-x86_64 | |
| focal | native_dyn | d | d | dB | dB | | | linux-x86_64-dyn |
| jammy | native_dyn | | | | | dBPS | | linux-x86_64-dyn |
# libzim CI is building alpine_dyn but not us
| focal | android_arm | dBP | dBP | | | | android-arm | android-arm |
| focal | android_arm64 | dBP | dBP | | | | android-arm64 | android-arm64 |
| focal | android_x86 | BP | BP | | | | android-x86 | |
| focal | android_x86_64 | BP | BP | | | | android-x86_64 | |
| focal | armv6_static | | | BP | BP | | linux-armv6 | |
| focal | armv6_mixed | BP | | | | | linux-armv6 | |
| focal | armv6_dyn | | | B | B | | | |
| focal | armv8_static | | | BP | BP | | linux-armv8 | |
| focal | armv8_mixed | BP | | | | | linux-armv8 | |
| focal | armv8_dyn | | | B | B | | | |
| focal | aarch64_static | | | BP | BP | | linux-aarch64 | |
| focal | aarch64_mixed | BP | | | | | linux-aarch64 | |
| focal | aarch64_dyn | d | | B | B | | | linux-aarch64-dyn |
| focal | aarch64_musl_static| | | BP | BP | | linux-aarch64-musl | |
| focal | aarch64_musl_mixed | BP | | | | | linux-aarch64-musl | |
| focal | aarch64_musl_dyn | d | | B | B | | | linux-aarch64-musl-dyn |
| focal | x86-64_musl_static | | | BP | BP | | linux-x86_64-musl | |
| focal | x86-64_musl_mixed | BP | | | | | linux-x86_64-musl | |
| focal | i586_static | | | BP | BP | | linux-i586 | |
| focal | i586_dyn | | | B | B | | | |
| focal | wasm | dBP | | | | | wasm-emscripten | wasm |
"""
class TableDialect(csv.Dialect):
delimiter = "|"
quoting = csv.QUOTE_NONE
lineterminator = "\n"
def strip_array(array_str):
"""Return a iterable of lines, skiping "decorative lines" and with all values in the line's cells stripped"""
for line in array_str.splitlines():
line = line.strip()
line_set = set(line)
if (
not line
or line.startswith("#")
or (len(line_set) == 1 and line_set.pop() in "-=")
):
continue
yield "|".join(c.strip() for c in line.split("|"))
def selector_match(selector, value):
if not selector:
return True
return re.fullmatch(selector, value) is not None
class Context(NamedTuple):
OS_NAME: str
COMPILE_CONFIG: str
def match(self, row):
for key in ["OS_NAME", "COMPILE_CONFIG"]:
context_value = getattr(self, key)
selector = row[key]
if not selector_match(selector, context_value):
return False
return True
BUILD = "B"
PUBLISH = "P"
SOURCE_PUBLISH = "S"
DEPS = "d"
DOCKER = "D"
def select_build_targets(criteria):
from common import COMPILE_CONFIG, OS_NAME
context = Context(COMPILE_CONFIG=COMPILE_CONFIG, OS_NAME=OS_NAME)
reader = csv.DictReader(strip_array(BUILD_DEF), dialect=TableDialect())
for row in reader:
if context.match(row):
build_order = [
k
for k in (
"libzim",
"libkiwix",
"zim-tools",
"kiwix-tools",
"kiwix-desktop",
)
if criteria in row[k]
]
print(build_order)
return build_order
raise ValueError("No definition match with current context.")
def get_column_value(column_name):
from common import COMPILE_CONFIG, OS_NAME
context = Context(COMPILE_CONFIG=COMPILE_CONFIG, OS_NAME=OS_NAME)
reader = csv.DictReader(strip_array(BUILD_DEF), dialect=TableDialect())
for row in reader:
if context.match(row):
name = row[column_name]
return name or None
raise ValueError("No definition match with current context.")
def get_platform_name():
return get_column_value("platform_name")
def get_dependency_archive_name():
return get_column_value("dependency_name")

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
from build_definition import select_build_targets, BUILD
from common import (
run_kiwix_build,
make_archive,
@ -8,16 +8,43 @@ from common import (
fix_macos_rpath,
upload_archive,
OS_NAME,
COMPILE_CONFIG,
PLATFORM_TARGET,
DESKTOP,
DEV_BRANCH,
)
for target in select_build_targets(BUILD):
run_kiwix_build(target, config=COMPILE_CONFIG)
if (PLATFORM_TARGET.startswith("android_")
or PLATFORM_TARGET.startswith("iOS")
or PLATFORM_TARGET.startswith("macOS")):
TARGETS = ("libzim", "libkiwix")
elif PLATFORM_TARGET.startswith("native_"):
if OS_NAME == "osx":
if PLATFORM_TARGET == "native_mixed":
TARGETS = ("libzim", "libkiwix")
else:
TARGETS = ("zim-tools", )
else:
if DESKTOP:
TARGETS = ("kiwix-desktop",)
elif PLATFORM_TARGET == "native_mixed":
TARGETS = ("libzim", "libkiwix")
else:
TARGETS = ("zim-tools", "kiwix-tools")
elif PLATFORM_TARGET in ("win32_static", "armhf_static", "armhf_dyn", "i586_static"):
TARGETS = ("kiwix-tools",)
elif PLATFORM_TARGET == "flatpak":
TARGETS = ("kiwix-desktop",)
elif PLATFORM_TARGET == "wasm":
TARGETS = ("libzim", )
else:
TARGETS = ("libzim", "zim-tools", "libkiwix", "kiwix-tools")
for target in TARGETS:
run_kiwix_build(target, platform=PLATFORM_TARGET)
if target == "kiwix-desktop":
archive = create_desktop_image(make_release=False)
else:
if COMPILE_CONFIG == "native_mixed" and OS_NAME == "macos":
if PLATFORM_TARGET == "native_mixed" and OS_NAME == "osx":
fix_macos_rpath(target)
archive = make_archive(target, make_release=False)
if archive and DEV_BRANCH:

View File

@ -11,65 +11,85 @@ from common import (
update_flathub_git,
upload_archive,
fix_macos_rpath,
trigger_docker_publish,
BASE_DIR,
TMP_DIR,
HOME,
OS_NAME,
COMPILE_CONFIG,
PLATFORM_TARGET,
DESKTOP,
MAKE_RELEASE,
notarize_macos_build,
)
from build_definition import select_build_targets, BUILD, PUBLISH, SOURCE_PUBLISH
def release_filter(project):
return release_versions.get(project) is not None
if PLATFORM_TARGET.startswith("android_") or PLATFORM_TARGET.startswith("iOS"):
TARGETS = ("libzim", "libkiwix")
elif PLATFORM_TARGET.startswith("native_"):
if OS_NAME == "osx":
if PLATFORM_TARGET == "native_mixed":
TARGETS = ("libzim", "libkiwix")
else:
TARGETS = ("zim-tools", )
else:
if DESKTOP:
TARGETS = ("kiwix-desktop",)
elif PLATFORM_TARGET == "native_mixed":
TARGETS = ("libzim", "libkiwix")
else:
TARGETS = ("zim-tools", "kiwix-tools")
elif PLATFORM_TARGET in ("win32_static", "armhf_static", "i586_static"):
TARGETS = ("kiwix-tools",)
elif PLATFORM_TARGET == "flatpak":
TARGETS = ("kiwix-desktop",)
elif PLATFORM_TARGET == "wasm":
TARGETS = ("libzim", )
else:
TARGETS = ("libzim", "zim-tools", "libkiwix", "kiwix-tools")
# Filter what to build if we are doing a release.
TARGETS = select_build_targets(PUBLISH)
if MAKE_RELEASE:
def release_filter(project):
return release_versions.get(project) is not None
TARGETS = tuple(filter(release_filter, TARGETS))
for target in TARGETS:
run_kiwix_build(target, config=COMPILE_CONFIG, make_release=MAKE_RELEASE)
run_kiwix_build(target, platform=PLATFORM_TARGET, make_release=MAKE_RELEASE)
if target == "kiwix-desktop":
archive = create_desktop_image(make_release=MAKE_RELEASE)
else:
if OS_NAME == "macos" and COMPILE_CONFIG.endswith("_mixed"):
if PLATFORM_TARGET == "native_mixed" and OS_NAME == "osx":
fix_macos_rpath(target)
notarize_macos_build(target)
archive = make_archive(target, make_release=MAKE_RELEASE)
if archive:
upload_archive(archive, target, make_release=MAKE_RELEASE)
if MAKE_RELEASE and target in ("zim-tools", "kiwix-tools"):
trigger_docker_publish(target)
# We have few more things to do for release:
if MAKE_RELEASE:
# Publish source archives
source_published_targets = select_build_targets(SOURCE_PUBLISH)
for target in TARGETS:
# Looping on TARGETS instead of source_published_targets ensures we are
# publishing sources only for target we are building.
# (source_published_targets must be a subset of TARGETS)
if release_versions.get(target) != 0:
continue
if target not in source_published_targets:
continue
run_kiwix_build(
target, config=COMPILE_CONFIG, make_release=MAKE_RELEASE, make_dist=True
)
full_target_name = "{}-{}".format(target, main_project_versions[target])
if target == "kiwix-desktop":
archive = BASE_DIR / full_target_name / "{}.tar.gz".format(full_target_name)
else:
archive = (
BASE_DIR
/ full_target_name
/ "meson-dist"
/ "{}.tar.xz".format(full_target_name)
if PLATFORM_TARGET in ("native_dyn", "native_mixed") and OS_NAME != "osx":
for target in TARGETS:
if release_versions.get(target) != 0:
continue
run_kiwix_build(
target, platform=PLATFORM_TARGET, make_release=MAKE_RELEASE, make_dist=True
)
upload_archive(archive, target, make_release=MAKE_RELEASE)
full_target_name = "{}-{}".format(target, main_project_versions[target])
if target == "kiwix-desktop":
archive = (
BASE_DIR / full_target_name / "{}.tar.gz".format(full_target_name)
)
else:
archive = (
BASE_DIR
/ full_target_name
/ "meson-dist"
/ "{}.tar.xz".format(full_target_name)
)
upload_archive(archive, target, make_release=MAKE_RELEASE)
# Publish flathub
if COMPILE_CONFIG == "flatpak" and "kiwix-desktop" in TARGETS:
if PLATFORM_TARGET == "flatpak" and "kiwix-desktop" in TARGETS:
update_flathub_git()

View File

@ -1,88 +1,77 @@
import os
from os import environ as _environ
from pathlib import Path, PurePosixPath
from pathlib import Path
from datetime import date
import tarfile
import zipfile
import subprocess
import re
import shutil
import platform
import requests
from build_definition import get_platform_name, get_dependency_archive_name
from kiwixbuild.dependencies.apple_xcframework import AppleXCFramework
from kiwixbuild.versions import (
main_project_versions,
release_versions,
base_deps_versions,
)
def get_build_dir(config) -> Path:
command = ["kiwix-build"]
command.extend(["--config", config])
command.append("--get-build-dir")
command.append("--use-target-arch-name")
return Path(
subprocess.run(command, cwd=str(HOME), check=True, stdout=subprocess.PIPE)
.stdout.strip()
.decode("utf8")
)
COMPILE_CONFIG = _environ["COMPILE_CONFIG"]
PLATFORM_TARGET = _environ["PLATFORM_TARGET"]
if PLATFORM_TARGET == "native_desktop":
PLATFORM_TARGET = "native_dyn"
DESKTOP = True
else:
DESKTOP = False
OS_NAME = _environ["OS_NAME"]
HOME = Path(os.path.expanduser("~"))
BASE_DIR = get_build_dir(COMPILE_CONFIG)
BASE_DIR = HOME / "BUILD_{}".format(PLATFORM_TARGET)
SOURCE_DIR = HOME / "SOURCE"
ARCHIVE_DIR = HOME / "ARCHIVE"
TOOLCHAIN_DIR = BASE_DIR / "TOOLCHAINS"
INSTALL_DIR = BASE_DIR / "INSTALL"
default_tmp_dir = os.getenv("TEMP") if platform.system() == "Windows" else "/tmp"
TMP_DIR = Path(os.getenv("TMP_DIR", default_tmp_dir))
if platform.system() == "Windows":
KBUILD_SOURCE_DIR = Path(_environ["GITHUB_WORKSPACE"])
BIN_EXT = ".exe"
else:
KBUILD_SOURCE_DIR = HOME / "kiwix-build"
BIN_EXT = ""
TMP_DIR = Path("/tmp")
KBUILD_SOURCE_DIR = HOME / "kiwix-build"
# [TODO]
KIWIX_DESKTOP_ONLY = False
_ref = _environ.get("GITHUB_REF", "").split("/")[-1]
MAKE_RELEASE = re.fullmatch(r"r_[0-9]+", _ref) is not None
MAKE_RELEASE = MAKE_RELEASE and (_environ.get("GITHUB_EVENT_NAME") != "schedule")
MAKE_RELEASE = MAKE_RELEASE and (_environ.get('GITHUB_EVENT_NAME') != 'schedule')
if not MAKE_RELEASE and _ref != "main":
if not MAKE_RELEASE and _ref != "master":
DEV_BRANCH = _ref
else:
DEV_BRANCH = None
RELEASE_OS_NAME = "macos" if OS_NAME == "osx" else "linux"
PLATFORM_TO_RELEASE = {
"native_mixed": "{os}-x86_64".format(os=RELEASE_OS_NAME),
"native_static": "{os}-x86_64".format(os=RELEASE_OS_NAME),
"win32_static": "win-i686",
"armhf_static": "{os}-armhf".format(os=RELEASE_OS_NAME),
"i586_static": "{os}-i586".format(os=RELEASE_OS_NAME),
"android_arm": "android-arm",
"android_arm64": "android-arm64",
"android_x86": "android-x86",
"android_x86_64": "android-x86_64",
"wasm": "wasm-emscripten",
}
FLATPAK_HTTP_GIT_REMOTE = "https://github.com/flathub/org.kiwix.desktop.git"
FLATPAK_GIT_REMOTE = "git@github.com:flathub/org.kiwix.desktop.git"
def major_version(version: str) -> str:
return version.split(".")[0]
# Depending of base distribution, libraries are in "lib64" (redhat base) or "lib/<arch>" (debian base).
# On top of that, when cross-compiling, libraries are always put in `lib/<arch>`.
# As we use this as glob regex to select which files to add to archive, this is not a problem to have both.
def lib_prefix(file):
yield "lib64/" + file
yield "lib/*/" + file
BIN_EXT = ".exe" if PLATFORM_TARGET.startswith("win32_") else ""
# We have build everything. Now create archives for public deployement.
EXPORT_FILES = {
"kiwix-tools": (
INSTALL_DIR / "bin",
[f + BIN_EXT for f in ("kiwix-manage", "kiwix-search", "kiwix-serve")]
+ ["icu*.dll"],
[
f + BIN_EXT
for f in ("kiwix-manage", "kiwix-search", "kiwix-serve")
],
),
"zim-tools": (
INSTALL_DIR / "bin",
@ -97,76 +86,40 @@ EXPORT_FILES = {
"zimpatch",
"zimsplit",
"zimwriterfs",
"zimrecreate",
"zimrecreate"
)
]
+ ["icu*.dll"],
],
),
"libzim": (
INSTALL_DIR,
(
## Linux
# We need to package all dependencies (`*.a`) on wasm
*lib_prefix("libzim.a" if COMPILE_CONFIG != "wasm" else "*.a"),
*lib_prefix("libzim.so"),
*lib_prefix(
"libzim.so.{version}".format(version=main_project_versions["libzim"])
"lib/*/libzim.a" if PLATFORM_TARGET != "wasm" else "lib/*/*.a",
"lib/*/libzim.so",
"lib/*/libzim.so.{version}".format(
version=main_project_versions["libzim"]
),
*lib_prefix(
"libzim.so.{version}".format(
version=major_version(main_project_versions["libzim"])
)
"lib/*/libzim.so.{version}".format(
version=main_project_versions["libzim"][0]
),
## MacOS
"lib/libzim.{}.dylib".format(
major_version(main_project_versions["libzim"])
main_project_versions["libzim"][0]
),
"lib/libzim.dylib",
"lib/*/libzim.pc",
## Windows
"bin/zim-{version}.dll".format(
version=major_version(main_project_versions["libzim"])
),
"bin/icu*.dll",
"bin/zim-{version}.pdb".format(
version=major_version(main_project_versions["libzim"])
),
"lib/zim.lib",
## Includes and others
"include/zim/**/*.h",
"share/icu/{}/icudt{}l.dat".format(
base_deps_versions["icu4c"], major_version(base_deps_versions["icu4c"])
),
),
),
"libkiwix": (
INSTALL_DIR,
(
"lib/CoreKiwix.xcframework/",
"lib/*/libkiwix.so",
"lib/*/libkiwix.so.{version}".format(
version=main_project_versions["libkiwix"]
),
"lib/*/libkiwix.so.{version}".format(
version=major_version(main_project_versions["libkiwix"])
),
"lib/libkiwix.{}.dylib".format(
major_version(main_project_versions["libkiwix"])
),
"bin/kiwix-{version}.dll".format(
version=major_version(main_project_versions["libkiwix"])
),
"bin/icu*.dll",
"bin/kiwix-{version}.pdb".format(
version=major_version(main_project_versions["libkiwix"])
),
"lib/kiwix.lib",
"lib/libkiwix.dylib",
"lib/*/libkiwix.pc",
"include/kiwix/**/*.h",
"share/icu/{}/icudt{}l.dat".format(
base_deps_versions["icu4c"], major_version(base_deps_versions["icu4c"])
version=main_project_versions["libkiwix"][0]
),
"include/kiwix/**/*.h"
),
),
}
@ -183,26 +136,23 @@ def print_message(message, *args, **kwargs):
MANIFEST_TEMPLATE = """{archive_name}
***************************
Dependencies archive for {target} using config {config}
Dependencies archive for {target} on platform {platform}
Generated at {date}
"""
def write_manifest(manifest_file, archive_name, target, config):
def write_manifest(manifest_file, archive_name, target, platform):
with manifest_file.open(mode="w") as f:
f.write(
MANIFEST_TEMPLATE.format(
archive_name=archive_name,
target=target,
config=config,
date=DATE,
archive_name=archive_name, target=target, platform=platform, date=DATE,
)
)
def run_kiwix_build(
target,
config,
platform,
build_deps_only=False,
target_only=False,
make_release=False,
@ -213,8 +163,7 @@ def run_kiwix_build(
command.append("--hide-progress")
command.append("--fast-clone")
command.append("--assume-packages-installed")
command.append("--use-target-arch-name")
command.extend(["--config", config])
command.extend(["--target-platform", platform])
if build_deps_only:
command.append("--build-deps-only")
if target_only:
@ -236,123 +185,52 @@ def run_kiwix_build(
print_message("Build ended")
try:
import paramiko
def upload(file_to_upload, host, dest_path):
if not file_to_upload.exists():
print_message("No {} to upload!", file_to_upload)
return
def upload(file_to_upload, host, dest_path):
if not file_to_upload.exists():
print_message("No {} to upload!", file_to_upload)
return
if ":" in host:
host, port = host.split(":", 1)
else:
port = "22"
if ":" in host:
host, port = host.split(":", 1)
else:
port = "22"
if "@" in host:
user, host = host.split("@", 1)
else:
user = None
from contextlib import contextmanager
@contextmanager
def get_client():
client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.client.WarningPolicy)
print_message(f"Connect to {host}:{port}")
client.connect(
host,
port=port,
username=user,
key_filename=_environ.get("SSH_KEY"),
look_for_keys=False,
compress=True,
)
try:
yield client
finally:
client.close()
@contextmanager
def get_sftp():
with get_client() as client:
sftp = client.open_sftp()
try:
yield sftp
finally:
sftp.close()
dest_path = PurePosixPath(dest_path)
remote_file = dest_path.joinpath(file_to_upload.name)
with get_sftp() as sftp:
for part in list(reversed(dest_path.parents)) + [dest_path]:
part = str(part)
try:
sftp.stat(part)
except FileNotFoundError:
sftp.mkdir(part)
print_message(f"Sending archive {file_to_upload} to {remote_file}")
sftp.put(str(file_to_upload), str(remote_file), confirm=True)
except ModuleNotFoundError:
# On old system (bionic) paramiko is really complex to install
# Keep the old implementaion on sush system.
def upload(file_to_upload, host, dest_path):
if not file_to_upload.exists():
print_message("No {} to upload!", file_to_upload)
return
if ":" in host:
host, port = host.split(":", 1)
else:
port = "22"
# Using SFTP to create the directory hierarchy because we can not
# use SSH (no shell for this user); and then scp to upload the file.
#
# Sending SFTP mkdir command to the SFTP interactive mode and not batch (-b) mode
# as the latter would exit on any mkdir error while it is most likely
# the first parts of the destination is already present and thus can't be created
sftp_commands = "\n".join(
[
f"mkdir {part}"
for part in list(reversed(Path(dest_path).parents)) + [dest_path]
]
)
command = [
"sftp",
"-c",
"aes128-ctr",
"-i",
_environ.get("SSH_KEY"),
"-P",
port,
"-o",
"StrictHostKeyChecking=no",
host,
# sending SFTP mkdir command to the sftp interactive mode and not batch (-b) mode
# as the latter would exit on any mkdir error while it is most likely
# the first parts of the destination is already present and thus can't be created
sftp_commands = "\n".join(
[
f"mkdir {part}"
for part in list(reversed(Path(dest_path).parents)) + [dest_path]
]
print_message("Creating dest path {}", dest_path)
subprocess.run(command, input=sftp_commands.encode("utf-8"), check=True)
)
command = [
"sftp",
"-i",
_environ.get("SSH_KEY"),
"-P",
port,
"-o",
"StrictHostKeyChecking=no",
host,
]
print_message("Creating dest path {}", dest_path)
subprocess.run(command, input=sftp_commands.encode("utf-8"), check=True)
command = [
"scp",
"-c",
"aes128-ctr",
"-rp",
"-P",
port,
"-i",
_environ.get("SSH_KEY"),
"-o",
"StrictHostKeyChecking=no",
str(file_to_upload),
"{}:{}".format(host, dest_path),
]
print_message("Sending archive with command {}", command)
subprocess.check_call(command)
command = [
"scp",
"-rp",
"-P",
port,
"-i",
_environ.get("SSH_KEY"),
"-o",
"StrictHostKeyChecking=no",
str(file_to_upload),
"{}:{}".format(host, dest_path),
]
print_message("Sending archive with command {}", command)
subprocess.check_call(command)
def upload_archive(archive, project, make_release, dev_branch=None):
@ -360,7 +238,7 @@ def upload_archive(archive, project, make_release, dev_branch=None):
print_message("No archive {} to upload!", archive)
return
if project.startswith("kiwix-") or project in ["libkiwix"]:
if project.startswith("kiwix-") or project in ['libkiwix']:
host = "ci@master.download.kiwix.org:30022"
dest_path = "/data/download/"
else:
@ -373,7 +251,7 @@ def upload_archive(archive, project, make_release, dev_branch=None):
dest_path = dest_path + "nightly/" + DATE
if dev_branch:
dest_path = "/data/tmp/ci/dev_preview/" + dev_branch
dest_path = "/data/tmp/ci/" + dev_branch
else:
# Make the archive read only. This way, scp will preserve rights.
# If somehow we try to upload twice the same archive, scp will fails.
@ -384,68 +262,56 @@ def upload_archive(archive, project, make_release, dev_branch=None):
# This remove "share/doc" and "share/man" from the thing to copy in the deps archive
def filter_install_dir(path):
for dir in path.glob("*"):
if dir.name not in ["share"]:
for dir in path.glob('*'):
if dir.name not in ['share']:
yield dir
else:
for sub_dir in dir.glob("*"):
if sub_dir.name not in ["doc", "man"]:
for sub_dir in dir.glob('*'):
if sub_dir.name not in ['doc', 'man']:
yield sub_dir
# Full: True if we are creating a full archive to be used as cache by kiwix-build (base_deps_{os}_{config}_{base_deps_version}.tar.gz)
# Full: False if we are creating a archive to be used as pre-cached dependencies for project's CI (deps_{config}_{target}.tar.gz)
def make_deps_archive(target=None, name=None, full=False):
archive_name = name or "deps_{}_{}.tar.gz".format(
get_dependency_archive_name(), target
archive_name = name or "deps2_{}_{}_{}.tar.xz".format(
OS_NAME, PLATFORM_TARGET, target
)
print_message("Create archive {}.", archive_name)
files_to_archive = list(filter_install_dir(INSTALL_DIR))
files_to_archive += HOME.glob("BUILD_*/LOGS")
if COMPILE_CONFIG == "apple_all_static":
for subconfig in AppleXCFramework.subConfigNames:
base_dir = get_build_dir(subconfig)
files_to_archive += filter_install_dir(base_dir / "INSTALL")
if (base_dir / "meson_cross_file.txt").exists():
files_to_archive.append(base_dir / "meson_cross_file.txt")
if COMPILE_CONFIG.endswith("_mixed"):
static_config = COMPILE_CONFIG.replace("_mixed", "_static")
files_to_archive += filter_install_dir(get_build_dir(static_config) / "INSTALL")
if COMPILE_CONFIG.startswith("android_"):
if PLATFORM_TARGET == "native_mixed":
files_to_archive += filter_install_dir(HOME / "BUILD_native_static" / "INSTALL")
if PLATFORM_TARGET.startswith("android_"):
files_to_archive += filter_install_dir(HOME / "BUILD_neutral" / "INSTALL")
base_dir = get_build_dir(COMPILE_CONFIG)
base_dir = HOME / "BUILD_{}".format(PLATFORM_TARGET)
if (base_dir / "meson_cross_file.txt").exists():
files_to_archive.append(base_dir / "meson_cross_file.txt")
# Copy any toolchain
files_to_archive += [TOOLCHAIN_DIR]
files_to_archive += HOME.glob("BUILD_neutral/TOOLCHAINS/*")
files_to_archive += HOME.glob("BUILD_*/android-ndk*")
files_to_archive += HOME.glob("BUILD_*/emsdk*")
if (BASE_DIR / "meson_cross_file.txt").exists():
files_to_archive.append(BASE_DIR / "meson_cross_file.txt")
manifest_file = BASE_DIR / "manifest.txt"
write_manifest(manifest_file, archive_name, target, COMPILE_CONFIG)
write_manifest(manifest_file, archive_name, target, PLATFORM_TARGET)
files_to_archive.append(manifest_file)
relative_path = HOME
if full:
files_to_archive += ARCHIVE_DIR.glob(".*_ok")
files_to_archive += BASE_DIR.glob("*/.*_ok")
# Add also static build for mixed target
if COMPILE_CONFIG.endswith("_mixed"):
static_config = COMPILE_CONFIG.replace("_mixed", "_static")
files_to_archive += get_build_dir(static_config).glob("*/.*_ok")
# Native dyn and static is needed for potential cross compilation that use native tools (icu)
files_to_archive += get_build_dir("native_dyn").glob("*/.*_ok")
files_to_archive += get_build_dir("native_static").glob("*/.*_ok")
files_to_archive += HOME.glob("BUILD_*android*/**/.*_ok")
files_to_archive += HOME.glob("BUILD_*apple-macos*/**/.*_ok")
files_to_archive += HOME.glob("BUILD_*apple-ios*/**/.*_ok")
files_to_archive += (HOME / "BUILD_native_dyn").glob("*/.*_ok")
files_to_archive += (HOME / "BUILD_native_static").glob("*/.*_ok")
files_to_archive += HOME.glob("BUILD_android*/**/.*_ok")
files_to_archive += SOURCE_DIR.glob("*/.*_ok")
files_to_archive += SOURCE_DIR.glob("zim-testing-suite-*/*")
if PLATFORM_TARGET.startswith("armhf"):
files_to_archive += (SOURCE_DIR / "armhf").glob("*")
toolchains_subdirs = HOME.glob("BUILD_*/TOOLCHAINS/*/*")
for subdir in toolchains_subdirs:
if not subdir.match("tools"):
files_to_archive.append(subdir)
archive_file = TMP_DIR / archive_name
with tarfile.open(str(archive_file), "w:gz") as tar:
with tarfile.open(str(archive_file), "w:xz") as tar:
for name in set(files_to_archive):
print(".{}".format(name), flush=True)
tar.add(str(name), arcname=str(name.relative_to(relative_path)))
@ -461,28 +327,11 @@ def get_postfix(project):
return postfix
def sign_binary(path):
# We assume here that signtool and certificate are properly configured.
# Env var `SIGNTOOL_THUMBPRINT` must contain thumbprint of the certificate to use.
command = [
os.getenv("SIGNTOOL_PATH", "signtool.exe"),
"sign",
"/fd",
"sha256",
"/tr",
"http://ts.ssl.com",
"/td",
"sha256",
"/sha1",
os.environ["SIGNTOOL_THUMBPRINT"],
str(path),
]
subprocess.run(command, check=True)
def make_archive(project, make_release):
platform_name = get_platform_name()
if not platform_name:
try:
platform = PLATFORM_TO_RELEASE[PLATFORM_TARGET]
except KeyError:
# We don't know how to name the release.
return None
try:
@ -496,18 +345,12 @@ def make_archive(project, make_release):
else:
postfix = DATE
archive_name = "{}_{}-{}".format(project, platform_name, postfix)
archive_name = "{}_{}-{}".format(project, platform, postfix)
files_to_archive = []
for export_file in export_files:
files_to_archive.extend(base_dir.glob(export_file))
if make_release and platform.system() == "Windows":
for file in files_to_archive:
if str(file).endswith(".exe"):
sign_binary(file)
if platform_name == "win-i686" or platform.system() == "Windows":
if platform == "win-i686":
open_archive = lambda a: zipfile.ZipFile(
str(a), "w", compression=zipfile.ZIP_DEFLATED
)
@ -537,31 +380,15 @@ def create_desktop_image(make_release):
postfix = DATE
src_dir = SOURCE_DIR / "kiwix-desktop"
if COMPILE_CONFIG == "flatpak":
if PLATFORM_TARGET == "flatpak":
build_path = BASE_DIR / "org.kiwix.desktop.flatpak"
app_name = "org.kiwix.desktop.{}.flatpak".format(postfix)
print_message("archive is {}", build_path)
elif platform.system() == "Windows":
archive_basename = "kiwix-desktop_windows_x64_{}".format(postfix)
working_dir = INSTALL_DIR / archive_basename
build_path = Path(str(working_dir) + ".zip")
app_name = build_path.name
command = [
"python",
KBUILD_SOURCE_DIR / "scripts" / "package_kiwix-desktop_windows.py",
str(INSTALL_DIR),
str(working_dir),
str(build_path),
]
if make_release:
command += ["-s"]
print_message("Package archive of kiwix-desktop")
subprocess.check_call(command, cwd=str(HOME))
else:
build_path = HOME / "Kiwix-{}-x86_64.AppImage".format(postfix)
app_name = "kiwix-desktop_x86_64_{}.appimage".format(postfix)
command = [
KBUILD_SOURCE_DIR / "scripts" / "create_kiwix-desktop_appImage.sh",
"kiwix-build/scripts/create_kiwix-desktop_appImage.sh",
str(INSTALL_DIR),
str(src_dir),
str(HOME / "AppDir"),
@ -589,13 +416,9 @@ def update_flathub_git():
command = ["git", "clone", FLATPAK_HTTP_GIT_REMOTE]
call(command, cwd=TMP_DIR)
branch_name = "v_{}".format(get_postfix("kiwix-desktop"))
command = ["git", "checkout", "-b", branch_name]
call(command)
shutil.copy(str(BASE_DIR / "org.kiwix.desktop.json"), str(git_repo_dir))
patch_dir = KBUILD_SOURCE_DIR / "kiwixbuild" / "patches"
for dep in ["pugixml", "libmicrohttpd"]:
for dep in ["pugixml"]:
for f in patch_dir.glob("{}_*.patch".format(dep)):
shutil.copy(str(f), str(git_repo_dir / "patches"))
command = ["git", "add", "-A", "."]
@ -604,7 +427,7 @@ def update_flathub_git():
"git",
"commit",
"-m",
"Update to version {}".format(get_postfix("kiwix-desktop")),
"Update to version {}".format(main_project_versions["kiwix-desktop"]),
]
try:
call(command)
@ -613,7 +436,7 @@ def update_flathub_git():
return
command = ["git", "config", "remote.origin.pushurl", FLATPAK_GIT_REMOTE]
call(command)
command = ["git", "push", "origin", branch_name]
command = ["git", "push"]
env["GIT_SSH_COMMAND"] = "ssh -o StrictHostKeyChecking=no -i " + _environ.get(
"SSH_KEY"
)
@ -621,6 +444,7 @@ def update_flathub_git():
def fix_macos_rpath(project):
base_dir, export_files = EXPORT_FILES[project]
for file in filter(lambda f: f.endswith(".dylib"), export_files):
lib = base_dir / file
@ -631,7 +455,7 @@ def fix_macos_rpath(project):
subprocess.check_call(command, env=os.environ)
def trigger_workflow(repo, workflow="docker.yml", ref="main", inputs=None):
def trigger_workflow(repo, workflow="docker.yml", ref="master", inputs=None):
"""triggers a `workflow_dispatch` event to the specified workflow on its repo
repo: {user}/{repo} format
@ -639,35 +463,22 @@ def trigger_workflow(repo, workflow="docker.yml", ref="main", inputs=None):
ref: branch or tag name
inputs: dict of inputs to pass to the workflow"""
print_message(
"triggering workflow `{workflow}` on {repo}@{ref} " "with inputs={inputs}",
workflow=workflow,
repo=repo,
ref=ref,
inputs=inputs,
)
"triggering workflow `{workflow}` on {repo}@{ref} "
"with inputs={inputs}", workflow=workflow, repo=repo, ref=ref, inputs=inputs)
url = "{base_url}/repos/{repo}/actions/workflows/{workflow}/dispatches".format(
base_url=os.getenv("GITHUB_API_URL", "https://api.github.com"),
repo=repo,
workflow=workflow,
)
repo=repo, workflow=workflow)
resp = requests.post(
url,
headers={
resp = requests.post(url, headers={
"Content-Type": "application/json",
"Authorization": "token {token}".format(token=os.getenv("GITHUB_PAT", "")),
"Authorization": "token {token}".format(
token=os.getenv('GITHUB_PAT', '')),
"Accept": "application/vnd.github.v3+json",
},
json={"ref": ref, "inputs": inputs},
timeout=5,
)
}, json={"ref": ref, "inputs": inputs}, timeout=5)
if resp.status_code != 204:
raise ValueError(
"Unexpected HTTP {code}: {reason}".format(
code=resp.status_code, reason=resp.reason
)
)
raise ValueError("Unexpected HTTP {code}: {reason}".format(
code=resp.status_code, reason=resp.reason))
def trigger_docker_publish(target):
@ -675,14 +486,13 @@ def trigger_docker_publish(target):
return
version = get_postfix(target)
repo = {"zim-tools": "openzim/zim-tools", "kiwix-tools": "kiwix/kiwix-tools"}.get(
target
)
repo = {
"zim-tools": "openzim/zim-tools",
"kiwix-tools": "kiwix/kiwix-tools"}.get(target)
try:
trigger_workflow(
repo, workflow="docker.yml", ref="main", inputs={"version": version}
)
trigger_workflow(repo, workflow="docker.yml", ref="master",
inputs={"version": version})
print_message("triggered docker workflow on {repo}", repo=repo)
except Exception as exc:
print_message("Error triggering workflow: {exc}", exc=exc)
@ -690,52 +500,39 @@ def trigger_docker_publish(target):
def notarize_macos_build(project):
"""sign and notarize files for macOS
""" sign and notarize files for macOS
Expects the following environment:
- `SIGNING_IDENTITY` environ with Certificate name/identity
- `KEYCHAIN` environ with path to the keychain storing credentials
- `KEYCHAIN_PROFILE` environ with name of the profile in that keychain
- `KEYCHAIN_PASSWORD` environ with password to unlock the keychain
"""
Expects the following environment:
- `SIGNING_IDENTITY` environ with Certificate name/identity
- `KEYCHAIN` environ with path to the keychain storing credentials
- `KEYCHAIN_PROFILE` environ with name of the profile in that keychain
- `KEYCHAIN_PASSWORD` environ with password to unlock the keychain
"""
if project != "libzim":
return
# currently only supports libzim use case: sign every dylib
base_dir, export_files = EXPORT_FILES[project]
filepaths = [
base_dir.joinpath(file)
for file in filter(lambda f: f.endswith(".dylib"), export_files)
if not base_dir.joinpath(file).is_symlink()
]
filepaths = [base_dir.joinpath(file)
for file in filter(lambda f: f.endswith(".dylib"), export_files)
if not base_dir.joinpath(file).is_symlink()]
if not filepaths:
return
for filepath in filepaths:
subprocess.check_call(
[
"/usr/bin/codesign",
"--force",
"--sign",
os.getenv("SIGNING_IDENTITY", "no-signing-ident"),
"--keychain",
os.getenv("KEYCHAIN", "no-keychain-path"),
str(filepath),
"--deep",
"--timestamp",
],
env=os.environ,
)
subprocess.check_call(["/usr/bin/codesign", "--force", "--sign",
os.getenv("SIGNING_IDENTITY", "no-signing-ident"),
"--keychain",
os.getenv("KEYCHAIN", "no-keychain-path"),
str(filepath), "--deep", "--timestamp"], env=os.environ)
# create a zip of the dylibs and upload for notarization
zip_name = "{}.zip".format(project)
subprocess.check_call(
["/usr/bin/ditto", "-c", "-k", "--keepParent"]
+ [str(f) for f in filepaths]
+ [zip_name],
env=os.environ,
)
+ [str(f) for f in filepaths] + [zip_name],
env=os.environ)
# make sure keychain is unlocked
subprocess.check_call(

View File

@ -6,17 +6,31 @@ from common import (
run_kiwix_build,
make_deps_archive,
upload,
COMPILE_CONFIG,
DEV_BRANCH,
OS_NAME,
PLATFORM_TARGET,
DESKTOP,
KIWIX_DESKTOP_ONLY,
)
from build_definition import select_build_targets, DEPS
for target in select_build_targets(DEPS):
run_kiwix_build(target, config=COMPILE_CONFIG, build_deps_only=True)
archive_file = make_deps_archive(target=target)
if DEV_BRANCH:
destination = "/data/tmp/ci/dev_preview/" + DEV_BRANCH
if PLATFORM_TARGET.startswith("android_") or PLATFORM_TARGET.startswith("iOS"):
TARGETS = ("libzim", "libkiwix")
elif PLATFORM_TARGET == "wasm":
TARGETS = ("libzim", )
elif PLATFORM_TARGET.startswith("native_"):
if OS_NAME == "osx":
TARGETS = ("libzim", "zim-tools", "libkiwix")
else:
destination = "/data/tmp/ci"
upload(archive_file, "ci@tmp.kiwix.org:30022", destination)
if DESKTOP:
TARGETS = ("kiwix-desktop",)
elif PLATFORM_TARGET == "native_mixed":
TARGETS = ("libzim",)
else:
TARGETS = ("libzim", "zim-tools", "libkiwix", "kiwix-tools")
else:
TARGETS = ("libzim", "zim-tools", "libkiwix", "kiwix-tools")
for target in TARGETS:
run_kiwix_build(target, platform=PLATFORM_TARGET, build_deps_only=True)
archive_file = make_deps_archive(target=target)
upload(archive_file, "ci@tmp.kiwix.org:30022", "/data/tmp/ci")
os.remove(str(archive_file))

View File

@ -13,12 +13,10 @@ from common import (
upload,
make_deps_archive,
HOME,
COMPILE_CONFIG,
PLATFORM_TARGET,
OS_NAME,
MAKE_RELEASE,
)
def download_base_archive(base_name):
url = "http://tmp.kiwix.org/ci/{}".format(base_name)
file_path = str(HOME / base_name)
@ -32,41 +30,29 @@ def download_base_archive(base_name):
file.write(batch)
return file_path
ARCHIVE_NAME_TEMPLATE = "base_deps2_{os}_{platform}_{version}.tar.xz"
def get_archive_name():
ARCHIVE_NAME_TEMPLATE = "base_deps_{os}_{config}_{version}.tar.gz"
if COMPILE_CONFIG == "flatpak":
return "base_deps_flatpak.tar.gz"
return ARCHIVE_NAME_TEMPLATE.format(
if PLATFORM_TARGET == 'flatpak':
base_dep_archive_name = "base_deps2_flatpak.tar.xz"
else:
base_dep_archive_name = ARCHIVE_NAME_TEMPLATE.format(
os=OS_NAME,
config=COMPILE_CONFIG,
platform=PLATFORM_TARGET,
version=base_deps_meta_version,
)
def main():
base_dep_archive_name = get_archive_name()
print_message("Getting archive {}", base_dep_archive_name)
try:
local_filename = download_base_archive(base_dep_archive_name)
with tarfile.open(local_filename) as f:
f.extractall(str(HOME))
os.remove(str(local_filename))
except URLError:
if COMPILE_CONFIG == "flatpak":
print_message("Cannot get archive. Move on")
else:
print_message("Cannot get archive. Build dependencies")
run_kiwix_build("alldependencies", config=COMPILE_CONFIG)
archive_file = make_deps_archive(name=base_dep_archive_name, full=True)
upload(archive_file, "ci@tmp.kiwix.org:30022", "/data/tmp/ci")
os.remove(str(archive_file))
if __name__ == "__main__":
if MAKE_RELEASE:
print_message("We are building release. Don't download deps archive.")
print_message("Getting archive {}", base_dep_archive_name)
try:
local_filename = download_base_archive(base_dep_archive_name)
with tarfile.open(local_filename) as f:
f.extractall(str(HOME))
os.remove(str(local_filename))
except URLError:
if PLATFORM_TARGET == "flatpak":
print_message("Cannot get archive. Move on")
else:
main()
print_message("Cannot get archive. Build dependencies")
run_kiwix_build("alldependencies", platform=PLATFORM_TARGET)
archive_file = make_deps_archive(name=base_dep_archive_name, full=True)
upload(archive_file, "ci@tmp.kiwix.org:30022", "/data/tmp/ci")
os.remove(str(archive_file))

View File

@ -1,17 +0,0 @@
#!/usr/bin/env python3
from common import (
trigger_docker_publish,
MAKE_RELEASE,
)
from build_definition import select_build_targets, DOCKER
# Filter what to build if we are doing a release.
if MAKE_RELEASE:
docker_trigger = select_build_targets(DOCKER)
else:
docker_trigger = []
for target in docker_trigger:
trigger_docker_publish(target)

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
import tarfile
from pathlib import Path
from common import upload, OS_NAME, COMPILE_CONFIG, HOME
ARCHIVE_NAME = Path(f"fail_log_{OS_NAME}_{COMPILE_CONFIG}.tar.gz")
files_to_archive = []
files_to_archive += HOME.glob("BUILD_*")
files_to_archive += [HOME / "SOURCE", HOME / "LOGS", HOME / "TOOLCHAINS"]
with tarfile.open(ARCHIVE_NAME, "w:xz") as tar:
for name in set(files_to_archive):
tar.add(str(name))
upload(ARCHIVE_NAME, "ci@tmp.kiwix.org:30022", "/data/tmp/ci")

16
.github/scripts/upload_failure_logs.sh vendored Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -e
cd $HOME
ARCHIVE_NAME=fail_log_${OS_NAME}_${PLATFORM_TARGET}.tar.gz
tar -czf ${ARCHIVE_NAME} $HOME/BUILD_* $HOME/SOURCE $HOME/LOGS $HOME/TOOLCHAINS
echo "Uploading archive $ARCHIVE_NAME"
scp -P 30022 -p -i ${SSH_KEY} \
-o PasswordAuthentication=no \
-o StrictHostKeyChecking=no \
$ARCHIVE_NAME \
ci@tmp.kiwix.org:/data/tmp/ci

15
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,15 @@
daysUntilClose: false
staleLabel: stale
issues:
daysUntilStale: 60
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be now be reviewed manually. Thank you
for your contributions.
pulls:
daysUntilStale: 7
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be now be reviewed manually. Thank you
for your contributions.

View File

@ -1,326 +0,0 @@
name: CD
on:
push:
tags:
- r_[0-9]+
schedule:
- cron: '0 3 * * *'
jobs:
Windows:
strategy:
fail-fast: false
matrix:
config:
- native_mixed
- native_dyn
- native_static
runs-on: windows-2022
env:
OS_NAME: windows
COMPILE_CONFIG: ${{matrix.config}}
HOME: 'C:\\Users\\runneradmin'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install packages
run: |
choco.exe install pkgconfiglite ninja
- name: Install python modules
shell: bash
run: |
pip3 install meson pytest requests distro paramiko
pip3 install --no-deps $GITHUB_WORKSPACE
- name: Install QT
if: ${{ matrix.config == 'native_mixed' }}
uses: jurplel/install-qt-action@v4
with:
version: 5.15.2
modules: "qtwebengine"
setup-python: false
env:
AQT_CONFIG: ${{ github.workspace }}/.github/configs/aqt.ini
- name: Setup MSVC compiler
uses: bus1/cabuild/action/msdevshell@v1
with:
architecture: x64
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Install and configure eSigner CKA and Windows SDK
if: github.event_name == 'push'
env:
ESIGNER_URL: https://github.com/SSLcom/eSignerCKA/releases/download/v1.0.7/SSL.COM-eSigner-CKA_1.0.7.zip
run: |
Set-StrictMode -Version 'Latest'
# Download and Unzip eSignerCKA Setup
Invoke-WebRequest -OutFile eSigner_CKA_Setup.zip "$env:ESIGNER_URL"
Expand-Archive -Force eSigner_CKA_Setup.zip
Remove-Item eSigner_CKA_Setup.zip
Move-Item -Destination “eSigner_CKA_Installer.exe” -Path “eSigner_CKA_*\*.exe”
# Install eSignerCKA
New-Item -ItemType Directory -Force -Path "C:\esigner"
./eSigner_CKA_Installer.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR=”C:\esigner” /TYPE=automatic | Out-Null
Remove-Item "eSigner_CKA_Installer.exe"
# Configure the CKA with SSL.com credentials
C:\esigner\eSignerCKATool.exe config -mode product -user "${{ secrets.ESIGNER_USERNAME }}" -pass "${{ secrets.ESIGNER_PASSWORD }}" -totp "${{ secrets.ESIGNER_TOTP_SECRET }}" -key "C:\esigner\master.key" -r
C:\esigner\eSignerCKATool.exe unload
C:\esigner\eSignerCKATool.exe load
# Find certificate
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
echo Certificate: $CodeSigningCert
# Extract thumbprint and subject name
$Thumbprint = $CodeSigningCert.Thumbprint
echo "SIGNTOOL_THUMBPRINT=$Thumbprint" >> $env:GITHUB_ENV
- name: Ensure base deps
run: |
python .github\\scripts\\ensure_base_deps.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Build Release
run: |
python .github\\scripts\\build_release_nightly.py
env:
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x86/signtool.exe"
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Upload failure logs
if: failure()
run: |
python .github\\scripts\\upload_failure_logs.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
Linux:
strategy:
fail-fast: false
matrix:
config:
- native_static
- native_mixed
- native_dyn
- wasm
- armv6_static
- armv6_mixed
- armv8_static
- armv8_mixed
- aarch64_static
- aarch64_mixed
- aarch64_musl_static
- aarch64_musl_mixed
- x86-64_musl_static
- x86-64_musl_mixed
- i586_static
- android_arm
- android_arm64
- android_x86
- android_x86_64
image_variant: ['focal']
include:
- config: native_mixed
image_variant: manylinux
- config: aarch64_mixed
image_variant: manylinux
- config: native_dyn
image_variant: jammy
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
runs-on: ubuntu-22.04
container:
image: "ghcr.io/kiwix/kiwix-build_ci_${{matrix.image_variant}}:2024-11-30"
options: "--device /dev/fuse --privileged"
steps:
- name: Checkout code
shell: bash
run: |
cd $HOME
git clone https://github.com/${REP}
cd ./${REP##*/}
git checkout --force ${GITHUB_SHA}
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: Ensure base deps
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/ensure_base_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
- name: Build release
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/build_release_nightly.py
env:
COMPILE_CONFIG: ${{matrix.config}}
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.py
env:
COMPILE_CONFIG: ${{matrix.config}}
Flatpak:
strategy:
fail-fast: false
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
COMPILE_CONFIG: flatpak
OS_NAME: focal
runs-on: ubuntu-22.04
steps:
- name: Checkout code
shell: bash
run: |
cd $HOME
git clone https://github.com/${REP}
cd ./${REP##*/}
git checkout --force ${GITHUB_SHA}
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
- name: Install flatpak tools
run: |
sudo apt-get update
sudo apt-get install flatpak-builder ninja-build meson
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: Ensure base deps
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/ensure_base_deps.py
- name: Build release
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/build_release_nightly.py
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.py
Macos:
strategy:
fail-fast: false
matrix:
config:
- native_dyn
- native_static
- native_mixed
- macOS_arm64_static
- macOS_arm64_mixed
- apple_all_static
runs-on: macos-13
env:
SSH_KEY: /tmp/id_rsa
OS_NAME: macos
CERTIFICATE: /tmp/wmch-devid.p12
SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
KEYCHAIN: /Users/runner/build.keychain-db
KEYCHAIN_PASSWORD: mysecretpassword
KEYCHAIN_PROFILE: build-profile
steps:
- name: Set Xcode version (15.0.1)
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
run: sudo xcode-select -s /Applications/Xcode_15.0.1.app
- name: Checkout code
uses: actions/checkout@v4
- name: Setup python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install packages
run:
brew install automake # ninja
- name: Install python modules
run: |
pip3 install meson pytest requests distro
pip3 install --no-deps $GITHUB_WORKSPACE
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: install Apple certificate
shell: bash
run: |
echo "${{ secrets.APPLE_SIGNING_CERTIFICATE }}" | base64 --decode -o $CERTIFICATE
security create-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN
security default-keychain -s $KEYCHAIN
security set-keychain-settings $KEYCHAIN
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN
security import $CERTIFICATE -k $KEYCHAIN -P "${{ secrets.APPLE_SIGNING_P12_PASSWORD }}" -A -T "/usr/bin/codesign"
rm $CERTIFICATE
security set-key-partition-list -S apple-tool:,apple: -s -k $KEYCHAIN_PASSWORD $KEYCHAIN
security find-identity -v $KEYCHAIN
xcrun notarytool store-credentials \
--apple-id "${{ secrets.APPLE_SIGNING_ALTOOL_USERNAME }}" \
--password "${{ secrets.APPLE_SIGNING_ALTOOL_PASSWORD }}" \
--team-id "${{ secrets.APPLE_SIGNING_TEAM }}" \
--validate \
--keychain $KEYCHAIN \
$KEYCHAIN_PROFILE
- name: Ensure base deps
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/ensure_base_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
- name: Build release
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/build_release_nightly.py
env:
COMPILE_CONFIG: ${{matrix.config}}
- name: Upload failure logs
if: failure()
run: $GITHUB_WORKSPACE/.github/scripts/upload_failure_logs.py
env:
COMPILE_CONFIG: ${{matrix.config}}
Trigger_Docker:
needs: [Linux]
runs-on: ubuntu-22.04
env:
COMPILE_CONFIG: native_static
OS_NAME: focal
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install python modules
shell: bash
run: |
pip3 install --user --no-deps $GITHUB_WORKSPACE
- name: Trigger docker workflow
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/trigger_docker_workflow.py
env:
GITHUB_PAT: ${{secrets.DOCKER_TRIGGER_GITHUB_PAT}}

View File

@ -6,119 +6,39 @@ on:
- cron: '0 1 * * *'
jobs:
Windows:
strategy:
fail-fast: false
matrix:
config:
- native_mixed
- native_dyn
- native_static
runs-on: windows-2022
env:
OS_NAME: windows
COMPILE_CONFIG: ${{matrix.config}}
HOME: 'C:\\Users\\runneradmin'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install packages
run: |
choco.exe install pkgconfiglite ninja
- name: Install python modules
shell: bash
run: |
pip3 install meson pytest requests distro paramiko
pip3 install --no-deps $GITHUB_WORKSPACE
- name: Install QT
if: ${{ matrix.config == 'native_mixed' }}
uses: jurplel/install-qt-action@v4
with:
version: 6.4.3
modules: "qtwebengine qtwebchannel qtpositioning"
setup-python: false
env:
AQT_CONFIG: ${{ github.workspace }}/.github/configs/aqt.ini
- name: Setup MSVC compiler
uses: bus1/cabuild/action/msdevshell@v1
with:
architecture: x64
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Ensure base deps
run: |
python .github\\scripts\\ensure_base_deps.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Compile all deps
run: |
python .github\\scripts\\compile_all_deps.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Build projects
run: |
python .github\\scripts\\build_projects.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
- name: Upload failure logs
if: failure()
run: |
python .github\\scripts\\upload_failure_logs.py
env:
SSH_KEY: ${{ runner.temp }}/id_rsa
Linux:
strategy:
fail-fast: false
matrix:
config:
target:
- native_static
- native_dyn
- native_mixed
- native_desktop
- wasm
- armv6_static
- armv6_dyn
- armv6_mixed
- armv8_static
- armv8_dyn
- armv8_mixed
- aarch64_static
- aarch64_dyn
- aarch64_mixed
- aarch64_musl_static
- aarch64_musl_dyn
- aarch64_musl_mixed
- x86-64_musl_static
- x86-64_musl_mixed
- armhf_static
- armhf_dyn
- i586_static
- i586_dyn
- android_arm
- android_arm64
- android_x86
- android_x86_64
image_variant: ['focal']
image_variant: ['bionic']
lib_postfix: ['/x86_64-linux-gnu']
include:
- config: native_mixed
image_variant: manylinux
- config: aarch64_mixed
image_variant: manylinux
- config: native_dyn
image_variant: jammy
- target: win32_static
image_variant: f35
lib_postfix: '64'
- target: win32_dyn
image_variant: f35
lib_postfix: '64'
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
OS_NAME: ${{matrix.image_variant}}
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
container:
image: "ghcr.io/kiwix/kiwix-build_ci_${{matrix.image_variant}}:2024-11-30"
image: "ghcr.io/kiwix/kiwix-build_ci_${{matrix.image_variant}}:dev"
options: "--device /dev/fuse --privileged"
steps:
- name: Checkout code
@ -131,10 +51,6 @@ jobs:
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
- name: Install paramiko
if: ${{matrix.image_variant != 'bionic' }}
shell: bash
run: pip3 install --user paramiko
- name: secret
shell: bash
run: |
@ -146,26 +62,26 @@ jobs:
cd $HOME
kiwix-build/.github/scripts/ensure_base_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Compile all deps
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/compile_all_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Build projects
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/build_projects.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.py
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.sh
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
Flatpak:
strategy:
@ -173,9 +89,9 @@ jobs:
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
COMPILE_CONFIG: flatpak
PLATFORM_TARGET: flatpak
OS_NAME: focal
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
shell: bash
@ -184,7 +100,6 @@ jobs:
git clone https://github.com/${REP}
cd ./${REP##*/}
git checkout --force ${GITHUB_SHA}
pip3 install --user paramiko
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
@ -209,43 +124,37 @@ jobs:
kiwix-build/.github/scripts/build_projects.py
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.py
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.sh
Macos:
strategy:
fail-fast: false
matrix:
config:
target:
- native_dyn
- native_static
- native_mixed
- iOS_arm64
- iOSSimulator_x86_64
- iOSSimulator_arm64
- macOS_arm64_static
- macOS_arm64_mixed
- iOS_x86_64
- iOS_Mac_ABI
- macOS_arm64
- macOS_x86_64
- apple_all_static
runs-on: macos-13
runs-on: macos-latest
env:
SSH_KEY: /tmp/id_rsa
OS_NAME: macos
OS_NAME: osx
steps:
- name: Set Xcode version (15.0.1)
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
run: sudo xcode-select -s /Applications/Xcode_15.0.1.app
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python 3.10
uses: actions/setup-python@v5
uses: actions/checkout@v3
- name: Setup python 3.8
uses: actions/setup-python@v3
with:
python-version: '3.10'
python-version: '3.8'
- name: Install packages
run:
brew install automake # ninja
brew install pkg-config ninja automake autoconf
- name: Install python modules
run: |
pip3 install meson pytest requests distro paramiko
pip3 install meson pytest requests distro
pip3 install --no-deps $GITHUB_WORKSPACE
- name: secret
shell: bash
@ -258,23 +167,23 @@ jobs:
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/ensure_base_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Compile all deps
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/compile_all_deps.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Build projects
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/build_projects.py
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}
- name: Upload failure logs
if: failure()
run: $GITHUB_WORKSPACE/.github/scripts/upload_failure_logs.py
run: $GITHUB_WORKSPACE/.github/scripts/upload_failure_logs.sh
env:
COMPILE_CONFIG: ${{matrix.config}}
PLATFORM_TARGET: ${{matrix.target}}

43
.github/workflows/container_images.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Container images CD
on:
push:
paths:
- 'ci_images/**'
release:
types: [published]
env:
IMAGE_PREFIX: ghcr.io/kiwix/kiwix-build_ci_
jobs:
Container:
strategy:
fail-fast: false
matrix:
variant: [bionic, f35, focal, alpine]
runs-on: ubuntu-22.04
steps:
- name: Retrieve the code
uses: actions/checkout@v3
- name: Setup container image name
id: env
run: |
echo "IMAGE_NAME=${{ env.IMAGE_PREFIX }}${{ matrix.variant }}" >> $GITHUB_OUTPUT
- name: Build container image
run: |
docker build -t ${{ steps.env.outputs.IMAGE_NAME }}:dev - < ci_images/${{ matrix.variant }}_builder.dockerfile
- name: Tag release container image
if: github.event.action == 'published'
run: |
docker tag ${{ steps.env.outputs.IMAGE_NAME }}:dev $GITHUB_REF_NAME
docker tag ${{ steps.env.outputs.IMAGE_NAME }}:dev latest
- name: Upload container image
run: |
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin
docker push --all-tags ${{ steps.env.outputs.IMAGE_NAME }}

227
.github/workflows/releaseNigthly.yml vendored Normal file
View File

@ -0,0 +1,227 @@
name: Release&Nigthly
on:
push:
tags:
- r_[0-9]+
schedule:
- cron: '0 1 * * *'
jobs:
Linux:
strategy:
fail-fast: false
matrix:
target:
- native_static
- native_dyn
- native_mixed
- native_desktop
- wasm
- armhf_static
- win32_static
- i586_static
- android_arm
- android_arm64
- android_x86
- android_x86_64
include:
- target: native_static
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: native_dyn
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: native_mixed
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: native_desktop
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: wasm
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: armhf_static
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: win32_static
image_variant: f35
lib_postfix: '64'
- target: i586_static
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: android_arm
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: android_arm64
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: android_x86
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
- target: android_x86_64
image_variant: bionic
lib_postfix: '/x86_64-linux-gnu'
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
runs-on: ubuntu-latest
needs: Docker
container:
image: "kiwix/kiwix-build_ci:${{matrix.image_variant}}-32"
options: "--device /dev/fuse --privileged"
steps:
- name: Checkout code
shell: bash
run: |
cd $HOME
git clone https://github.com/${REP}
cd ./${REP##*/}
git checkout --force ${GITHUB_SHA}
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: Ensure base deps
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/ensure_base_deps.py
env:
PLATFORM_TARGET: ${{matrix.target}}
- name: Build release
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/build_release_nightly.py
env:
PLATFORM_TARGET: ${{matrix.target}}
BINTRAY_USER: kiwix
BINTRAY_PASS: ${{secrets.bintray_pass}}
GITHUB_PAT: ${{secrets.GHCR_TOKEN}}
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.sh
env:
PLATFORM_TARGET: ${{matrix.target}}
Flatpak:
strategy:
fail-fast: false
env:
HOME: /home/runner
SSH_KEY: /tmp/id_rsa
PLATFORM_TARGET: flatpak
OS_NAME: focal
runs-on: ubuntu-latest
steps:
- name: Checkout code
shell: bash
run: |
cd $HOME
git clone https://github.com/${REP}
cd ./${REP##*/}
git checkout --force ${GITHUB_SHA}
pip3 install --user --no-deps .
env:
REP: ${{github.repository}}
- name: Install flatpak tools
run: |
sudo apt-get update
sudo apt-get install flatpak-builder ninja-build meson
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: Ensure base deps
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/ensure_base_deps.py
- name: Build release
shell: bash
run: |
cd $HOME
kiwix-build/.github/scripts/build_release_nightly.py
- name: Upload failure logs
if: failure()
run: $HOME/kiwix-build/.github/scripts/upload_failure_logs.sh
Macos:
strategy:
fail-fast: false
matrix:
target:
- native_dyn
- native_mixed
runs-on: macos-latest
env:
SSH_KEY: /tmp/id_rsa
OS_NAME: osx
CERTIFICATE: /tmp/wmch-devid.p12
SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
KEYCHAIN: /Users/runner/build.keychain-db
KEYCHAIN_PASSWORD: mysecretpassword
KEYCHAIN_PROFILE: build-profile
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup python 3.8
uses: actions/setup-python@v3
with:
python-version: '3.8'
- name: Install packages
run:
brew install pkg-config ninja automake autoconf
- name: Install python modules
run: |
pip3 install meson pytest requests distro
pip3 install --no-deps $GITHUB_WORKSPACE
- name: secret
shell: bash
run: |
echo "${{secrets.ssh_key}}" > $SSH_KEY
chmod 600 $SSH_KEY
- name: install Apple certificate
shell: bash
run: |
echo "${{ secrets.APPLE_SIGNING_CERTIFICATE }}" | base64 --decode -o $CERTIFICATE
security create-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN
security default-keychain -s $KEYCHAIN
security set-keychain-settings $KEYCHAIN
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN
security import $CERTIFICATE -k $KEYCHAIN -P "${{ secrets.APPLE_SIGNING_P12_PASSWORD }}" -A -T "/usr/bin/codesign"
rm $CERTIFICATE
security set-key-partition-list -S apple-tool:,apple: -s -k $KEYCHAIN_PASSWORD $KEYCHAIN
security find-identity -v $KEYCHAIN
xcrun notarytool store-credentials \
--apple-id "${{ secrets.APPLE_SIGNING_ALTOOL_USERNAME }}" \
--password "${{ secrets.APPLE_SIGNING_ALTOOL_PASSWORD }}" \
--team-id "${{ secrets.APPLE_SIGNING_TEAM }}" \
--validate \
--keychain $KEYCHAIN \
$KEYCHAIN_PROFILE
- name: Ensure base deps
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/ensure_base_deps.py
env:
PLATFORM_TARGET: ${{matrix.target}}
- name: Build release
shell: bash
run: |
cd $HOME
$GITHUB_WORKSPACE/.github/scripts/build_release_nightly.py
env:
PLATFORM_TARGET: ${{matrix.target}}
- name: Upload failure logs
if: failure()
run: $GITHUB_WORKSPACE/.github/scripts/upload_failure_logs.sh
env:
PLATFORM_TARGET: ${{matrix.target}}

View File

@ -1,3 +1,2 @@
include kiwixbuild/templates/*_cross_file.txt
include kiwixbuild/patches/*.patch
include kiwixbuild/dependencies/icu4c_data_filter.json

View File

@ -4,15 +4,9 @@ Kiwix Build provides advanced tools to (cross-)compile easily
[Kiwix](https://kiwix.org) & [openZIM](https://openzim.org) softwares
and libraries and deploy them. They have been tested on
[Fedora](https://getfedora.org) 35+ & [Ubuntu](https://ubuntu.com)
20.04+.
18.04+.
Kiwix Build audience is:
* Advanced users who don't want/can handle all the dependencies
compilations manually
* Kiwix developer team for its own CI/CD
[![CI Build Status](https://github.com/kiwix/kiwix-build/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/kiwix/kiwix-build/actions/workflows/ci.yml?query=branch%3Amain)
[![CD Build Status](https://github.com/kiwix/kiwix-build/actions/workflows/cd.yml/badge.svg?branch=main)](https://github.com/kiwix/kiwix-build/actions/workflows/cd.yml?query=branch%3Amain)
[![Build Status](https://github.com/kiwix/kiwix-build/workflows/CI/badge.svg?query=branch%3Amain)](https://github.com/kiwix/kiwix-build/actions?query=branch%3Amain)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
Prerequisites
@ -78,17 +72,19 @@ invalid choice: 'not-existing-target' (choose from 'alldependencies', 'android-n
...
```
#### Config
#### Target platform
If no config is specified, the default will be `native_dyn`.
If no target platform is specified, the default will be `native_dyn`.
You can select another config using the option
`--config`. For now, there is ten different supported
You can select another target platform using the option
`--target-platform`. For now, there is ten different supported
platforms:
- native_dyn
- native_mixed
- native_static
- win32_dyn
- win32_static
- android
- android_arm
- android_arm64
@ -96,31 +92,42 @@ platforms:
- android_x86_64
- flatpak
All `native_*` config means using the native compiler without any cross-compilation option.
Other may simply use cross-compilation or may download a specific toolchain to use.
So, if you want to compile `kiwix-tools` for win32 using static linkage:
```bash
kiwix-build --target-platform win32_dyn
```
Android
-------
`kiwix-android` (https://github.com/kiwix/kiwix-android) depends of
the `libkiwix` project.
It uses a special `.aar` file that represent (and embed) the libkiwix for
all supported android arch. This is a kind of fat archive we have for MacOs.
The `.aar` file is build using the `libkiwix-app` project.
`libkiwix-app` itself is architecture independent (it is just a packaging of
other archives) but it use `libkiwix` who is architecture dependent.
When building `libkiwix`, you should directly use the
target-platform `android_<arch>`:
```bash
kiwix-build libkiwix --config android_arm
kiwix-build libkiwix --target-platform android_arm
```
You may directly use the special config `android` which will build different android architectures
But, `libkiwix-app` is mainly multi arch.
To compile `libkiwix-app`, you must use the `android` platform:
```bash
kiwix-build --config android libkiwix
kiwix-build --target-platform android libkiwix-app
kiwix-build libkiwix-app # because `android` platform is the default for `libkiwix-app`
```
By default, it will build for all android architecture,
you can limit this with option `--android-arch`:
By default, when using platform `android`, `libkiwix` will be build for
all architectures. This can be changed by using the option `--android-arch`:
```bash
kiwix-build libkiwix --config android --android-arch arm # aar with arm architecture
kiwix-build libkiwix --config android --android-arch arm --android-arch arm64 # aan with arm and arm64 architectures
kiwix-build libkiwix-app # aar with all architectures
kiwix-build libkiwix-app --android-arch arm # aar with arm architecture
kiwix-build libkiwix-app --android-arch arm --android-arch arm64 # aan with arm and arm64 architectures
```
To build `kiwix-android` itself, you should see the documentation of `kiwix-android`.
@ -135,13 +142,13 @@ To do so, you should directly use the target-platfrom `ios_multi`.
As for `android`, `kiwix-build` will build the library several times
(once for each platform) and then create the fat library.
```bash
kiwix-build --config iOS_multi libkiwix
kiwix-build --target-platform iOS_multi libkiwix
```
You can specify the supported architectures with the option `--ios-arch`:
```bash
kiwix-build --config iOS_multi libkiwix # all architetures
kiwix-build --config iOS_multi --ios-arch arm --ios-arch arm64 # arm and arm64 arch only
kiwix-build --target-platform iOS_multi libkiwix # all architetures
kiwix-build --target-platform iOS_multi --ios-arch arm --ios-arch arm64 # arm and arm64 arch only
```
Outputs
@ -150,13 +157,31 @@ Outputs
Kiwix-build.py will create several directories:
- `ARCHIVES`: All the downloaded archives go there.
- `SOURCES`: All the sources (extracted from archives and patched) go there.
- `BUILD_<config>`: All the build files go there.
- `BUILD_<config>/INSTALL`: The installed files go there.
- `BUILD_<config>/LOGS`: The logs files of the build.
- `BUILD_<target_platform>`: All the build files go there.
- `BUILD_<target_platform>/INSTALL`: The installed files go there.
- `BUILD_<target_platform>/LOGS`: The logs files of the build.
If you want to install all those directories elsewhere, you can pass the
`--working-dir` option to `kiwix-build`:
CI/CD containerised environments
--------------------------------
Beside the `kiwix-build` command line tool, Kiwix Build proposes
[prepared compilation environments for multiple GNU/Linux
systems](.github/ci_images/) too.
These prepared environments include: compilers, binary toolchains and
any third-party tool necessary to run the compilation toolchain. They
don't contain pre-compiled library dependences build by kiwix-build, (like Xapian, Libicu,
Libmicrohttps, ...) but it contains dependencies installed with package manager.
These container images are necessary and intended to be used by Kiwix
itself in many of its CI. But they are free to download et can be
reused, although they can break anytime, therefore at your won risk.
You can find them on
[here](https://github.com/orgs/kiwix/packages?repo_name=kiwix-build).
Troubleshooting
---------------

View File

@ -1 +0,0 @@
node_modules

View File

@ -1,55 +0,0 @@
# Download dependencies archive action
This action download dependencies archive made by kiwix-build.
It is intended to be used in projects using theses dependencies
## Inputs
### `base_url`
The base url where we can download the archive.
This input is provided for greater customization but you probably shouldn't set it.
### `os_name`
The os "name" on which the compilation is done.
By default this use the `OS_NAME` env var, which is set in the docker file.
### `target_platform`
**Required** The targeted platform. Must be provided. Values are kind of :
- native_dyn
- android_arm
- ...
### `project`
The name of the project being compiled.
By default, the name of the repository.
### `branch`
The name of the "branch" to try to download (`/dev_preview/<branch>`).
By default, the current branch on which the action is run.
### `extract_dir`
Where to extract the dependencies archive. By default it is `$HOME`
## Example usage
```yaml
uses: kiwix/kiwix-build/actions/dl_deps_archive@main
with:
target_platform: ${{ matrix.target_platform }}
```
```
uses: kiwix/kiwix-build/actions/dl_deps_archive@main
with:
target_platform: native_mixed
os_name: windows
```

View File

@ -1,25 +0,0 @@
name: 'DL deps archive'
description: 'Download the dependencies archive of the project'
inputs:
base_url: # id of input
description: 'What is the base url to download the archive'
required: false
default: 'https://tmp.kiwix.org/ci'
os_name:
description: "On which os are we running. [Default to env var `OS_NAME`]"
required: false
target_platform:
description: "What platform are we targetting"
required: true
project:
description: "What project are we building"
required: false
branch:
description: "On which branch are we ?"
required: false
extract_dir:
description: "Where to extract our dependencies. [Default to env var `HOME`]"
required: false
runs:
using: 'node20'
main: 'dist/index.js'

File diff suppressed because one or more lines are too long

View File

@ -1,59 +0,0 @@
const tc = require("@actions/tool-cache");
const core = require("@actions/core");
const path = require("path");
const os = require("os");
function getInput(name, dflt) {
const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`];
if (!val) {
return dflt;
}
return val;
}
function addLocalPath(inputPath) {
process.env["PATH"] = `${inputPath}${path.delimiter}${process.env["PATH"]}`;
}
async function run() {
try {
const base_url = core.getInput("base_url");
const target = core.getInput("target_platform");
const project = getInput(
"project",
process.env["GITHUB_REPOSITORY"].split("/")[1],
);
const branch = getInput(
"branch",
process.env["GITHUB_HEAD_REF"] || process.env["GITHUB_REF_NAME"],
);
const extract_dir = getInput(
"extract_dir",
process.env["HOME"] || process.env["GITHUB_WORKSPACE"],
);
let archivePath;
try {
const archive_url = `${base_url}/dev_preview/${branch}/deps_${target}_${project}.tar.gz`;
process.stdout.write("Downloading " + archive_url + "\n");
archivePath = await tc.downloadTool(archive_url);
} catch (error) {
const archive_url = `${base_url}/deps_${target}_${project}.tar.gz`;
process.stdout.write("Downloading " + archive_url + "\n");
archivePath = await tc.downloadTool(archive_url);
}
process.stdout.write("Extracting " + archivePath + " to " + extract_dir);
const archive_dir = await tc.extractTar(archivePath, extract_dir);
process.stdout.write("Extracted to " + archive_dir);
} catch (error) {
core.setFailed(error.message);
}
}
if (os.platform() === "win32") {
addLocalPath("C:\\Program Files\\Git\\usr\\bin");
}
core.setCommandEcho(true);
run();

View File

@ -1,144 +0,0 @@
{
"name": "dl_deps_archive",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dl_deps_archive",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/tool-cache": "^2.0.1",
"path": "^0.12.7"
}
},
"node_modules/@actions/core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/http-client": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^5.25.4"
}
},
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@actions/tool-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz",
"integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^2.0.1",
"@actions/io": "^1.1.1",
"semver": "^6.1.0",
"uuid": "^3.3.2"
}
},
"node_modules/@actions/tool-cache/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/@fastify/busboy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
"engines": {
"node": ">=14"
}
},
"node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
},
"node_modules/path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
"dependencies": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/undici": {
"version": "5.28.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"dependencies": {
"inherits": "2.0.3"
}
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
}
}
}

View File

@ -1,17 +0,0 @@
{
"name": "dl_deps_archive",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/tool-cache": "^2.0.1",
"path": "^0.12.7"
}
}

69
appveyor.yml Normal file
View File

@ -0,0 +1,69 @@
image: Visual Studio 2019
version: '0.1.{build}'
environment:
EXTRA_DIR: 'C:\extra'
MINGW64_EXTRA_DIR: '/c/extra'
PATH: 'C:\\Python36\\Scripts;%PATH%;%EXTRA_DIR%\bin;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\%platform%'
PKG_CONFIG_PATH: '%EXTRA_DIR%\lib\pkgconfig'
MSYS2_PATH_TYPE: 'inherit'
MSYS2_ARG_CONV_EXCL: '-Tp'
MINGW64_RUN: 'C:\msys64\usr\bin\bash.exe --login -c'
MSYSTEM: 'MINGW64'
KIWIX_DESKTOP_VERSION: '2.3.1'
KIWIX_DESKTOP_RELEASE: 0
init:
- cmd: |
echo %TEST_VAR%
REM Set VC 2019
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
mkdir C:\extra\bin
install:
- cmd: |
cd C:\projects
REM Install meson
C:\Python36\Scripts\pip install meson
REM Install ninja
curl -o ninja-win.zip -L https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip
7z e ninja-win.zip -o%EXTRA_DIR%\bin
REM Install pkg-config-lite
curl --insecure -o pkg-config-lite-0.28-1.zip https://netix.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip
7z e pkg-config-lite-0.28-1.zip -o%EXTRA_DIR%\bin pkg-config-lite-0.28-1/bin/pkg-config.exe
cd kiwix-build
REM Install openssh (scp) for deployement
choco install openssh openssl.light
- cmd: openssl enc -d -aes-256-cbc -md sha256 -pass pass:%ENC_PASSWD% -in appveyor\nightlybot_id_key.enc -out appveyor\nightlybot_id_key
build_script:
- IF "%USE_CACHE%" EQU "1" appveyor\setup_from_cache.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_zlib.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_lzma.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_zstd.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_libcurl.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_pthread.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_dirent.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_xapian.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_icu.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_pugixml.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_aria2.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_mustache.cmd
- IF "%USE_CACHE%" NEQ "1" appveyor\install_libmicrohttpd.cmd
- IF "%USE_CACHE%" NEQ "1" %MINGW64_RUN% "cd /c/projects/kiwix-build && appveyor/create_cache.sh"
- appveyor\install_libzim.cmd
- appveyor\install_libkiwix.cmd
- appveyor\install_kiwix-desktop.cmd
before_deploy:
- cmd: openssl enc -d -pbkdf2 -aes-256-cbc -md sha256 -pass pass:%win_certificate_secret% -in appveyor\kiwix.pfx.enc -out appveyor\kiwix.pfx
- cmd: '%MINGW64_RUN% "cd /c/projects/kiwix-build && appveyor/package_kiwix-desktop.sh"'
deploy_script:
- cmd: '%MINGW64_RUN% "cd /c/projects/kiwix-build && appveyor/deploy.sh"'

16
appveyor/build_xapian.sh Normal file
View File

@ -0,0 +1,16 @@
XAPIAN_SOURCE=$(pwd)/..
$XAPIAN_SOURCE/configure \
CC="cl -nologo" \
CXX="$XAPIAN_SOURCE/compile cl -nologo" \
CXXFLAGS="-EHsc -MD" AR=lib \
CPPFLAGS="-I${MINGW64_EXTRA_DIR}/include" \
LDFLAGS="-L${MINGW64_EXTRA_DIR}/lib" \
--disable-backend-remote \
--disable-documentation \
--prefix=${MINGW64_EXTRA_DIR}
make -j2
make install

11
appveyor/create_cache.sh Normal file
View File

@ -0,0 +1,11 @@
set -e
ARCHIVE_NAME="deps_windows_windows.zip"
SSH_KEY=C:\\projects\\kiwix-build\\appveyor\\nightlybot_id_key
7z a -tzip $ARCHIVE_NAME $MINGW64_EXTRA_DIR
scp -P 30022 -vrp -i ${SSH_KEY} -o StrictHostKeyChecking=no \
${ARCHIVE_NAME} \
ci@tmp.kiwix.org:/data/tmp/ci

21
appveyor/deploy.sh Executable file
View File

@ -0,0 +1,21 @@
set -e
NIGHTLY_DATE=$(date +%Y-%m-%d)
NIGHTLY_KIWIX_ARCHIVES_DIR=/c/projects/NIGHTLY_KIWIX_ARCHIVES/${NIGHTLY_DATE}
RELEASE_KIWIX_ARCHIVES_DIR=/c/projects/RELEASE_KIWIX_ARCHIVES
SSH_KEY=C:\\projects\\kiwix-build\\appveyor\\nightlybot_id_key
if [[ "$APPVEYOR_SCHEDULED_BUILD" = "True" ]]
then
scp -P 30022 -vrp -i ${SSH_KEY} -o StrictHostKeyChecking=no \
${NIGHTLY_KIWIX_ARCHIVES_DIR} \
ci@master.download.kiwix.org:/data/download/nightly
fi
if [[ "$APPVEYOR_REPO_TAG" = "true" ]]
then
RELEASE_ARCHIVES=$(find $RELEASE_KIWIX_ARCHIVES_DIR -type f)
scp -P 30022 -vrp -i ${SSH_KEY} -o StrictHostKeyChecking=no \
${RELEASE_ARCHIVES} \
ci@master.download.kiwix.org:/data/download/release/kiwix-desktop
fi

View File

@ -0,0 +1,29 @@
import re, sys, os
makefile = sys.argv[-1]
print("Patching '{}'".format(makefile))
with open(makefile, 'r') as f:
lines = f.readlines()
with open(makefile, 'w') as f:
for line in lines:
# if "/SUBSYSTEM:WINDOWS" in line:
# line = line.replace("/SUBSYSTEM:WINDOWS", "/SUBSYSTEM:CONSOLE")
# f.write(line)
# continue
if not line.startswith('LIBS '):
f.write(line)
continue
print("-- INPUT : {}".format(line))
for lib in ('kiwix', 'zim', 'pugixml', 'z', 'zstd'):
line = line.replace('{}.lib'.format(lib), 'lib{}.a'.format(lib))
for lib in ('lzma', 'curl'):
line = line.replace('lib{}.lib'.format(lib), 'lib{}.a'.format(lib))
line = line.strip()
# line += " pthreadVC2.lib"
# line += " icuin.lib icudt.lib icuuc.lib"
line += " Rpcrt4.lib Ws2_32.lib winmm.lib Shlwapi.lib"
line += os.linesep
print("++ OUTPUT : {}".format(line))
f.write(line)

View File

@ -0,0 +1,4 @@
REM ========================================================
REM Install aria2
curl -fsSL -O https://github.com/aria2/aria2/releases/download/release-1.36.0/aria2-1.36.0-win-64bit-build1.zip || exit /b 1
7z e aria2-1.36.0-win-64bit-build1.zip -o%EXTRA_DIR% aria2-1.36.0-win-64bit-build1\aria2c.exe || exit /b 1

View File

@ -0,0 +1,3 @@
REM ========================================================
REM Install dirent.h
curl -fsSL -o%EXTRA_DIR%\include\dirent.h https://raw.githubusercontent.com/tronkko/dirent/master/include/dirent.h || exit /b 1

View File

@ -0,0 +1,14 @@
REM Set VC 2017
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
mkdir C:\extra\bin
cd C:\projects
C:\Python36\Scripts\pip install meson || exit /b 1
REM Set ninja
curl -fsSL -o ninja-win.zip https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip || exit /b 1
7z e ninja-win.zip -o%EXTRA_DIR%\bin || exit /b 1
REM Set pkg-config-lit
curl --insecure -fsSL -o pkg-config-lite-0.28-1.zip https://netix.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip || exit /b 1
7z e pkg-config-lite-0.28-1.zip -o%EXTRA_DIR%\bin pkg-config-lite-0.28-1/bin/pkg-config.exe || exit /b 1
cd kiwix-build

7
appveyor/install_icu.cmd Normal file
View File

@ -0,0 +1,7 @@
REM ========================================================
REM Install icu
curl -SL -O http://public.kymeria.fr/KIWIX/windows/icu4c-62_1-Win64-MSVC2017.zip || exit /b 1
7z x icu4c-62_1-Win64-MSVC2017.zip -o%EXTRA_DIR% -r include || exit /b 1
7z e icu4c-62_1-Win64-MSVC2017.zip -o%EXTRA_DIR%\lib lib64\* || exit /b 1
7z e icu4c-62_1-Win64-MSVC2017.zip -o%EXTRA_DIR%\bin bin64\*.dll || exit /b 1
curl -fsSL -o%PKG_CONFIG_PATH%\icu-i18n.pc http://public.kymeria.fr/KIWIX/windows/icu-i18n.pc || exit /b 1

View File

@ -0,0 +1,22 @@
REM ========================================================
REM Install kiwix-desktop
git clone https://github.com/kiwix/kiwix-desktop || exit /b 1
cd kiwix-desktop
echo "Running qmake"
SET _WITH_CONSOLE=1
IF %KIWIX_DESKTOP_RELEASE% EQU 1 (
IF %APPVEYOR_REPO_TAG% == true (
SET _WITH_CONSOLE=0
)
)
IF %_WITH_CONSOLE% EQU 1 (
C:\Qt\5.15\msvc2019_64\bin\qmake.exe "CONFIG+=static console" || exit /b 1
) else (
C:\Qt\5.15\msvc2019_64\bin\qmake.exe "CONFIG+=static" || exit /b 1
)
echo "Running fix_desktop"
C:\Python36\Python ..\appveyor\fix_desktop_makefile.py Makefile.Release || exit /b 1
echo "Running nmake"
nmake || exit /b 1
cd ..

View File

@ -0,0 +1,14 @@
REM ========================================================
REM Install libcurl
curl -fsSL -O https://curl.haxx.se/download/curl-7.61.1.zip || exit /b 1
7z x curl-7.61.1.zip || exit /b 1
cd curl-7.61.1\winbuild
nmake /f Makefile.vc mode=static MACHINE=x64 DEBUG=no VC=15 ENABLE_IDN=no || exit /b 1
mkdir %EXTRA_DIR%\include\curl
copy ..\builds\libcurl-vc15-x64-release-static-ipv6-sspi-winssl\include\curl\*.h %EXTRA_DIR%\include\curl
copy ..\builds\libcurl-vc15-x64-release-static-ipv6-sspi-winssl\lib\libcurl_a.lib %EXTRA_DIR%\lib
move %EXTRA_DIR%\lib\libcurl_a.lib %EXTRA_DIR%\lib\libcurl.a
dir %EXTRA_DIR%\include\curl
dir %EXTRA_DIR%\lib
curl -fsSl -o%PKG_CONFIG_PATH%\libcurl.pc http://public.kymeria.fr/KIWIX/windows/libcurl.pc || exit /b 1
cd ..\..

View File

@ -0,0 +1,10 @@
REM ========================================================
REM Install libkiwix
git clone https://github.com/kiwix/libkiwix.git || exit /b 1
cd libkiwix
set CPPFLAGS="-I%EXTRA_DIR%/include"
meson . build --prefix %EXTRA_DIR% --default-library static --buildtype release || exit /b 1
cd build
ninja || exit /b 1
ninja install || exit /b 1
cd ..\..

View File

@ -0,0 +1,11 @@
REM ========================================================
REM Install libmicrohttpd
curl -fsSL -O https://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-latest-w32-bin.zip || exit /b 1
7z e libmicrohttpd-latest-w32-bin.zip -o%EXTRA_DIR%/include libmicrohttpd-*-w32-bin/x86_64/VS2019/Release-static/microhttpd.h || exit /b 1
7z e libmicrohttpd-latest-w32-bin.zip -o%EXTRA_DIR%/lib libmicrohttpd-*-w32-bin/x86_64/VS2019/Release-static/libmicrohttpd.lib || exit /b 1
7z e libmicrohttpd-latest-w32-bin.zip -o%EXTRA_DIR%/lib/pkgconfig libmicrohttpd-*-w32-bin/x86_64/MinGW/static/mingw64/lib/pkgconfig/* || exit /b 1
rename %EXTRA_DIR%\lib\libmicrohttpd.lib microhttpd.lib
dir %EXTRA_DIR%
dir %EXTRA_DIR%\lib
dir %EXTRA_DIR%\lib\pkgconfig

View File

@ -0,0 +1,9 @@
REM ========================================================
REM Install libzim
git clone https://github.com/openzim/libzim.git || exit /b 1
cd libzim
meson . build --prefix %EXTRA_DIR% --default-library static --buildtype release || exit /b 1
cd build
ninja || exit /b 1
ninja install || exit /b 1
cd ..\..

View File

@ -0,0 +1,6 @@
REM ========================================================
REM Install lzma
curl -fsSL -O https://tukaani.org/xz/xz-5.2.4-windows.zip || exit /b 1
7z x xz-5.2.4-windows.zip -o%EXTRA_DIR% -r include || exit /b 1
7z e xz-5.2.4-windows.zip -o%EXTRA_DIR%\lib bin_x86-64\liblzma.a || exit /b 1
curl -fsSL -o%PKG_CONFIG_PATH%\liblzma.pc http://public.kymeria.fr/KIWIX/windows/liblzma.pc || exit /b 1

View File

@ -0,0 +1,3 @@
REM ========================================================
REM Install mustache.hpp
curl -fsSL -o%EXTRA_DIR%\include\mustache.hpp https://raw.githubusercontent.com/kainjow/mustache/v3.2.1/mustache.hpp || exit /b 1

View File

@ -0,0 +1,14 @@
REM ========================================================
REM Install pthread
curl -fsSL -O ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip || exit /b 1
7z x pthreads-w32-2-9-1-release.zip -r pthreads.2 || exit /b 1
cd pthreads.2
REM Patch is pthread_timespec.patch
curl -fsSL -O http://public.kymeria.fr/KIWIX/windows/pthread.h || exit /b 1
nmake clean VC-inlined || exit /b 1
copy pthread.h %EXTRA_DIR%\include
copy sched.h %EXTRA_DIR%\include
copy pthreadVC2.lib %EXTRA_DIR%\lib
copy pthreadVC2.dll %EXTRA_DIR%\bin
curl -fsSL -o%PKG_CONFIG_PATH%\libpthreadVC2.pc http://public.kymeria.fr/KIWIX/windows/libpthreadVC2.pc || exit /b 1
cd ..

View File

@ -0,0 +1,10 @@
REM ========================================================
REM Install pugixml
curl -fsSL -O http://public.kymeria.fr/KIWIX/windows/pugixml-1.2-meson.zip || exit /b 1
7z x pugixml-1.2-meson.zip -o. || exit /b 1
cd pugixml-1.2-meson
meson . build --prefix %EXTRA_DIR% --default-library static --buildtype release || exit /b 1
cd build
ninja || exit /b 1
ninja install || exit /b 1
cd ..\..

View File

@ -0,0 +1,9 @@
REM ========================================================
REM Install xapian
curl -fsSL -O http://mirror.download.kiwix.org/dev/kiwix-build/xapian-core-1.4.18.zip || exit /b 1
7z x xapian-core-1.4.18.zip || exit /b 1
cd xapian-core-1.4.18
mkdir build
cd build
%MINGW64_RUN% "cd /c/Projects/kiwix-build/xapian-core-1.4.18/build && /c/Projects/kiwix-build/appveyor/build_xapian.sh" > build_xapian.log || exit /b 1
cd ..\..

10
appveyor/install_zlib.cmd Normal file
View File

@ -0,0 +1,10 @@
REM ========================================================
REM Install zlib
curl -fsSL -O http://mirror.download.kiwix.org/dev/kiwix-build/zlib-1.2.12.meson.zip || exit /b 1
7z x zlib-1.2.12.meson.zip || exit /b 1
cd zlib-1.2.12
meson . build --prefix %EXTRA_DIR% --default-library static --buildtype release || exit /b 1
cd build
ninja || exit /b 1
ninja install || exit /b 1
cd ..\..

10
appveyor/install_zstd.cmd Normal file
View File

@ -0,0 +1,10 @@
REM ========================================================
REM Install zstd
curl -fsSL -o zstd-v1.5.2.zip https://github.com/facebook/zstd/archive/refs/tags/v1.5.2.zip || exit /b 1
7z x zstd-v1.5.2.zip || exit /b 1
cd zstd-1.5.2/build/meson
meson . builddir --prefix %EXTRA_DIR% --default-library static --buildtype release -Dbin_programs=false -Dbin_contrib=false || exit /b 1
cd builddir
ninja || exit /b 1
ninja install || exit /b 1
cd ..\..\..\..

BIN
appveyor/kiwix.pfx.enc Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,35 @@
set -e
if [[ "$APPVEYOR_REPO_TAG" = "false" ]]
then
NIGHTLY_DATE=$(date +%Y-%m-%d)
KIWIX_ARCHIVES_DIR=/c/projects/NIGHTLY_KIWIX_ARCHIVES/${NIGHTLY_DATE}
KIWIX_DIR=kiwix-desktop_windows_x64_$NIGHTLY_DATE
else
if [ $KIWIX_DESKTOP_RELEASE -eq 1 ]
then
KIWIX_ARCHIVES_DIR=/c/projects/RELEASE_KIWIX_ARCHIVES
KIWIX_DIR=kiwix-desktop_windows_x64_${KIWIX_DESKTOP_VERSION}
fi
fi
if [[ "$KIWIX_DIR" ]]
then
KIWIX_ARCH_NAME=${KIWIX_DIR}.zip
mkdir $KIWIX_DIR
mkdir -p KIWIX_ARCHIVES_DIR
cp /c/projects/kiwix-build/kiwix-desktop/Release/kiwix-desktop.exe $KIWIX_DIR
/c/Qt/5.15/msvc2019_64/bin/windeployqt --compiler-runtime $KIWIX_DIR
cp $MINGW64_EXTRA_DIR/aria2c.exe $KIWIX_DIR
cp $MINGW64_EXTRA_DIR/bin/*.dll $KIWIX_DIR
cp /c/OpenSSL-v111-Win64/bin/libcrypto-1_1-x64.dll $KIWIX_DIR
cp /c/OpenSSL-v111-Win64/bin/libssl-1_1-x64.dll $KIWIX_DIR
signtool.exe sign -f appveyor/kiwix.pfx -p $win_certificate_password -t http://timestamp.digicert.com -d "Kiwix-desktop application" -fd SHA256 $KIWIX_DIR/kiwix-desktop.exe
7z a -tzip $KIWIX_ARCHIVES_DIR/$KIWIX_ARCH_NAME $KIWIX_DIR
fi

View File

@ -0,0 +1,4 @@
REM ========================================================
REM Setup from cache
curl -fsSL -O http://tmp.kiwix.org/ci/deps_windows_windows.zip || exit /b 1
7z x deps_windows_windows.zip -oc: -aoa || exit /b 1

View File

@ -0,0 +1,23 @@
FROM alpine:3.16
ENV LANG C.UTF-8
ENV OS_NAME alpine
RUN apk update -q \
&& apk add -q --no-cache \
# Base build tools
bash build-base git py3-pip \
# Packaged dependencies
xz-dev \
zstd-dev \
xapian-core-dev \
icu-dev icu-data-full \
gtest-dev
# Create user
RUN addgroup --gid 121 runner
RUN adduser -u 1001 -G runner -h /home/runner -D runner
USER runner
ENV PATH /home/runner/.local/bin:$PATH
RUN pip3 install meson ninja ; \
ln -s /usr/bin/python3 /home/runner/.local/bin/python

View File

@ -0,0 +1,47 @@
FROM ubuntu:bionic
ENV LANG C.UTF-8
ENV OS_NAME bionic
RUN apt update -q \
&& dpkg --add-architecture i386 \
&& apt install -q -y --no-install-recommends software-properties-common \
&& add-apt-repository ppa:beineri/opt-qt-5.15.2-bionic \
&& apt-get update \
&& apt install -q -y --no-install-recommends \
# Base build tools
build-essential automake libtool cmake ccache pkg-config autopoint patch \
python3-pip python3-setuptools python3-wheel git subversion wget unzip \
ninja-build openssh-client curl libgl-dev \
# Python (2) is needed to install android-ndk
python \
# Packaged dependencies
libbz2-dev libmagic-dev uuid-dev zlib1g-dev \
libmicrohttpd-dev aria2 libgtest-dev libgl-dev \
# Devel package to compile python modules
libxml2-dev libxslt-dev python3-dev \
# Qt packages
qt515base qt515webengine qt515svg qt515imageformats qt515wayland \
# To create the appimage of kiwix-desktop
libfuse2 fuse patchelf \
# Flatpak tools
elfutils flatpak flatpak-builder \
# Cross compile i586
libc6-dev-i386 lib32stdc++6 gcc-multilib g++-multilib \
# Other tools (to remove)
# vim less grep \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc/* /var/cache/debconf/* \
&& pip3 install meson pytest gcovr requests distro
# Set qt515 environment (the equivalent of "source /opt/qt515/bin/qt515-env.sh")
# RUN echo "source /opt/qt515/bin/qt515-env.sh" >> /home/runner/.bashrc
ENV PATH=/opt/qt515/bin:$PATH \
LD_LIBRARY_PATH=/opt/qt515/lib/x86_64-linux-gnu:/opt/qt515/lib:$LD_LIBRARY_PATH \
PKG_CONFIG_PATH=/opt/qt515/lib/pkgconfig:$PKG_CONFIG_PATH
# Create user
RUN groupadd --gid 121 runner
RUN useradd --uid 1001 --gid 121 --create-home runner
USER runner
ENV PATH /home/runner/.local/bin:$PATH

View File

@ -0,0 +1,28 @@
FROM fedora:35
ENV LANG C.UTF-8
ENV OS_NAME f35
RUN dnf install -y --nodocs \
# Base build tools
make automake libtool cmake git-core subversion pkg-config gcc-c++ \
wget unzip ninja-build ccache which patch gcovr xz openssh-clients \
python3-pip \
# Cross win32 compiler
mingw32-gcc-c++ mingw32-bzip2-static mingw32-win-iconv-static \
mingw32-winpthreads-static mingw32-zlib-static mingw32-xz-libs-static \
mingw32-libmicrohttpd \
# python3
python3-pip python-unversioned-command \
# Other tools (to remove)
# vim less grep
&& dnf remove -y "*-doc" \
&& dnf autoremove -y \
&& dnf clean all \
&& pip3 install meson pytest requests distro
# Create user
RUN groupadd --gid 121 runner
RUN useradd --uid 1001 --gid 121 --create-home runner
USER runner
ENV PATH /home/runner/.local/bin:$PATH

View File

@ -0,0 +1,34 @@
FROM ubuntu:focal
ENV LANG C.UTF-8
ENV OS_NAME focal
ENV DEBIAN_FRONTEND noninteractive
RUN apt update -q \
&& apt install -q -y --no-install-recommends \
# Base build tools
build-essential automake libtool cmake ccache pkg-config autopoint patch \
python3-pip python3-setuptools python3-wheel git subversion wget unzip \
ninja-build openssh-client \
# Packaged dependencies
libbz2-dev libmagic-dev uuid-dev zlib1g-dev \
libmicrohttpd-dev aria2 libgtest-dev \
# Qt packages
libqt5gui5 qtbase5-dev qtwebengine5-dev libqt5svg5-dev qt5-image-formats-plugins qt5-default \
# To create the appimage of kiwix-desktop
libfuse2 fuse patchelf \
# Flatpak tools
elfutils flatpak flatpak-builder \
# Cross win32 compiler
g++-mingw-w64-i686 gcc-mingw-w64-i686 gcc-mingw-w64-base mingw-w64-tools \
# Other tools (to remove)
# vim less grep \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc/* /var/cache/debconf/* \
&& pip3 install meson pytest gcovr requests distro
# Create user
RUN groupadd --gid 121 runner
RUN useradd --uid 1001 --gid 121 --create-home runner
USER runner
ENV PATH /home/runner/.local/bin:$PATH

View File

@ -4,163 +4,81 @@ import os, sys
import argparse
from .dependencies import Dependency
from .configs import ConfigInfo
from .platforms import PlatformInfo
from .builder import Builder
from .flatpak_builder import FlatpakBuilder
from . import _global
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"target",
default="kiwix-tools",
nargs="?",
metavar="TARGET",
choices=Dependency.all_deps.keys(),
)
parser.add_argument(
"--working-dir",
default=".",
help=(
"Directory where kiwix-build puts all its files "
"(source, archive and build)\n"
"working-dir can be absolute path or a relative (to cwd) one."
),
)
parser.add_argument(
"--build-dir",
default=".",
help=(
"Directory where kiwix-build puts all build files.\n"
"build-dir can be absolute path or a relative (to working-dir) one."
),
)
parser.add_argument("--libprefix", default=None)
parser.add_argument(
"--config", choices=ConfigInfo.all_configs, default="native_dyn"
)
parser.add_argument(
"--verbose",
"-v",
action="store_true",
help=(
"Print all logs on stdout instead of in specific" " log files per commands"
),
)
parser.add_argument(
"--hide-progress",
action="store_false",
dest="show_progress",
help="Hide intermediate progress information.",
)
parser.add_argument(
"--skip-source-prepare",
action="store_true",
help="Skip the source download part",
)
parser.add_argument(
"--build-deps-only",
action="store_true",
help="Build only the dependencies of the specified target.",
)
parser.add_argument(
"--build-nodeps",
action="store_true",
help="Build only the target, not its dependencies.",
)
parser.add_argument(
"--make-dist",
action="store_true",
help="Build distrubution (dist) source archive",
)
parser.add_argument(
"--make-release", action="store_true", help="Build a release version"
)
subgroup = parser.add_argument_group("advanced")
subgroup.add_argument(
"--no-cert-check",
action="store_true",
help="Skip SSL certificate verification during download",
)
subgroup.add_argument(
"--clean-at-end",
action="store_true",
help="Clean all intermediate files after the (successfull) build",
)
subgroup.add_argument(
"--dont-install-packages",
action="store_true",
help="Do not try to install packages before compiling",
)
subgroup.add_argument(
"--assume-packages-installed",
action="store_true",
help="Assume the package to install to be aleady installed",
)
subgroup.add_argument(
"--android-arch",
action="append",
help=(
"Specify the architecture to build for android application/libraries.\n"
"Can be specified several times to build for several architectures.\n"
"If not specified, all architectures will be build."
),
)
subgroup.add_argument(
"--ios-arch",
action="append",
help=(
"Specify the architecture to build for ios application/libraries.\n"
"Can be specified several times to build for several architectures.\n"
"If not specified, all architectures will be build."
),
)
subgroup.add_argument(
"--fast-clone",
action="store_true",
help=(
"Do not clone the whole repository.\n"
"This is useful for one shot build but it is not recommended if you want "
"to develop with the cloned sources."
),
)
subgroup.add_argument(
"--use-target-arch-name",
action="store_true",
help=(
"Name the build directory using the arch name instead of the config name.\n"
"Different configs may create binary for the same arch so this option is "
"not recommended when working with several config on the same computer.\n"
"However, when generating dependencies for other it is better to have a "
"directory named using the target instead of the used config.\n"
"Intended to be used in CI only."
),
)
subgroup.add_argument(
"--get-build-dir", action="store_true", help="Print the output directory."
)
parser.add_argument('target', default='kiwix-tools', nargs='?', metavar='TARGET',
choices=Dependency.all_deps.keys())
parser.add_argument('--working-dir', default=".",
help=("Directory where kiwix-build puts all its files "
"(source, archive and build)\n"
"working-dir can be absolute path or a relative (to cwd) one."))
parser.add_argument('--build-dir', default=".",
help=("Directory where kiwix-build puts all build files.\n"
"build-dir can be absolute path or a relative (to working-dir) one."))
parser.add_argument('--libprefix', default=None)
parser.add_argument('--target-platform', choices=PlatformInfo.all_platforms)
parser.add_argument('--verbose', '-v', action="store_true",
help=("Print all logs on stdout instead of in specific"
" log files per commands"))
parser.add_argument('--hide-progress', action='store_false', dest='show_progress',
help="Hide intermediate progress information.")
parser.add_argument('--skip-source-prepare', action='store_true',
help="Skip the source download part")
parser.add_argument('--build-deps-only', action='store_true',
help="Build only the dependencies of the specified target.")
parser.add_argument('--build-nodeps', action='store_true',
help="Build only the target, not its dependencies.")
parser.add_argument('--make-dist', action='store_true',
help="Build distrubution (dist) source archive")
parser.add_argument('--make-release', action='store_true',
help="Build a release version")
subgroup = parser.add_argument_group('advanced')
subgroup.add_argument('--no-cert-check', action='store_true',
help="Skip SSL certificate verification during download")
subgroup.add_argument('--clean-at-end', action='store_true',
help="Clean all intermediate files after the (successfull) build")
subgroup.add_argument('--dont-install-packages', action='store_true',
help="Do not try to install packages before compiling")
subgroup.add_argument('--assume-packages-installed', action='store_true',
help="Assume the package to install to be aleady installed")
subgroup.add_argument('--android-arch', action='append',
help=("Specify the architecture to build for android application/libraries.\n"
"Can be specified several times to build for several architectures.\n"
"If not specified, all architectures will be build."))
subgroup.add_argument('--ios-arch', action='append',
help=("Specify the architecture to build for ios application/libraries.\n"
"Can be specified several times to build for several architectures.\n"
"If not specified, all architectures will be build."))
subgroup.add_argument('--fast-clone', action='store_true',
help=("Do not clone the whole repository.\n"
"This is useful for one shot build but it is not recommended if you want "
"to develop with the cloned sources."))
options = parser.parse_args()
if not options.android_arch:
options.android_arch = ["arm", "arm64", "x86", "x86_64"]
options.android_arch = ['arm', 'arm64', 'x86', 'x86_64']
if not options.ios_arch:
options.ios_arch = ["arm64", "x86_64"]
options.ios_arch = ['arm64', 'x86_64']
if not options.target_platform:
options.target_platform = 'native_dyn'
return options
def main():
options = parse_args()
options.working_dir = os.path.abspath(options.working_dir)
_global.set_options(options)
neutralEnv = buildenv.NeutralEnv(options.get_build_dir)
neutralEnv = buildenv.PlatformNeutralEnv()
_global.set_neutralEnv(neutralEnv)
if options.config == "flatpak":
if options.target_platform == 'flatpak':
builder = FlatpakBuilder()
else:
builder = Builder()
if options.get_build_dir:
print(ConfigInfo.get_config(options.config).buildEnv.build_dir)
else:
builder.run()
builder.run()

View File

@ -5,29 +5,23 @@ _neutralEnv = None
_options = None
_target_steps = _OrderedDict()
def set_neutralEnv(env):
global _neutralEnv
_neutralEnv = env
def neutralEnv(what):
return getattr(_neutralEnv, what)
def set_options(options):
global _options
_options = options
def option(what):
return getattr(_options, what)
def add_target_step(key, what):
_target_steps[key] = what
def get_target_step(key, default_context=None):
if isinstance(key, tuple):
context, target = key
@ -35,6 +29,24 @@ def get_target_step(key, default_context=None):
context, target = default_context, key
return _target_steps[(context, target)]
def target_steps():
return _target_steps
def backend():
global _backend
if _backend is not None:
return _backend
_platform = platform.system()
if _platform == 'Windows':
print('ERROR: kiwix-build is not intented to run on Windows platform.\n'
'There is no backend for Windows, so we can\'t launch any commands.')
sys.exit(0)
if _platform == 'Linux':
_platform, _, _ = platform.linux_distribution()
_platform = _platform.lower()
_backend = backends.Linux()
return _backend

View File

@ -1,96 +1,93 @@
import os, sys, shutil
import subprocess
import platform
import distro
from .utils import pj, download_remote, escape_path
from .utils import pj, download_remote, Defaultdict
from ._global import neutralEnv, option
class NeutralEnv:
def __init__(self, dummy_run):
self.working_dir = option("working_dir")
class PlatformNeutralEnv:
def __init__(self):
self.working_dir = option('working_dir')
self.source_dir = pj(self.working_dir, "SOURCE")
self.archive_dir = pj(self.working_dir, "ARCHIVE")
self.toolchain_dir = pj(self.working_dir, "TOOLCHAINS")
self.log_dir = pj(self.working_dir, "LOGS")
for d in (self.source_dir, self.archive_dir, self.toolchain_dir, self.log_dir):
self.log_dir = pj(self.working_dir, 'LOGS')
for d in (self.source_dir,
self.archive_dir,
self.toolchain_dir,
self.log_dir):
os.makedirs(d, exist_ok=True)
self.detect_platform()
if dummy_run:
# If this is for a dummy run, we will not run anything.
# To check for command (and so, don't enforce their presence)
return
self.ninja_command = self._detect_command(
"ninja", default=[["ninja"], ["ninja-build"]]
)
self.meson_command = self._detect_command(
"meson", default=[["meson.py"], ["meson"]]
)
self.mesontest_command = [*self.meson_command, "test"]
self.patch_command = self._detect_command("patch")
self.git_command = self._detect_command("git")
if platform.system() == "Windows":
self.make_command = self._detect_command("nmake", options=["/?", "/NOLOGO"])
else:
self.make_command = self._detect_command("make")
self.cmake_command = self._detect_command("cmake")
self.qmake_command = self._detect_command(
"qmake", required=False, default=[["qmake"], ["qmake-qt5"]]
)
self.ninja_command = self._detect_ninja()
if not self.ninja_command:
sys.exit("ERROR: ninja command not found.")
self.meson_command = self._detect_meson()
if not self.meson_command:
sys.exit("ERROR: meson command not found.")
self.qmake_command = self._detect_qmake()
if not self.qmake_command:
print("WARNING: qmake command not found.", file=sys.stderr)
self.mesontest_command = "{} test".format(self.meson_command)
def detect_platform(self):
_platform = platform.system()
self.distname = _platform
if _platform == "Linux":
if _platform == 'Windows':
print('ERROR: kiwix-build is not intented to run on Windows platform.\n'
'It should probably not work, but well, you still can have a try.')
cont = input('Do you want to continue ? [y/N]')
if cont.lower() != 'y':
sys.exit(0)
if _platform == 'Linux':
self.distname = distro.id()
if self.distname == "ubuntu":
self.distname = "debian"
if self.distname == 'ubuntu':
self.distname = 'debian'
def download(self, what, where=None):
where = where or self.archive_dir
download_remote(what, where)
def _detect_command(self, name, default=None, options=["--version"], required=True):
if default is None:
default = [[name]]
env_key = "KBUILD_{}_COMMAND".format(name.upper())
if env_key in os.environ:
default = [os.environ[env_key].split()] + default
for command in default:
def _detect_binary(self, *bin_variants):
for n in bin_variants:
try:
retcode = subprocess.check_call(
command + options, stdout=subprocess.DEVNULL
)
except (FileNotFoundError, PermissionError, OSError):
retcode = subprocess.check_call([n, '--version'],
stdout=subprocess.DEVNULL)
except (FileNotFoundError, PermissionError):
# Doesn't exist in PATH or isn't executable
continue
if retcode == 0:
return command
else:
if required:
sys.exit("ERROR: {} command not found".format(name))
else:
print("WARNING: {} command not found".format(name), file=sys.stderr)
return ["{}_NOT_FOUND".format(name.upper())]
return n
def _detect_ninja(self):
return self._detect_binary('ninja', 'ninja-build')
def _detect_meson(self):
return self._detect_binary('meson.py', 'meson')
def _detect_qmake(self):
return self._detect_binary('qmake-qt5', 'qmake')
class BuildEnv:
def __init__(self, configInfo):
self.configInfo = configInfo
self.base_build_dir = pj(option("working_dir"), option("build_dir"))
build_dir = (
configInfo.arch_name if option("use_target_arch_name") else configInfo.name
)
build_dir = f"BUILD_{build_dir}"
def __init__(self, platformInfo):
build_dir = "BUILD_{}".format(platformInfo.name)
self.platformInfo = platformInfo
self.base_build_dir = pj(option('working_dir'), option('build_dir'))
self.build_dir = pj(self.base_build_dir, build_dir)
self.install_dir = pj(self.build_dir, "INSTALL")
self.toolchain_dir = pj(self.build_dir, "TOOLCHAINS")
self.log_dir = pj(self.build_dir, "LOGS")
for d in (self.build_dir, self.install_dir, self.toolchain_dir, self.log_dir):
self.log_dir = pj(self.build_dir, 'LOGS')
for d in (self.build_dir,
self.install_dir,
self.toolchain_dir,
self.log_dir):
os.makedirs(d, exist_ok=True)
self.libprefix = option("libprefix") or self._detect_libdir()
self.libprefix = option('libprefix') or self._detect_libdir()
def clean_intermediate_directories(self):
for subdir in os.listdir(self.build_dir):
@ -103,81 +100,69 @@ class BuildEnv:
os.remove(subpath)
def _is_debianlike(self):
return os.path.isfile("/etc/debian_version")
return os.path.isfile('/etc/debian_version')
def _detect_libdir(self):
if self.configInfo.libdir is not None:
return self.configInfo.libdir
if self.platformInfo.libdir is not None:
return self.platformInfo.libdir
if self._is_debianlike():
try:
pc = subprocess.Popen(
["dpkg-architecture", "-qDEB_HOST_MULTIARCH"],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
)
pc = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL)
(stdo, _) = pc.communicate()
if pc.returncode == 0:
archpath = stdo.decode().strip()
return "lib/" + archpath
return 'lib/' + archpath
except Exception:
pass
if os.path.isdir("/usr/lib64") and not os.path.islink("/usr/lib64"):
return "lib64"
return "lib"
if os.path.isdir('/usr/lib64') and not os.path.islink('/usr/lib64'):
return 'lib64'
return 'lib'
def get_env(self, *, cross_comp_flags, cross_compilers, cross_path):
env = self.configInfo.get_env()
pkgconfig_path = pj(self.install_dir, self.libprefix, "pkgconfig")
env["PKG_CONFIG_PATH"].append(pkgconfig_path)
env = self.platformInfo.get_env()
pkgconfig_path = pj(self.install_dir, self.libprefix, 'pkgconfig')
env['PKG_CONFIG_PATH'] = ':'.join([env['PKG_CONFIG_PATH'], pkgconfig_path])
env["PATH"].insert(0, pj(self.install_dir, "bin"))
env['PATH'] = ':'.join([pj(self.install_dir, 'bin'), env['PATH']])
env["LD_LIBRARY_PATH"].extend(
[
pj(self.install_dir, "lib"),
pj(self.install_dir, self.libprefix),
]
)
env['LD_LIBRARY_PATH'] = ':'.join([env['LD_LIBRARY_PATH'],
pj(self.install_dir, 'lib'),
pj(self.install_dir, self.libprefix)
])
env["QMAKE_CXXFLAGS"] = " ".join(
[escape_path("-I" + pj(self.install_dir, "include")), env["QMAKE_CXXFLAGS"]]
)
env["CPPFLAGS"] = " ".join(
[escape_path("-I" + pj(self.install_dir, "include")), env["CPPFLAGS"]]
)
env["QMAKE_LFLAGS"] = " ".join(
[
escape_path("-L" + pj(self.install_dir, "lib")),
escape_path("-L" + pj(self.install_dir, self.libprefix)),
env["QMAKE_LFLAGS"],
]
)
env["LDFLAGS"] = " ".join(
[
escape_path("-L" + pj(self.install_dir, "lib")),
escape_path("-L" + pj(self.install_dir, self.libprefix)),
env["LDFLAGS"],
]
)
env['QMAKE_CXXFLAGS'] = " ".join(['-I'+pj(self.install_dir, 'include'), env['QMAKE_CXXFLAGS']])
env['CPPFLAGS'] = " ".join(['-I'+pj(self.install_dir, 'include'), env['CPPFLAGS']])
env['QMAKE_LFLAGS'] = " ".join(['-L'+pj(self.install_dir, 'lib'),
'-L'+pj(self.install_dir, self.libprefix),
env['QMAKE_LFLAGS']])
env['LDFLAGS'] = " ".join(['-L'+pj(self.install_dir, 'lib'),
'-L'+pj(self.install_dir, self.libprefix),
env['LDFLAGS']])
if cross_comp_flags:
self.configInfo.set_comp_flags(env)
self.platformInfo.set_comp_flags(env)
if cross_compilers:
self.configInfo.set_compiler(env)
self.platformInfo.set_compiler(env)
if cross_path:
env["PATH"][0:0] = self.configInfo.get_bin_dir()
env['PATH'] = ':'.join(self.platformInfo.get_bin_dir() + [env['PATH']])
return env
@property
def configure_wrapper(self):
try:
yield self.configInfo.configure_wrapper
except AttributeError:
pass
wrapper = getattr(self.platformInfo, "configure_wrapper", "")
if wrapper:
return "{} ".format(wrapper)
else:
return ""
@property
def make_wrapper(self):
try:
yield self.configInfo.make_wrapper
except AttributeError:
pass
wrapper = getattr(self.platformInfo, "make_wrapper", "")
if wrapper:
return "{} ".format(wrapper)
else:
return ""

View File

@ -1,36 +1,30 @@
import sys
from collections import OrderedDict
from .buildenv import *
from .configs import ConfigInfo
from .platforms import PlatformInfo
from .utils import remove_duplicates, StopBuild, colorize
from .dependencies import Dependency
from .packages import PACKAGE_NAME_MAPPERS
from ._global import (
neutralEnv,
option,
add_target_step,
get_target_step,
target_steps,
)
neutralEnv, option,
add_target_step, get_target_step, target_steps,
backend)
from . import _global
class Builder:
def __init__(self):
self._targets = {}
ConfigInfo.get_config("neutral", self._targets)
PlatformInfo.get_platform('neutral', self._targets)
config_name = option("config")
config = ConfigInfo.get_config(config_name, self._targets)
if neutralEnv("distname") not in config.compatible_hosts:
print(
(
colorize("ERROR") + ": The config {} cannot be build on host {}.\n"
"Select another config or change your host system."
).format(config.name, neutralEnv("distname"))
)
self.targetDefs = config.add_targets(option("target"), self._targets)
target_platform = option('target_platform')
platform = PlatformInfo.get_platform(target_platform, self._targets)
if neutralEnv('distname') not in platform.compatible_hosts:
print((colorize('ERROR')+': The target platform {} cannot be build on host {}.\n'
'Select another target platform or change your host system.'
).format(platform.name, neutralEnv('distname')))
self.targetDefs = platform.add_targets(option('target'), self._targets)
def finalize_target_steps(self):
steps = []
@ -38,36 +32,36 @@ class Builder:
steps += self.order_steps(targetDef)
steps = list(remove_duplicates(steps))
if option("build_nodeps"):
# add all config steps
if option('build_nodeps'):
# add all platform steps
for dep in steps:
stepClass = Dependency.all_deps[dep[1]]
if stepClass.dont_skip:
add_target_step(dep, self._targets[dep])
src_targetDef = ("source", targetDef[1])
src_targetDef = ('source', targetDef[1])
add_target_step(src_targetDef, self._targets[src_targetDef])
add_target_step(targetDef, self._targets[targetDef])
else:
for dep in steps:
if option("build_deps_only") and dep[1] == targetDef[1]:
if option('build_deps_only') and dep[1] == targetDef[1]:
continue
add_target_step(dep, self._targets[dep])
self.instanciate_steps()
def order_steps(self, targetDef):
for cfgName in ConfigInfo.all_running_configs:
cfg = ConfigInfo.all_configs[cfgName]
for tlcName in cfg.toolchain_names:
for pltName in PlatformInfo.all_running_platforms:
plt = PlatformInfo.all_platforms[pltName]
for tlcName in plt.toolchain_names:
tlc = Dependency.all_deps[tlcName]
yield ("source", tlcName)
yield ("neutral" if tlc.neutral else cfgName, tlcName)
_targets = dict(self._targets)
yield('source', tlcName)
yield('neutral' if tlc.neutral else pltName, tlcName)
_targets =dict(self._targets)
yield from self.order_dependencies(targetDef, _targets)
def order_dependencies(self, targetDef, targets):
targetConfigName, targetName = targetDef
if targetConfigName == "source":
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
@ -76,45 +70,43 @@ class Builder:
except KeyError:
return
targetConfig = ConfigInfo.get_config(targetConfigName)
for dep in target.get_dependencies(targetConfig, True):
depConfig, depName = targetConfig.get_fully_qualified_dep(dep)
if (depConfig, depName) in targets:
yield from self.order_dependencies((depConfig, depName), targets)
yield ("source", targetName)
targetPlatform = PlatformInfo.get_platform(targetPlatformName)
for dep in target.get_dependencies(targetPlatform, True):
depPlatform, depName = targetPlatform.get_fully_qualified_dep(dep)
if (depPlatform, depName) in targets:
yield from self.order_dependencies((depPlatform, depName), targets)
yield ('source', targetName)
yield targetDef
def instanciate_steps(self):
for stepDef in list(target_steps()):
stepConfig, stepName = stepDef
stepPlatform, stepName = stepDef
stepClass = Dependency.all_deps[stepName]
if stepConfig == "source":
if stepPlatform == 'source':
source = get_target_step(stepDef)(stepClass)
add_target_step(stepDef, source)
else:
source = get_target_step(stepName, "source")
env = ConfigInfo.get_config(stepConfig).buildEnv
source = get_target_step(stepName, 'source')
env = PlatformInfo.get_platform(stepPlatform).buildEnv
builder = get_target_step(stepDef)(stepClass, source, env)
add_target_step(stepDef, builder)
def prepare_sources(self):
if option("skip_source_prepare"):
if option('skip_source_prepare'):
print(colorize("SKIP"))
return
sourceDefs = remove_duplicates(
tDef for tDef in target_steps() if tDef[0] == "source"
)
sourceDefs = remove_duplicates(tDef for tDef in target_steps() if tDef[0]=='source')
for sourceDef in sourceDefs:
print("prepare sources {} :".format(sourceDef[1]))
source = get_target_step(sourceDef)
source.prepare()
def build(self):
builderDefs = (tDef for tDef in target_steps() if tDef[0] != "source")
builderDefs = (tDef for tDef in target_steps() if tDef[0] != 'source')
for builderDef in builderDefs:
builder = get_target_step(builderDef)
if option("make_dist") and builderDef[1] == option("target"):
if option('make_dist') and builderDef[1] == option('target'):
print("make dist {} ({}):".format(builder.name, builderDef[0]))
builder.make_dist()
continue
@ -124,19 +116,19 @@ class Builder:
def _get_packages(self):
packages_list = []
for config in ConfigInfo.all_running_configs.values():
mapper_name = "{host}_{config}".format(
host=neutralEnv("distname"), config=config
)
for platform in PlatformInfo.all_running_platforms.values():
mapper_name = "{host}_{target}".format(
host=neutralEnv('distname'),
target=platform)
package_name_mapper = PACKAGE_NAME_MAPPERS.get(mapper_name, {})
packages_list += package_name_mapper.get("COMMON", [])
packages_list += package_name_mapper.get('COMMON', [])
to_drop = []
for builderDef in self._targets:
configName, builderName = builderDef
mapper_name = "{host}_{config}".format(
host=neutralEnv("distname"), config=configName
)
platformName, builderName = builderDef
mapper_name = "{host}_{target}".format(
host=neutralEnv('distname'),
target=platformName)
package_name_mapper = PACKAGE_NAME_MAPPERS.get(mapper_name, {})
packages = package_name_mapper.get(builderName)
if packages:
@ -152,20 +144,20 @@ class Builder:
packages_to_have = self._get_packages()
packages_to_have = remove_duplicates(packages_to_have)
if option("assume_packages_installed"):
if option('assume_packages_installed'):
print(colorize("SKIP") + ", Assume package installed")
return
distname = neutralEnv("distname")
if distname in ("fedora", "redhat", "centos"):
package_installer = "sudo dnf install {}"
package_checker = "rpm -q --quiet {}"
elif distname in ("debian", "Ubuntu"):
package_installer = "sudo apt-get install {}"
distname = neutralEnv('distname')
if distname in ('fedora', 'redhat', 'centos'):
package_installer = 'sudo dnf install {}'
package_checker = 'rpm -q --quiet {}'
elif distname in ('debian', 'Ubuntu'):
package_installer = 'sudo apt-get install {}'
package_checker = 'LANG=C dpkg -s {} 2>&1 | grep Status | grep "ok installed" 1>/dev/null 2>&1'
elif distname == "Darwin":
package_installer = "brew install {}"
package_checker = "brew ls --version {} > /dev/null"
elif distname == 'Darwin':
package_installer = 'brew install {}'
package_checker = 'brew ls --version {} > /dev/null'
packages_to_install = []
for package in packages_to_have:
@ -184,30 +176,31 @@ class Builder:
print(command)
subprocess.check_call(command, shell=True)
else:
print(colorize("SKIP") + ", No package to install.")
print(colorize("SKIP")+ ", No package to install.")
def run(self):
try:
print("[INSTALL PACKAGES]")
if option("dont_install_packages"):
if option('dont_install_packages'):
print(colorize("SKIP"))
else:
self.install_packages()
self.finalize_target_steps()
print("[SETUP TOOLCHAINS]")
for config in ConfigInfo.all_running_configs.values():
config.finalize_setup()
print("[SETUP PLATFORMS]")
for platform in PlatformInfo.all_running_platforms.values():
platform.finalize_setup()
print("[PREPARE]")
self.prepare_sources()
print("[BUILD]")
self.build()
# No error, clean intermediate file at end of build if needed.
print("[CLEAN]")
if option("clean_at_end"):
for config in ConfigInfo.all_running_configs.values():
config.clean_intermediate_directories()
if option('clean_at_end'):
for platform in PlatformInfo.all_running_platforms.values():
platform.clean_intermediate_directories()
else:
print(colorize("SKIP"))
except StopBuild as e:
print(e)
sys.exit("Stopping build due to errors")

View File

@ -1,3 +0,0 @@
from .base import *
from . import android, armhf, musl, flatpak, i586, ios, native, neutral, wasm

View File

@ -1,169 +0,0 @@
from .base import ConfigInfo, MetaConfigInfo
from kiwixbuild.utils import pj
from kiwixbuild._global import get_target_step, option
class AndroidConfigInfo(ConfigInfo):
build = "android"
static = True
toolchain_names = ["android-ndk"]
compatible_hosts = ["fedora", "debian"]
def __str__(self):
return "android"
@property
def libdir(self):
return "lib/{}".format(self.arch_full)
@property
def binaries_name(self):
arch_full = self.arch_full
return {
"CC": "{}-{}".format(arch_full, "clang"),
"CXX": "{}-{}".format(arch_full, "clang++"),
"AR": "{}-{}".format(arch_full, "ar"),
"STRIP": "{}-{}".format(arch_full, "strip"),
"RANLIB": "{}-{}".format(arch_full, "ranlib"),
"LD": "{}-{}".format(arch_full, "ld"),
}
def binaries(self):
install_path = self.install_path
binaries = {
k: pj(install_path, "bin", v) for k, v in self.binaries_name.items()
}
binaries["PKGCONFIG"] = "pkg-config"
return binaries
@property
def ndk_builder(self):
return get_target_step("android-ndk", self.name)
@property
def install_path(self):
return self.ndk_builder.install_path
def get_cross_config(self):
extra_libs = [
"-llog",
"-Wl,--exclude-libs,libgcc.a",
"-Wl,--exclude-libs,libunwind.a",
]
extra_cflags = [
"-I{}".format(include_dir) for include_dir in self.get_include_dirs()
]
if hasattr(self, "march"):
extra_libs.append("-march={}".format(self.march))
extra_cflags.append("-march={}".format(self.march))
return {
"exe_wrapper_def": "",
"install_path": self.install_path,
"binaries": self.binaries(),
"root_path": pj(self.install_path, "sysroot"),
"extra_libs": extra_libs,
"extra_cflags": extra_cflags,
"host_machine": {
"system": "Android",
"lsystem": "android",
"cpu_family": self.arch,
"cpu": self.cpu,
"endian": "little",
"abi": self.abi,
},
}
def get_env(self):
env = super().get_env()
root_path = pj(self.install_path, "sysroot")
env["PKG_CONFIG_LIBDIR"] = pj(root_path, "lib", "pkgconfig")
env["NDK_DEBUG"] = "0"
return env
def get_bin_dir(self):
return [pj(self.install_path, "bin")]
def set_comp_flags(self, env):
super().set_comp_flags(env)
root_path = pj(self.install_path, "sysroot")
march = "-march={}".format(self.march) if hasattr(self, "march") else ""
env["CFLAGS"] = (
"-fPIC -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 --sysroot={} {} ".format(
root_path, march
)
+ env["CFLAGS"]
)
env["CXXFLAGS"] = (
"-fPIC -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 --sysroot={} {} ".format(
root_path, march
)
+ env["CXXFLAGS"]
)
env["LDFLAGS"] = "--sysroot={} {} ".format(root_path, march) + env["LDFLAGS"]
def set_compiler(self, env):
binaries = self.binaries()
for k, v in binaries.items():
env[k] = v
@property
def configure_options(self):
yield "--host={}".format(self.arch_full)
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile(
"cmake_android_cross_file.txt", "cmake_cross_file.txt"
)
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")
class AndroidArm(AndroidConfigInfo):
name = "android_arm"
arch = cpu = "arm"
arch_full = "arm-linux-androideabi"
abi = "armeabi-v7a"
march = "armv7-a"
class AndroidArm64(AndroidConfigInfo):
name = "android_arm64"
arch = "arm64"
arch_full = "aarch64-linux-android"
cpu = "aarch64"
abi = "arm64-v8a"
class AndroidX86(AndroidConfigInfo):
name = "android_x86"
arch = abi = "x86"
arch_full = "i686-linux-android"
cpu = "i686"
class AndroidX8664(AndroidConfigInfo):
name = "android_x86_64"
arch = cpu = abi = "x86_64"
arch_full = "x86_64-linux-android"
class Android(MetaConfigInfo):
name = "android"
compatible_hosts = ["fedora", "debian"]
@property
def arch_name(self):
return "multi-linux-android"
@property
def subConfigNames(self):
return ["android_{}".format(arch) for arch in option("android_arch")]
def add_targets(self, targetName, targets):
return super().add_targets(targetName, targets)
def __str__(self):
return self.name
def set_comp_flags(self, env):
pass

View File

@ -1,183 +0,0 @@
from .base import ConfigInfo, MixedMixin
from kiwixbuild.utils import pj
from kiwixbuild._global import get_target_step
# Base config for arm
class ArmConfigInfo(ConfigInfo):
compatible_hosts = ["fedora", "debian", "almalinux"]
def get_cross_config(self):
return {
"binaries": self.binaries,
"exe_wrapper_def": "",
"root_path": self.root_path,
"extra_libs": [],
"extra_cflags": [
"-I{}".format(include_dir) for include_dir in self.get_include_dirs()
],
"host_machine": {
"system": "linux",
"lsystem": "linux",
"cpu_family": self.cpu_family,
"cpu": self.cpu,
"endian": "little",
"abi": "",
},
}
@property
def libdir(self):
return "lib/{}".format(self.arch_full)
@property
def toolchain(self):
return get_target_step(self.build, "neutral")
@property
def root_path(self):
return self.toolchain.build_path
@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"),
("LDSHARED", "g++ -shared"),
)
)
binaries = {k: pj(self.root_path, "bin", v) for k, v in binaries}
binaries["PKGCONFIG"] = "pkg-config"
return binaries
@property
def exe_wrapper_def(self):
try:
which("qemu-arm")
except subprocess.CalledProcessError:
return ""
else:
return "exe_wrapper = 'qemu-arm'"
@property
def configure_options(self):
yield "--host={}".format(self.arch_full)
def get_bin_dir(self):
return [pj(self.root_path, "bin")]
def get_env(self):
env = super().get_env()
env["LD_LIBRARY_PATH"][0:0] = [
pj(self.root_path, self.arch_full, "lib64"),
pj(self.root_path, "lib"),
]
env["PKG_CONFIG_LIBDIR"] = pj(self.root_path, "lib", "pkgconfig")
env["QEMU_LD_PREFIX"] = pj(self.root_path, self.arch_full, "libc")
env["QEMU_SET_ENV"] = "LD_LIBRARY_PATH={}".format(
":".join(
[pj(self.root_path, self.arch_full, "lib"), str(env["LD_LIBRARY_PATH"])]
)
)
return env
def set_comp_flags(self, env):
super().set_comp_flags(env)
env["CFLAGS"] = (
" -fPIC -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CFLAGS"]
)
env["CXXFLAGS"] = (
" -fPIC -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CXXFLAGS"]
)
def set_compiler(self, env):
for k, v in self.binaries.items():
env[k] = v
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile("cmake_cross_file.txt")
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")
class Armv6(ArmConfigInfo):
build = "armv6"
arch_full = "armv6-rpi-linux-gnueabihf"
toolchain_names = ["armv6"]
cpu_family = "arm"
cpu = "armv6"
class Armv6Dyn(Armv6):
name = "armv6_dyn"
static = False
class Armv6Static(Armv6):
name = "armv6_static"
static = True
class Armv6Mixed(MixedMixin("armv6_static"), Armv6):
name = "armv6_mixed"
static = False
class Armv8(ArmConfigInfo):
build = "armv8"
arch_full = "armv8-rpi3-linux-gnueabihf"
toolchain_names = ["armv8"]
cpu_family = "arm"
cpu = "armv8"
class Armv8Dyn(Armv8):
name = "armv8_dyn"
static = False
class Armv8Static(Armv8):
name = "armv8_static"
static = True
class Armv8Mixed(MixedMixin("armv8_static"), Armv8):
name = "armv8_mixed"
static = False
class Aarch64(ArmConfigInfo):
build = "aarch64"
arch_full = "aarch64-linux-gnu"
toolchain_names = ["aarch64"]
cpu_family = "aarch64"
cpu = "aarch64"
@property
def root_path(self):
return self.toolchain.build_path
class Aarch64Dyn(Aarch64):
name = "aarch64_dyn"
static = False
class Aarch64Static(Aarch64):
name = "aarch64_static"
static = True
class Aarch64Mixed(MixedMixin("aarch64_static"), Aarch64):
name = "aarch64_mixed"
static = False

View File

@ -1,179 +0,0 @@
import os, sys
import subprocess
from kiwixbuild.dependencies import Dependency
from kiwixbuild.utils import pj, remove_duplicates, DefaultEnv
from kiwixbuild.buildenv import BuildEnv
from kiwixbuild._global import neutralEnv, option, target_steps
_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
TEMPLATES_DIR = pj(os.path.dirname(_SCRIPT_DIR), "templates")
class _MetaConfig(type):
def __new__(cls, name, bases, dct):
_class = type.__new__(cls, name, bases, dct)
if name not in ("ConfigInfo", "MetaConfigInfo") and "name" in dct:
dep_name = dct["name"]
ConfigInfo.all_configs[dep_name] = _class
return _class
class ConfigInfo(metaclass=_MetaConfig):
all_configs = {}
all_running_configs = {}
toolchain_names = []
configure_options = []
mixed = False
libdir = None
@property
def arch_name(self):
return self.arch_full
@classmethod
def get_config(cls, name, targets=None):
if name not in cls.all_running_configs:
if targets is None:
print("Should not got there.")
print(cls.all_running_configs)
raise KeyError(name)
cls.all_running_configs[name] = cls.all_configs[name](targets)
return cls.all_running_configs[name]
def __init__(self, targets):
self.all_running_configs[self.name] = self
self.buildEnv = BuildEnv(self)
self.setup_toolchains(targets)
def __str__(self):
return "{}_{}".format(self.build, "static" if self.static else "dyn")
def setup_toolchains(self, targets):
for tlc_name in self.toolchain_names:
ToolchainClass = Dependency.all_deps[tlc_name]
targets[("source", tlc_name)] = ToolchainClass.Source
cfg_name = "neutral" if ToolchainClass.neutral else self.name
targets[(cfg_name, tlc_name)] = ToolchainClass.Builder
def add_targets(self, targetName, targets):
if (self.name, targetName) in targets:
return []
targetClass = Dependency.all_deps[targetName]
targets[("source", targetName)] = targetClass.Source
targets[(self.name, targetName)] = targetClass.Builder
for dep in targetClass.Builder.get_dependencies(self, False):
if isinstance(dep, tuple):
depConfigName, depName = dep
else:
depConfigName, depName = self.name, dep
depConfig = self.get_config(depConfigName, targets)
depConfig.add_targets(depName, targets)
return [(self.name, targetName)]
def get_fully_qualified_dep(self, dep):
if isinstance(dep, tuple):
return dep
else:
return self.name, dep
def get_cross_config(self):
return {}
def get_include_dirs(self):
return [pj(self.buildEnv.install_dir, "include")]
def get_env(self):
return DefaultEnv()
def get_bin_dir(self):
return []
def set_compiler(self, env):
pass
def set_comp_flags(self, env):
if self.static:
env["CFLAGS"] = env["CFLAGS"] + " -fPIC"
env["CXXFLAGS"] = env["CXXFLAGS"] + " -fPIC"
def _gen_crossfile(self, name, outname=None):
if outname is None:
outname = name
crossfile = pj(self.buildEnv.build_dir, outname)
template_file = pj(TEMPLATES_DIR, name)
with open(template_file, "r") as f:
template = f.read()
content = template.format(**self.get_cross_config())
with open(crossfile, "w") as outfile:
outfile.write(content)
return crossfile
def finalize_setup(self):
self.buildEnv.cross_config = self.get_cross_config()
self.buildEnv.meson_crossfile = None
self.buildEnv.cmake_crossfile = None
def clean_intermediate_directories(self):
self.buildEnv.clean_intermediate_directories()
class MetaConfigInfo(ConfigInfo):
subConfigNames = []
def add_targets(self, targetName, targets):
targetDefs = []
for configName in self.subConfigNames:
config = self.get_config(configName, targets)
targetDefs += config.add_targets(targetName, targets)
return targetDefs
def MixedMixin(static_name):
class MixedMixinClass:
mixed = True
static = False
def add_targets(self, targetName, targets):
if option("target") == targetName:
return super().add_targets(targetName, targets)
else:
static_config = self.get_config(static_name, targets)
return static_config.add_targets(targetName, targets)
def get_fully_qualified_dep(self, dep):
if isinstance(dep, tuple):
return dep
if option("target") == dep:
return self.name, dep
return static_name, dep
@property
def static_buildEnv(self):
static_config = self.get_config(static_name)
return static_config.buildEnv
def get_include_dirs(self):
return [
pj(self.buildEnv.install_dir, "include"),
pj(self.static_buildEnv.install_dir, "include"),
]
def get_env(self):
env = super().get_env()
env["PATH"].insert(0, pj(self.static_buildEnv.install_dir, "bin"))
pkgconfig_path = pj(
self.static_buildEnv.install_dir,
self.static_buildEnv.libprefix,
"pkgconfig",
)
env["PKG_CONFIG_PATH"].append(pkgconfig_path)
env["CPPFLAGS"] = " ".join(
[
"-I" + pj(self.static_buildEnv.install_dir, "include"),
env["CPPFLAGS"],
]
)
return env
return MixedMixinClass

View File

@ -1,19 +0,0 @@
from .base import ConfigInfo
from kiwixbuild._global import option, neutralEnv
class FlatpakConfigInfo(ConfigInfo):
name = "flatpak"
arch_name = "flatpak"
build = "flatpak"
static = ""
toolchain_names = ["org.kde", "io.qt.qtwebengine"]
compatible_hosts = ["debian", "fedora"]
def __str__(self):
return "flatpak"
def get_env(self):
env = super().get_env()
env["FLATPAK_USER_DIR"] = self.buildEnv.build_dir
return env

View File

@ -1,79 +0,0 @@
import os
from .base import ConfigInfo
from kiwixbuild.utils import which, pj
class I586ConfigInfo(ConfigInfo):
build = "i586"
arch_full = "i586-linux-gnu"
compatible_hosts = ["fedora", "debian"]
def get_cross_config(self):
return {
"binaries": self.binaries,
"exe_wrapper_def": "",
"extra_libs": ["-m32", "-march=i586", "-mno-sse"],
"extra_cflags": [
"-m32",
"-march=i586",
"-mno-sse",
*(
"-I{}".format(include_dir)
for include_dir in self.get_include_dirs()
),
],
"host_machine": {
"system": "linux",
"lsystem": "linux",
"cpu_family": "x86",
"cpu": "i586",
"endian": "little",
"abi": "",
},
}
@property
def configure_options(self):
yield f"--host={self.arch_full}"
@property
def binaries(self):
return {
k: which(v)
for k, v in (
("CC", os.environ.get("CC", "gcc")),
("CXX", os.environ.get("CXX", "g++")),
("AR", "ar"),
("STRIP", "strip"),
("RANLIB", "ranlib"),
("LD", "ld"),
("PKGCONFIG", "pkg-config"),
)
}
def set_comp_flags(self, env):
super().set_comp_flags(env)
env["CFLAGS"] = "-m32 -march=i586 -mno-sse " + env["CFLAGS"]
env["CXXFLAGS"] = "-m32 -march=i586 -mno-sse " + env["CXXFLAGS"]
env["LDFLAGS"] = "-m32 -march=i586 -mno-sse " + env["LDFLAGS"]
def get_bin_dir(self):
return []
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile(
"cmake_i586_cross_file.txt", "cmake_cross_file.txt"
)
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")
class I586Dyn(I586ConfigInfo):
name = "i586_dyn"
static = False
class I586Static(I586ConfigInfo):
name = "i586_static"
static = True

View File

@ -1,249 +0,0 @@
import subprocess
from kiwixbuild._global import option
from kiwixbuild.utils import pj, xrun_find
from .base import ConfigInfo, MetaConfigInfo, MixedMixin
from kiwixbuild.dependencies.apple_xcframework import AppleXCFramework
MIN_MACOS_VERSION = "12.0"
class AppleConfigInfo(ConfigInfo):
build = "iOS"
static = True
compatible_hosts = ["Darwin"]
arch = None
host = None
target = None
sdk_name = None
min_iphoneos_version = None
min_macos_version = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._root_path = None
@property
def arch_name(self):
return self.target
@property
def root_path(self):
if self._root_path is None:
command = "xcrun --sdk {} --show-sdk-path".format(self.sdk_name)
self._root_path = subprocess.check_output(command, shell=True)[:-1].decode()
return self._root_path
def __str__(self):
return "iOS"
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile(
"cmake_ios_cross_file.txt", "cmake_cross_file.txt"
)
self.buildEnv.meson_crossfile = self._gen_crossfile(
"meson_ios_cross_file.txt", "meson_cross_file.txt"
)
def get_cross_config(self):
config = {
"root_path": self.root_path,
"binaries": self.binaries,
"exe_wrapper_def": "",
"extra_libs": [
"-isysroot",
self.root_path,
"-arch",
self.arch,
"-target",
self.target,
],
"extra_cflags": [
"-isysroot",
self.root_path,
"-arch",
self.arch,
"-target",
self.target,
*(
"-I{}".format(include_dir)
for include_dir in self.get_include_dirs()
),
],
"host_machine": {
"system": "Darwin",
"lsystem": "darwin",
"cpu_family": self.arch,
"cpu": self.cpu,
"endian": "",
"abi": "",
},
}
if self.min_iphoneos_version:
config["extra_libs"].append(
"-miphoneos-version-min={}".format(self.min_iphoneos_version)
)
config["extra_cflags"].append(
"-miphoneos-version-min={}".format(self.min_iphoneos_version)
)
if self.min_macos_version:
config["extra_libs"].append(
"-mmacosx-version-min={}".format(self.min_macos_version)
)
config["extra_cflags"].append(
"-mmacosx-version-min={}".format(self.min_macos_version)
)
return config
def get_env(self):
env = super().get_env()
cflags = [env["CFLAGS"]]
if self.min_iphoneos_version:
cflags.append("-miphoneos-version-min={}".format(self.min_iphoneos_version))
if self.min_macos_version:
cflags.append("-mmacosx-version-min={}".format(self.min_macos_version))
env["CFLAGS"] = " ".join(cflags)
return env
def set_comp_flags(self, env):
super().set_comp_flags(env)
cflags = [
"-isysroot {}".format(self.root_path),
"-arch {}".format(self.arch),
"-target {}".format(self.target),
env["CFLAGS"],
]
if self.min_iphoneos_version:
cflags.append("-miphoneos-version-min={}".format(self.min_iphoneos_version))
env["CFLAGS"] = " ".join(cflags)
env["CXXFLAGS"] = " ".join(
[
env["CFLAGS"],
"-std=c++11",
env["CXXFLAGS"],
]
)
env["LDFLAGS"] = " ".join(
[
" -arch {}".format(self.arch),
"-isysroot {}".format(self.root_path),
]
)
def get_bin_dir(self):
return [pj(self.root_path, "bin")]
@property
def binaries(self):
return {
"CC": xrun_find("clang"),
"CXX": xrun_find("clang++"),
"AR": xrun_find("ar"),
"STRIP": xrun_find("strip"),
"RANLIB": xrun_find("ranlib"),
"LD": xrun_find("ld"),
"PKGCONFIG": "pkg-config",
}
@property
def configure_options(self):
yield f"--host={self.host}"
class iOSArm64(AppleConfigInfo):
name = "iOS_arm64"
arch = cpu = "arm64"
host = "arm-apple-darwin"
target = "aarch64-apple-ios"
sdk_name = "iphoneos"
min_iphoneos_version = "15.0"
class iOSx64Simulator(AppleConfigInfo):
name = "iOSSimulator_x86_64"
arch = cpu = "x86_64"
host = "x86_64-apple-darwin"
target = "x86-apple-ios-simulator"
sdk_name = "iphonesimulator"
min_iphoneos_version = "15.0"
class iOSArm64Simulator(AppleConfigInfo):
name = "iOSSimulator_arm64"
arch = cpu = "arm64"
host = "arm-apple-darwin"
target = "aarch64-apple-ios-simulator"
sdk_name = "iphonesimulator"
min_iphoneos_version = "15.0"
class macOSArm64(AppleConfigInfo):
name = "macOS_arm64_static"
arch = cpu = "arm64"
host = "aarch64-apple-darwin"
target = "arm64-apple-macos"
sdk_name = "macosx"
min_iphoneos_version = None
min_macos_version = MIN_MACOS_VERSION
class macOSArm64Mixed(MixedMixin("macOS_arm64_static"), AppleConfigInfo):
name = "macOS_arm64_mixed"
arch = cpu = "arm64"
host = "aarch64-apple-darwin"
target = "arm64-apple-macos"
sdk_name = "macosx"
min_iphoneos_version = None
min_macos_version = MIN_MACOS_VERSION
class macOSx64(AppleConfigInfo):
name = "macOS_x86_64"
arch = cpu = "x86_64"
host = "x86_64-apple-darwin"
target = "x86_64-apple-macos"
sdk_name = "macosx"
min_iphoneos_version = None
min_macos_version = MIN_MACOS_VERSION
class IOS(MetaConfigInfo):
name = "iOS_multi"
compatible_hosts = ["Darwin"]
@property
def arch_name(self):
return self.name
@property
def subConfigNames(self):
return ["iOS_{}".format(arch) for arch in option("ios_arch")]
def add_targets(self, targetName, targets):
super().add_targets(targetName, targets)
return ConfigInfo.add_targets(self, "_ios_fat_lib", targets)
def __str__(self):
return self.name
class AppleStaticAll(MetaConfigInfo):
name = "apple_all_static"
compatible_hosts = ["Darwin"]
@property
def arch_name(self):
return self.name
@property
def subConfigNames(self):
return AppleXCFramework.subConfigNames
def add_targets(self, targetName, targets):
super().add_targets(targetName, targets)
return ConfigInfo.add_targets(self, "apple_xcframework", targets)
def __str__(self):
return self.name

View File

@ -1,157 +0,0 @@
from .base import ConfigInfo, MixedMixin
from kiwixbuild.utils import pj
from kiwixbuild._global import get_target_step
class MuslConfigInfo(ConfigInfo):
compatible_hosts = ["fedora", "debian"]
def get_cross_config(self):
return {
"binaries": self.binaries,
"exe_wrapper_def": "",
"root_path": self.root_path,
"extra_libs": [],
"extra_cflags": [
"-I{}".format(include_dir) for include_dir in self.get_include_dirs()
],
"host_machine": {
"system": "linux",
"lsystem": "linux",
"cpu_family": self.cpu_family,
"cpu": self.cpu,
"endian": "little",
"abi": "",
},
}
@property
def toolchain(self):
return get_target_step(self.build, "neutral")
@property
def root_path(self):
return self.toolchain.build_path
@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"),
("LDSHARED", "g++ -shared"),
)
)
binaries = {k: pj(self.root_path, "bin", v) for k, v in binaries}
binaries["PKGCONFIG"] = "pkg-config"
return binaries
@property
def exe_wrapper_def(self):
try:
which(self.qemu)
except subprocess.CalledProcessError:
return ""
except AttributeError:
return ""
else:
return f"exe_wrapper = '{self.qemu}'"
@property
def configure_options(self):
return [f"--host={self.arch_full}"]
def get_bin_dir(self):
return [pj(self.root_path, "bin")]
def get_env(self):
env = super().get_env()
env["LD_LIBRARY_PATH"][0:0] = [
pj(self.root_path, self.arch_full, "lib64"),
pj(self.root_path, "lib"),
]
env["PKG_CONFIG_LIBDIR"] = pj(self.root_path, "lib", "pkgconfig")
env["QEMU_LD_PREFIX"] = pj(self.root_path, self.arch_full, "libc")
env["QEMU_SET_ENV"] = "LD_LIBRARY_PATH={}".format(
":".join(
[pj(self.root_path, self.arch_full, "lib"), str(env["LD_LIBRARY_PATH"])]
)
)
return env
def set_comp_flags(self, env):
super().set_comp_flags(env)
env["LD_LIBRARY_PATH"].insert(0, pj(self.root_path, self.arch_full, "lib"))
env["CFLAGS"] = (
" -fPIC -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CFLAGS"]
)
env["CXXFLAGS"] = (
" -fPIC -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CXXFLAGS"]
)
def set_compiler(self, env):
for k, v in self.binaries.items():
env[k] = v
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile("cmake_cross_file.txt")
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")
class Aarch64MuslConfigInfo(MuslConfigInfo):
build = "aarch64_musl"
arch_full = "aarch64-linux-musl"
toolchain_names = ["aarch64_musl"]
libdir = "lib/aarch64-linux-musl"
cpu_family = "arm"
cpu = "armhf"
qemu = "qemu-arm"
class Aarch64MuslDyn(Aarch64MuslConfigInfo):
name = "aarch64_musl_dyn"
static = False
class Aarch64MuslStatic(Aarch64MuslConfigInfo):
name = "aarch64_musl_static"
static = True
class Aarch64MuslMixed(MixedMixin("aarch64_musl_static"), Aarch64MuslConfigInfo):
name = "aarch64_musl_mixed"
static = False
class X86_64MuslConfigInfo(MuslConfigInfo):
build = "x86-64_musl"
arch_full = "x86_64-linux-musl"
toolchain_names = ["x86-64_musl"]
libdir = "lib/x86_64-linux-musl"
cpu_family = "x86_64"
cpu = "x86_64"
class X86_64MuslDyn(X86_64MuslConfigInfo):
name = "x86-64_musl_dyn"
static = False
class X86_64MuslStatic(X86_64MuslConfigInfo):
name = "x86-64_musl_static"
static = True
class x86_64MuslMixed(MixedMixin("x86-64_musl_static"), X86_64MuslConfigInfo):
name = "x86-64_musl_mixed"
static = False

View File

@ -1,44 +0,0 @@
from .base import ConfigInfo, MixedMixin
from kiwixbuild.utils import pj
from kiwixbuild._global import option, neutralEnv
from kiwixbuild.configs.ios import MIN_MACOS_VERSION
import sysconfig
import platform
import sys
class NativeConfigInfo(ConfigInfo):
build = "native"
def get_env(self):
env = super().get_env()
if neutralEnv("distname") == "fedora":
env["QT_SELECT"] = "5-64"
if neutralEnv("distname") == "Darwin":
env["CFLAGS"] += f"-mmacosx-version-min={MIN_MACOS_VERSION}"
return env
@property
def arch_name(self):
if sys.platform == "darwin":
return f"{platform.machine()}-apple-darwin"
return sysconfig.get_platform()
class NativeDyn(NativeConfigInfo):
name = "native_dyn"
static = False
compatible_hosts = ["fedora", "debian", "Darwin", "almalinux", "Windows"]
class NativeStatic(NativeConfigInfo):
name = "native_static"
static = True
compatible_hosts = ["fedora", "debian", "Darwin", "almalinux", "Windows"]
class NativeMixed(MixedMixin("native_static"), NativeConfigInfo):
name = "native_mixed"
static = False
compatible_hosts = ["fedora", "debian", "Darwin", "almalinux", "Windows"]

View File

@ -1,11 +0,0 @@
from .base import ConfigInfo
class NeutralConfigInfo(ConfigInfo):
name = "neutral"
arch_name = "neutral"
static = ""
compatible_hosts = ["fedora", "debian", "Darwin"]
def __str__(self):
return "neutral"

View File

@ -1,113 +0,0 @@
from .base import ConfigInfo
from kiwixbuild.utils import pj
from kiwixbuild._global import get_target_step
class WasmConfigInfo(ConfigInfo):
name = "wasm"
static = True
build = "wasm"
arch_full = "wasm64-emscripten"
libdir = "lib"
# arch_full = 'wasm64-linux'
toolchain_names = ["emsdk"]
compatible_hosts = ["fedora", "debian"]
exe_wrapper_def = ""
def get_cross_config(self):
return {
"binaries": self.binaries,
"exe_wrapper_def": "",
"root_path": self.root_path,
"extra_libs": [],
"extra_cflags": [],
"host_machine": {
"system": "emscripten",
"lsystem": "emscripten",
"cpu_family": "wasm64",
"cpu": "wasm64",
"endian": "little",
"abi": "",
},
}
@property
def wasm_sdk(self):
return get_target_step("emsdk", self.name)
@property
def install_path(self):
return self.wasm_sdk.install_path
@property
def root_path(self):
return self.install_path
@property
def binaries(self):
binaries = (
("CC", "emcc"),
("CXX", "em++"),
("AR", "emar"),
("STRIP", "emstrip"),
("WINDRES", "windres"),
("RANLIB", "emranlib"),
("LD", "wasm-ld"),
)
binaries = {
k: pj(self.install_path, "upstream", "emscripten", v) for k, v in binaries
}
binaries["PKGCONFIG"] = "pkg-config"
return binaries
@property
def configure_options(self):
# return ""
return [f"--host={self.arch_full}"]
@property
def configure_wrapper(self):
return "emconfigure"
@property
def make_wrapper(self):
return "emmake"
def get_bin_dir(self):
return [pj(self.install_path, "bin")]
def get_env(self):
env = super().get_env()
env["PATH"].extend(
[
self.install_path,
pj(self.install_path, "upstream", "emscripten"),
pj(self.install_path, "node", "14.18.2_64bit", "bin"),
]
)
env["EMSDK"] = self.install_path
env["EMSDK_NODE"] = pj(
self.install_path, "node", "14.18.2_64bit", "bin", "node"
)
return env
def set_comp_flags(self, env):
super().set_comp_flags(env)
env["CFLAGS"] = (
" -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CFLAGS"]
)
env["CXXFLAGS"] = (
" -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 "
+ env["CXXFLAGS"]
)
def set_compiler(self, env):
for k, v in self.binaries.items():
env[k] = v
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile("cmake_cross_file.txt")
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")

View File

@ -1,103 +0,0 @@
import subprocess
from .base import ConfigInfo
from kiwixbuild.utils import which, pj
from kiwixbuild._global import neutralEnv
class Win64ConfigInfo(ConfigInfo):
extra_libs = [
"-lmingw32",
"-lwinmm",
"-lws2_32",
"-lshlwapi",
"-lrpcrt4",
"-lmsvcr100",
"-liphlpapi",
"-lshell32",
"-lkernel32",
]
build = "win64"
compatible_hosts = ["fedora", "debian"]
arch_full = "x86_64-w64-mingw32"
def get_cross_config(self):
return {
"exe_wrapper_def": self.exe_wrapper_def,
"binaries": self.binaries,
"root_path": self.root_path,
"extra_libs": self.extra_libs,
"extra_cflags": ["-DWIN32"],
"host_machine": {
"system": "Windows",
"lsystem": "windows",
"cpu_family": "x86_64",
"cpu": "x86_64",
"endian": "little",
"abi": "",
},
}
def finalize_setup(self):
super().finalize_setup()
self.buildEnv.cmake_crossfile = self._gen_crossfile("cmake_cross_file.txt")
self.buildEnv.meson_crossfile = self._gen_crossfile("meson_cross_file.txt")
@property
def root_path(self):
root_paths = {
"fedora": "/usr/x86_64-w64-mingw32/sys-root/mingw",
"debian": "/usr/x86_64-w64-mingw32",
}
return root_paths[neutralEnv("distname")]
@property
def binaries(self):
return {
k: which("{}-{}".format(self.arch_full, v))
for k, v in (
("CC", "gcc"),
("CXX", "g++"),
("AR", "ar"),
("STRIP", "strip"),
("WINDRES", "windres"),
("RANLIB", "ranlib"),
("PKGCONFIG", "pkg-config"),
)
}
@property
def exe_wrapper_def(self):
try:
which("wine")
except subprocess.CalledProcessError:
return ""
else:
return "exe_wrapper = 'wine'"
@property
def configure_options(self):
return [f"--host={self.arch_full}"]
def set_compiler(self, env):
for k, v in self.binaries.items():
env[k] = v
def get_bin_dir(self):
return [pj(self.root_path, "bin")]
def get_env(self):
env = super().get_env()
env["PKG_CONFIG_LIBDIR"] = pj(self.root_path, "lib", "pkgconfig")
env["LIBS"] = " ".join(self.extra_libs) + " " + env["LIBS"]
return env
class Win64Dyn(Win64ConfigInfo):
name = "win64_dyn"
static = False
class Win64Static(Win64ConfigInfo):
name = "win64_static"
static = True

View File

@ -1,14 +1,13 @@
from .base import *
from . import (
all_dependencies,
boostregex,
tc_android_ndk,
android_ndk,
aria2,
tc_armhf,
tc_musl,
armhf,
docoptcpp,
tc_emsdk,
tc_flatpak,
emsdk,
flatpak,
gumbo,
icu4c,
ios_fat_lib,
@ -28,5 +27,5 @@ from . import (
zim_tools,
zim_testing_suite,
zlib,
zstd,
zstd
)

View File

@ -1,61 +1,30 @@
from os import environ
from .base import Dependency, NoopSource, NoopBuilder
from .base import (
Dependency,
NoopSource,
NoopBuilder)
from kiwixbuild._global import neutralEnv
class AllBaseDependencies(Dependency):
name = "alldependencies"
Source = NoopSource
class Builder(NoopBuilder):
@classmethod
def get_dependencies(cls, configInfo, allDeps):
if configInfo.build == "wasm" or environ.get("OS_NAME") == "manylinux":
return ["zlib", "lzma", "zstd", "icu4c", "xapian-core"]
def get_dependencies(cls, platformInfo, allDeps):
if platformInfo.build == "wasm":
return ['zlib', 'lzma', 'zstd', 'icu4c', 'xapian-core']
if neutralEnv("distname") == "Windows":
base_deps = [
"zlib",
"zstd",
"xapian-core",
"zim-testing-suite",
"icu4c",
"boostregex",
"docoptcpp",
]
if not configInfo.name.endswith("_dyn"):
base_deps += [
"pugixml",
"libcurl",
"mustache",
"libmicrohttpd",
]
else:
base_deps = [
"zlib",
"lzma",
"zstd",
"xapian-core",
"pugixml",
"libcurl",
"icu4c",
"mustache",
"libmicrohttpd",
"zim-testing-suite",
]
# Add specific dependencies depending of the config
if configInfo.build not in ("android", "iOS"):
# For zimtools
base_deps += ["docoptcpp", "libmagic", "gumbo"]
if (
configInfo.build == "native"
and neutralEnv("distname") != "Darwin"
):
# We compile kiwix-desktop only on native and not on `Darwin`
# So we need aria2 only there
base_deps += ["aria2"]
base_deps = ['zlib', 'lzma', 'zstd', 'xapian-core', 'pugixml', 'libcurl', 'icu4c', 'mustache', 'libmicrohttpd', 'zim-testing-suite']
# Add specific dependencies depending of the platform
if platformInfo.build not in ('android', 'iOS'):
# For zimtools
base_deps += ['docoptcpp']
if platformInfo.build != 'win32':
# zimwriterfs
base_deps += ['libmagic', 'gumbo']
if platformInfo.build == 'native' and neutralEnv('distname') != 'Darwin':
# We compile kiwix-desktop only on native and not on `Darwin`
# So we need aria2 only there
base_deps += ['aria2']
return base_deps

View File

@ -0,0 +1,79 @@
import os
from .base import Dependency, ReleaseDownload, Builder
from kiwixbuild.utils import Remotefile, add_execution_right, run_command
pj = os.path.join
class android_ndk(Dependency):
dont_skip = True
neutral = False
name = 'android-ndk'
gccver = '4.9.x'
api = '24'
class Source(ReleaseDownload):
archive = Remotefile('android-ndk-r21e-linux-x86_64.zip',
'ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
'https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip')
@property
def source_dir(self):
return self.target.full_name()
class Builder(Builder):
@property
def install_path(self):
return self.build_path
@property
def api(self):
return self.target.api
@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
def _build_platform(self, context):
context.try_skip(self.build_path)
script = pj(self.source_path, 'build/tools/make_standalone_toolchain.py')
add_execution_right(script)
command = '{script} --arch={arch} --api={api} --install-dir={install_dir} --force'
command = command.format(
script=script,
arch=self.arch,
api=self.api,
install_dir=self.install_path
)
env = self.buildEnv.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=False)
run_command(command, self.build_path, context, env=env)
def _fix_permission_right(self, context):
context.try_skip(self.build_path)
bin_dirs = [pj(self.install_path, 'bin'),
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:
continue
for file_ in files:
file_path = pj(root, file_)
if os.path.islink(file_path):
continue
add_execution_right(file_path)
def build(self):
self.command('build_platform', self._build_platform)
self.command('fix_permission_right', self._fix_permission_right)

View File

@ -1,126 +0,0 @@
import os
import shutil
from pathlib import Path
from kiwixbuild.configs import ConfigInfo
from kiwixbuild.utils import pj, run_command
from .base import Dependency, NoopSource, Builder as BaseBuilder
class AppleXCFramework(Dependency):
name = "apple_xcframework"
subConfigNames = [
"macOS_x86_64",
"macOS_arm64_static",
"iOS_arm64",
"iOSSimulator_x86_64",
"iOSSimulator_arm64",
]
Source = NoopSource
class Builder(BaseBuilder):
@property
def all_subconfigs(self):
return self.buildEnv.configInfo.subConfigNames
@property
def macos_subconfigs(self):
return [
target for target in self.all_subconfigs if target.startswith("macOS")
]
@property
def iossimulator_subconfigs(self):
return [
target
for target in self.all_subconfigs
if target.startswith("iOSSimulator")
]
@property
def ios_subconfigs(self):
return [
target for target in self.all_subconfigs if target.startswith("iOS_")
]
@classmethod
def get_dependencies(cls, configInfo, alldeps):
return [(target, "libkiwix") for target in AppleXCFramework.subConfigNames]
@property
def final_path(self):
return pj(self.buildEnv.install_dir, "lib", "CoreKiwix.xcframework")
def _remove_if_exists(self, context):
if not os.path.exists(self.final_path):
return
shutil.rmtree(self.final_path)
def _merge_libs(self, context):
"""create merged.a in all targets to bundle all static archives"""
xcf_libs = []
for target in self.all_subconfigs:
static_ars = []
cfg = ConfigInfo.get_config(target)
lib_dir = pj(cfg.buildEnv.install_dir, "lib")
static_ars = [str(f) for f in Path(lib_dir).glob("*.a")]
# create merged.a from all *.a in install_dir/lib
command = ["libtool", "-static", "-o", "merged.a", *static_ars]
run_command(command, lib_dir, context)
# will be included in xcframework
if target in self.ios_subconfigs:
xcf_libs.append(pj(lib_dir, "merged.a"))
return xcf_libs
def make_fat_with(self, configs, folder_name, context):
"""create fat merged.a in {folder_name} install/lib with {configs}"""
libs = []
for target in configs:
cfg = ConfigInfo.get_config(target)
libs.append(pj(cfg.buildEnv.install_dir, "lib", "merged.a"))
fat_dir = pj(self.buildEnv.build_dir, folder_name)
os.makedirs(fat_dir, exist_ok=True)
output_merged = pj(fat_dir, "merged.a")
command = ["lipo", "-create", "-output", output_merged, *libs]
run_command(command, self.buildEnv.build_dir, context)
return [output_merged]
def _build_xcframework(self, xcf_libs, context):
# create xcframework
ref_conf = ConfigInfo.get_config(self.macos_subconfigs[0])
command = ["xcodebuild", "-create-xcframework"]
for lib in xcf_libs:
command += [
"-library",
lib,
"-headers",
pj(ref_conf.buildEnv.install_dir, "include"),
]
command += ["-output", self.final_path]
run_command(command, self.buildEnv.build_dir, context)
def build(self):
xcf_libs = []
self.command("remove_if_exists", self._remove_if_exists)
xcf_libs += self.command("merge_libs", self._merge_libs)
xcf_libs += self.command(
"make_macos_fat",
self.make_fat_with,
self.macos_subconfigs,
"macOS_fat",
)
xcf_libs += self.command(
"make_simulator_fat",
self.make_fat_with,
self.iossimulator_subconfigs,
"iOS-simulator_fat",
)
self.command("build_xcframework", self._build_xcframework, xcf_libs)

View File

@ -1,53 +1,24 @@
from .base import Dependency, ReleaseDownload, MakeBuilder, NoopBuilder
from .base import (
Dependency,
ReleaseDownload,
MakeBuilder
)
from kiwixbuild.utils import Remotefile, run_command, pj
import platform
from shutil import copy2
# Important: in case of aria2c update,
# 'scripts/create_kiwix-desktop_appImage.sh' should not be forgotten!
from kiwixbuild.utils import Remotefile, run_command
class Aria2(Dependency):
name = "aria2"
if platform.system() == "Windows":
class Source(ReleaseDownload):
archive = Remotefile('aria2-1.36.0.tar.xz',
'58d1e7608c12404f0229a3d9a4953d0d00c18040504498b483305bcb3de907a5',
'https://github.com/aria2/aria2/releases/download/release-1.36.0/aria2-1.36.0.tar.xz')
class Source(ReleaseDownload):
archive = Remotefile(
"aria2-1.37.0-win-64bit-build1.zip",
"67d015301eef0b612191212d564c5bb0a14b5b9c4796b76454276a4d28d9b288",
"https://dev.kiwix.org/kiwix-desktop/aria2-1.37.0-win-64bit-build1.zip",
)
def _post_prepare_script(self, context):
context.try_skip(self.extract_path)
command = "autoreconf -i"
run_command(command, self.extract_path, context)
class Builder(NoopBuilder):
def build(self):
self.command("copy_binary", self._copy_binary)
def _copy_binary(self, context):
context.try_skip(self.build_path)
copy2(
pj(self.source_path, "aria2c.exe"),
pj(self.buildEnv.install_dir, "bin"),
)
else:
class Source(ReleaseDownload):
archive = Remotefile(
"aria2-1.37.0.tar.xz",
"60a420ad7085eb616cb6e2bdf0a7206d68ff3d37fb5a956dc44242eb2f79b66b",
"https://dev.kiwix.org/kiwix-desktop/aria2-1.37.0.tar.xz",
)
def _post_prepare_script(self, context):
context.try_skip(self.extract_path)
command = ["autoreconf", "-i"]
run_command(command, self.extract_path, context)
class Builder(MakeBuilder):
dependencies = ["zlib"]
configure_options = [
"--disable-libaria2",
"--disable-websocket",
"--without-sqlite3",
]
class Builder(MakeBuilder):
dependencies = ['zlib']
configure_option = "--disable-libaria2 --disable-websocket --without-sqlite3"

View File

@ -0,0 +1,13 @@
from .base import Dependency, ReleaseDownload, NoopBuilder
from kiwixbuild.utils import Remotefile
class armhf_toolchain(Dependency):
dont_skip = True
neutral = True
name = 'armhf'
class Source(ReleaseDownload):
archive = Remotefile('raspberrypi-tools.tar.gz',
'e72b35436f2f23f2f7df322d6c318b9be57b21596b5ff0b8936af4ad94e04f2e')
Builder = NoopBuilder

View File

@ -2,19 +2,8 @@ import subprocess
import os
import shutil
import time
import platform
from kiwixbuild.utils import (
pj,
Context,
SkipCommand,
WarningMessage,
extract_archive,
StopBuild,
run_command,
colorize,
copy_tree,
)
from kiwixbuild.utils import pj, Context, SkipCommand, WarningMessage, extract_archive, Defaultdict, StopBuild, run_command, colorize
from kiwixbuild.versions import main_project_versions, base_deps_versions
from kiwixbuild._global import neutralEnv, option, get_target_step
@ -24,8 +13,8 @@ SCRIPT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
class _MetaDependency(type):
def __new__(cls, name, bases, dct):
_class = type.__new__(cls, name, bases, dct)
if name != "Dependency":
dep_name = dct["name"]
if name != 'Dependency':
dep_name = dct['name']
Dependency.all_deps[dep_name] = _class
return _class
@ -40,7 +29,7 @@ class Dependency(metaclass=_MetaDependency):
def version(cls):
if cls.name in base_deps_versions:
return base_deps_versions[cls.name]
elif option("make_release"):
elif option('make_release'):
return main_project_versions.get(cls.name, None)
return None
@ -53,9 +42,8 @@ class Dependency(metaclass=_MetaDependency):
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."""
A source preparator must install source in the self.source_dir attribute
inside the neutralEnv.source_dir."""
def __init__(self, target):
self.target = target
@ -73,22 +61,22 @@ class Source:
@property
def source_path(self):
return pj(neutralEnv("source_dir"), self.source_dir)
return pj(neutralEnv('source_dir'), self.source_dir)
@property
def _log_dir(self):
return neutralEnv("log_dir")
return neutralEnv('log_dir')
def _patch(self, context):
context.try_skip(self.source_path)
for p in self.patches:
patch_file_path = pj(SCRIPT_DIR, "patches", p)
patch_command = [*neutralEnv("patch_command"), "-p1", "-i", patch_file_path]
patch_file_path = pj(SCRIPT_DIR, 'patches', p)
patch_command = "patch -p1 -i {patch}".format(patch=patch_file_path)
run_command(patch_command, self.source_path, context)
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))
log = pj(self._log_dir, 'cmd_{}_{}.log'.format(name, self.name))
context = Context(name, log, True)
try:
start_time = time.time()
@ -104,7 +92,7 @@ class Source:
except subprocess.CalledProcessError:
print(colorize("ERROR"))
try:
with open(log, "r") as f:
with open(log, 'r') as f:
print(f.read())
except:
pass
@ -122,47 +110,30 @@ class NoopSource(Source):
class ReleaseDownload(Source):
archive_top_dir = None
@property
def archives(self):
return (self.archive,)
@property
def extract_path(self):
return pj(neutralEnv("source_dir"), self.source_dir)
return pj(neutralEnv('source_dir'), self.source_dir)
def _download(self, context):
context.try_skip(neutralEnv("archive_dir"), self.full_name)
archive_iter = iter(self.archives)
archive = next(archive_iter, None)
while archive:
try:
neutralEnv("download")(archive)
except SkipCommand as e:
archive = next(archive_iter, None)
if not archive:
raise e
continue
archive = next(archive_iter, None)
context.try_skip(neutralEnv('archive_dir'), self.full_name)
neutralEnv('download')(self.archive)
def _extract(self, context):
context.try_skip(self.extract_path)
if os.path.exists(self.extract_path):
shutil.rmtree(self.extract_path)
for archive in self.archives:
extract_archive(
pj(neutralEnv("archive_dir"), archive.name),
neutralEnv("source_dir"),
topdir=self.archive_top_dir,
name=self.source_dir,
)
extract_archive(pj(neutralEnv('archive_dir'), self.archive.name),
neutralEnv('source_dir'),
topdir=self.archive_top_dir,
name=self.source_dir)
def prepare(self):
self.command("download", self._download)
self.command("extract", self._extract)
if hasattr(self, "patches"):
self.command("patch", self._patch)
if hasattr(self, "_post_prepare_script"):
self.command("post_prepare_script", self._post_prepare_script)
self.command('download', self._download)
self.command('extract', self._extract)
if hasattr(self, 'patches'):
self.command('patch', self._patch)
if hasattr(self, '_post_prepare_script'):
self.command('post_prepare_script', self._post_prepare_script)
class GitClone(Source):
@ -175,66 +146,70 @@ class GitClone(Source):
@property
def source_dir(self):
if option("make_release"):
if option('make_release'):
return "{}_release".format(self.git_dir)
else:
return self.git_dir
@property
def git_path(self):
return pj(neutralEnv("source_dir"), self.source_dir)
return pj(neutralEnv('source_dir'), self.source_dir)
@property
def git_ref(self):
if option("make_release"):
if option('make_release'):
return self.release_git_ref
else:
return self.base_git_ref
def _git_init(self, context):
if option("fast_clone") and self.force_full_clone == False:
command = [
*neutralEnv("git_command"),
"clone",
"--depth=1",
"--branch",
self.git_ref,
self.git_remote,
self.source_dir,
]
run_command(command, neutralEnv("source_dir"), 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 = [
*neutralEnv("git_command"),
"clone",
self.git_remote,
self.source_dir,
]
run_command(command, neutralEnv("source_dir"), context)
command = [*neutralEnv("git_command"), "checkout", self.git_ref]
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 _git_update(self, context):
command = [*neutralEnv("git_command"), "fetch", "origin", self.git_ref]
command = "git fetch origin {}".format(self.git_ref)
run_command(command, self.git_path, context)
try:
command = [
*neutralEnv("git_command"),
"merge",
"--ff-only",
f"origin/{self.git_ref}",
]
command = "git merge --ff-only origin/{}".format(self.git_ref)
run_command(command, self.git_path, context)
except subprocess.CalledProcessError:
raise WarningMessage("Cannot update, please check log for information")
def prepare(self):
if not os.path.exists(self.git_path):
self.command("gitinit", self._git_init)
self.command('gitinit', self._git_init)
else:
self.command("gitupdate", self._git_update)
if hasattr(self, "_post_prepare_script"):
self.command("post_prepare_script", self._post_prepare_script)
self.command('gitupdate', self._git_update)
if hasattr(self, '_post_prepare_script'):
self.command('post_prepare_script', self._post_prepare_script)
class SvnClone(Source):
@property
def source_dir(self):
return self.svn_dir
@property
def svn_path(self):
return pj(neutralEnv('source_dir'), self.svn_dir)
def _svn_export(self, context):
if os.path.exists(self.svn_path):
raise SkipCommand()
command = "svn export {} {}".format(self.svn_remote, self.svn_dir)
run_command(command, neutralEnv('source_dir'), context)
def prepare(self):
self.command('svnexport', self._svn_export)
if hasattr(self, 'patches'):
self.command('patch', self._patch)
class Builder:
@ -247,7 +222,7 @@ class Builder:
self.buildEnv = buildEnv
@classmethod
def get_dependencies(cls, configInfo, allDeps):
def get_dependencies(cls, platformInfo, allDeps):
return cls.dependencies
@property
@ -271,7 +246,7 @@ class Builder:
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))
log = pj(self._log_dir, 'cmd_{}_{}.log'.format(name, self.name))
context = Context(name, log, self.target.force_native_build)
if self.target.force_build:
context.no_skip = True
@ -289,7 +264,7 @@ class Builder:
except subprocess.CalledProcessError:
print(colorize("ERROR"))
try:
with open(log, "r") as f:
with open(log, 'r') as f:
print(f.read())
except:
pass
@ -299,43 +274,37 @@ class Builder:
raise
def build(self):
if hasattr(self, "_pre_build_script"):
self.command("pre_build_script", self._pre_build_script)
self.command("configure", self._configure)
if hasattr(self, "_post_configure_script"):
self.command("post_configure_script", self._post_configure_script)
self.command("compile", self._compile)
if hasattr(self, "_test"):
self.command("test", self._test)
self.command("install", self._install)
if hasattr(self, "_post_build_script"):
self.command("post_build_script", self._post_build_script)
if hasattr(self, '_pre_build_script'):
self.command('pre_build_script', self._pre_build_script)
self.command('configure', self._configure)
self.command('compile', self._compile)
if hasattr(self, '_test'):
self.command('test', self._test)
self.command('install', self._install)
if hasattr(self, '_post_build_script'):
self.command('post_build_script', self._post_build_script)
def make_dist(self):
if hasattr(self, "_pre_build_script"):
self.command("pre_build_script", self._pre_build_script)
self.command("configure", self._configure)
self.command("make_dist", self._make_dist)
if hasattr(self, '_pre_build_script'):
self.command('pre_build_script', self._pre_build_script)
self.command('configure', self._configure)
self.command('make_dist', self._make_dist)
def set_flatpak_buildsystem(self, module):
if getattr(self, "flatpak_buildsystem", None):
module["buildsystem"] = self.flatpak_buildsystem
if getattr(self, "subsource_dir", None):
module["subdir"] = self.subsource_dir
if getattr(self, "flatpack_build_options", None):
module["build-options"] = self.flatpack_build_options
if getattr(self, "configure_options", ""):
module["config-opts"] = list(self.configure_options)
if getattr(self, 'flatpak_buildsystem', None):
module['buildsystem'] = self.flatpak_buildsystem
if getattr(self, 'subsource_dir', None):
module['subdir'] = self.subsource_dir
if getattr(self, 'flatpack_build_options', None):
module['build-options'] = self.flatpack_build_options
if getattr(self, 'configure_option', ''):
module['config-opts'] = self.configure_option.split(' ')
def get_env(self, *, cross_comp_flags, cross_compilers, cross_path):
env = self.buildEnv.get_env(
cross_comp_flags=cross_comp_flags,
cross_compilers=cross_compilers,
cross_path=cross_path,
)
for dep in self.get_dependencies(self.buildEnv.configInfo, False):
env = self.buildEnv.get_env(cross_comp_flags=cross_comp_flags, cross_compilers=cross_compilers, cross_path=cross_path)
for dep in self.get_dependencies(self.buildEnv.platformInfo, False):
try:
builder = get_target_step(dep, self.buildEnv.configInfo.name)
builder = get_target_step(dep, self.buildEnv.platformInfo.name)
builder.set_env(env)
except KeyError:
# Some target may be missing (installed by a package, ...)
@ -354,262 +323,234 @@ class NoopBuilder(Builder):
pass
class TcCopyBuilder(Builder):
src_subdir = None
@property
def build_path(self):
return pj(self.buildEnv.toolchain_dir, self.target.full_name())
def build(self):
self.command("copy", self._copy)
def _copy(self, context):
context.try_skip(self.build_path)
if self.src_subdir:
source_path = pj(self.source_path, self.src_subdir)
else:
source_path = self.source_path
copy_tree(source_path, self.build_path)
def make_dist(self):
pass
class MakeBuilder(Builder):
configure_options = []
dynamic_configure_options = ["--enable-shared", "--disable-static"]
static_configure_options = ["--enable-static", "--disable-shared"]
make_options = ["-j4"]
install_options = []
configure_option_template = "{dep_options} {static_option} {env_option} --prefix {install_dir} --libdir {libdir}"
configure_option = ""
dynamic_configure_option = "--enable-shared --disable-static"
static_configure_option = "--enable-static --disable-shared"
make_option = ""
install_option = ""
configure_script = "configure"
configure_env = {
"_format_CFLAGS": "{env[CFLAGS]} -O3",
"_format_CXXFLAGS": "{env[CXXFLAGS]} -O3",
'_format_CFLAGS' : '{env[CFLAGS]} -O3',
'_format_CXXFLAGS': '{env[CXXFLAGS]} -O3'
}
make_targets = []
make_target = ""
flatpak_buildsystem = None
@property
def make_install_targets(self):
if self.buildEnv.configInfo.build in ("iOS", "wasm"):
yield "install"
else:
yield "install-strip"
def make_install_target(self):
if self.buildEnv.platformInfo.build in ('iOS', "wasm"):
return 'install'
return 'install-strip'
@property
def all_configure_options(self):
yield from self.configure_options
if self.buildEnv.configInfo.static:
yield from self.static_configure_options
else:
yield from self.dynamic_configure_options
if not self.target.force_native_build:
yield from self.buildEnv.configInfo.configure_options
yield from ("--prefix", self.buildEnv.install_dir)
yield from ("--libdir", pj(self.buildEnv.install_dir, self.buildEnv.libprefix))
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.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)
)
return option
def set_configure_env(self, env):
dep_conf_env = self.configure_env
if not dep_conf_env:
return
for k, v in dep_conf_env.items():
if k.startswith("_format_"):
if k.startswith('_format_'):
v = v.format(buildEnv=self.buildEnv, env=env)
env[k[8:]] = v
else:
env[k] = v
def _configure(self, context):
context.try_skip(self.build_path)
command = [
*self.buildEnv.configure_wrapper,
pj(self.source_path, self.configure_script),
*self.all_configure_options,
]
command = "{configure_wrapper}{configure_script} {configure_option}"
command = command.format(
configure_wrapper=self.buildEnv.configure_wrapper,
configure_script=pj(self.source_path, self.configure_script),
configure_option=self.all_configure_option
)
env = self.get_env(cross_comp_flags=True, cross_compilers=True, cross_path=True)
self.set_configure_env(env)
run_command(command, self.build_path, context, env=env)
def _compile(self, context):
context.try_skip(self.build_path)
command = [
*self.buildEnv.make_wrapper,
*neutralEnv("make_command"),
*self.make_targets,
*self.make_options,
]
command = "{make_wrapper}make -j4 {make_target} {make_option}".format(
make_wrapper=self.buildEnv.make_wrapper,
make_target=self.make_target,
make_option=self.make_option
)
env = self.get_env(cross_comp_flags=True, cross_compilers=True, cross_path=True)
run_command(command, self.build_path, context, env=env)
def _install(self, context):
context.try_skip(self.build_path)
command = [
*self.buildEnv.make_wrapper,
*neutralEnv("make_command"),
*self.make_install_targets,
*self.make_options,
]
command = "{make_wrapper}make {make_install_target} {make_option}".format(
make_wrapper=self.buildEnv.make_wrapper,
make_install_target=self.make_install_target,
make_option=self.make_option
)
env = self.get_env(cross_comp_flags=True, cross_compilers=True, cross_path=True)
run_command(command, self.build_path, context, env=env)
def _make_dist(self, context):
context.try_skip(self.build_path)
command = [*self.buildEnv.make_wrapper, *neutralEnv("make_command"), "dist"]
command = "{make_wrapper}make dist".format(
make_wrapper=self.buildEnv.make_wrapper
)
env = self.get_env(cross_comp_flags=True, cross_compilers=True, cross_path=True)
run_command(command, self.build_path, context, env=env)
class CMakeBuilder(MakeBuilder):
flatpak_buildsystem = "cmake"
flatpak_buildsystem = 'cmake'
def _configure(self, context):
context.try_skip(self.build_path)
cross_options = []
cross_option = ""
if not self.target.force_native_build and self.buildEnv.cmake_crossfile:
cross_options += [f"-DCMAKE_TOOLCHAIN_FILE={self.buildEnv.cmake_crossfile}"]
command = [
*neutralEnv("cmake_command"),
*self.configure_options,
"-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON",
f"-DCMAKE_INSTALL_PREFIX={self.buildEnv.install_dir}",
f"-DCMAKE_INSTALL_LIBDIR={self.buildEnv.libprefix}",
self.source_path,
*cross_options,
]
env = self.get_env(
cross_comp_flags=True, cross_compilers=False, cross_path=True
cross_option = "-DCMAKE_TOOLCHAIN_FILE={}".format(self.buildEnv.cmake_crossfile)
command = ("cmake {configure_option}"
" -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"
" -DCMAKE_INSTALL_PREFIX={install_dir}"
" -DCMAKE_INSTALL_LIBDIR={libdir}"
" {source_path}"
" {cross_option}")
command = command.format(
configure_option=self.configure_option,
install_dir=self.buildEnv.install_dir,
libdir=self.buildEnv.libprefix,
source_path=self.source_path,
cross_option=cross_option
)
env = self.get_env(cross_comp_flags=True, cross_compilers=False, cross_path=True)
self.set_configure_env(env)
run_command(command, self.build_path, context, env=env)
def set_flatpak_buildsystem(self, module):
super().set_flatpak_buildsystem(module)
module["buildir"] = True
super().set_flatpak_buildsystem( module)
module['buildir'] = True
class QMakeBuilder(MakeBuilder):
qmake_targets = []
flatpak_buildsystem = "qmake"
qmake_target = ""
flatpak_buildsystem = 'qmake'
@property
def make_options(self):
if platform.system() == "Windows":
return []
return super().make_options
@property
def env_options(self):
if "QMAKE_CC" in os.environ:
yield f"QMAKE_CC={os.environ['QMAKE_CC']}"
if "QMAKE_CXX" in os.environ:
yield f"QMAKE_CXX={os.environ['QMAKE_CXX']}"
def env_option(self):
options = ""
if 'QMAKE_CC' in os.environ:
options += 'QMAKE_CC={} '.format(os.environ['QMAKE_CC'])
if 'QMAKE_CXX' in os.environ:
options += 'QMAKE_CXX={} '.format(os.environ['QMAKE_CXX'])
return options
def _configure(self, context):
context.try_skip(self.build_path)
command = [
*neutralEnv("qmake_command"),
*self.configure_options,
*self.env_options,
self.source_path,
]
env = self.get_env(
cross_comp_flags=True, cross_compilers=False, cross_path=True
cross_option = ""
command = ("{command} {configure_option}"
" {env_option}"
" {source_path}"
" {cross_option}")
command = command.format(
command = neutralEnv('qmake_command'),
configure_option=self.configure_option,
env_option=self.env_option,
source_path=self.source_path,
cross_option=cross_option
)
env = self.get_env(cross_comp_flags=True, cross_compilers=False, cross_path=True)
self.set_configure_env(env)
run_command(command, self.build_path, context, env=env)
def _make_dist(self, context):
command = [
*neutralEnv("git_command"),
"archive",
"-o",
f"{self.build_path}/{self.target.full_name()}.tar.gz",
f"--prefix={self.target.full_name()}/",
"HEAD",
]
command = "git archive -o {build_dir}/{name}.tar.gz --prefix={name}/ HEAD"
command = command.format(
build_dir = self.build_path,
name = self.target.full_name()
)
run_command(command, self.source_path, context)
class MesonBuilder(Builder):
configure_options = []
test_options = []
flatpak_buildsystem = "meson"
configure_option = ""
test_option = ""
flatpak_buildsystem = 'meson'
@property
def build_type(self):
if platform.system() == "Windows":
return "release"
return "release" if option("make_release") else "debug"
return 'release' if option('make_release') else 'debug'
@property
def strip_options(self):
if option("make_release"):
yield "--strip"
def strip_option(self):
return '--strip' if option('make_release') else ''
@property
def library_type(self):
return "static" if self.buildEnv.configInfo.static else "shared"
return 'static' if self.buildEnv.platformInfo.static else 'shared'
def _configure(self, context):
context.no_skip = False
context.try_skip(self.build_path)
if os.path.exists(self.build_path):
shutil.rmtree(self.build_path)
os.makedirs(self.build_path)
cross_options = []
configure_option = self.configure_option.format(buildEnv=self.buildEnv)
cross_option = ""
if not self.target.force_native_build and self.buildEnv.meson_crossfile:
cross_options += ["--cross-file", self.buildEnv.meson_crossfile]
command = [
*neutralEnv("meson_command"),
"setup",
".",
self.build_path,
f"--buildtype={self.build_type}",
*self.strip_options,
f"--default-library={self.library_type}",
*self.configure_options,
f"--prefix={self.buildEnv.install_dir}",
f"--libdir={self.buildEnv.libprefix}",
*cross_options,
]
env = self.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=True
cross_option = "--cross-file {}".format(
self.buildEnv.meson_crossfile)
command = ("{command} . {build_path}"
" --buildtype={build_type} {strip_option}"
" --default-library={library_type}"
" {configure_option}"
" --prefix={buildEnv.install_dir}"
" --libdir={buildEnv.libprefix}"
" {cross_option}")
command = command.format(
command=neutralEnv('meson_command'),
build_type=self.build_type,
strip_option=self.strip_option,
library_type=self.library_type,
configure_option=configure_option,
build_path=self.build_path,
buildEnv=self.buildEnv,
cross_option=cross_option
)
env = self.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=True)
run_command(command, self.source_path, context, env=env)
def _compile(self, context):
context.try_skip(self.build_path)
command = [*neutralEnv("ninja_command"), "-v"]
env = self.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=True
)
command = "{} -v".format(neutralEnv('ninja_command'))
env = self.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=True)
run_command(command, self.build_path, context, env=env)
def _test(self, context):
context.try_skip(self.build_path)
if self.buildEnv.configInfo.build == "android" or (
self.buildEnv.configInfo.build != "native"
and not self.buildEnv.configInfo.static
):
if ( self.buildEnv.platformInfo.build == 'android'
or (self.buildEnv.platformInfo.build != 'native'
and not self.buildEnv.platformInfo.static)
):
raise SkipCommand()
command = [*neutralEnv("mesontest_command"), "--verbose", *self.test_options]
env = self.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=True
)
command = "{} --verbose {}".format(neutralEnv('mesontest_command'), self.test_option)
env = self.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=True)
run_command(command, self.build_path, context, env=env)
def _install(self, context):
context.try_skip(self.build_path)
command = [*neutralEnv("ninja_command"), "-v", "install"]
env = self.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=True
)
command = "{} -v install".format(neutralEnv('ninja_command'))
env = self.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=True)
run_command(command, self.build_path, context, env=env)
def _make_dist(self, context):
command = [*neutralEnv("ninja_command"), "-v", "dist"]
env = self.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=True
)
command = "{} -v dist".format(neutralEnv('ninja_command'))
env = self.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=True)
run_command(command, self.build_path, context, env=env)

View File

@ -1,27 +0,0 @@
from .base import Dependency, ReleaseDownload, Builder as BaseBuilder
from kiwixbuild.utils import Remotefile, pj
from shutil import copytree
class BoostRegex(Dependency):
name = "boostregex"
class Source(ReleaseDownload):
archive = Remotefile(
"regex-boost-1.86.0.zip",
"",
"https://codeload.github.com/boostorg/regex/zip/refs/tags/boost-1.86.0",
)
class Builder(BaseBuilder):
def build(self):
self.command("copy_headers", self._copy_headers)
def _copy_headers(self, context):
context.try_skip(self.build_path)
copytree(
pj(self.source_path, "include", "boost"),
pj(self.buildEnv.install_dir, "include", "boost"),
dirs_exist_ok=True,
)

View File

@ -1,34 +1,21 @@
from .base import Dependency, ReleaseDownload, MesonBuilder
from .base import (
Dependency,
GitClone,
CMakeBuilder)
from kiwixbuild.utils import Remotefile
from kiwixbuild._global import neutralEnv
class docoptcpp(Dependency):
name = "docoptcpp"
name = 'docoptcpp'
class Source(ReleaseDownload):
name = "docoptcpp"
src_archive = Remotefile(
"v0.6.3.tar.gz",
"28af5a0c482c6d508d22b14d588a3b0bd9ff97135f99c2814a5aa3cbff1d6632",
"https://github.com/docopt/docopt.cpp/archive/v0.6.3.tar.gz",
)
class Source(GitClone):
git_remote = "https://github.com/docopt/docopt.cpp.git"
git_dir = "docopt.cpp"
force_full_clone = True
git_ref = "3dd23e3280f213bacefdf5fcb04857bf52e90917"
meson_archive = Remotefile(
"docopt_0.6.3-3_patch.zip",
"1f641187f9d3f35b0a5ebd2011876ef8e9b04b69b7b163095dd7dfa16219ad01",
"https://wrapdb.mesonbuild.com/v2/docopt_0.6.3-3/get_patch",
)
class Builder(CMakeBuilder):
make_install_target = 'install'
archives = [src_archive, meson_archive]
patches = [
"docopt_meson_install_pkgconfig.patch",
"docopt_meson_use_boostregex.patch",
]
class Builder(MesonBuilder):
@classmethod
def get_dependencies(cls, configInfo, allDeps):
if neutralEnv("distname") == "Windows":
return ["boostregex"]
return []

View File

@ -0,0 +1,47 @@
import os
from .base import Dependency, ReleaseDownload, Builder
from kiwixbuild.utils import Remotefile, run_command, copy_tree
pj = os.path.join
class emsdk(Dependency):
dont_skip = True
neutral = False
name = 'emsdk'
class Source(ReleaseDownload):
archive = Remotefile('emsdk-3.1.24.tar.gz',
'1aa5365ccb2147701cc9d1e59a5a49577c1d6aea55da7c450df2d5ffa48b8a58',
'https://codeload.github.com/emscripten-core/emsdk/tar.gz/refs/tags/3.1.24')
@property
def source_dir(self):
return self.target.full_name()
class Builder(Builder):
@property
def install_path(self):
return self.build_path
def _copy_source(self, context):
context.try_skip(self.build_path)
copy_tree(self.source_path, self.build_path)
def _install(self, context):
context.try_skip(self.build_path)
command = "./emsdk install 3.1.24"
run_command(command, self.build_path, context)
def _activate(self, context):
context.try_skip(self.build_path)
command = "./emsdk activate 3.1.24"
run_command(command, self.build_path, context)
def build(self):
self.command('copy_source', self._copy_source)
self.command('install', self._install)
self.command('activate', self._activate)

View File

@ -0,0 +1,68 @@
import os
from .base import Dependency, NoopSource, Builder
from kiwixbuild.utils import Remotefile, add_execution_right, run_command
pj = os.path.join
class org_kde(Dependency):
neutral = False
name = 'org.kde'
Source = NoopSource
class Builder(Builder):
def _setup_remote(self, context):
command = "flatpak --user remote-add --if-not-exists {remote_name} {remote_url}"
command = command.format(
remote_name = 'flathub',
remote_url = 'https://flathub.org/repo/flathub.flatpakrepo'
)
env = self.buildEnv.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=False)
run_command(command, self.buildEnv.build_dir, context, env=env)
def _install_sdk(self, context):
command = "flatpak --user install --noninteractive --verbose -y {remote_name} {name}.Sdk//{version} {name}.Platform//{version}"
command = command.format(
remote_name = 'flathub',
name = self.target.name,
version = self.target.version()
)
env = self.buildEnv.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=False)
run_command(command, self.buildEnv.build_dir, context, env=env)
def build(self):
self.command('setup_remote', self._setup_remote)
self.command('install_sdk', self._install_sdk)
class io_qt_qtwebengine(Dependency):
neutral = False
name = 'io.qt.qtwebengine'
Source = NoopSource
class Builder(Builder):
def _setup_remote(self, context):
command = "flatpak --user remote-add --if-not-exists {remote_name} {remote_url}"
command = command.format(
remote_name = 'flathub',
remote_url = 'https://flathub.org/repo/flathub.flatpakrepo'
)
env = self.buildEnv.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=False)
run_command(command, self.buildEnv.build_dir, context, env=env)
def _install_sdk(self, context):
command = "flatpak --user install -y {remote_name} {name}.BaseApp//{version}"
command = command.format(
remote_name = 'flathub',
name = self.target.name,
version = self.target.version()
)
env = self.buildEnv.get_env(cross_comp_flags=False, cross_compilers=False, cross_path=False)
run_command(command, self.buildEnv.build_dir, context, env=env)
def build(self):
self.command('setup_remote', self._setup_remote)
self.command('install_sdk', self._install_sdk)

View File

@ -1,4 +1,8 @@
from .base import Dependency, ReleaseDownload, MakeBuilder
from .base import (
Dependency,
ReleaseDownload,
MakeBuilder
)
from kiwixbuild.utils import Remotefile, run_command
@ -7,15 +11,13 @@ class Gumbo(Dependency):
name = "gumbo"
class Source(ReleaseDownload):
archive = Remotefile(
"gumbo-parser-0.12.1.tar.gz",
"c0bb5354e46539680724d638dbea07296b797229a7e965b13305c930ddc10d82",
"https://dev.kiwix.org/kiwix-build/gumbo-parser-0.12.1.tar.gz",
)
archive = Remotefile('gumbo-0.10.1.tar.gz',
'28463053d44a5dfbc4b77bcf49c8cee119338ffa636cc17fc3378421d714efad',
'https://github.com/google/gumbo-parser/archive/v0.10.1.tar.gz')
def _post_prepare_script(self, context):
context.try_skip(self.extract_path)
command = ["./autogen.sh"]
command = "./autogen.sh"
run_command(command, self.extract_path, context)
Builder = MakeBuilder

View File

@ -1,191 +1,49 @@
from .base import (
Dependency,
ReleaseDownload,
MakeBuilder,
Builder as BaseBuilder,
MakeBuilder
)
from kiwixbuild.utils import pj, SkipCommand, Remotefile, extract_archive
from kiwixbuild._global import get_target_step, neutralEnv
import os, shutil
import fileinput
import platform
from kiwixbuild.utils import SkipCommand, Remotefile
from kiwixbuild._global import get_target_step
if platform.system() == "Windows":
class Icu(Dependency):
name = "icu4c"
class Icu(Dependency):
name = "icu4c"
class Source(ReleaseDownload):
archive = Remotefile('icu4c_svn_58-2.tar.gz',
'fd8fcc1f1b8b2b71b879e88844480ebec107189c21076c81573f71dca5686a0d')
patches = ["icu4c_fix_static_lib_name_mingw.patch",
"icu4c_android_elf64_st_info.patch",
"icu4c_custom_data.patch",
"icu4c_noxlocale.patch",
"icu4c_rpath.patch",
"icu4c_build_config.patch",
"icu4c_wasm.patch"
]
class Source(ReleaseDownload):
archive = Remotefile(
"icu4c-74_1-Win64-MSVC2022.zip",
"",
"https://github.com/unicode-org/icu/releases/download/release-74-1/icu4c-74_1-Win64-MSVC2022.zip",
)
class Builder(BaseBuilder):
def build(self):
self.command("copy_headers", self._copy_headers)
self.command("copy_bins", self._copy_bin)
self.command("generate_pkg_config", self._generate_pkg_config)
class Builder(MakeBuilder):
subsource_dir = "source"
make_install_target = "install"
def _copy_headers(self, context):
context.try_skip(self.build_path)
shutil.copytree(
pj(self.source_path, "include", "unicode"),
pj(self.buildEnv.install_dir, "include", "unicode"),
)
@classmethod
def get_dependencies(cls, platformInfo, allDeps):
plt = 'native_static' if platformInfo.static else 'native_dyn'
return [(plt, 'icu4c')]
def _copy_bin(self, context):
context.try_skip(self.build_path)
shutil.copytree(
pj(self.source_path, "lib64"),
pj(self.buildEnv.install_dir, "lib"),
dirs_exist_ok=True,
)
def ignore_non_dll(path, names):
return [n for n in names if not n.endswith(".dll")]
shutil.copytree(
pj(self.source_path, "bin64"),
pj(self.buildEnv.install_dir, "bin"),
ignore=ignore_non_dll,
dirs_exist_ok=True,
)
def _generate_pkg_config(self, context):
context.try_skip(self.build_path)
pkg_config_template = """ Copyright (C) 2016 and later: Unicode, Inc. and others.
# License & terms of use: http://www.unicode.org/copyright.html
# Copyright (C) 2010-2013, International Business Machines Corporation. All Rights Reserved.
# CFLAGS contains only anything end users should set
CFLAGS =
# CXXFLAGS contains only anything end users should set
CXXFLAGS = -std=c++11
# DEFS only contains those UCONFIG_CPPFLAGS which are not auto-set by platform.h
DEFS =
prefix = {prefix}
exec_prefix = ${{prefix}}
libdir = ${{exec_prefix}}/lib
includedir = ${{prefix}}/include
baselibs = -lpthread -lm
UNICODE_VERSION=15.0
ICUPREFIX=icu
ICULIBSUFFIX=
LIBICU=lib${{ICUPREFIX}}
pkglibdir=${{libdir}}/icu${{ICULIBSUFFIX}}/73.1
ICUDATA_NAME = icudt73l
ICUDESC=International Components for Unicode
Version: 73.1
Cflags: -I${{includedir}}
Description: International Components for Unicode: Internationalization library
Name: icu-i18n
Libs: -L${{libdir}} -licuin -licuuc -licudt"""
pkg_config_content = pkg_config_template.format(
prefix=self.buildEnv.install_dir
)
os.makedirs(
pj(self.buildEnv.install_dir, "lib", "pkgconfig"), exist_ok=True
)
with open(
pj(self.buildEnv.install_dir, "lib", "pkgconfig", "icu-i18n.pc"),
mode="w",
) as f:
f.write(pkg_config_content)
else:
class Icu(Dependency):
name = "icu4c"
class Source(ReleaseDownload):
archive_src = Remotefile(
"icu4c-73_2-src.tgz",
"818a80712ed3caacd9b652305e01afc7fa167e6f2e94996da44b90c2ab604ce1",
"https://github.com/unicode-org/icu/releases/download/release-73-2/icu4c-73_2-src.tgz",
)
archive_data = Remotefile(
"icu4c-73_2-data.zip",
"ca1ee076163b438461e484421a7679fc33a64cd0a54f9d4b401893fa1eb42701",
"https://github.com/unicode-org/icu/releases/download/release-73-2/icu4c-73_2-data.zip",
)
archives = [archive_src, archive_data]
def _extract(self, context):
context.try_skip(self.extract_path)
if os.path.exists(self.extract_path):
shutil.rmtree(self.extract_path)
extract_archive(
pj(neutralEnv("archive_dir"), self.archive_src.name),
neutralEnv("source_dir"),
topdir=None,
name=self.source_dir,
)
shutil.rmtree(
pj(neutralEnv("source_dir"), self.source_dir, "source", "data")
)
extract_archive(
pj(neutralEnv("archive_dir"), self.archive_data.name),
pj(neutralEnv("source_dir"), self.source_dir, "source"),
topdir="data",
name="data",
)
patches = [
"icu4c_fix_static_lib_name_mingw.patch",
"icu4c_rpath.patch",
"icu4c_wasm.patch",
]
class Builder(MakeBuilder):
subsource_dir = "source"
make_install_targets = ["install"]
@classmethod
def get_dependencies(cls, configInfo, allDeps):
plt = "native_static" if configInfo.static else "native_dyn"
return [(plt, "icu4c")]
@property
def configure_options(self):
yield "--disable-samples"
yield "--disable-tests"
yield "--disable-extras"
yield "--disable-dyload"
yield "--enable-rpath"
yield "--disable-icuio"
yield "--disable-layoutex"
configInfo = self.buildEnv.configInfo
if configInfo.build != "native":
icu_native_builder = get_target_step(
"icu4c", "native_static" if configInfo.static else "native_dyn"
)
yield f"--with-cross-build={icu_native_builder.build_path}"
yield "--disable-tools"
if configInfo.build in ("android", "wasm"):
yield "--with-data-packaging=archive"
def set_env(self, env):
env["ICU_DATA_FILTER_FILE"] = pj(
os.path.dirname(os.path.realpath(__file__)),
"icu4c_data_filter.json",
)
def _post_configure_script(self, context):
if self.buildEnv.configInfo.build != "wasm":
context.skip()
context.try_skip(self.build_path)
for line in fileinput.input(
pj(self.build_path, "Makefile"), inplace=True
):
if line == "#DATASUBDIR = data\n":
print("DATASUBDIR = data")
else:
print(line, end="")
@property
def configure_option(self):
options = ("--disable-samples --disable-tests --disable-extras "
"--disable-dyload --enable-rpath "
"--disable-icuio --disable-layoutex")
platformInfo = self.buildEnv.platformInfo
if platformInfo.build != 'native':
icu_native_builder = get_target_step(
'icu4c',
'native_static' if platformInfo.static else 'native_dyn')
options += " --with-cross-build={} --disable-tools".format(
icu_native_builder.build_path)
if platformInfo.build in ('android', 'wasm'):
options += " --with-data-packaging=archive"
return options

View File

@ -1,14 +0,0 @@
{
"strategy": "additive",
"featureFilters": {
"lang_tree": "include",
"locales_tree": "include",
"translit": "include",
"misc": {
"includelist": [
"likelySubtags",
"metadata"
]
}
}
}

View File

@ -1,9 +1,13 @@
import os
from kiwixbuild.configs import ConfigInfo
from kiwixbuild.platforms import PlatformInfo
from kiwixbuild.utils import pj, copy_tree, run_command
from kiwixbuild._global import option
from .base import Dependency, NoopSource, Builder as BaseBuilder
from .base import (
Dependency,
NoopSource,
Builder as BaseBuilder)
class IOSFatLib(Dependency):
@ -12,39 +16,37 @@ class IOSFatLib(Dependency):
Source = NoopSource
class Builder(BaseBuilder):
@classmethod
def get_dependencies(self, platfomInfo, alldeps):
base_target = option("target")
return [("iOS_{}".format(arch), base_target) for arch in option("ios_arch")]
base_target = option('target')
return [('iOS_{}'.format(arch), base_target) for arch in option('ios_arch')]
def _copy_headers(self, context):
plt = ConfigInfo.get_config("iOS_{}".format(option("ios_arch")[0]))
include_src = pj(plt.buildEnv.install_dir, "include")
include_dst = pj(self.buildEnv.install_dir, "include")
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 _merge_libs(self, context):
lib_dirs = []
for arch in option("ios_arch"):
plt = ConfigInfo.get_config("iOS_{}".format(arch))
lib_dirs.append(pj(plt.buildEnv.install_dir, "lib"))
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"):
if f.endswith('.a') or f.endswith('.dylib'):
libs.append(f)
os.makedirs(pj(self.buildEnv.install_dir, "lib"), exist_ok=True)
os.makedirs(pj(self.buildEnv.install_dir, 'lib'), exist_ok=True)
command_tmp = "lipo -create {input} -output {output}"
for l in libs:
command = [
"lipo",
"-create",
*[pj(d, l) for d in lib_dirs],
"-output",
pj(self.buildEnv.install_dir, "lib", l),
]
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 build(self):
self.command("copy_headers", self._copy_headers)
self.command("merge_libs", self._merge_libs)
self.command('copy_headers', self._copy_headers)
self.command('merge_libs', self._merge_libs)

View File

@ -1,7 +1,7 @@
from kiwixbuild._global import option
from .base import Dependency, GitClone, QMakeBuilder
import platform
from .base import (
Dependency,
GitClone,
QMakeBuilder)
class KiwixDesktop(Dependency):
name = "kiwix-desktop"
@ -13,27 +13,25 @@ class KiwixDesktop(Dependency):
class Builder(QMakeBuilder):
dependencies = ["qt", "qtwebengine", "libkiwix", "aria2"]
make_install_target = 'install'
configure_env = None
flatpack_build_options = {"env": {"QMAKEPATH": "/app"}}
flatpack_build_options = {
"env": [
"QMAKEPATH=/app/lib"
]
}
@property
def make_targets(self):
if platform.system() == "Windows":
yield "release-all"
def configure_option(self):
if self.buildEnv.platformInfo.name == 'flatpak':
options = [
'QMAKE_INCDIR+=/app/include/QtWebEngine',
'QMAKE_INCDIR+=/app/include/QtWebEngineCore',
'QMAKE_INCDIR+=/app/include/QtWebEngineWidgets'
]
else:
yield from super().make_targets
@property
def make_install_targets(self):
if platform.system() == "Windows":
yield "release-install"
else:
yield "install"
@property
def configure_options(self):
if self.buildEnv.configInfo.name != "flatpak":
yield f"PREFIX={self.buildEnv.install_dir}"
if self.buildEnv.configInfo.static:
yield "CONFIG+=static"
options = ["PREFIX={}".format(self.buildEnv.install_dir)]
if self.buildEnv.platformInfo.static:
options.append('"CONFIG+=static"')
return " ".join(options)

View File

@ -1,5 +1,7 @@
from .base import Dependency, GitClone, MesonBuilder
from .base import (
Dependency,
GitClone,
MesonBuilder)
class KiwixTools(Dependency):
name = "kiwix-tools"
@ -10,9 +12,10 @@ class KiwixTools(Dependency):
git_dir = "kiwix-tools"
class Builder(MesonBuilder):
dependencies = ["libkiwix", "docoptcpp"]
dependencies = ["libkiwix"]
@property
def configure_options(self):
if self.buildEnv.configInfo.static:
yield "-Dstatic-linkage=true"
def configure_option(self):
if self.buildEnv.platformInfo.static:
return "-Dstatic-linkage=true"
return ""

View File

@ -3,59 +3,28 @@ import os
from .base import (
Dependency,
ReleaseDownload,
MesonBuilder,
MakeBuilder,
)
from kiwixbuild.utils import Remotefile, pj, Defaultdict, SkipCommand, run_command
from kiwixbuild._global import get_target_step
class LibCurl(Dependency):
name = "libcurl"
class Source(ReleaseDownload):
name = "libcurl"
src_archive = Remotefile(
"curl-8.4.0.tar.xz",
"16c62a9c4af0f703d28bda6d7bbf37ba47055ad3414d70dec63e2e6336f2a82d",
"https://curl.se/download/curl-8.4.0.tar.xz",
)
meson_archive = Remotefile(
"curl_8.4.0-2_patch.zip",
"bbb6ae75225c36ef9bb336cface729794c7c070c623a003fff40bd416042ff6e",
"https://dev.kiwix.org/libkiwix/curl_8.4.0-2_patch.zip",
)
archives = [src_archive, meson_archive]
archive = Remotefile('curl-7.67.0.tar.xz',
'f5d2e7320379338c3952dcc7566a140abb49edb575f9f99272455785c40e536c',
'https://curl.haxx.se/download/curl-7.67.0.tar.xz')
class Builder(MesonBuilder):
dependencies = ["zlib"]
configure_options = [
f"-D{p}=disabled"
for p in (
"psl",
"kerberos-auth",
"gss-api",
"ssh",
"rtmp",
"http2",
"idn",
"brotli",
"ftp",
"file",
"ldap",
"ldaps",
"rtsp",
"dict",
"telnet",
"tftp",
"pop3",
"imap",
"smb",
"smtp",
"gopher",
"tool",
)
]
def _test(self, context):
context.skip("No Test")
class Builder(MakeBuilder):
dependencies = ['zlib']
configure_option = " ".join(
["--without-{}".format(p)
for p in ('libssh2', 'ssl', 'libmetalink', 'librtmp',
'nghttp2', 'libidn2', 'brotli')] +
["--disable-{}".format(p)
for p in ('ftp', 'file', 'ldap', 'ldaps', 'rtsp', 'dict',
'telnet', 'tftp', 'pop3', 'imap', 'smb', 'smtp',
'gopher', 'manual')])

View File

@ -1,10 +1,12 @@
import shutil, os
from .base import Dependency, GitClone, MesonBuilder
from .base import (
Dependency,
GitClone,
MesonBuilder)
from kiwixbuild.utils import pj, copy_tree
from kiwixbuild._global import option, get_target_step, neutralEnv
class Libkiwix(Dependency):
name = "libkiwix"
force_build = True
@ -14,39 +16,24 @@ class Libkiwix(Dependency):
git_dir = "libkiwix"
class Builder(MesonBuilder):
dependencies = [
"pugixml",
"libzim",
"zlib",
"libcurl",
"libmicrohttpd",
"icu4c",
"mustache",
"xapian-core",
]
strip_options = []
dependencies = ["pugixml", "libzim", "zlib", "lzma", "libcurl", "libmicrohttpd", "icu4c", "mustache", "xapian-core"]
strip_option = ''
@property
def build_type(self):
if self.buildEnv.configInfo.build == "android":
return "debug"
return super().build_type
@property
def configure_options(self):
configInfo = self.buildEnv.configInfo
if configInfo.build == "android":
yield "-Dstatic-linkage=true"
yield "-Dwerror=false"
if configInfo.build == "iOS":
yield "-Db_bitcode=true"
if configInfo.name == "flatpak":
yield "--wrap-mode=nodownload"
if configInfo.mixed and option("target") == "libkiwix":
yield "-Dstatic-linkage=true"
def configure_option(self):
platformInfo = self.buildEnv.platformInfo
if platformInfo.build == 'android':
return '-Dstatic-linkage=true -Dwerror=false'
if platformInfo.build == 'iOS':
return '-Db_bitcode=true'
if platformInfo.name == 'flatpak':
return '--wrap-mode=nodownload'
if platformInfo.name == 'native_mixed' and option('target') == 'libkiwix':
return "-Dstatic-linkage=true"
return ''
@property
def library_type(self):
if self.buildEnv.configInfo.build == "android":
return "shared"
if self.buildEnv.platformInfo.build == 'android':
return 'shared'
return super().library_type

View File

@ -6,45 +6,37 @@ from .base import (
MakeBuilder,
)
from kiwixbuild.utils import Remotefile, pj, SkipCommand, run_command
from kiwixbuild.utils import Remotefile, pj, Defaultdict, SkipCommand, run_command
from kiwixbuild._global import get_target_step
class LibMagic(Dependency):
name = "libmagic"
class Source(ReleaseDownload):
name = "libmagic"
source_dir = "libmagic"
archive_top_dir = "file-5.44"
archive = Remotefile(
"file-5.44.tar.gz",
"3751c7fba8dbc831cb8d7cc8aff21035459b8ce5155ef8b0880a27d028475f3b",
)
archive_top_dir = 'file-5.35'
archive = Remotefile('file-5.35.tar.gz',
'30c45e817440779be7aac523a905b123cba2a6ed0bf4f5439e1e99ba940b5546')
class Builder(MakeBuilder):
@property
def configure_options(self):
yield "--disable-bzlib"
yield "--disable-xzlib"
yield "--disable-zstdlib"
yield "--disable-lzlib"
@classmethod
def get_dependencies(cls, configInfo, allDeps):
if configInfo.build != "native":
return [("native_static", "libmagic")]
def get_dependencies(cls, platformInfo, allDeps):
if platformInfo.build != 'native':
return [('native_static', 'libmagic')]
return []
def _compile(self, context):
configInfo = self.buildEnv.configInfo
if configInfo.build == "native":
platformInfo = self.buildEnv.platformInfo
if platformInfo.build == 'native':
return super()._compile(context)
context.try_skip(self.build_path)
command = ["make", "-j4", *self.make_targets, *self.make_options]
env = self.buildEnv.get_env(
cross_comp_flags=True, cross_compilers=True, cross_path=True
command = "make -j4 {make_target} {make_option}".format(
make_target=self.make_target,
make_option=self.make_option
)
libmagic_native_builder = get_target_step("libmagic", "native_static")
env["PATH"].insert(0, pj(libmagic_native_builder.build_path, "src"))
env = self.buildEnv.get_env(cross_comp_flags=True, cross_compilers=True, cross_path=True)
libmagic_native_builder = get_target_step('libmagic', 'native_static')
env['PATH'] = ':'.join([pj(libmagic_native_builder.build_path, 'src'), env['PATH']])
run_command(command, self.build_path, context, env=env)

View File

@ -1,33 +1,17 @@
from .base import Dependency, ReleaseDownload, MesonBuilder
from .base import (
Dependency,
ReleaseDownload,
MakeBuilder)
from kiwixbuild.utils import Remotefile
class MicroHttpd(Dependency):
name = "libmicrohttpd"
class Source(ReleaseDownload):
src_archive = Remotefile(
"libmicrohttpd-0.9.76.tar.gz",
"f0b1547b5a42a6c0f724e8e1c1cb5ce9c4c35fb495e7d780b9930d35011ceb4c",
"https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.76.tar.gz",
)
meson_archive = Remotefile(
"libmicrohttpd_0.9.16-3_patch.zip",
"0954c094a0d4cfe0dd799d8df8a04face6669f7b4d51a7386a9c3e2d37b9c3b3",
"https://wrapdb.mesonbuild.com/v2/libmicrohttpd_0.9.76-3/get_patch",
)
archives = [src_archive, meson_archive]
patches = [
"libmicrohttpd_meson_pkgconfig.patch",
"libmicrohttpd_meson_timeval_tvsec_size.patch",
"libmicrohttpd_meson_winet6.patch",
]
archive = Remotefile('libmicrohttpd-0.9.76.tar.gz',
'f0b1547b5a42a6c0f724e8e1c1cb5ce9c4c35fb495e7d780b9930d35011ceb4c',
'https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.76.tar.gz')
class Builder(MesonBuilder):
configure_options = [
"-Dgnutls=disabled",
"-Dgcrypt=disabled",
"-Dcurl=disabled",
"-Dexpat=disabled",
]
class Builder(MakeBuilder):
configure_option = "--disable-https --without-libgcrypt --without-libcurl --disable-doc --disable-examples"

View File

@ -1,6 +1,8 @@
from .base import Dependency, GitClone, MesonBuilder
from kiwixbuild._global import option, get_target_step, neutralEnv
from .base import (
Dependency,
GitClone,
MesonBuilder)
from kiwixbuild._global import option, get_target_step
class Libzim(Dependency):
name = "libzim"
@ -11,47 +13,40 @@ class Libzim(Dependency):
git_dir = "libzim"
class Builder(MesonBuilder):
test_options = ["-t", "8"]
strip_options = []
@property
def build_type(self):
if self.buildEnv.configInfo.build == "android":
return "debug"
return super().build_type
test_option = "-t 8"
strip_option = ''
@classmethod
def get_dependencies(cls, configInfo, allDeps):
if neutralEnv("distname") == "Windows":
return ["zstd", "xapian-core", "icu4c", "zim-testing-suite"]
deps = ["lzma", "zstd", "xapian-core", "icu4c"]
if configInfo.name not in ("flatpak", "wasm"):
deps.append("zim-testing-suite")
def get_dependencies(cls, platformInfo, allDeps):
deps = ['lzma', 'zstd', 'xapian-core', 'icu4c']
if platformInfo.name not in ('flatpak', 'wasm'):
deps.append('zim-testing-suite')
return deps
@property
def configure_options(self):
configInfo = self.buildEnv.configInfo
if neutralEnv("distname") == "Windows":
yield "-Dwith_xapian_fuller=false"
yield "-Dwerror=false"
if configInfo.build == "android":
yield "-DUSE_BUFFER_HEADER=false"
yield "-Dstatic-linkage=true"
if configInfo.mixed and option("target") == "libzim":
yield "-Dstatic-linkage=true"
if configInfo.name == "flatpak":
yield "--wrap-mode=nodownload"
yield "-Dtest_data_dir=none"
if configInfo.name == "wasm":
yield "-Dexamples=false"
yield "-DUSE_MMAP=false"
if configInfo.name not in ("flatpak", "wasm"):
zim_testing_suite = get_target_step("zim-testing-suite", "source")
yield "-Dtest_data_dir={}".format(zim_testing_suite.source_path)
def configure_option(self):
platformInfo = self.buildEnv.platformInfo
config_options = []
if platformInfo.build == 'android':
config_options.append("-DUSE_BUFFER_HEADER=false")
config_options.append("-Dstatic-linkage=true")
if platformInfo.build == 'iOS':
config_options.append("-Db_bitcode=true")
if platformInfo.name == 'native_mixed' and option('target') == 'libzim':
config_options.append("-Dstatic-linkage=true")
if platformInfo.name == "flatpak":
config_options.append("--wrap-mode=nodownload")
config_options.append("-Dtest_data_dir=none")
if platformInfo.name == "wasm":
config_options.append("-Dexamples=false")
config_options.append("-DUSE_MMAP=false")
if platformInfo.name not in ("flatpak", "wasm"):
zim_testing_suite = get_target_step('zim-testing-suite', 'source')
config_options.append('-Dtest_data_dir={}'.format(zim_testing_suite.source_path))
return " ".join(config_options)
@property
def library_type(self):
if self.buildEnv.configInfo.build == "android":
return "shared"
if self.buildEnv.platformInfo.build == 'android':
return 'shared'
return super().library_type

View File

@ -1,26 +1,28 @@
from .base import (
Dependency,
ReleaseDownload,
MesonBuilder)
MakeBuilder)
from kiwixbuild.utils import Remotefile
class lzma(Dependency):
name = 'lzma'
class Source(ReleaseDownload):
src_archive = Remotefile(
"xz-5.2.6.tar.gz",
"a2105abee17bcd2ebd15ced31b4f5eda6e17efd6b10f921a01cda4a44c91b3a0",
"https://altushost-swe.dl.sourceforge.net/project/lzmautils/xz-5.2.6.tar.gz",
)
meson_patch = Remotefile(
"liblzma_5.2.6-3_patch.zip",
"1c71536d364e1a3ce6bea61266576f89cc5cce4d3b9e11f3494417dafa29780b",
"https://wrapdb.mesonbuild.com/v2/liblzma_5.2.6-3/get_patch",
)
archives = [src_archive, meson_patch]
patches = ['lzma_meson_install.patch']
archive = Remotefile('xz-5.2.6.tar.gz',
'a2105abee17bcd2ebd15ced31b4f5eda6e17efd6b10f921a01cda4a44c91b3a0',
'https://altushost-swe.dl.sourceforge.net/project/lzmautils/xz-5.2.6.tar.gz'
)
Builder = MesonBuilder
class Builder(MakeBuilder):
@property
def configure_option(self):
return ("--disable-xz "
"--disable-xzdec "
"--disable-lzmadec "
"--disable-lzmainfo "
"--disable-lzma-links "
"--disable-scripts "
"--disable-doc "
# "--disable-symbol-versions "
)

View File

@ -1,30 +1,28 @@
from .base import Dependency, ReleaseDownload, Builder as BaseBuilder
from .base import (
Dependency,
ReleaseDownload,
Builder as BaseBuilder)
from kiwixbuild.utils import Remotefile, pj
from shutil import copy2
class Mustache(Dependency):
name = "mustache"
class Source(ReleaseDownload):
archive = Remotefile(
"Mustache-4.1.tar.gz",
"acd66359feb4318b421f9574cfc5a511133a77d916d0b13c7caa3783c0bfe167",
"https://github.com/kainjow/Mustache/archive/v4.1.tar.gz",
)
archive = Remotefile('Mustache-4.1.tar.gz',
'acd66359feb4318b421f9574cfc5a511133a77d916d0b13c7caa3783c0bfe167',
'https://github.com/kainjow/Mustache/archive/v4.1.tar.gz')
class Builder(BaseBuilder):
def build(self):
self.command("copy_header", self._copy_header)
self.command('copy_header', self._copy_header)
def _copy_header(self, context):
context.try_skip(self.build_path)
copy2(
pj(self.source_path, "mustache.hpp"),
pj(self.buildEnv.install_dir, "include"),
)
copy2(pj(self.source_path, 'mustache.hpp'),
pj(self.buildEnv.install_dir, 'include'))
def set_flatpak_buildsystem(self, module):
module["buildsystem"] = "simple"
module["build-commands"] = ["cp mustache.hpp /app/include"]
module['buildsystem'] = 'simple'
module['build-commands'] = ['cp mustache.hpp /app/include']

View File

@ -1,18 +1,19 @@
from .base import Dependency, ReleaseDownload, MesonBuilder
from .base import (
Dependency,
ReleaseDownload,
MesonBuilder)
from kiwixbuild.utils import Remotefile
class Pugixml(Dependency):
name = "pugixml"
class Source(ReleaseDownload):
archive = Remotefile(
"pugixml-1.2.tar.gz",
"0f422dad86da0a2e56a37fb2a88376aae6e931f22cc8b956978460c9db06136b",
)
archive = Remotefile('pugixml-1.2.tar.gz',
'0f422dad86da0a2e56a37fb2a88376aae6e931f22cc8b956978460c9db06136b')
patches = ["pugixml_meson.patch"]
flatpak_dest = "src"
class Builder(MesonBuilder):
strip_options = []
build_type = 'release'
strip_option = ''

View File

@ -1,25 +1,70 @@
import shutil
from .base import Dependency, NoopBuilder, NoopSource
from .base import (
Dependency,
ReleaseDownload,
MakeBuilder,
QMakeBuilder)
from kiwixbuild.utils import SkipCommand, colorize
from kiwixbuild.utils import Remotefile, pj, SkipCommand
class Qt(Dependency):
name = "qt"
name = 'qt'
Source = NoopSource
class Source(ReleaseDownload):
name = "qt"
source_dir = "qt-5.10.1"
archive = Remotefile('qt-everywhere-src-5.10.1.tar.xz',
'',
'http://ftp.oregonstate.edu/.1/blfs/conglomeration/qt5/qt-everywhere-src-5.10.1.tar.xz')
class Builder(NoopBuilder):
def build(self):
error_msg = f"""WARNING: kiwix-build cannot build {self.name} for you.
You must install it yourself using official Qt installer or your distribution system."""
print(colorize(error_msg, "WARNING"))
class Builder(MakeBuilder):
dependencies = ['icu4c', 'zlib']
configure_option_template = "{dep_options} {static_option} {env_option} -prefix {install_dir} -libdir {libdir}"
dynamic_configure_option = "-shared"
static_configure_option = "-static"
@property
def configure_option(self):
skip_modules = [
'qt3d',
'qtcanvas3d',
'qtcharts',
'qtconnectivity',
'qtdatavis3d',
# 'qtdeclarative',
'qtdoc',
'qtgamepad',
'qtgraphicaleffects',
'qtlocation',
'qtmultimedia',
'qtnetworkauth',
'qtpurchasing',
# 'qtquickcontrols',
'qtquickcontrols2',
'qtremoteobjects',
'qtscript',
'qtscxml',
'qtsensors',
'qtserialbus',
'qtserialport',
'qtspeech',
'qtvirtualkeyboard',
'qtwayland',
'qtwebglplugin',
'qtwebsockets',
# 'qtwebview',
]
skip_modules = " ".join("-skip {}".format(m) for m in skip_modules)
options = "-recheck -opensource -confirm-license -ccache -make libs {}".format(skip_modules)
return options
class QtWebEngine(Dependency):
name = "qtwebengine"
Source = NoopSource
Source = Qt.Source
Builder = Qt.Builder
class Builder(QMakeBuilder):
dependencies = ['qt']
subsource_dir = "qtwebengine"

View File

@ -1,93 +0,0 @@
import os
from .base import Dependency, ReleaseDownload, Builder
from kiwixbuild.utils import Remotefile, add_execution_right, run_command
pj = os.path.join
class android_ndk(Dependency):
dont_skip = True
neutral = False
name = "android-ndk"
gccver = "4.9.x"
api = "24"
class Source(ReleaseDownload):
archive = Remotefile(
"android-ndk-r21e-linux-x86_64.zip",
"ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e",
"https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip",
)
@property
def source_dir(self):
return self.target.full_name()
patches = [
"android-ndk-r21e-linux-x86_64-python3.12+.patch",
]
class Builder(Builder):
@property
def install_path(self):
return pj(self.buildEnv.toolchain_dir, self.target.full_name())
@property
def api(self):
return self.target.api
@property
def config(self):
return "android-" + self.api
@property
def arch(self):
return self.buildEnv.configInfo.arch
@property
def arch_full(self):
return self.buildEnv.configInfo.arch_full
def _build_toolchain(self, context):
context.try_skip(self.build_path)
script = pj(self.source_path, "build/tools/make_standalone_toolchain.py")
add_execution_right(script)
command = [
script,
f"--arch={self.arch}",
f"--api={self.api}",
f"--install-dir={self.install_path}",
"--force",
]
env = self.buildEnv.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=False
)
run_command(command, self.build_path, context, env=env)
def _fix_permission_right(self, context):
context.try_skip(self.build_path)
bin_dirs = [
pj(self.install_path, "bin"),
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:
continue
for file_ in files:
file_path = pj(root, file_)
if os.path.islink(file_path):
continue
add_execution_right(file_path)
def build(self):
self.command("build_toolchain", self._build_toolchain)
self.command("fix_permission_right", self._fix_permission_right)

View File

@ -1,55 +0,0 @@
from .base import Dependency, ReleaseDownload, TcCopyBuilder
from kiwixbuild.utils import Remotefile
# The arm toolchains
# This is based on toolchains published here : https://github.com/tttapa/docker-arm-cross-toolchain
base_url = (
"https://github.com/tttapa/docker-arm-cross-toolchain/releases/download/0.1.0/"
)
class armv6_toolchain(Dependency):
dont_skip = True
neutral = True
name = "armv6"
class Source(ReleaseDownload):
archive = Remotefile(
"x-tools-armv6-rpi-linux-gnueabihf.tar.xz",
"4c371c4c5b55ebd1f3d7dd26b14703632d9ba47423f901bcd9303d83ad444434",
base_url + "x-tools-armv6-rpi-linux-gnueabihf.tar.xz",
)
class Builder(TcCopyBuilder):
src_subdir = "armv6-rpi-linux-gnueabihf"
class armv8_toolchain(Dependency):
dont_skip = True
neutral = True
name = "armv8"
class Source(ReleaseDownload):
archive = Remotefile(
"x-tools-armv8-rpi-linux-gnueabihf.tar.xz",
"cc28f5c3f6a3e7d9985f98779c4e72224b4eb5a7e4dc2bcdefd90cb241fb94a5",
base_url + "x-tools-armv8-rpi3-linux-gnueabihf.tar.xz",
)
class Builder(TcCopyBuilder):
src_subdir = "armv8-rpi3-linux-gnueabihf"
class aarch64_toolchain(Dependency):
dont_skip = True
neutral = True
name = "aarch64"
class Source(ReleaseDownload):
archive = Remotefile(
"cross-gcc-6.3.0-pi_64.tar.gz",
"1b048bb8886ad63d21797cd9129fc37b9ea0dfaac7e3c36f888aa16fbec1d320",
)
Builder = TcCopyBuilder

View File

@ -1,47 +0,0 @@
import os
from .base import Dependency, ReleaseDownload, Builder
from kiwixbuild.utils import Remotefile, run_command, copy_tree
pj = os.path.join
class emsdk(Dependency):
dont_skip = True
neutral = False
name = "emsdk"
class Source(ReleaseDownload):
archive = Remotefile(
"emsdk-3.1.41.tar.gz",
"147a2d72df34227bdb4ffedc587a8cb674a42269c40458f3f69ae37e8966cdc6",
"https://codeload.github.com/emscripten-core/emsdk/tar.gz/refs/tags/3.1.41",
)
@property
def source_dir(self):
return self.target.full_name()
class Builder(Builder):
@property
def install_path(self):
return pj(self.buildEnv.toolchain_dir, self.target.full_name())
def _copy_source(self, context):
context.try_skip(self.build_path)
copy_tree(self.source_path, self.install_path)
def _install(self, context):
context.try_skip(self.build_path)
command = ["./emsdk", "install", "3.1.24"]
run_command(command, self.install_path, context)
def _activate(self, context):
context.try_skip(self.build_path)
command = ["./emsdk", "activate", "3.1.24"]
run_command(command, self.install_path, context)
def build(self):
self.command("copy_source", self._copy_source)
self.command("install", self._install)
self.command("activate", self._activate)

View File

@ -1,89 +0,0 @@
import os
from .base import Dependency, NoopSource, Builder
from kiwixbuild.utils import Remotefile, add_execution_right, run_command
pj = os.path.join
class org_kde(Dependency):
neutral = False
name = "org.kde"
Source = NoopSource
class Builder(Builder):
def _setup_remote(self, context):
command = [
"flatpak",
"--user",
"remote-add",
"--if-not-exists",
"flathub",
"https://flathub.org/repo/flathub.flatpakrepo",
]
env = self.buildEnv.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=False
)
run_command(command, self.buildEnv.build_dir, context, env=env)
def _install_sdk(self, context):
command = [
"flatpak",
"--user",
"install",
"--noninteractive",
"--verbose",
"-y",
"flathub",
f"{self.target.name}.Sdk//{self.target.version()}",
f"{self.target.name}.Platform//{self.target.version()}",
]
env = self.buildEnv.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=False
)
run_command(command, self.buildEnv.build_dir, context, env=env)
def build(self):
self.command("setup_remote", self._setup_remote)
self.command("install_sdk", self._install_sdk)
class io_qt_qtwebengine(Dependency):
neutral = False
name = "io.qt.qtwebengine"
Source = NoopSource
class Builder(Builder):
def _setup_remote(self, context):
command = [
"flatpak",
"--user",
"remote-add",
"--if-not-exists",
"flathub",
"https://flathub.org/repo/flathub.flatpakrepo",
]
env = self.buildEnv.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=False
)
run_command(command, self.buildEnv.build_dir, context, env=env)
def _install_sdk(self, context):
command = [
"flatpak",
"--user",
"install",
"-y",
"flathub",
f"{self.target.name}.BaseApp//{self.target.version()}",
]
env = self.buildEnv.get_env(
cross_comp_flags=False, cross_compilers=False, cross_path=False
)
run_command(command, self.buildEnv.build_dir, context, env=env)
def build(self):
self.command("setup_remote", self._setup_remote)
self.command("install_sdk", self._install_sdk)

Some files were not shown because too many files have changed in this diff Show More