mirror of
https://github.com/rosalinux/image-builder.git
synced 2025-02-23 10:22:50 +00:00
init new os-image-builder tool
This commit is contained in:
commit
723ed5ce4c
7 changed files with 221 additions and 0 deletions
0
bootstrap/README.md
Normal file
0
bootstrap/README.md
Normal file
7
bootstrap/rosa13
Normal file
7
bootstrap/rosa13
Normal file
|
@ -0,0 +1,7 @@
|
|||
RELEASE="rosa13"
|
||||
ABF_DOWNLOADS="https://abf-downloads.rosalinux.ru"
|
||||
PKGS="basesystem-minimal locales-en dbus coreutils findutils util-linux xz e2fsprogs passwd openssh-server"
|
||||
WEAK_DEPS="false"
|
||||
DEFAULT_USER="rosa"
|
||||
DEFAULT_USER_PASSWORD="rosa"
|
||||
PASSWD_ROOT="root"
|
87
build.py
Executable file
87
build.py
Executable file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
from utils.bootstrap_setup import setup_bootstrap, load_config
|
||||
|
||||
BASE_DIR = os.getcwd()
|
||||
TMP_DIR = os.path.join(BASE_DIR, "tmp")
|
||||
NUM_CORES = str(multiprocessing.cpu_count())
|
||||
|
||||
|
||||
def clone_repo(repo_url, branch, dest_dir, name):
|
||||
if os.path.exists(dest_dir):
|
||||
print(f"Warning: {name} directory '{dest_dir}' already exists. Skipping clone.")
|
||||
else:
|
||||
os.makedirs(dest_dir, exist_ok=True)
|
||||
subprocess.run(["git", "clone", "--depth", "1", repo_url, "-b", branch, dest_dir], check=True)
|
||||
|
||||
|
||||
def build_kernel(config, vendor, device):
|
||||
kernel_dir = os.path.join(TMP_DIR, vendor, device, "kernel")
|
||||
clone_repo(config["KERNEL"].split("#")[0], config["KERNEL"].split("#")[1], kernel_dir, "Kernel")
|
||||
|
||||
os.chdir(kernel_dir)
|
||||
subprocess.run(["make", config["KERNEL_CONFIG"]], check=True)
|
||||
subprocess.run(["make", config.get("KERNELTARGET", "Image"), "-j" + NUM_CORES], check=True)
|
||||
os.chdir(BASE_DIR)
|
||||
|
||||
|
||||
def build_uboot(config, vendor, device):
|
||||
if "UBOOT" not in config or "UBOOT_VERSION" not in config:
|
||||
print("U-Boot configuration not found. Skipping U-Boot build.")
|
||||
return
|
||||
|
||||
uboot_dir = os.path.join(TMP_DIR, vendor, device, "u-boot")
|
||||
clone_repo(config["UBOOT"], config["UBOOT_VERSION"], uboot_dir, "U-Boot")
|
||||
|
||||
os.chdir(uboot_dir)
|
||||
subprocess.run(["make", config["UBOOT_CONFIG"]], check=True)
|
||||
subprocess.run(["make", "-j" + NUM_CORES], check=True)
|
||||
os.chdir(BASE_DIR)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3 or "--distro" not in sys.argv:
|
||||
print("Usage: python build.py --distro <distro_name> <vendor/device> [--skip-kernel] [--skip-uboot]")
|
||||
sys.exit(1)
|
||||
|
||||
distro_idx = sys.argv.index("--distro") + 1
|
||||
distro = sys.argv[distro_idx]
|
||||
vendor_device = sys.argv[distro_idx + 1]
|
||||
vendor, device = vendor_device.split("/")
|
||||
config_path = os.path.join("device", vendor, device, "config")
|
||||
skip_kernel = "--skip-kernel" in sys.argv
|
||||
skip_uboot = "--skip-uboot" in sys.argv
|
||||
|
||||
if not os.path.exists(config_path):
|
||||
print(f"Configuration file for {vendor}/{device} not found.")
|
||||
sys.exit(1)
|
||||
|
||||
config = load_config(config_path)
|
||||
if config["ARCH"] != "aarch64":
|
||||
print("Unsupported architecture.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Building for {vendor}/{device} with distro {distro}...")
|
||||
|
||||
if not skip_kernel:
|
||||
build_kernel(config, vendor, device)
|
||||
else:
|
||||
print("Skipping kernel build.")
|
||||
|
||||
if not skip_uboot:
|
||||
build_uboot(config, vendor, device)
|
||||
else:
|
||||
print("Skipping U-Boot build.")
|
||||
|
||||
setup_bootstrap("bootstrap", TMP_DIR, vendor, device, distro)
|
||||
|
||||
print(f"Build completed for {vendor}/{device} with distro {distro}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
7
device/raspberry/pi4b/config
Normal file
7
device/raspberry/pi4b/config
Normal file
|
@ -0,0 +1,7 @@
|
|||
ARCH="aarch64"
|
||||
KERNEL="https://github.com/raspberrypi/linux.git#rpi-6.6.y"
|
||||
KERNEL_CONFIG="bcm2711_defconfig"
|
||||
KERNEL_EXTRACONFIG="--module NTFS3_FS --enable NTFS3_LZX_XPRESS --enable NTFS3_FS_POSIX_ACL --disable NTFS3_64BIT_CLUSTER"
|
||||
DTB="broadcom/bcm2711-rpi-4-b"
|
||||
CMDLINE="dwc_otg.lpm_enable=0 console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait"
|
||||
NEED_INITRD=no
|
25
device/raspberry/pi4b/config.txt
Normal file
25
device/raspberry/pi4b/config.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
# See
|
||||
# https://www.raspberrypi.org/documentation/configuration/config-txt
|
||||
arm_64bit=1
|
||||
kernel=kernel8.img
|
||||
dtoverlay=vc4-kms-v3d-pi4
|
||||
# Force the monitor to HDMI mode so that sound will be sent over HDMI cable
|
||||
hdmi_drive=2
|
||||
# Force monitor mode to DMT
|
||||
hdmi_group=2
|
||||
# Force monitor resolution (e.g. 16 = 1920x1080)
|
||||
#hdmi_mode=16
|
||||
# Some displays might have issues with text/pixels spilling off the screen.
|
||||
# If this affects you, uncomment the overscan_* settings and adjust the values
|
||||
#overscan_left=20
|
||||
#overscan_right=12
|
||||
#overscan_top=10
|
||||
#overscan_bottom=10
|
||||
# For i2c & spi
|
||||
dtparam=i2c_arm=on
|
||||
dtparam=spi=on
|
||||
# Memory reserved for the GPU (in MB)
|
||||
mem_gpu=256
|
||||
|
||||
# Enable audio (loads snd_bcm2835)
|
||||
dtparam=audio=on
|
BIN
utils/__pycache__/bootstrap_setup.cpython-311.pyc
Normal file
BIN
utils/__pycache__/bootstrap_setup.cpython-311.pyc
Normal file
Binary file not shown.
95
utils/bootstrap_setup.py
Normal file
95
utils/bootstrap_setup.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
def load_config(config_path):
|
||||
config = {}
|
||||
with open(config_path, "r") as f:
|
||||
for line in f:
|
||||
if "=" in line and not line.strip().startswith("#"):
|
||||
key, value = line.strip().split("=", 1)
|
||||
config[key] = value.strip('"')
|
||||
return config
|
||||
|
||||
|
||||
def load_bootstrap_config(bootstrap_path):
|
||||
"""Load the bootstrap configuration from the specified file."""
|
||||
config = {}
|
||||
with open(bootstrap_path, "r") as f:
|
||||
for line in f:
|
||||
if "=" in line and not line.strip().startswith("#"):
|
||||
key, value = line.strip().split("=", 1)
|
||||
config[key] = value.strip('"')
|
||||
return config
|
||||
|
||||
|
||||
def generate_dnf_conf(dnf_conf_path, abf_downloads, release):
|
||||
"""Generate dnf.conf based on the bootstrap configuration."""
|
||||
dnf_conf_content = f"""
|
||||
[main]
|
||||
keepcache=1
|
||||
debuglevel=2
|
||||
reposdir=/dev/null
|
||||
retries=20
|
||||
obsoletes=1
|
||||
gpgcheck=0
|
||||
assumeyes=1
|
||||
syslog_ident=mock
|
||||
syslog_device=
|
||||
install_weak_deps=0
|
||||
metadata_expire=60s
|
||||
best=1
|
||||
|
||||
[{release}_main_release]
|
||||
name={release}_main_release
|
||||
baseurl={abf_downloads}/{release}/repository/aarch64/main/release
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
|
||||
[{release}_main_updates]
|
||||
name={release}_main_updates
|
||||
baseurl={abf_downloads}/{release}/repository/aarch64/main/updates
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.dirname(dnf_conf_path), exist_ok=True)
|
||||
with open(dnf_conf_path, "w") as f:
|
||||
f.write(dnf_conf_content)
|
||||
|
||||
|
||||
def run_dnf_install(config, dnf_conf_path, rootfs_dir):
|
||||
"""Run dnf command to install packages based on the bootstrap configuration."""
|
||||
pkgs = config["PKGS"]
|
||||
weak_deps = config["WEAK_DEPS"].lower()
|
||||
|
||||
dnf_command = [
|
||||
"sudo",
|
||||
"dnf",
|
||||
"--setopt=install_weak_deps=" + str(weak_deps),
|
||||
"--config", dnf_conf_path,
|
||||
"--installroot", rootfs_dir,
|
||||
"install"
|
||||
] + pkgs.split()
|
||||
|
||||
subprocess.run(dnf_command, check=True)
|
||||
|
||||
|
||||
def setup_bootstrap(bootstrap_dir, tmp_dir, vendor, device, distro):
|
||||
# load distro config
|
||||
# bootstrap/DISTRO_NAME
|
||||
distro_config_path = os.path.join(bootstrap_dir, distro)
|
||||
if not os.path.exists(distro_config_path):
|
||||
print(f"Bootstrap configuration for distro '{distro}' not found.")
|
||||
sys.exit(1)
|
||||
|
||||
config = load_config(distro_config_path)
|
||||
|
||||
dnf_conf_path = os.path.join(tmp_dir, vendor, device, "dnf.conf")
|
||||
rootfs_dir = os.path.join(tmp_dir, vendor, device, "rootfs")
|
||||
|
||||
generate_dnf_conf(dnf_conf_path, config["ABF_DOWNLOADS"], config["RELEASE"])
|
||||
run_dnf_install(config, dnf_conf_path, rootfs_dir)
|
||||
|
||||
#setup_user(rootfs_dir, config["DEFAULT_USER"], config["DEFAULT_USER_PASSWORD"], config["PASSWD_ROOT"])
|
Loading…
Add table
Reference in a new issue