212 lines
5.8 KiB
Python
Executable File
212 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import sys
|
|
import subprocess
|
|
import threading
|
|
import os
|
|
from datetime import datetime
|
|
|
|
__FILENAME = ""
|
|
|
|
MAX_JOBS = max(1, len(os.sched_getaffinity(0)) - 2)
|
|
TS_VRB = 2
|
|
CWD = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
BUILD_D = f"{CWD}/build"
|
|
|
|
|
|
def shift(arr):
|
|
if not arr:
|
|
return None # or raise IndexError if you prefer
|
|
return arr.pop(0)
|
|
|
|
|
|
def timestamp(dt=datetime.now(), fmt="hours"):
|
|
return f"{dt.hour:0>2}:{dt.minute:0>2}:{dt.second:0>2}"
|
|
|
|
|
|
def run(*cmds, parallel=False, tag=None, interactive=False):
|
|
threads = []
|
|
|
|
def run_single(cmd, tag):
|
|
env = os.environ.copy()
|
|
env["MAKE_TERMOUT"] = "true"
|
|
env["MAKE_TERMERR"] = "true"
|
|
start_time = datetime.now()
|
|
print(f"{f"{timestamp(start_time)} | " if TS_VRB > 0 else ""}CMD: {cmd}")
|
|
with subprocess.Popen(
|
|
cmd, shell=True,
|
|
stdout=None if interactive else subprocess.PIPE,
|
|
stderr=None if interactive else subprocess.STDOUT,
|
|
# text=None if interactive else True,
|
|
) as proc:
|
|
if not interactive:
|
|
for line in proc.stdout:
|
|
dt = datetime.now()
|
|
if tag:
|
|
print(f"{f"{timestamp(dt)} | " if TS_VRB >
|
|
0 else ""}stdout ({tag}): ", flush=True, end='')
|
|
else:
|
|
print(f"{f"{timestamp(dt)} | " if TS_VRB >
|
|
0 else ""}stdout: ", flush=True, end='')
|
|
sys.stdout.buffer.write(line)
|
|
sys.stdout.buffer.flush()
|
|
proc.wait()
|
|
if proc.returncode != 0:
|
|
print(f"ERROR: Command '{
|
|
cmd}' exited with code {proc.returncode}")
|
|
exit(1)
|
|
for i, command in enumerate(cmds):
|
|
|
|
current_tag = tag if len(cmds) <= 1 else (
|
|
f"{tag}-{i}" if tag else None)
|
|
if parallel:
|
|
t = threading.Thread(
|
|
target=run_single, args=(command, current_tag))
|
|
t.start()
|
|
threads.append(t)
|
|
else:
|
|
run_single(command, current_tag)
|
|
|
|
for t in threads:
|
|
t.join()
|
|
|
|
|
|
def todo(reason):
|
|
print(f"ERROR: Unimplemented {reason}")
|
|
exit(1)
|
|
|
|
|
|
def cmd_configure(args):
|
|
|
|
def cmd_help():
|
|
print(f"Usage: {__FILENAME} configure [component]")
|
|
print("Components:")
|
|
print(" help - Show this help")
|
|
print(" kernel - The linux kernel")
|
|
print(" busybox - Busybox")
|
|
|
|
# $(MAKE) -C $(MAKEFILE_DIR)/kernel O=$(KERNEL_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.kernel-config" menuconfig
|
|
subc = shift(args)
|
|
if not subc or subc == "help":
|
|
cmd_help()
|
|
exit(1)
|
|
elif subc == "kernel":
|
|
run(f"make -C {CWD}/linux/kernel O={BUILD_D}/linux/kernel KCONFIG_CONFIG='{
|
|
CWD}/linux/.kernel-config' menuconfig", interactive=True)
|
|
elif subc == "busybox":
|
|
run(f"make -C {CWD}/linux/busybox O={BUILD_D}/linux/busybox KCONFIG_CONFIG='{
|
|
CWD}/linux/.busybox-config' menuconfig", interactive=True)
|
|
else:
|
|
print(f"ERROR: Unknown component {subc}")
|
|
cmd_help()
|
|
exit(1)
|
|
|
|
|
|
def cmd_build(args):
|
|
def cmd_help():
|
|
print(f"Usage: {__FILENAME} build [component]")
|
|
print("Components:")
|
|
print(" help - Show this help")
|
|
print(" all - Builds everything")
|
|
print(" linux - Everything bellow")
|
|
print(" kernel - The linux kernel")
|
|
print(" busybox - Busybox")
|
|
print(" rust - Builds all of the rust components")
|
|
print(" img - Rebuilds the image")
|
|
|
|
def build_init():
|
|
run(
|
|
f"mkdir -p {BUILD_D}/linux/kernel",
|
|
f"mkdir -p {BUILD_D}/linux/busybox",
|
|
parallel=True
|
|
)
|
|
|
|
def build_kernel(args):
|
|
run(f"make -C {CWD}/linux/kernel O={BUILD_D}/linux/kernel KCONFIG_CONFIG='{
|
|
CWD}/linux/.kernel-config' -j{MAX_JOBS}", tag="kernel")
|
|
|
|
def build_busybox(args):
|
|
run(
|
|
f"cp {CWD}/linux/.busybox-config {
|
|
BUILD_D}/linux/busybox/.config",
|
|
f"make -C {CWD}/linux/busybox O={BUILD_D}/linux/busybox KCONFIG_CONFIG='{
|
|
CWD}/linux/.busybox-config' -j{MAX_JOBS}",
|
|
tag="busybox"
|
|
)
|
|
|
|
def build_rust(args):
|
|
todo("build_rust")
|
|
|
|
def build_image(args):
|
|
# for the later bootable.img or whatever file
|
|
todo("build_image")
|
|
|
|
cmd = shift(args)
|
|
|
|
if not cmd or cmd == "help":
|
|
cmd_help()
|
|
exit(1)
|
|
elif cmd == "all":
|
|
build_init()
|
|
build_kernel(args)
|
|
build_busybox(args)
|
|
build_rust(args)
|
|
build_image(args)
|
|
elif cmd == "linux":
|
|
build_init()
|
|
build_kernel(args)
|
|
build_busybox(args)
|
|
elif cmd == "kernel":
|
|
build_init()
|
|
build_kernel(args)
|
|
elif cmd == "busybox":
|
|
build_init()
|
|
build_busybox(args)
|
|
elif cmd == "rust":
|
|
build_init()
|
|
build_rust(args)
|
|
elif cmd == "img":
|
|
build_init()
|
|
build_image(args)
|
|
else:
|
|
print(f"ERROR: Unknown component '{cmd}'")
|
|
cmd_help()
|
|
exit(1)
|
|
|
|
|
|
AVAILABLE_SUBCOMMANDS = {
|
|
"help": help,
|
|
"configure": cmd_configure,
|
|
"build": cmd_build
|
|
}
|
|
|
|
|
|
def help():
|
|
print(f"Usage: {__FILENAME} [subcommand]")
|
|
print("Subcommands:")
|
|
print(" help - Show this help")
|
|
print(" configure - Configure components")
|
|
print(" build - Compile/build components")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv
|
|
__FILENAME = shift(args)
|
|
|
|
cmd = shift(args)
|
|
|
|
if not cmd:
|
|
help()
|
|
exit(1)
|
|
|
|
cmd_v = AVAILABLE_SUBCOMMANDS[cmd]
|
|
if not cmd_v:
|
|
print(f"ERROR: Unknown subcommand '{cmd}'")
|
|
help()
|
|
exit(1)
|
|
|
|
(cmd_v)(args)
|
|
|
|
exit(0)
|