mirror of
https://github.com/andreili/SBC_builder.git
synced 2025-08-23 19:04:06 +02:00
155 lines
5.4 KiB
Python
155 lines
5.4 KiB
Python
import json, os, stat, re
|
|
from pathlib import Path
|
|
from . import *
|
|
|
|
units = { "B": 1, "K": 2**10, "M": 2**20, "G": 2**30 }
|
|
|
|
class Board:
|
|
def __init__(self, name, js_fn, targets_meta):
|
|
self.name = name
|
|
self.out_dir = f"{ROOT_DIR}/out/{name}"
|
|
self.out_sh = f"{ROOT_DIR}/out"
|
|
with open(js_fn) as json_data:
|
|
self.json = json.load(json_data)
|
|
json_data.close()
|
|
self.build_list = self.json["build"]
|
|
self.installs = self.json["install"]
|
|
self.targets = []
|
|
self.variables = []
|
|
self.__load_vars()
|
|
for target in self.json["targets"]:
|
|
t = self.__find_meta(targets_meta, target["parent"])
|
|
if (t == 0):
|
|
Logger.error("Unable to find parent for package!")
|
|
t.load_detail(self.name, target, self.parse_variables)
|
|
self.targets.append(t)
|
|
self.__scan_deps()
|
|
|
|
def __scan_deps(self):
|
|
# scan for dependencies
|
|
for target in self.targets:
|
|
for dep_name in target.dep_names:
|
|
dep = self.__find_target(dep_name)
|
|
if (dep == 0):
|
|
Logger.error("Unable to find package!")
|
|
target.depends.append(dep)
|
|
|
|
def __find_meta(self, targets_meta, name):
|
|
for meta in targets_meta:
|
|
if (meta.name == name):
|
|
t = meta
|
|
t.depends = []
|
|
return t
|
|
return 0
|
|
|
|
def __find_target(self, name):
|
|
for target in self.targets:
|
|
if (target.name == name):
|
|
return target
|
|
return 0
|
|
|
|
def __load_vars(self):
|
|
for var_def in self.json["variables"]:
|
|
self.variables.append(var_def.split(":"))
|
|
self.variables.append(["board_name", self.name])
|
|
self.variables.append(["build_dir", f"{ROOT_DIR}/build/{self.name}"])
|
|
self.variables.append(["out_dir", self.out_dir])
|
|
self.variables.append(["out_sh", self.out_sh])
|
|
|
|
def parse_variables(self, string):
|
|
for var_d in self.variables:
|
|
string = string.replace("%{"+var_d[0]+"}%", var_d[1])
|
|
#out_dir
|
|
return string
|
|
|
|
def sync(self):
|
|
for target in self.targets:
|
|
target.source_sync()
|
|
|
|
def build(self, target_name):
|
|
sub_target = ""
|
|
if (target_name == "all"):
|
|
target_list = self.build_list
|
|
else:
|
|
targets = target_name.split('-')
|
|
target_list = [ targets[0] ]
|
|
if (len(targets) > 1):
|
|
sub_target = targets[1]
|
|
is_finded = False
|
|
for t_name in target_list:
|
|
for target in self.targets:
|
|
if (t_name == target.name):
|
|
is_finded = True
|
|
for dep in target.depends:
|
|
if (sub_target == ""):
|
|
#when run sub-target - not need to check a deps
|
|
dep.build("", self.out_dir)
|
|
target.build(sub_target, self.out_dir)
|
|
break
|
|
if (not is_finded):
|
|
Logger.error("Don't find target!")
|
|
|
|
def __do_cmd(self, args, cwd=None, env=None, stdin=None):
|
|
if (stdin != None):
|
|
p = subprocess.Popen(args, cwd=cwd, env=env, stdin=subprocess.PIPE, text=True)
|
|
else:
|
|
p = subprocess.Popen(args, cwd=cwd, env=env)
|
|
if (stdin != None):
|
|
p.communicate(input=stdin)
|
|
if (p.wait() != 0):
|
|
Logger.error(f"Command '{args[0]}' finished with error code!")
|
|
|
|
def __make_blk_struct(self, dev):
|
|
Logger.install("\tBlock device. Prepare and mount it...")
|
|
|
|
def __create_img_file(self, path, size):
|
|
Logger.install("\tCreate image file...")
|
|
img_f = Path(path)
|
|
if (img_f.is_file()):
|
|
shutil.rmtree(path, ignore_errors=True)
|
|
blk_size = 1024*1024
|
|
blk_count = int(size / blk_size)
|
|
self.__do_cmd(["dd", "if=/dev/zero", f"of={path}", f"bs={blk_size}", f"count={blk_count}"])
|
|
|
|
def __parse_size(elf, size):
|
|
size = size.upper()
|
|
if not re.match(r' ', size):
|
|
size = re.sub(r'([KMGT])', r' \1', size)
|
|
number, unit = [string.strip() for string in size.split()]
|
|
return int(float(number)*units[unit])
|
|
|
|
def __create_parts(self, img_or_dev):
|
|
args = ""
|
|
args += "o\n"
|
|
for part in self.installs["partitions"]:
|
|
part_sz = part["size"]
|
|
args += "n\n"
|
|
args += "p\n"
|
|
args += "\n"
|
|
args += "\n"
|
|
args += f"+{part_sz}\n"
|
|
args += "w\n"
|
|
args += "q\n"
|
|
self.__do_cmd(["fdisk", img_or_dev], stdin=args)
|
|
|
|
def __install_to_img(self):
|
|
Logger.install("\tImage. Prepare and mount it...")
|
|
img_fn = f"{self.out_dir}/all.img"
|
|
# basic image offset - space for partition table and bootloader
|
|
img_sz = 1024*1024 + 512
|
|
parts = self.installs["partitions"]
|
|
for part in parts:
|
|
img_sz += self.__parse_size(part["size"])
|
|
self.__create_img_file(img_fn, img_sz)
|
|
self.__create_parts(img_fn)
|
|
|
|
def install(self, dir):
|
|
Logger.install(f"Install to '{dir}'")
|
|
if (self.installs["target"] == "image"):
|
|
self.__install_to_img()
|
|
else:
|
|
Logger.error("Unsupported instalation type!")
|
|
#is_blk = False
|
|
#if (stat.S_ISBLK(os.stat(dir).st_mode)):
|
|
# dir = self.__make_blk_struct(dir)
|