Commit b8875f9
authored
BaseTools/Trim.py: Strip "#pragma once" from inlined ASL content (#1840)
## Description
The pragma once changes in edk2 were not made until the end of February
and are first released in the
[edk2-stable202605](https://github.com/tianocore/edk2/releases/tag/edk2-stable202605)
tag. However, some Mu platforms have moved ahead with pragma once
changes in code outside of Mu. The main issue reported with doing so is
compiling ASL where some of the header files in subprojects are using
pragma once.
This PR introduces the change to Mu first so the platforms that need
this support now can have it and confirm the change with their platform
build. There is not impact to existing use cases that do not use pragma
once in header files included in ASL builds.
Note: If a broader move to pragma once is needed before the 202605
stable tag is released in Mu, that needs to be requested in a GitHub
issue and will require additional changes.
---
Note: I've made this description verbose because (1) I'm not sure
everyone is familiar with the details and nuances of this flow and (2) I
tried to balance a simple solution versus practical concerns and I want
that to be obvious for feedback on the approach. TLDR is this addresses
a potential warning in some C preprocessors if `#pragma once` is used in
header files included in certain ways in ASL source files.
---
When `Trim` processes an ASL file (`--asl-file`), it textually inlines
the body of every `Include()`'d file directly into the constructed
preprocessor input, once per include site.
Its has duplicate protection in the form of a circular-include stack
(`gIncludedAslFile`), that prevents A->B->A cycles. But, as far as the
script is concerned, each `Include()` is a unique include site.
Various combinations of includes and file types are possible and handled
slightly differently.
Starting with file types as defined in
BaseTools\Conf\build_rule.template:
- `.aslc`, `.act` files fall under `Acpi-Table-Code-File` and are
compiled, linked, and processed by `genfw`.
- `.asl`, `.Asl`, and `.ASL` files fall in `Acpi-Source-Language-File`
and are processed by `Trim`:
1. `Trim --asl-file` to produce a single combined .i file with includes
inlined.
2. `ASLPP` (ASL preprocessor, a C preprocessor) on the output of `Trim`
to produce a .iii file with all macros expanded and conditional branches
resolved. AutoGen.h is also included and processed here to resolve fixed
PCD values if needed.
3. `Trim --source-code` which takes the pre-processed .iii file and
produces a .iiii file with content like linemarkers cleaned up.
4. The ACPI compiler compiles the .iiii file to produce AML bytecode in
a .aml file.
Because the `.aslc`/`.act` files are directly passed to normal C
processing tools, they are not part of the `Trim` change made in this
commit and the remainder of this message focuses on the ACPI Source
Language File case.
ASL files can use either an ASL `Include()` directive or a C-style
`#include` directive. In addition, different file types may be included
such as a `.asl` file or a `.h` file.
`Trim` handles these cases differently:
- For ASL `Include()` directives, `Trim` inlines the content of the
included file directly into the output at the include site. This is done
for all included ASL files regardless of their extension. The inlining
is purely textual and does not attempt to resolve or preserve any
preprocessor directives such as `#pragma once` or include guards.
- For C-style `#include` directives, `Trim` checks the file extension of
the included file. If the file is an ASL file (`.asl` or `.asi`), `Trim`
treats the file the same as the `Include()` case. Otherwise, `Trim`
passes the directive through verbatim to the output, allowing the
downstream C preprocessor (`ASLPP`) to handle it according to normal C
preprocessor rules.
This creates a situtation in which the resulting `.i` might include:
- Inlined file content (from a `.asl` or `.h` file) depending on the
include type and file extension.
- Verbatim `#include` directives for non-ASL files which will be
processed by the C preprocessor.
Focusing on the "inlined" case, historically `.h` files would have
traditional C include guards (`#ifndef`/`#define`, `#endif`). However,
files might also include `#pragma once` as a guard.
In that case, the inlined content of the `.i` file could contain
multiple `#pragma once` directives, one per include site. When the C
preprocessor (`ASLPP`) processes the `.i` file, it sees multiple
`#pragma once` directives in what it considers the main file, and could
emit a warning like the following from gcc:
> warning: '#pragma once' in main file [-Wpragma-once-outside-header]
The remainder of this commit message describes the change made to
address this warning.
This change strips "#pragma once" lines on the ASL content path in
`DoInclude()` in `Trim.py` so the directive is removed before it reaches
the C preprocessor.
- "#include" directives for non-ASL files are still passed through
verbatim for the C preprocessor to resolve where the contents of those
.h files might contain "#pragma once" or traditional guards.
- Traditional include guards are untouched and continue to behave as
before where multiple include sites might inline the same content in the
.i file before reaching the C preprocessor.
The change:
In the case that a file is inlined with a `#pragma once` directive, the
directive is stripped from the inlined content which prevents the
warning.
This is considered acceptable because it only removes the `#pragma once`
directive from the inlined content for these specific cases. So, the
`.i` file might contain multiple inlined copies of the same header
content (like always in this inline case) but without the `#pragma once`
directives. Because actual C content was already not processed or
trimmed out (e.g. `typedef struct`) duplicate content that could cause
multiple symbol definitions is not considered to be a problem (`#define`
multiple times is not a problem for the C preprocessor).
---
- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?
## How This Was Tested
- edk2/Mu CI
- Platform build with no pragma once in header files
- Look at the output (`.i`, `.iii` files, etc.) of Trim.py and C
preprocessor output with gcc and MSVC linkers.
- Test against platforms using complex variations of include types
including the inlining case with `#pragma once` in .h files.
## Integration Instructions
- N/A
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>1 parent f11f110 commit b8875f9
1 file changed
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
57 | 61 | | |
58 | 62 | | |
59 | 63 | | |
| |||
322 | 326 | | |
323 | 327 | | |
324 | 328 | | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
325 | 333 | | |
326 | 334 | | |
327 | 335 | | |
| |||
0 commit comments