blight.actions
Actions supported by blight.
1""" 2Actions supported by blight. 3""" 4 5from .benchmark import Benchmark 6from .cc_for_cxx import CCForCXX 7from .demo import Demo 8from .embed_bitcode import EmbedBitcode 9from .find_inputs import FindInputs 10from .find_outputs import FindOutputs 11from .ignore_flags import IgnoreFlags 12from .ignore_flto import IgnoreFlto 13from .ignore_werror import IgnoreWerror 14from .inject_flags import InjectFlags 15from .lint import Lint 16from .record import Record 17from .skip_strip import SkipStrip 18 19__all__ = [ 20 "Benchmark", 21 "CCForCXX", 22 "Demo", 23 "EmbedBitcode", 24 "FindInputs", 25 "FindOutputs", 26 "IgnoreFlags", 27 "IgnoreFlto", 28 "IgnoreWerror", 29 "InjectFlags", 30 "Lint", 31 "Record", 32 "SkipStrip", 33]
44class Benchmark(Action): 45 def before_run(self, tool: Tool) -> None: 46 self._start_nanos = time.monotonic_ns() 47 48 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 49 elapsed = (time.monotonic_ns() - self._start_nanos) // 1000 50 bench = BenchmarkRecord(tool=tool, elapsed=elapsed, run_skipped=run_skipped) 51 52 if tool.is_journaling(): 53 self._result = bench.dict() 54 else: 55 bench_file = Path(self._config["output"]) 56 with flock_append(bench_file) as io: 57 print(bench.json(), file=io)
A generic action, run with every tool (both before and after the tool's execution).
48 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 49 elapsed = (time.monotonic_ns() - self._start_nanos) // 1000 50 bench = BenchmarkRecord(tool=tool, elapsed=elapsed, run_skipped=run_skipped) 51 52 if tool.is_journaling(): 53 self._result = bench.dict() 54 else: 55 bench_file = Path(self._config["output"]) 56 with flock_append(bench_file) as io: 57 print(bench.json(), file=io)
Invoked right after the underlying tool is run.
Args: tool: The tool that just ran
Inherited Members
10class CCForCXX(CCAction): 11 """ 12 An action for detecting whether the C compiler is being used as if it's 13 a C++ compiler, and correcting the build when so. 14 15 This action is used to fix a particular kind of misconfigured C++ build, 16 where the C++ compiler is referred to as if it were a C compiler. 17 18 For example, in Make: 19 20 ```make 21 CC := clang++ 22 CFLAGS := -std=c++17 23 24 all: 25 $(CC) $(CFLAGS) -o whatever foo.cpp bar.cpp 26 ``` 27 28 Whereas the correct use would be: 29 30 ```make 31 CXX := clang++ 32 CXXFLAGS := -std=c++17 33 34 all: 35 $(CXX) $(CXXFLAGS) -o whatever foo.cpp bar.cpp 36 ``` 37 38 This action fixes these builds by checking whether `CC` is being used 39 as a C++ compiler. If it is, it explicitly injects additional flags 40 to force the compiler into C++ mode. 41 """ 42 43 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 44 # substitution principle violation -- it can't see that `CompilerAction` 45 # is safely specialized for `CompilerTool`. 46 def before_run(self, tool: CC) -> None: # type: ignore 47 # NOTE(ww): Currently, the only way we check whether CC is being used 48 # as a C++ compiler is by checking whether one of the `-std=c++XX` 49 # flags has been passed. This won't catch all cases; someone could use 50 # CC as a C++ compiler with the default C++ standard. 51 # Other options for detecting this: 52 # * Check for common C++-only linkages, like -lstdc++fs 53 # * Check whether tool.inputs contains files that look like C++ 54 if tool.std.is_cxxstd(): 55 tool.args[:0] = ["-x", "c++"]
An action for detecting whether the C compiler is being used as if it's a C++ compiler, and correcting the build when so.
This action is used to fix a particular kind of misconfigured C++ build, where the C++ compiler is referred to as if it were a C compiler.
For example, in Make:
CC := clang++
CFLAGS := -std=c++17
all:
$(CC) $(CFLAGS) -o whatever foo.cpp bar.cpp
Whereas the correct use would be:
CXX := clang++
CXXFLAGS := -std=c++17
all:
$(CXX) $(CXXFLAGS) -o whatever foo.cpp bar.cpp
This action fixes these builds by checking whether CC
is being used
as a C++ compiler. If it is, it explicitly injects additional flags
to force the compiler into C++ mode.
46 def before_run(self, tool: CC) -> None: # type: ignore 47 # NOTE(ww): Currently, the only way we check whether CC is being used 48 # as a C++ compiler is by checking whether one of the `-std=c++XX` 49 # flags has been passed. This won't catch all cases; someone could use 50 # CC as a C++ compiler with the default C++ standard. 51 # Other options for detecting this: 52 # * Check for common C++-only linkages, like -lstdc++fs 53 # * Check whether tool.inputs contains files that look like C++ 54 if tool.std.is_cxxstd(): 55 tool.args[:0] = ["-x", "c++"]
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
12class Demo(Action): 13 def before_run(self, tool: Tool) -> None: 14 print(f"[demo] before-run: {tool.wrapped_tool()}", file=sys.stderr) 15 16 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 17 print(f"[demo] after-run: {tool.wrapped_tool()}", file=sys.stderr)
A generic action, run with every tool (both before and after the tool's execution).
13 def before_run(self, tool: Tool) -> None: 14 print(f"[demo] before-run: {tool.wrapped_tool()}", file=sys.stderr)
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
16 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 17 print(f"[demo] after-run: {tool.wrapped_tool()}", file=sys.stderr)
Invoked right after the underlying tool is run.
Args: tool: The tool that just ran
Inherited Members
14class EmbedBitcode(CompilerAction): 15 """ 16 An action to embed bitcode in compiler tool outputs. 17 18 This action assumes that the compiler toolchain is LLVM based, and supports 19 the `-fembed-bitcode` option. It injects `-fembed-bitcode` into each invocation, 20 and lets the compiler tools take care of the rest. 21 22 Example: 23 24 ```bash 25 export BLIGHT_ACTIONS="EmbedBitcode" 26 make CC=blight-cc 27 ``` 28 """ 29 30 def before_run(self, tool: CompilerTool) -> None: # type: ignore 31 # TODO(ww): It probably makes sense to sanity check the arguments here, 32 # just in case the build is being run with some other flags that are 33 # relevant to bitcode generation (e.g. `-emit-llvm` or `-flto`). 34 tool.args = ["-fembed-bitcode", *tool.args]
An action to embed bitcode in compiler tool outputs.
This action assumes that the compiler toolchain is LLVM based, and supports
the -fembed-bitcode
option. It injects -fembed-bitcode
into each invocation,
and lets the compiler tools take care of the rest.
Example:
export BLIGHT_ACTIONS="EmbedBitcode"
make CC=blight-cc
30 def before_run(self, tool: CompilerTool) -> None: # type: ignore 31 # TODO(ww): It probably makes sense to sanity check the arguments here, 32 # just in case the build is being run with some other flags that are 33 # relevant to bitcode generation (e.g. `-emit-llvm` or `-flto`). 34 tool.args = ["-fembed-bitcode", *tool.args]
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
83class FindInputs(Action): 84 def before_run(self, tool: Tool) -> None: 85 inputs = [] 86 for input in tool.inputs: 87 input_path = Path(input) 88 if not input_path.is_absolute(): 89 input_path = tool.cwd / input_path 90 91 kind = INPUT_SUFFIX_KIND_MAP.get(input_path.suffix, InputKind.Unknown) 92 93 inputs.append(Input(prenormalized_path=input, kind=kind, path=input_path)) 94 95 self._inputs = inputs 96 97 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 98 inputs = InputsRecord(tool=tool, inputs=self._inputs) 99 100 if tool.is_journaling(): 101 # NOTE(ms): The `tool` member is excluded to avoid journal bloat. 102 self._result = inputs.dict(exclude={"tool"}) 103 else: 104 output_path = Path(self._config["output"]) 105 with flock_append(output_path) as io: 106 print(inputs.json(), file=io)
A generic action, run with every tool (both before and after the tool's execution).
84 def before_run(self, tool: Tool) -> None: 85 inputs = [] 86 for input in tool.inputs: 87 input_path = Path(input) 88 if not input_path.is_absolute(): 89 input_path = tool.cwd / input_path 90 91 kind = INPUT_SUFFIX_KIND_MAP.get(input_path.suffix, InputKind.Unknown) 92 93 inputs.append(Input(prenormalized_path=input, kind=kind, path=input_path)) 94 95 self._inputs = inputs
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
97 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 98 inputs = InputsRecord(tool=tool, inputs=self._inputs) 99 100 if tool.is_journaling(): 101 # NOTE(ms): The `tool` member is excluded to avoid journal bloat. 102 self._result = inputs.dict(exclude={"tool"}) 103 else: 104 output_path = Path(self._config["output"]) 105 with flock_append(output_path) as io: 106 print(inputs.json(), file=io)
Invoked right after the underlying tool is run.
Args: tool: The tool that just ran
Inherited Members
89class FindOutputs(Action): 90 def before_run(self, tool: Tool) -> None: 91 outputs = [] 92 for output in tool.outputs: 93 output_path = Path(output) 94 if not output_path.is_absolute(): 95 output_path = tool.cwd / output_path 96 97 # Special cases: a.out is produced by both the linker and compiler tools by default, 98 # and some tools (like `install`) have modes that produce directories as outputs. 99 if output_path.name == "a.out" and isinstance(tool, (CC, CXX, LD)): 100 kind = OutputKind.Executable 101 elif tool.__class__ == INSTALL and tool.directory_mode: # type: ignore 102 kind = OutputKind.Directory 103 else: 104 kind = OUTPUT_SUFFIX_KIND_MAP.get(output_path.suffix, OutputKind.Unknown) 105 106 # Last attempt: try some common patterns for output kinds if we can't 107 # match the suffix precisely. 108 if kind == OutputKind.Unknown: 109 kind = next( 110 ( 111 k 112 for (p, k) in OUTPUT_SUFFIX_PATTERN_MAP.items() 113 if re.match(p, str(output_path)) 114 ), 115 OutputKind.Unknown, 116 ) 117 118 outputs.append(Output(prenormalized_path=output, kind=kind, path=output_path)) 119 120 self._outputs = outputs 121 122 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 123 store = self._config.get("store") 124 if store is not None: 125 store_path = Path(store) 126 store_path.mkdir(parents=True, exist_ok=True) 127 128 for output in self._outputs: 129 # We don't copy output directories into the store, for now. 130 if output.path.is_dir(): 131 continue 132 133 if not output.path.exists(): 134 logger.warning(f"tool={tool}'s output ({output.path}) does not exist") 135 continue 136 137 # Outputs aren't guaranteed to have unique basenames and subsequent 138 # steps in the build system could even modify a particular output 139 # in-place, so we give each output a `store_path` based on a hash 140 # of its content. 141 content_hash = hashlib.sha256(output.path.read_bytes()).hexdigest() 142 # Append hash to the filename unless `append_hash=false` is specified in the config 143 append_hash = self._config.get("append_hash") != "false" 144 filename = f"{output.path.name}-{content_hash}" if append_hash else output.path.name 145 output_store_path = store_path / filename 146 if not output_store_path.exists(): 147 shutil.copy(output.path, output_store_path) 148 output.store_path = output_store_path 149 output.content_hash = content_hash 150 151 outputs = OutputsRecord(tool=tool, outputs=self._outputs) 152 153 if tool.is_journaling(): 154 # NOTE(ms): The `tool` member is excluded to avoid journal bloat. 155 self._result = outputs.dict(exclude={"tool"}) 156 else: 157 output_path = Path(self._config["output"]) 158 with flock_append(output_path) as io: 159 print(outputs.json(), file=io)
A generic action, run with every tool (both before and after the tool's execution).
90 def before_run(self, tool: Tool) -> None: 91 outputs = [] 92 for output in tool.outputs: 93 output_path = Path(output) 94 if not output_path.is_absolute(): 95 output_path = tool.cwd / output_path 96 97 # Special cases: a.out is produced by both the linker and compiler tools by default, 98 # and some tools (like `install`) have modes that produce directories as outputs. 99 if output_path.name == "a.out" and isinstance(tool, (CC, CXX, LD)): 100 kind = OutputKind.Executable 101 elif tool.__class__ == INSTALL and tool.directory_mode: # type: ignore 102 kind = OutputKind.Directory 103 else: 104 kind = OUTPUT_SUFFIX_KIND_MAP.get(output_path.suffix, OutputKind.Unknown) 105 106 # Last attempt: try some common patterns for output kinds if we can't 107 # match the suffix precisely. 108 if kind == OutputKind.Unknown: 109 kind = next( 110 ( 111 k 112 for (p, k) in OUTPUT_SUFFIX_PATTERN_MAP.items() 113 if re.match(p, str(output_path)) 114 ), 115 OutputKind.Unknown, 116 ) 117 118 outputs.append(Output(prenormalized_path=output, kind=kind, path=output_path)) 119 120 self._outputs = outputs
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
122 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 123 store = self._config.get("store") 124 if store is not None: 125 store_path = Path(store) 126 store_path.mkdir(parents=True, exist_ok=True) 127 128 for output in self._outputs: 129 # We don't copy output directories into the store, for now. 130 if output.path.is_dir(): 131 continue 132 133 if not output.path.exists(): 134 logger.warning(f"tool={tool}'s output ({output.path}) does not exist") 135 continue 136 137 # Outputs aren't guaranteed to have unique basenames and subsequent 138 # steps in the build system could even modify a particular output 139 # in-place, so we give each output a `store_path` based on a hash 140 # of its content. 141 content_hash = hashlib.sha256(output.path.read_bytes()).hexdigest() 142 # Append hash to the filename unless `append_hash=false` is specified in the config 143 append_hash = self._config.get("append_hash") != "false" 144 filename = f"{output.path.name}-{content_hash}" if append_hash else output.path.name 145 output_store_path = store_path / filename 146 if not output_store_path.exists(): 147 shutil.copy(output.path, output_store_path) 148 output.store_path = output_store_path 149 output.content_hash = content_hash 150 151 outputs = OutputsRecord(tool=tool, outputs=self._outputs) 152 153 if tool.is_journaling(): 154 # NOTE(ms): The `tool` member is excluded to avoid journal bloat. 155 self._result = outputs.dict(exclude={"tool"}) 156 else: 157 output_path = Path(self._config["output"]) 158 with flock_append(output_path) as io: 159 print(outputs.json(), file=io)
Invoked right after the underlying tool is run.
Args: tool: The tool that just ran
Inherited Members
16class IgnoreFlags(CompilerAction): 17 """ 18 An action for ignoring specific flags passed to compiler 19 commands (specifically, `cc` and `c++`). 20 21 For example: 22 23 ```bash 24 export BLIGHT_WRAPPED_CC=clang 25 export BLIGHT_ACTIONS="IgnoreFlags" 26 export BLIGHT_ACTIONS_IGNOREFLAGS="FLAGS='-Werror -ffunction-sections'" 27 make CC=blight-cc 28 ``` 29 30 will cause blight to remove `-Werror` and `--ffunction-sections` arguments 31 from each `clang` invocation. 32 """ 33 34 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 35 # substitution principle violation -- it can't see that `CompilerAction` 36 # is safely specialized for `CompilerTool`. 37 def before_run(self, tool: CompilerTool) -> None: # type: ignore 38 ignore_flags = shlex.split(self._config.get("FLAGS", "")) 39 if tool.lang in [Lang.C, Lang.Cxx]: 40 tool.args = [a for a in tool.args if a not in ignore_flags] 41 else: 42 logger.debug("not ignoring flags for an unknown language")
An action for ignoring specific flags passed to compiler
commands (specifically, cc
and c++
).
For example:
export BLIGHT_WRAPPED_CC=clang
export BLIGHT_ACTIONS="IgnoreFlags"
export BLIGHT_ACTIONS_IGNOREFLAGS="FLAGS='-Werror -ffunction-sections'"
make CC=blight-cc
will cause blight to remove -Werror
and --ffunction-sections
arguments
from each clang
invocation.
37 def before_run(self, tool: CompilerTool) -> None: # type: ignore 38 ignore_flags = shlex.split(self._config.get("FLAGS", "")) 39 if tool.lang in [Lang.C, Lang.Cxx]: 40 tool.args = [a for a in tool.args if a not in ignore_flags] 41 else: 42 logger.debug("not ignoring flags for an unknown language")
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
14class IgnoreFlto(CompilerAction): 15 """ 16 An action for ignoring the `-flto` flag passed to compiler 17 commands (specifically, `cc` and `c++`). Related commands that 18 control LTO (`-flto=...`) are also ignored. 19 20 For example: 21 22 ```bash 23 export BLIGHT_WRAPPED_CC=clang 24 export BLIGHT_ACTIONS="IgnoreFlto" 25 make CC=blight-cc 26 ``` 27 28 will cause blight to remove `-flto` arguments from each `clang` 29 invocation. 30 """ 31 32 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 33 # substitution principle violation -- it can't see that `CompilerAction` 34 # is safely specialized for `CompilerTool`. 35 def before_run(self, tool: CompilerTool) -> None: # type: ignore 36 tool.args = [a for a in tool.args if not a.startswith("-flto")]
An action for ignoring the -flto
flag passed to compiler
commands (specifically, cc
and c++
). Related commands that
control LTO (-flto=...
) are also ignored.
For example:
export BLIGHT_WRAPPED_CC=clang
export BLIGHT_ACTIONS="IgnoreFlto"
make CC=blight-cc
will cause blight to remove -flto
arguments from each clang
invocation.
35 def before_run(self, tool: CompilerTool) -> None: # type: ignore 36 tool.args = [a for a in tool.args if not a.startswith("-flto")]
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
15class IgnoreWerror(CompilerAction): 16 """ 17 An action for ignoring the `-Werror` flag passed to compiler 18 commands (specifically, `cc` and `c++`). 19 20 For example: 21 22 ```bash 23 export BLIGHT_WRAPPED_CC=clang 24 export BLIGHT_ACTIONS="IgnoreWerror" 25 make CC=blight-cc 26 ``` 27 28 will cause blight to remove `-Werror` arguments from each `clang` 29 invocation. 30 """ 31 32 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 33 # substitution principle violation -- it can't see that `CompilerAction` 34 # is safely specialized for `CompilerTool`. 35 def before_run(self, tool: CompilerTool) -> None: # type: ignore 36 if tool.lang in [Lang.C, Lang.Cxx]: 37 tool.args = [a for a in tool.args if a != "-Werror"] 38 else: 39 logger.debug("not injecting flags for an unknown language")
An action for ignoring the -Werror
flag passed to compiler
commands (specifically, cc
and c++
).
For example:
export BLIGHT_WRAPPED_CC=clang
export BLIGHT_ACTIONS="IgnoreWerror"
make CC=blight-cc
will cause blight to remove -Werror
arguments from each clang
invocation.
35 def before_run(self, tool: CompilerTool) -> None: # type: ignore 36 if tool.lang in [Lang.C, Lang.Cxx]: 37 tool.args = [a for a in tool.args if a != "-Werror"] 38 else: 39 logger.debug("not injecting flags for an unknown language")
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
16class InjectFlags(CompilerAction): 17 """ 18 An action for injecting flags into compiler commands (specifically, `cc` and `c++`). 19 20 This action takes the following flags in its configuration and appends them 21 (after shell-splitting) as appropriate: 22 - `CFLAGS`: Flags to append to every C compiler call 23 - `CFLAGS_LINKER`: Flags to append to every C compiler call that runs the linking 24 stage (i.e: no `-c`, `-e`, `-S`, etc. flags present) 25 - `CXXFLAGS`: Same as `CFLAGS` but for C++ 26 - `CFLAGS_LINKER`: Same as `CFLAGS_LINKER`, but for C++ 27 - `CPPFLAGS`: Flags to append for the preprocessor stage 28 29 For example: 30 31 ```bash 32 export BLIGHT_WRAPPED_CC=clang 33 export BLIGHT_ACTIONS="InjectFlags" 34 export BLIGHT_ACTION_INJECTFLAGS="CFLAGS='-g -O0' CPPFLAGS='-DWHATEVER'" 35 make CC=blight-cc 36 ``` 37 38 will cause blight to add `-g -O0 -DWHATEVER` to each `clang` invocation 39 (unless it's a C++ invocation, e.g. via `-x c++`). 40 """ 41 42 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 43 # substitution principle violation -- it can't see that `CompilerAction` 44 # is safely specialized for `CompilerTool`. 45 def before_run(self, tool: CompilerTool) -> None: # type: ignore 46 cflags = shlex.split(self._config.get("CFLAGS", "")) 47 cflags_linker = shlex.split(self._config.get("CFLAGS_LINKER", "")) 48 cxxflags = shlex.split(self._config.get("CXXFLAGS", "")) 49 cxxflags_linker = shlex.split(self._config.get("CXXFLAGS_LINKER", "")) 50 cppflags = shlex.split(self._config.get("CPPFLAGS", "")) 51 52 if tool.lang == Lang.C: 53 tool.args += cflags 54 tool.args += cppflags 55 if tool.stage is CompilerStage.AllStages: 56 tool.args += cflags_linker 57 elif tool.lang == Lang.Cxx: 58 tool.args += cxxflags 59 tool.args += cppflags 60 if tool.stage is CompilerStage.AllStages: 61 tool.args += cxxflags_linker 62 else: 63 logger.debug("not injecting flags for an unknown language")
An action for injecting flags into compiler commands (specifically, cc
and c++
).
This action takes the following flags in its configuration and appends them (after shell-splitting) as appropriate:
CFLAGS
: Flags to append to every C compiler callCFLAGS_LINKER
: Flags to append to every C compiler call that runs the linking stage (i.e: no-c
,-e
,-S
, etc. flags present)CXXFLAGS
: Same asCFLAGS
but for C++CFLAGS_LINKER
: Same asCFLAGS_LINKER
, but for C++CPPFLAGS
: Flags to append for the preprocessor stage
For example:
export BLIGHT_WRAPPED_CC=clang
export BLIGHT_ACTIONS="InjectFlags"
export BLIGHT_ACTION_INJECTFLAGS="CFLAGS='-g -O0' CPPFLAGS='-DWHATEVER'"
make CC=blight-cc
will cause blight to add -g -O0 -DWHATEVER
to each clang
invocation
(unless it's a C++ invocation, e.g. via -x c++
).
45 def before_run(self, tool: CompilerTool) -> None: # type: ignore 46 cflags = shlex.split(self._config.get("CFLAGS", "")) 47 cflags_linker = shlex.split(self._config.get("CFLAGS_LINKER", "")) 48 cxxflags = shlex.split(self._config.get("CXXFLAGS", "")) 49 cxxflags_linker = shlex.split(self._config.get("CXXFLAGS_LINKER", "")) 50 cppflags = shlex.split(self._config.get("CPPFLAGS", "")) 51 52 if tool.lang == Lang.C: 53 tool.args += cflags 54 tool.args += cppflags 55 if tool.stage is CompilerStage.AllStages: 56 tool.args += cflags_linker 57 elif tool.lang == Lang.Cxx: 58 tool.args += cxxflags 59 tool.args += cppflags 60 if tool.stage is CompilerStage.AllStages: 61 tool.args += cxxflags_linker 62 else: 63 logger.debug("not injecting flags for an unknown language")
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
14class Lint(CompilerAction): 15 """ 16 A "linting" action for common command-line mistakes. 17 18 At the moment, this catches mistakes like: 19 20 * `-DFORTIFY_SOURCE=...` instead of `-D_FORTIFY_SOURCE=...` 21 22 For example: 23 24 ```bash 25 export BLIGHT_WRAPPED_CC=clang 26 export BLIGHT_ACTIONS="Lint" 27 make CC=blight-cc 28 ``` 29 """ 30 31 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 32 # substitution principle violation -- it can't see that `CompilerAction` 33 # is safely specialized for `CompilerTool`. 34 def before_run(self, tool: CompilerTool) -> None: # type: ignore 35 for name, _ in tool.defines: 36 # TODO: Maybe do something more drastic here, like stopping the run. 37 if name == "FORTIFY_SOURCE": 38 logger.warning("found -DFORTIFY_SOURCE; you probably meant: -D_FORTIFY_SOURCE")
A "linting" action for common command-line mistakes.
At the moment, this catches mistakes like:
-DFORTIFY_SOURCE=...
instead of-D_FORTIFY_SOURCE=...
For example:
export BLIGHT_WRAPPED_CC=clang
export BLIGHT_ACTIONS="Lint"
make CC=blight-cc
34 def before_run(self, tool: CompilerTool) -> None: # type: ignore 35 for name, _ in tool.defines: 36 # TODO: Maybe do something more drastic here, like stopping the run. 37 if name == "FORTIFY_SOURCE": 38 logger.warning("found -DFORTIFY_SOURCE; you probably meant: -D_FORTIFY_SOURCE")
Invoked right before the underlying tool is run.
Args: tool: The tool about to run
Inherited Members
22class Record(Action): 23 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 24 # TODO(ww): Restructure this dictionary; it should be more like: 25 # { run: {...}, tool: {...}} 26 tool_record = tool.asdict() 27 tool_record["run_skipped"] = run_skipped 28 29 if tool.is_journaling(): 30 self._result = tool_record 31 else: 32 record_file = Path(self._config["output"]) 33 with flock_append(record_file) as io: 34 print(json.dumps(tool_record), file=io)
A generic action, run with every tool (both before and after the tool's execution).
23 def after_run(self, tool: Tool, *, run_skipped: bool = False) -> None: 24 # TODO(ww): Restructure this dictionary; it should be more like: 25 # { run: {...}, tool: {...}} 26 tool_record = tool.asdict() 27 tool_record["run_skipped"] = run_skipped 28 29 if tool.is_journaling(): 30 self._result = tool_record 31 else: 32 record_file = Path(self._config["output"]) 33 with flock_append(record_file) as io: 34 print(json.dumps(tool_record), file=io)
Invoked right after the underlying tool is run.
Args: tool: The tool that just ran
Inherited Members
15class SkipStrip(STRIPAction): 16 # NOTE(ww): type ignore here because mypy thinks this is a Liskov 17 # substitution principle violation -- it can't see that `CompilerAction` 18 # is safely specialized for `CompilerTool`. 19 def before_run(self, tool: STRIP) -> None: # type: ignore 20 raise SkipRun
A strip
action, run whenever the tool is a blight.tool.STRIP
instance.