mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-03 06:54:16 +01:00
store objcopy of these extra symbols and .map from the linker distribution will have an extra debug .zip file that could be used with the exception decoder also fixes relative paths in the build-and-copy (although, yet again loses the pio target in the gui)
140 lines
4.4 KiB
Python
140 lines
4.4 KiB
Python
import os
|
|
import shutil
|
|
import tempfile
|
|
|
|
from .version import app_full_version_for_env
|
|
|
|
|
|
# to avoid distributing the original .elf, just extract the debug symbols
|
|
# which then can be used /w addr2line (since it would still be an .elf format)
|
|
def app_add_extract_debug_symbols(env):
|
|
def builder_generator(target, source, env, for_signature):
|
|
return env.VerboseAction(
|
|
"$OBJCOPY --only-keep-debug $SOURCE $TARGET",
|
|
"Extracting debug symbols from $SOURCE",
|
|
)
|
|
|
|
env.Append(
|
|
BUILDERS={
|
|
"ExtractDebugSymbols": env.Builder(
|
|
generator=builder_generator, suffix=".debug", src_suffix=".elf"
|
|
)
|
|
}
|
|
)
|
|
|
|
|
|
# emulate .ino concatenation to speed up compilation times
|
|
def merge_cpp(target, source, env, encoding="utf-8"):
|
|
with tempfile.TemporaryFile() as tmp:
|
|
tmp.write(b"// !!! Automatically generated file; DO NOT EDIT !!! \n")
|
|
tmp.write(
|
|
'#include "{}"\n'.format(
|
|
env.File("${PROJECT_DIR}/espurna/espurna.h").get_abspath()
|
|
).encode(encoding)
|
|
)
|
|
for src in source:
|
|
src_include = '#include "{}"\n'.format(src.get_abspath())
|
|
tmp.write(src_include.encode(encoding))
|
|
|
|
tmp.seek(0)
|
|
|
|
with open(target[0].get_abspath(), "wb") as fobj:
|
|
shutil.copyfileobj(tmp, fobj)
|
|
|
|
|
|
def app_add_builder_single_source(env):
|
|
# generate things in the $BUILD_DIR, so there's no need for any extra clean-up code
|
|
source = os.path.join("${BUILD_DIR}", "espurna_single_source", "src", "main.cpp")
|
|
|
|
# substitute a single node instead of building it somewhere else as a lib or extra source dir
|
|
# (...and since we can't seem to modify src_filter specifically for the project dir, only middleware works :/)
|
|
def ignore_node(node):
|
|
if node.name.endswith("main.cpp"):
|
|
return env.File(source)
|
|
return None
|
|
|
|
project = env.Dir("${PROJECT_DIR}/espurna")
|
|
env.AddBuildMiddleware(ignore_node, os.path.join(project.get_abspath(), "*.cpp"))
|
|
env.Command(
|
|
source,
|
|
env.Glob("${PROJECT_DIR}/espurna/*.cpp"),
|
|
env.VerboseAction(merge_cpp, "Merging project sources into $TARGET"),
|
|
)
|
|
|
|
|
|
# common name for all our output files (.bin, .elf, .map, etc.)
|
|
|
|
|
|
def firmware_prefix(env):
|
|
return f"espurna-{app_full_version_for_env(env)}"
|
|
|
|
|
|
def firmware_filename(env):
|
|
return "-".join(
|
|
[firmware_prefix(env), env.get("ESPURNA_BUILD_NAME", env["PIOENV"])]
|
|
)
|
|
|
|
|
|
def firmware_destination(env):
|
|
dest = env.get("ESPURNA_BUILD_DESTINATION")
|
|
|
|
# implicit default to a local directory
|
|
if not dest:
|
|
dest = "${PROJECT_DIR}/build"
|
|
# its a SCons var
|
|
elif dest.startswith("$"):
|
|
pass
|
|
# due to runtime (?) quirks, we will end up in scripts/
|
|
# without specifying this as relative to the projdir
|
|
elif not dest.startswith("/"):
|
|
dest = f"${{PROJECT_DIR}}/{dest}"
|
|
|
|
return env.Dir(dest)
|
|
|
|
|
|
def app_add_target_build_and_copy(env):
|
|
env.Replace(ESPURNA_BUILD_DESTINATION=firmware_destination(env))
|
|
env.Replace(ESPURNA_BUILD_FILENAME=firmware_filename(env))
|
|
|
|
app_add_extract_debug_symbols(env)
|
|
env.ExtractDebugSymbols("$BUILD_DIR/${PROGNAME}")
|
|
|
|
env.InstallAs(
|
|
"${ESPURNA_BUILD_DESTINATION}/${ESPURNA_BUILD_FILENAME}.bin",
|
|
"$BUILD_DIR/${PROGNAME}.bin",
|
|
)
|
|
for suffix in ("map", "elf.debug"):
|
|
env.InstallAs(
|
|
f"${{ESPURNA_BUILD_DESTINATION}}/debug/${{ESPURNA_BUILD_FILENAME}}.{suffix}",
|
|
f"$BUILD_DIR/${{PROGNAME}}.{suffix}",
|
|
)
|
|
|
|
env.Alias("install", "$ESPURNA_BUILD_DESTINATION")
|
|
env.Alias("build-and-copy", ["$BUILD_DIR/${PROGNAME}.bin", "install"])
|
|
|
|
|
|
# NOTICE that .re <-> .re.ipp dependency is tricky, b/c we want these to exist *before* any source is built
|
|
# (or, attempted to be built. `projenv` does not exist yet, and so there are no dependecies generated)
|
|
|
|
|
|
def app_add_target_build_re2c(env):
|
|
from SCons.Script import COMMAND_LINE_TARGETS
|
|
|
|
targets = []
|
|
|
|
for target in COMMAND_LINE_TARGETS:
|
|
if target.endswith(".re.ipp"):
|
|
targets.append(target)
|
|
|
|
if targets:
|
|
action = env.VerboseAction(
|
|
"re2c --no-generation-date --case-ranges -W -Werror -o $TARGET $SOURCE",
|
|
"Generating $TARGET",
|
|
)
|
|
|
|
for target in targets:
|
|
action(
|
|
[env.File(target)], [env.File(target.replace(".re.ipp", ".re"))], env
|
|
)
|
|
env.Exit(0)
|