mirror of https://github.com/ARMmbed/mbed-os.git
Simplify hook tool implementation
The "hook tools" were capable of hooking into many commands run by the build system. To my knowlage, the only hook is the "post-build-hook". The post build hook could be easier to reason about if the implementation is specialized for just post-build hooking. This commit make it much easier to point out where post build hooks are called by making the call explicit.pull/9738/head
parent
355f09bbac
commit
aeeb43fb3c
214
tools/hooks.py
214
tools/hooks.py
|
|
@ -1,214 +0,0 @@
|
|||
""" Configurable hooks in the build system. Can be used by various platforms
|
||||
to customize the build process.
|
||||
"""
|
||||
|
||||
################################################################################
|
||||
# Hooks for the various parts of the build process
|
||||
|
||||
# Internal mapping of hooks per tool
|
||||
_HOOKS = {}
|
||||
|
||||
# Internal mapping of running hooks
|
||||
_RUNNING_HOOKS = {}
|
||||
|
||||
# Available hook types
|
||||
_HOOK_TYPES = ["binary", "compile", "link", "assemble"]
|
||||
|
||||
# Available hook steps
|
||||
_HOOK_STEPS = ["pre", "replace", "post"]
|
||||
|
||||
# Hook the given function. Use this function as a decorator
|
||||
def hook_tool(function):
|
||||
"""Decorate a function as a tool that may be hooked"""
|
||||
tool = function.__name__
|
||||
tool_flag = "_" + tool + "_done"
|
||||
def wrapper(t_self, *args, **kwargs):
|
||||
"""The hooked function itself"""
|
||||
# if a hook for this tool is already running, it's most likely
|
||||
# coming from a derived class, so don't hook the super class version
|
||||
if _RUNNING_HOOKS.get(tool, False):
|
||||
return function(t_self, *args, **kwargs)
|
||||
_RUNNING_HOOKS[tool] = True
|
||||
# If this tool isn't hooked, return original function
|
||||
if tool not in _HOOKS:
|
||||
res = function(t_self, *args, **kwargs)
|
||||
_RUNNING_HOOKS[tool] = False
|
||||
return res
|
||||
tooldesc = _HOOKS[tool]
|
||||
setattr(t_self, tool_flag, False)
|
||||
# If there is a replace hook, execute the replacement instead
|
||||
if "replace" in tooldesc:
|
||||
res = tooldesc["replace"](t_self, *args, **kwargs)
|
||||
# If the replacement has set the "done" flag, exit now
|
||||
# Otherwise continue as usual
|
||||
if getattr(t_self, tool_flag, False):
|
||||
_RUNNING_HOOKS[tool] = False
|
||||
return res
|
||||
# Execute pre-function before main function if specified
|
||||
if "pre" in tooldesc:
|
||||
tooldesc["pre"](t_self, *args, **kwargs)
|
||||
# Execute the main function now
|
||||
res = function(t_self, *args, **kwargs)
|
||||
# Execute post-function after main function if specified
|
||||
if "post" in tooldesc:
|
||||
post_res = tooldesc["post"](t_self, *args, **kwargs)
|
||||
_RUNNING_HOOKS[tool] = False
|
||||
return post_res or res
|
||||
else:
|
||||
_RUNNING_HOOKS[tool] = False
|
||||
return res
|
||||
return wrapper
|
||||
|
||||
class Hook(object):
|
||||
"""A compiler class that may be hooked"""
|
||||
def __init__(self, target, toolchain):
|
||||
_HOOKS.clear()
|
||||
self._cmdline_hooks = {}
|
||||
self.toolchain = toolchain
|
||||
target.init_hooks(self, toolchain)
|
||||
|
||||
# Hook various functions directly
|
||||
@staticmethod
|
||||
def _hook_add(hook_type, hook_step, function):
|
||||
"""Add a hook to a compile function
|
||||
|
||||
Positional arguments:
|
||||
hook_type - one of the _HOOK_TYPES
|
||||
hook_step - one of the _HOOK_STEPS
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
if hook_type not in _HOOK_TYPES or hook_step not in _HOOK_STEPS:
|
||||
return False
|
||||
if hook_type not in _HOOKS:
|
||||
_HOOKS[hook_type] = {}
|
||||
_HOOKS[hook_type][hook_step] = function
|
||||
return True
|
||||
|
||||
def hook_add_compiler(self, hook_step, function):
|
||||
"""Add a hook to the compiler
|
||||
|
||||
Positional Arguments:
|
||||
hook_step - one of the _HOOK_STEPS
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
return self._hook_add("compile", hook_step, function)
|
||||
|
||||
def hook_add_linker(self, hook_step, function):
|
||||
"""Add a hook to the linker
|
||||
|
||||
Positional Arguments:
|
||||
hook_step - one of the _HOOK_STEPS
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
return self._hook_add("link", hook_step, function)
|
||||
|
||||
def hook_add_assembler(self, hook_step, function):
|
||||
"""Add a hook to the assemble
|
||||
|
||||
Positional Arguments:
|
||||
hook_step - one of the _HOOK_STEPS
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
return self._hook_add("assemble", hook_step, function)
|
||||
|
||||
def hook_add_binary(self, hook_step, function):
|
||||
"""Add a hook to the elf to binary tool
|
||||
|
||||
Positional Arguments:
|
||||
hook_step - one of the _HOOK_STEPS
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
return self._hook_add("binary", hook_step, function)
|
||||
|
||||
# Hook command lines
|
||||
def _hook_cmdline(self, hook_type, function):
|
||||
"""Add a hook to a command line function
|
||||
|
||||
Positional arguments:
|
||||
hook_type - one of the _HOOK_TYPES
|
||||
function - the function to add to the list of hooks
|
||||
"""
|
||||
if hook_type not in _HOOK_TYPES:
|
||||
return False
|
||||
self._cmdline_hooks[hook_type] = function
|
||||
return True
|
||||
|
||||
def hook_cmdline_compiler(self, function):
|
||||
"""Add a hook to the compiler command line
|
||||
|
||||
Positional arguments:
|
||||
function - the function to call
|
||||
"""
|
||||
return self._hook_cmdline("compile", function)
|
||||
|
||||
def hook_cmdline_linker(self, function):
|
||||
"""Add a hook to the linker command line
|
||||
|
||||
Positional arguments:
|
||||
function - the function to call
|
||||
"""
|
||||
return self._hook_cmdline("link", function)
|
||||
|
||||
def hook_cmdline_assembler(self, function):
|
||||
"""Add a hook to the assembler command line
|
||||
|
||||
Positional arguments:
|
||||
function - the function to call
|
||||
"""
|
||||
return self._hook_cmdline("assemble", function)
|
||||
|
||||
def hook_cmdline_binary(self, function):
|
||||
"""Add a hook to the elf to bin tool command line
|
||||
|
||||
Positional arguments:
|
||||
function - the function to call
|
||||
"""
|
||||
return self._hook_cmdline("binary", function)
|
||||
|
||||
# Return the command line after applying the hook
|
||||
def _get_cmdline(self, hook_type, cmdline):
|
||||
"""Get the command line after running all hooks
|
||||
|
||||
Positional arguments:
|
||||
hook_type - one of the _HOOK_TYPES
|
||||
cmdline - the initial command line
|
||||
"""
|
||||
if hook_type in self._cmdline_hooks:
|
||||
cmdline = self._cmdline_hooks[hook_type](
|
||||
self.toolchain.__class__.__name__, cmdline)
|
||||
return cmdline
|
||||
|
||||
def get_cmdline_compiler(self, cmdline):
|
||||
"""Get the compiler command line after running all hooks
|
||||
|
||||
Positional arguments:
|
||||
cmdline - the initial command line
|
||||
"""
|
||||
return self._get_cmdline("compile", cmdline)
|
||||
|
||||
def get_cmdline_linker(self, cmdline):
|
||||
"""Get the linker command line after running all hooks
|
||||
|
||||
Positional arguments:
|
||||
cmdline - the initial command line
|
||||
"""
|
||||
return self._get_cmdline("link", cmdline)
|
||||
|
||||
def get_cmdline_assembler(self, cmdline):
|
||||
"""Get the assmebler command line after running all hooks
|
||||
|
||||
Positional arguments:
|
||||
cmdline - the initial command line
|
||||
"""
|
||||
return self._get_cmdline("assemble", cmdline)
|
||||
|
||||
def get_cmdline_binary(self, cmdline):
|
||||
"""Get the binary command line after running all hooks
|
||||
|
||||
Positional arguments:
|
||||
cmdline - the initial command line
|
||||
"""
|
||||
return self._get_cmdline("binary", cmdline)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ class Target(namedtuple("Target", "name json_data resolution_order resolution_or
|
|||
def is_PSA_non_secure_target(self):
|
||||
return 'NSPE_Target' in self.labels
|
||||
|
||||
def init_hooks(self, hook, toolchain):
|
||||
def get_post_build_hook(self, toolchain):
|
||||
"""Initialize the post-build hooks for a toolchain. For now, this
|
||||
function only allows "post binary" hooks (hooks that are executed
|
||||
after the binary image is extracted from the executable file)
|
||||
|
|
@ -404,8 +404,7 @@ class Target(namedtuple("Target", "name json_data resolution_order resolution_or
|
|||
if toolchain_restrictions and \
|
||||
not toolchain_labels.intersection(toolchain_restrictions):
|
||||
return
|
||||
# Finally, hook the requested function
|
||||
hook.hook_add_binary("post", getattr(cls, function_name))
|
||||
return getattr(cls, function_name)
|
||||
|
||||
################################################################################
|
||||
# Target specific code goes in this section
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ from hashlib import md5
|
|||
from ..utils import (run_cmd, mkdir, rel_path, ToolException,
|
||||
NotSupportedException, split_path, compile_worker)
|
||||
from ..settings import MBED_ORG_USER, PRINT_COMPILER_OUTPUT_AS_LINK
|
||||
from .. import hooks
|
||||
from ..notifier.term import TerminalNotifier
|
||||
from ..resources import FileType
|
||||
from ..memap import MemapParser
|
||||
|
|
@ -96,7 +95,7 @@ class mbedToolchain:
|
|||
self.name = self.__class__.__name__
|
||||
|
||||
# compile/assemble/link/binary hooks
|
||||
self.hook = hooks.Hook(target, self)
|
||||
self._post_build_hook = target.get_post_build_hook(self.name)
|
||||
|
||||
# Toolchain flags
|
||||
self.flags = deepcopy(build_profile or self.profile_template)
|
||||
|
|
@ -653,6 +652,9 @@ class mbedToolchain:
|
|||
self.progress("elf2bin", name)
|
||||
self.binary(r, elf, bin)
|
||||
|
||||
if self._post_build_hook:
|
||||
self.progress("post-build", name)
|
||||
self._post_build_hook(self, r, elf, bin)
|
||||
# Initialize memap and process map file. This doesn't generate output.
|
||||
self.mem_stats(mapfile)
|
||||
|
||||
|
|
@ -1002,9 +1004,6 @@ class mbedToolchain:
|
|||
|
||||
Side effects:
|
||||
None
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
@ -1024,9 +1023,6 @@ class mbedToolchain:
|
|||
|
||||
Side effects:
|
||||
None
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
@ -1046,9 +1042,6 @@ class mbedToolchain:
|
|||
|
||||
Side effects:
|
||||
None
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
@ -1068,9 +1061,6 @@ class mbedToolchain:
|
|||
|
||||
Side effect:
|
||||
Runs the linker to produce the executable.
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
@ -1087,9 +1077,6 @@ class mbedToolchain:
|
|||
|
||||
Side effect:
|
||||
Runs the archiving tool to produce the library file.
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
@ -1107,9 +1094,6 @@ class mbedToolchain:
|
|||
|
||||
Side effect:
|
||||
Runs the elf2bin tool to produce the simplified binary file.
|
||||
|
||||
Note:
|
||||
This method should be decorated with @hook_tool.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ from distutils.version import LooseVersion
|
|||
|
||||
from tools.targets import CORE_ARCH
|
||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||
from tools.hooks import hook_tool
|
||||
from tools.utils import mkdir, NotSupportedException, run_cmd
|
||||
|
||||
class ARM(mbedToolchain):
|
||||
|
|
@ -192,7 +191,6 @@ class ARM(mbedToolchain):
|
|||
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
# Preprocess first, then assemble
|
||||
dir = join(dirname(object), '.temp')
|
||||
|
|
@ -208,14 +206,9 @@ class ARM(mbedToolchain):
|
|||
# Build main assemble command
|
||||
cmd = self.asm + ["-o", object, tempfile]
|
||||
|
||||
# Call cmdline hook
|
||||
cmd_pre = self.hook.get_cmdline_assembler(cmd_pre)
|
||||
cmd = self.hook.get_cmdline_assembler(cmd)
|
||||
|
||||
# Return command array, don't execute
|
||||
return [cmd_pre, cmd]
|
||||
|
||||
@hook_tool
|
||||
def compile(self, cc, source, object, includes):
|
||||
# Build compile command
|
||||
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
|
||||
|
|
@ -224,9 +217,6 @@ class ARM(mbedToolchain):
|
|||
|
||||
cmd.extend(["-o", object, source])
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_compiler(cmd)
|
||||
|
||||
return [cmd]
|
||||
|
||||
def compile_c(self, source, object, includes):
|
||||
|
|
@ -269,7 +259,6 @@ class ARM(mbedToolchain):
|
|||
|
||||
return new_scatter
|
||||
|
||||
@hook_tool
|
||||
def link(self, output, objects, libraries, lib_dirs, scatter_file):
|
||||
base, _ = splitext(output)
|
||||
map_file = base + ".map"
|
||||
|
|
@ -283,7 +272,6 @@ class ARM(mbedToolchain):
|
|||
args.extend(["--scatter", new_scatter])
|
||||
|
||||
cmd_pre = self.ld + args
|
||||
cmd = self.hook.get_cmdline_linker(cmd_pre)
|
||||
|
||||
if self.RESPONSE_FILES:
|
||||
cmd_linker = cmd[0]
|
||||
|
|
@ -293,7 +281,6 @@ class ARM(mbedToolchain):
|
|||
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
|
||||
self.default_cmd(cmd)
|
||||
|
||||
@hook_tool
|
||||
def archive(self, objects, lib_path):
|
||||
if self.RESPONSE_FILES:
|
||||
param = ['--via', self.get_arch_file(objects)]
|
||||
|
|
@ -301,13 +288,11 @@ class ARM(mbedToolchain):
|
|||
param = objects
|
||||
self.default_cmd([self.ar, '-r', lib_path] + param)
|
||||
|
||||
@hook_tool
|
||||
def binary(self, resources, elf, bin):
|
||||
_, fmt = splitext(bin)
|
||||
# On .hex format, combine multiple .hex files (for multiple load regions) into one
|
||||
bin_arg = {".bin": "--bin", ".hex": "--i32combined"}[fmt]
|
||||
cmd = [self.elf2bin, bin_arg, '-o', bin, elf]
|
||||
cmd = self.hook.get_cmdline_binary(cmd)
|
||||
|
||||
# remove target binary file/path
|
||||
if exists(bin):
|
||||
|
|
@ -518,18 +503,15 @@ class ARMC6(ARM_STD):
|
|||
"--cpreproc_opts=%s" % ",".join(self.flags['common'] + opts)]
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
cmd_pre = copy(self.asm)
|
||||
cmd_pre.extend(self.get_compile_options(
|
||||
self.get_symbols(True), includes, for_asm=True))
|
||||
cmd_pre.extend(["-o", object, source])
|
||||
return [self.hook.get_cmdline_assembler(cmd_pre)]
|
||||
return [cmd_pre]
|
||||
|
||||
@hook_tool
|
||||
def compile(self, cc, source, object, includes):
|
||||
cmd = copy(cc)
|
||||
cmd.extend(self.get_compile_options(self.get_symbols(), includes))
|
||||
cmd.extend(["-o", object, source])
|
||||
cmd = self.hook.get_cmdline_compiler(cmd)
|
||||
return [cmd]
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ from distutils.version import LooseVersion
|
|||
|
||||
from tools.targets import CORE_ARCH
|
||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||
from tools.hooks import hook_tool
|
||||
from tools.utils import run_cmd, NotSupportedException
|
||||
|
||||
class GCC(mbedToolchain):
|
||||
|
|
@ -195,18 +194,13 @@ class GCC(mbedToolchain):
|
|||
opts = opts + self.get_config_option(config_header)
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
# Build assemble command
|
||||
cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes) + ["-o", object, source]
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_assembler(cmd)
|
||||
|
||||
# Return command array, don't execute
|
||||
return [cmd]
|
||||
|
||||
@hook_tool
|
||||
def compile(self, cc, source, object, includes):
|
||||
# Build compile command
|
||||
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
|
||||
|
|
@ -215,8 +209,6 @@ class GCC(mbedToolchain):
|
|||
|
||||
cmd.extend(["-o", object, source])
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_compiler(cmd)
|
||||
if self.use_distcc:
|
||||
cmd = ["distcc"] + cmd
|
||||
|
||||
|
|
@ -228,7 +220,6 @@ class GCC(mbedToolchain):
|
|||
def compile_cpp(self, source, object, includes):
|
||||
return self.compile(self.cppc, source, object, includes)
|
||||
|
||||
@hook_tool
|
||||
def link(self, output, objects, libraries, lib_dirs, mem_map):
|
||||
libs = []
|
||||
for l in libraries:
|
||||
|
|
@ -256,9 +247,6 @@ class GCC(mbedToolchain):
|
|||
cmd.extend(['-L', L])
|
||||
cmd.extend(libs)
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_linker(cmd)
|
||||
|
||||
if self.RESPONSE_FILES:
|
||||
# Split link command to linker executable + response file
|
||||
cmd_linker = cmd[0]
|
||||
|
|
@ -269,7 +257,6 @@ class GCC(mbedToolchain):
|
|||
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
|
||||
self.default_cmd(cmd)
|
||||
|
||||
@hook_tool
|
||||
def archive(self, objects, lib_path):
|
||||
if self.RESPONSE_FILES:
|
||||
param = ["@%s" % self.get_arch_file(objects)]
|
||||
|
|
@ -279,16 +266,12 @@ class GCC(mbedToolchain):
|
|||
# Exec command
|
||||
self.default_cmd([self.ar, 'rcs', lib_path] + param)
|
||||
|
||||
@hook_tool
|
||||
def binary(self, resources, elf, bin):
|
||||
# Build binary command
|
||||
_, fmt = splitext(bin)
|
||||
bin_arg = {'.bin': 'binary', '.hex': 'ihex'}[fmt]
|
||||
cmd = [self.elf2bin, "-O", bin_arg, elf, bin]
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_binary(cmd)
|
||||
|
||||
# Exec command
|
||||
self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd))
|
||||
self.default_cmd(cmd)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ from distutils.version import LooseVersion
|
|||
|
||||
from tools.targets import CORE_ARCH
|
||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||
from tools.hooks import hook_tool
|
||||
from tools.utils import run_cmd, NotSupportedException
|
||||
|
||||
class IAR(mbedToolchain):
|
||||
|
|
@ -185,7 +184,6 @@ class IAR(mbedToolchain):
|
|||
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
# Build assemble command
|
||||
cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes, True) + ["-o", object, source]
|
||||
|
|
@ -196,7 +194,6 @@ class IAR(mbedToolchain):
|
|||
# Return command array, don't execute
|
||||
return [cmd]
|
||||
|
||||
@hook_tool
|
||||
def compile(self, cc, source, object, includes):
|
||||
# Build compile command
|
||||
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
|
||||
|
|
@ -218,7 +215,6 @@ class IAR(mbedToolchain):
|
|||
def compile_cpp(self, source, object, includes):
|
||||
return self.compile(self.cppc, source, object, includes)
|
||||
|
||||
@hook_tool
|
||||
def link(self, output, objects, libraries, lib_dirs, mem_map):
|
||||
# Build linker command
|
||||
map_file = splitext(output)[0] + ".map"
|
||||
|
|
@ -240,7 +236,6 @@ class IAR(mbedToolchain):
|
|||
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
|
||||
self.default_cmd(cmd)
|
||||
|
||||
@hook_tool
|
||||
def archive(self, objects, lib_path):
|
||||
if self.RESPONSE_FILES:
|
||||
param = ['-f', self.get_arch_file(objects)]
|
||||
|
|
@ -252,16 +247,12 @@ class IAR(mbedToolchain):
|
|||
|
||||
self.default_cmd([self.ar, lib_path] + param)
|
||||
|
||||
@hook_tool
|
||||
def binary(self, resources, elf, bin):
|
||||
_, fmt = splitext(bin)
|
||||
bin_arg = {".bin": "--bin", ".hex": "--ihex"}[fmt]
|
||||
# Build binary command
|
||||
cmd = [self.elf2bin, bin_arg, elf, bin]
|
||||
|
||||
# Call cmdline hook
|
||||
cmd = self.hook.get_cmdline_binary(cmd)
|
||||
|
||||
# Exec command
|
||||
self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd))
|
||||
self.default_cmd(cmd)
|
||||
|
|
|
|||
Loading…
Reference in New Issue