feat: add support of atom builds

Signed-off-by: sisungo <[email protected]>
This commit is contained in:
2026-07-07 11:25:02 +08:00
parent f76006e595
commit 72055b21cc
13 changed files with 268 additions and 10 deletions
+136
View File
@@ -0,0 +1,136 @@
import os
import shutil
import subprocess
from . import packie
BASE_REQUIREMENTS = [
# Basic packages for running shell scripts
"mksh",
"coreutils",
"findutils",
"diffutils",
# Packages for running `semios-packages` scripts
"python",
"packie",
"patch",
"zstd",
# Basic libraries
"sqlite",
"libgcc-compat",
"libcxx",
"semi-libc",
"libz-ng",
# Networking
"ca-certificates",
"certutil",
"aws-lc-libssl",
"aws-lc-tools",
]
def _prepare_build_env_base_files(root: str):
os.makedirs(root, exist_ok=True)
os.mkdir(f"{root}/var")
os.mkdir(f"{root}/var/tmp")
os.mkdir(f"{root}/var/run")
os.mkdir(f"{root}/tmp")
os.mkdir(f"{root}/run")
os.makedirs(f"{root}/var/db/packie")
shutil.copytree("/var/config/packie/repos.d", f"{root}/var/config/packie/repos.d")
os.mkdir(f"{root}/dev")
os.mkdir(f"{root}/sys")
os.mkdir(f"{root}/proc")
os.makedirs(f"{root}/home/root")
def prepare_build_env(root: str, extreq: list[str] = []):
# Skip if the environment is already initialized
if os.path.exists(f"{root}/.INIT"):
return
try:
shutil.rmtree(root)
except:
pass
# Prepare basic filesystem hierarchy
_prepare_build_env_base_files(root)
# Install packages
packie.chroot_update(root)
packie.chroot_install(root, BASE_REQUIREMENTS + extreq)
# Refresh certificates
enter_build_env(root, ["certutil", "refresh"])
# Copy DNS config
os.makedirs(f"{root}/etc", exist_ok=True)
shutil.copy2("/etc/resolv.conf", f"{root}/etc/resolv.conf")
# Create initialized tag
with open(f"{root}/.INIT", "wt+") as file:
file.write("OK")
def enter_build_env(root: str, cmd: list[str], chdir: str = "/"):
reserve_env = ["https_proxy", "http_proxy", "all_proxy"]
reserve_env_args = []
for i in reserve_env:
if os.environ.get(i):
reserve_env_args += ["--setenv", i, os.environ[i]]
subprocess.run(
[
"bwrap",
"--bind",
root,
"/",
"--unshare-pid",
"--unshare-user",
"--uid",
"0",
"--gid",
"0",
"--dev",
"/dev",
"--bind",
"/sys",
"/sys",
"--proc",
"/proc",
"--clearenv",
"--setenv",
"HOME",
"/home/root",
"--setenv",
"PATH",
"/bin",
"--setenv",
"SEMIOS_PKGBUILD_IN_ATOMIC",
"1",
"--chdir",
chdir,
]
+ reserve_env_args
+ cmd
)
def copy_pkgbuild_tree(repo_root: str, pkgname: str, build_env_root: str):
build_dir = f"{build_env_root}/Atom"
if os.path.exists(build_dir):
return
os.mkdir(build_dir)
shutil.copytree(f"{repo_root}/hooks", f"{build_dir}/hooks")
shutil.copytree(f"{repo_root}/lib", f"{build_dir}/lib")
shutil.copy2(f"{repo_root}/x", f"{build_dir}/x")
shutil.copy2(f"{repo_root}/x.py", f"{build_dir}/x.py")
os.makedirs(f"{build_dir}/packages/{pkgname}")
for i in os.listdir(f"{repo_root}/packages/{pkgname}"):
srcpath = f"{repo_root}/packages/{pkgname}/{i}"
dstpath = f"{build_dir}/packages/{pkgname}/{i}"
if i in ["target", "__pycache__"]:
continue
if os.path.isdir(srcpath):
shutil.copytree(srcpath, dstpath)
elif os.path.isfile(srcpath):
shutil.copy2(srcpath, dstpath)
+20 -2
View File
@@ -24,9 +24,25 @@ _pkginfo: dict[str, dict[str, typing.Any]] = {
_supported_arch: typing.Callable[[str], bool] = lambda x: True
_on_build: typing.Callable[[], None] | None = None
_in_atombuild = False
_builddep: list[str] = []
_blocked_hooks: list[str] = []
def builddep(s: str):
global _builddep
if s == "shortcut/c":
_builddep += ["semi-libc-dev", "clang", "llvm", "lld"]
elif s == "shortcut/c++":
builddep("shortcut/c")
_builddep += ["libcxx-dev"]
elif s == "shortcut/autotools":
_builddep += ["gnu-make", "gnu-sed", "awk", "grep"]
else:
_builddep += [s]
def package(s: str):
global _current_pkgname
_current_pkgname = s
@@ -103,8 +119,10 @@ def block_hook(hook: str):
def source_url(url: str):
sources.source_url(url)
if not _in_atombuild:
sources.source_url(url)
def source_git(url: str, branch: str | None = None):
sources.source_git(url, branch)
if not _in_atombuild:
sources.source_git(url, branch)
+22 -2
View File
@@ -1,11 +1,31 @@
import subprocess
import os
import subprocess
PACKIE_EXEC = os.getenv("PACKIE", "packie")
def host_arch() -> str:
result = subprocess.run(
[PACKIE_EXEC, "print", "profile.host_arch"],
check=True, capture_output=True,
check=True,
capture_output=True,
)
return result.stdout.decode().strip()
def chroot_update(root: str):
subprocess.run([PACKIE_EXEC, "--chroot", root, "update"], check=True)
def chroot_install(root: str, requirements: list[str]):
subprocess.run(
[PACKIE_EXEC, "--chroot", root, "install", "--yes"] + requirements, check=True
)
def update():
subprocess.run([PACKIE_EXEC, "update"], check=True)
def install(requirements: list[str]):
subprocess.run([PACKIE_EXEC, "install", "--yes"] + requirements, check=True)
+4
View File
@@ -8,6 +8,10 @@ VERSION = "2026.6.19"
version(VERSION)
source_url("https://www.crufty.net/ftp/pub/sjg/bmake-20260619.tar.gz")
builddep("shortcut/c")
builddep("shortcut/autotools")
builddep("bc")
def build():
cpp.configure(
+6 -2
View File
@@ -6,13 +6,17 @@ from lib.make import *
upstream_version = "1.0.8"
builddep("shortcut/c")
builddep("shortcut/autotools")
version(f"{upstream_version}")
source_url(f"https://sourceware.org/pub/bzip2/bzip2-{upstream_version}.tar.gz")
def build():
cpp.make(["-f", "Makefile-libbz2_so"])
cpp.make_install(["PREFIX=../cpp_install"], chdir=False)
makevars = [f"CC={os.environ.get('CC', 'cc')}"]
cpp.make(["-f", "Makefile-libbz2_so"] + makevars)
cpp.make_install(["PREFIX=../cpp_install"] + makevars, chdir=False)
shutil.copy2(f"libbz2.so.{upstream_version}", "../cpp_install/lib/libbz2.so")
os.chdir("../cpp_install")
+3
View File
@@ -8,6 +8,9 @@ source_url(
"https://github.com/sabotage-linux/gettext-tiny/releases/download/v0.3.3/gettext-tiny-0.3.3.tar.xz"
)
builddep("shortcut/c")
builddep("shortcut/autotools")
def build():
cpp.make(["LIBINTL=musl"])
+8 -3
View File
@@ -1,13 +1,18 @@
import os
import subprocess
from lib.make import *
version("1.59.2")
source_git("https://github.com/mirabilos/mksh-cvs2git.git", "mksh-R59c")
source_url(
"https://github.com/mirabilos/mksh-cvs2git/archive/refs/tags/mksh-R59c.tar.gz"
)
builddep("shortcut/c")
builddep("sed")
def build():
os.system("sh ./Build.sh")
subprocess.run(["sh", "./Build.sh"], check=True)
on_build(build)
+3
View File
@@ -6,6 +6,9 @@ from lib.make import *
version("6.6")
source_url("https://invisible-island.net/archives/ncurses/ncurses-6.6.tar.gz")
builddep("shortcut/c")
builddep("shortcut/autotools")
def build():
cpp.configure(
+3
View File
@@ -5,6 +5,9 @@ from lib.make import *
version("2.5.1")
source_url("https://distfiles.ariadne.space/pkgconf/pkgconf-2.5.1.tar.gz")
builddep("shortcut/c")
builddep("shortcut/autotools")
def build():
cpp.configure(
+4
View File
@@ -5,6 +5,10 @@ version("1.2.6+1")
source_url("https://gitea.semilabs.org/semios/semi-libc/archive/v1.2.6-1.tar.gz")
builddep("shortcut/c")
builddep("shortcut/autotools")
def build():
cpp.configure(["--prefix=/"])
cpp.make()
+6
View File
@@ -1,9 +1,15 @@
import os
import lib.cpp as cpp
from lib.make import *
version("3.53.2")
source_url("https://sqlite.org/2026/sqlite-autoconf-3530200.tar.gz")
builddep("shortcut/autotools")
builddep("shortcut/c")
builddep("linenoise-dev")
def build():
cpp.configure(
+6
View File
@@ -1,3 +1,5 @@
import os
from lib import cpp
from lib.make import *
@@ -6,8 +8,12 @@ source_url(
"https://github.com/tukaani-project/xz/releases/download/v5.8.3/xz-5.8.3.tar.gz"
)
builddep("shortcut/c")
builddep("shortcut/autotools")
def build():
os.environ["FGREP"] = "grep -F"
cpp.configure(
[
"--prefix=/",
+47 -1
View File
@@ -7,7 +7,9 @@ import typing
import hooks
import lib.arch
import lib.atombuild
import lib.make
import lib.packie
import lib.pkgcomposer
import lib.sources
@@ -20,6 +22,7 @@ argparser = argparse.ArgumentParser(
argparser.add_argument(
"--target", type=str, help="Target architecture to build the package for"
)
argparser.add_argument("--atombuild", action="store_true", help="Enable Atom Build")
subparsers = argparser.add_subparsers(dest="subcommand")
parser_build = subparsers.add_parser("build")
parser_build.add_argument("BUILD_PKGNAME")
@@ -64,6 +67,9 @@ def run_build_package(package: str):
print(f"Architecture {lib.arch.get_target()} is not supported for this package")
exit(1)
if os.environ.get("SEMIOS_PKGBUILD_IN_ATOMIC", "0") == "1":
lib.packie.install(lib.make._builddep)
# Run `pre_build` hooks
run_hooks(hooks.pre_build)
@@ -151,8 +157,48 @@ def run_list(item):
print(i)
def run_build_atom(pkgname: str):
# Declare necessary paths
repo_root = os.getcwd()
package_dir = f"{repo_root}/packages/{pkgname}"
target_dir = f"{package_dir}/target"
build_env_root = f"{target_dir}/atombuild_root"
# Read `pkgbuild.py` of that package
lib.make._in_atombuild = True
try:
os.chdir(package_dir)
os.makedirs(target_dir, exist_ok=True)
except Exception:
print(f"No such package {pkgname}")
exit(1)
importlib.import_module(f"packages.{pkgname}.pkgbuild")
os.chdir(repo_root)
# Initialize build environment
lib.atombuild.prepare_build_env(build_env_root, lib.make._builddep)
lib.atombuild.copy_pkgbuild_tree(repo_root, pkgname, build_env_root)
lib.atombuild.enter_build_env(
build_env_root,
["./x", "--target", lib.arch.get_target(), "build", pkgname],
chdir="/Atom",
)
# Copy artifacts
atom_target_dir = f"{build_env_root}/Atom/packages/{pkgname}/target"
try:
for i in os.listdir(atom_target_dir):
if i.endswith(".pkg"):
shutil.copy2(f"{atom_target_dir}/{i}", f"{target_dir}/{i}")
except Exception:
pass
if args.subcommand == "build":
run_build_package(args.BUILD_PKGNAME)
if args.atombuild:
run_build_atom(args.BUILD_PKGNAME)
else:
run_build_package(args.BUILD_PKGNAME)
elif args.subcommand == "clean":
run_clean_package(args.CLEAN_PKGNAME)
elif args.subcommand == "list":