fbt fixes pt4 (#1899)
* fbt: fixed py scripts for gdb * fbt: removed compiled dolphin assets from tracked files; resolved cached dependency issues by globally disabling deps cache; changed dependency tracking for dolphin assets * fbt: fix for "resources" node lookup * toolchain: bump to v.16 with scons + x64 win binaries * fbt: using scons from toolchain * vscode: fixed paths for 64-bit Windows toolchain * fbt: added colors! * fbt: moved import validator to ansi lib coloring * fbt: moved COMSTR vars to tools * fbt: custom action for fap dist * fbt: added OPENOCD_ADAPTER_SERIAL configuration var for openocd operations * fbt: added get_stlink target * docs: details on libs for faps * vscode: added DAP config for using Flipper as a debugger for a 2nd Flipper * fbt: blind deps fix for sdk_origin * fbt: sdk: moved deployment actions to pure python * Github: disable disableLicenseExpirationCheck option for pvs Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -30,22 +30,25 @@ def dolphin_emitter(target, source, env):
|
||||
res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"])
|
||||
source = [res_root_dir]
|
||||
source.extend(
|
||||
env.GlobRecursive("*.*", res_root_dir),
|
||||
env.GlobRecursive("*.*", res_root_dir.srcnode()),
|
||||
)
|
||||
|
||||
target_base_dir = target[0]
|
||||
env.Replace(_DOLPHIN_OUT_DIR=target[0])
|
||||
|
||||
if env["DOLPHIN_RES_TYPE"] == "external":
|
||||
target = []
|
||||
target.extend(
|
||||
map(
|
||||
lambda node: target_base_dir.File(
|
||||
res_root_dir.rel_path(node).replace(".png", ".bm")
|
||||
),
|
||||
filter(lambda node: isinstance(node, SCons.Node.FS.File), source),
|
||||
)
|
||||
)
|
||||
target = [target_base_dir.File("manifest.txt")]
|
||||
## A detailed list of files to be generated
|
||||
## works better if we just leave target the folder
|
||||
# target = []
|
||||
# target.extend(
|
||||
# map(
|
||||
# lambda node: target_base_dir.File(
|
||||
# res_root_dir.rel_path(node).replace(".png", ".bm")
|
||||
# ),
|
||||
# filter(lambda node: isinstance(node, SCons.Node.FS.File), source),
|
||||
# )
|
||||
# )
|
||||
else:
|
||||
asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}"
|
||||
target = [
|
||||
@@ -53,6 +56,13 @@ def dolphin_emitter(target, source, env):
|
||||
target_base_dir.File(asset_basename + ".h"),
|
||||
]
|
||||
|
||||
# Debug output
|
||||
# print(
|
||||
# f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:",
|
||||
# list(f.path for f in target),
|
||||
# f"\nsource files:",
|
||||
# list(f.path for f in source),
|
||||
# )
|
||||
return target, source
|
||||
|
||||
|
||||
|
@@ -1,4 +1,39 @@
|
||||
from re import search
|
||||
|
||||
from SCons.Errors import UserError
|
||||
from fbt_options import OPENOCD_OPTS
|
||||
|
||||
|
||||
def _get_device_serials(search_str="STLink"):
|
||||
import serial.tools.list_ports as list_ports
|
||||
|
||||
return set([device.serial_number for device in list_ports.grep(search_str)])
|
||||
|
||||
|
||||
def GetDevices(env):
|
||||
serials = _get_device_serials()
|
||||
if len(serials) == 0:
|
||||
raise UserError("No devices found")
|
||||
|
||||
print("\n".join(serials))
|
||||
|
||||
|
||||
def generate(env, **kw):
|
||||
env.AddMethod(GetDevices)
|
||||
|
||||
if (adapter_serial := env.subst("$OPENOCD_ADAPTER_SERIAL")) != "auto":
|
||||
env.Append(
|
||||
OPENOCD_OPTS=[
|
||||
"-c",
|
||||
f"adapter serial {adapter_serial}",
|
||||
]
|
||||
)
|
||||
|
||||
# Final command is "init", always explicitly added
|
||||
env.Append(
|
||||
OPENOCD_OPTS=["-c", "init"],
|
||||
)
|
||||
|
||||
env.SetDefault(
|
||||
OPENOCD_GDB_PIPE=[
|
||||
"|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import shutil
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Errors import UserError
|
||||
@@ -9,6 +10,7 @@ from fbt.elfmanifest import assemble_manifest_data
|
||||
from fbt.appmanifest import FlipperApplication, FlipperManifestException
|
||||
from fbt.sdk import SdkCache
|
||||
import itertools
|
||||
from ansi.color import fg
|
||||
|
||||
|
||||
def BuildAppElf(env, app):
|
||||
@@ -175,7 +177,8 @@ def validate_app_imports(target, source, env):
|
||||
if unresolved_syms:
|
||||
SCons.Warnings.warn(
|
||||
SCons.Warnings.LinkWarning,
|
||||
f"\033[93m{source[0].path}: app won't run. Unresolved symbols: \033[95m{unresolved_syms}\033[0m",
|
||||
fg.brightyellow(f"{source[0].path}: app won't run. Unresolved symbols: ")
|
||||
+ fg.brightmagenta(f"{unresolved_syms}"),
|
||||
)
|
||||
|
||||
|
||||
@@ -209,14 +212,51 @@ def GetExtAppFromPath(env, app_dir):
|
||||
return (app, app_elf[0], app_validator[0])
|
||||
|
||||
|
||||
def fap_dist_emitter(target, source, env):
|
||||
target_dir = target[0]
|
||||
|
||||
target = []
|
||||
for dist_entry in env["_extapps"]["dist"].values():
|
||||
target.append(target_dir.Dir(dist_entry[0]).File(dist_entry[1][0].name))
|
||||
|
||||
for compact_entry in env["_extapps"]["compact"].values():
|
||||
source.extend(compact_entry)
|
||||
|
||||
return (target, source)
|
||||
|
||||
|
||||
def fap_dist_action(target, source, env):
|
||||
# FIXME
|
||||
target_dir = env.Dir("#/assets/resources/apps")
|
||||
|
||||
shutil.rmtree(target_dir.path, ignore_errors=True)
|
||||
for src, target in zip(source, target):
|
||||
os.makedirs(os.path.dirname(target.path), exist_ok=True)
|
||||
shutil.copy(src.path, target.path)
|
||||
|
||||
|
||||
def generate(env, **kw):
|
||||
env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR"))
|
||||
# env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), env.Dir("#"), duplicate=False)
|
||||
|
||||
if not env["VERBOSE"]:
|
||||
env.SetDefault(
|
||||
FAPDISTCOMSTR="\tFAPDIST\t${TARGET}",
|
||||
APPMETA_COMSTR="\tAPPMETA\t${TARGET}",
|
||||
APPMETAEMBED_COMSTR="\tFAP\t${TARGET}",
|
||||
APPCHECK_COMSTR="\tAPPCHK\t${SOURCE}",
|
||||
)
|
||||
|
||||
env.AddMethod(BuildAppElf)
|
||||
env.AddMethod(GetExtAppFromPath)
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
"FapDist": Builder(
|
||||
action=Action(
|
||||
fap_dist_action,
|
||||
"$FAPDISTCOMSTR",
|
||||
),
|
||||
emitter=fap_dist_emitter,
|
||||
),
|
||||
"EmbedAppMetadata": Builder(
|
||||
action=[
|
||||
Action(prepare_app_metadata, "$APPMETA_COMSTR"),
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import shutil
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Errors import UserError
|
||||
@@ -117,42 +118,30 @@ class SdkTreeBuilder:
|
||||
target = [target_folder.File("sdk.opts")]
|
||||
return target, source
|
||||
|
||||
def _create_deploy_commands(self):
|
||||
def _run_deploy_commands(self):
|
||||
dirs_to_create = set(
|
||||
self.sdk_deploy_dir.Dir(dirpath) for dirpath in self.header_dirs
|
||||
self.sdk_deploy_dir.Dir(dirpath).path for dirpath in self.header_dirs
|
||||
)
|
||||
actions = [
|
||||
Delete(self.sdk_deploy_dir),
|
||||
Mkdir(self.sdk_deploy_dir),
|
||||
Copy(
|
||||
self.sdk_root_dir,
|
||||
self.env["SDK_DEFINITION"],
|
||||
),
|
||||
]
|
||||
actions += [Mkdir(d) for d in dirs_to_create]
|
||||
|
||||
actions += [
|
||||
Action(
|
||||
Copy(self.sdk_deploy_dir.File(h).path, h),
|
||||
# f"Copy {h} to {self.sdk_deploy_dir}",
|
||||
)
|
||||
for h in self.header_depends
|
||||
]
|
||||
return actions
|
||||
shutil.rmtree(self.sdk_root_dir.path, ignore_errors=False)
|
||||
|
||||
def generate_actions(self):
|
||||
for sdkdir in dirs_to_create:
|
||||
os.makedirs(sdkdir, exist_ok=True)
|
||||
|
||||
shutil.copy2(self.env["SDK_DEFINITION"].path, self.sdk_root_dir.path)
|
||||
|
||||
for header in self.header_depends:
|
||||
shutil.copy2(header, self.sdk_deploy_dir.File(header).path)
|
||||
|
||||
def deploy_action(self):
|
||||
self._parse_sdk_depends()
|
||||
self._run_deploy_commands()
|
||||
self._generate_sdk_meta()
|
||||
|
||||
return self._create_deploy_commands()
|
||||
|
||||
|
||||
def deploy_sdk_tree(target, source, env, for_signature):
|
||||
if for_signature:
|
||||
return []
|
||||
|
||||
def deploy_sdk_tree_action(target, source, env):
|
||||
sdk_tree = SdkTreeBuilder(env, target, source)
|
||||
return sdk_tree.generate_actions()
|
||||
return sdk_tree.deploy_action()
|
||||
|
||||
|
||||
def deploy_sdk_tree_emitter(target, source, env):
|
||||
@@ -217,6 +206,30 @@ def generate_sdk_symbols(source, target, env):
|
||||
|
||||
|
||||
def generate(env, **kw):
|
||||
if not env["VERBOSE"]:
|
||||
env.SetDefault(
|
||||
SDK_PREGEN_COMSTR="\tPREGEN\t${TARGET}",
|
||||
SDK_COMSTR="\tSDKSRC\t${TARGET}",
|
||||
SDKSYM_UPDATER_COMSTR="\tSDKCHK\t${TARGET}",
|
||||
SDKSYM_GENERATOR_COMSTR="\tSDKSYM\t${TARGET}",
|
||||
SDKDEPLOY_COMSTR="\tSDKTREE\t${TARGET}",
|
||||
)
|
||||
|
||||
# Filtering out things cxxheaderparser cannot handle
|
||||
env.SetDefault(
|
||||
SDK_PP_FLAGS=[
|
||||
'-D"_Static_assert(x,y)="',
|
||||
'-D"__asm__(x)="',
|
||||
'-D"__attribute__(x)="',
|
||||
"-Drestrict=",
|
||||
"-D_Noreturn=",
|
||||
"-D__restrict=",
|
||||
"-D__extension__=",
|
||||
"-D__inline=inline",
|
||||
"-D__inline__=inline",
|
||||
]
|
||||
)
|
||||
|
||||
env.AddMethod(ProcessSdkDepends)
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
@@ -235,7 +248,10 @@ def generate(env, **kw):
|
||||
suffix=".i",
|
||||
),
|
||||
"SDKTree": Builder(
|
||||
generator=deploy_sdk_tree,
|
||||
action=Action(
|
||||
deploy_sdk_tree_action,
|
||||
"$SDKDEPLOY_COMSTR",
|
||||
),
|
||||
emitter=deploy_sdk_tree_emitter,
|
||||
src_suffix=".d",
|
||||
),
|
||||
|
43
scripts/fbt_tools/fbt_tweaks.py
Normal file
43
scripts/fbt_tools/fbt_tweaks.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import SCons.Warnings as Warnings
|
||||
|
||||
# from SCons.Script.Main import find_deepest_user_frame
|
||||
|
||||
from ansi.color import fg, bg, fx
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def find_deepest_user_frame(tb):
|
||||
tb.reverse()
|
||||
|
||||
# find the deepest traceback frame that is not part
|
||||
# of SCons:
|
||||
for frame in tb:
|
||||
filename = frame[0]
|
||||
if filename.find("fbt_tweaks") != -1:
|
||||
continue
|
||||
if filename.find(os.sep + "SCons" + os.sep) == -1:
|
||||
return frame
|
||||
return tb[0]
|
||||
|
||||
|
||||
def fbt_warning(e):
|
||||
filename, lineno, routine, dummy = find_deepest_user_frame(
|
||||
traceback.extract_stack()
|
||||
)
|
||||
fbt_line = "\nfbt: warning: %s\n" % e.args[0]
|
||||
sys.stderr.write(fg.boldmagenta(fbt_line))
|
||||
fbt_line = (
|
||||
fg.yellow("%s, line %d, " % (routine, lineno)) + 'in file "%s"\n' % filename
|
||||
)
|
||||
sys.stderr.write(fg.yellow(fbt_line))
|
||||
|
||||
|
||||
def generate(env):
|
||||
Warnings._warningOut = fbt_warning
|
||||
|
||||
|
||||
def exists():
|
||||
return True
|
@@ -12,6 +12,14 @@ def generate(env):
|
||||
OBJCOPY=__OBJCOPY_ARM_BIN, # FIXME
|
||||
NM=__NM_ARM_BIN, # FIXME
|
||||
)
|
||||
|
||||
if not env["VERBOSE"]:
|
||||
env.SetDefault(
|
||||
HEXCOMSTR="\tHEX\t${TARGET}",
|
||||
BINCOMSTR="\tBIN\t${TARGET}",
|
||||
DFUCOMSTR="\tDFU\t${TARGET}",
|
||||
)
|
||||
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
"HEXBuilder": Builder(
|
||||
|
@@ -6,8 +6,6 @@ def generate(env):
|
||||
env.SetDefault(
|
||||
GDB="gdb",
|
||||
GDBPY="gdb-py",
|
||||
GDBOPTS="",
|
||||
GDBPYOPTS="",
|
||||
GDBCOM="$GDB $GDBOPTS $SOURCES", # no $TARGET
|
||||
GDBPYCOM="$GDBPY $GDBOPTS $GDBPYOPTS $SOURCES", # no $TARGET
|
||||
)
|
||||
|
Reference in New Issue
Block a user