Files
libretiny/builder/utils.py
2022-06-02 22:21:51 +02:00

133 lines
4.0 KiB
Python

# Copyright (c) Kuba Szczodrzyński 2022-05-04.
import fnmatch
from glob import glob
from os.path import isdir, join
from typing import List
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
platform = env.PioPlatform()
board = env.BoardConfig()
def env_add_defaults(env, platform_name: str, sdk_name: str):
vars = dict(
SDK_DIR=platform.get_package_dir(sdk_name),
LT_DIR=platform.get_dir(),
# Root dirs
BOARD_DIR=join("${LT_DIR}", "boards", "${VARIANT}"),
ARDUINO_DIR=join("${LT_DIR}", "arduino", platform_name),
PLATFORM_DIR=join("${LT_DIR}", "platform", platform_name),
TOOLS_DIR=join("${LT_DIR}", "tools"),
# Platform-specific dirs
BIN_DIR=join("${PLATFORM_DIR}", "bin"),
FIXUPS_DIR=join("${PLATFORM_DIR}", "fixups"),
LD_DIR=join("${PLATFORM_DIR}", "ld"),
OPENOCD_DIR=join("${PLATFORM_DIR}", "openocd"),
# Board config variables
MCU=board.get("build.mcu").upper(),
FAMILY=board.get("build.family"),
VARIANT=board.get("build.variant"),
LDSCRIPT_SDK=board.get("build.ldscript_sdk"),
LDSCRIPT_ARDUINO=board.get("build.ldscript_arduino"),
# Link2Bin tool
LINK2BIN="${PYTHONEXE} ${LT_DIR}/tools/link2bin.py",
UF2OTA_PY="${PYTHONEXE} ${LT_DIR}/tools/uf2ota/uf2ota.py",
)
env.Replace(**vars)
for k, v in vars.items():
if "DIR" in k:
assert isdir(env.subst(v)), f"{env.subst(v)} is not a directory"
env.Prepend(
CPPPATH=[
"$BOARD_DIR",
"$FIXUPS_DIR",
"$FIXUPS_DIR/inc",
],
LIBPATH=[
"$LD_DIR",
],
CPPDEFINES=[
("LT_VERSION", platform.version),
("LT_BOARD", board.get("build.variant")),
("F_CPU", board.get("build.f_cpu")),
("MCU", board.get("build.mcu").upper()),
("FAMILY", board.get("build.family")),
],
)
def env_add_library(
env,
name: str,
base_dir: str,
srcs: List[str],
includes: List[str] = [],
):
name = env.subst(name)
# add base dir to all source globs
sources = []
for src in srcs:
if src[1] != "<" or src[-1] != ">":
raise ValueError(f"Not a source glob: {src}")
if src[2] == "$": # do not append base path
expr = src[2:-1]
else:
expr = join(base_dir, src[2:-1])
sources.append(src[0] + "<" + expr + ">")
# allow removing sources from parent builders
key = f"LIB_{name.upper()}_SKIP"
if key in env:
for expr in env[key]:
sources.append("-<" + expr + ">")
# queue library for further env clone and build
env.Prepend(LIBQUEUE=[[join("$BUILD_DIR", name), base_dir, sources]])
base_dir = env.subst(base_dir) # expand base_dir for includes
for dir in includes:
if dir[1] != "<" or dir[-1] != ">":
env.Append(CPPPATH=[dir])
continue
if dir[2] == "$": # do not append base path
expr = dir[2:-1]
else:
expr = join(base_dir, dir[2:-1])
expr = env.subst(expr)
if dir[0] == "-":
for item in fnmatch.filter(env["CPPPATH"], expr):
if item in env["CPPPATH"]:
env["CPPPATH"].remove(item)
else:
for item in glob(expr, recursive=True):
if not isdir(item):
continue
if dir[0] == "!":
env.Prepend(CPPPATH=[item])
else:
env.Append(CPPPATH=[item])
def env_build_libraries(env, safe: bool = True):
# add lib targets and clone safe envs
if not "LIBQUEUE" in env:
return
queue = env["LIBQUEUE"]
env["LIBQUEUE"] = []
envsafe = env.Clone() if safe else env
for lib in queue:
target = envsafe.BuildLibrary(*lib)
env.Prepend(LIBS=[target])
env.AddMethod(env_add_defaults, "AddDefaults")
env.AddMethod(env_add_library, "AddLibrary")
env.AddMethod(env_build_libraries, "BuildLibraries")