Skip to content

BaseTools/Trim.py: Strip "#pragma once" from inlined ASL content#1840

Merged
makubacki merged 1 commit into
microsoft:release/202511from
makubacki:trim_pragma_once_update
Jun 30, 2026
Merged

BaseTools/Trim.py: Strip "#pragma once" from inlined ASL content#1840
makubacki merged 1 commit into
microsoft:release/202511from
makubacki:trim_pragma_once_update

Conversation

@makubacki

Copy link
Copy Markdown
Member

Description

The pragma once changes in edk2 were not made until the end of February and are first released in the 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.

A change was upstreamed to edk2 for this that is in review (PR 12667). The change there has been tested against several likely scenarios.

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.


Original PR Description From the edk2 PR

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

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 is
not considered to be a problem (`#define` multiple times is not a
problem for the C preprocessor).

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
@makubacki makubacki requested review from apop5, kuqin12 and os-d June 30, 2026 15:24
@makubacki makubacki self-assigned this Jun 30, 2026
@mu-automation

mu-automation Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

✅ QEMU Validation Passed

Source Dependencies

Repository Commit
mu_basecore 11c90cc
mu_tiano_platforms a3f899f

Results

Platform Target Build Boot Overall Boot Time Build Logs Boot Logs
Q35 DEBUG ✅ success ✅ success 0m 20s Build Logs Boot Logs
ArmVirt DEBUG ✅ success ✅ success 0m 15s Build Logs Boot Logs

Workflow run: https://github.com/microsoft/mu_basecore/actions/runs/28456259777

This comment was automatically generated by the Mu QEMU PR Validation workflow.

@codecov-commenter

codecov-commenter commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (release/202511@f11f110). Learn more about missing BASE report.

Additional details and impacted files
@@                Coverage Diff                @@
##             release/202511    #1840   +/-   ##
=================================================
  Coverage                  ?    2.25%           
=================================================
  Files                     ?     1640           
  Lines                     ?   421475           
  Branches                  ?     5048           
=================================================
  Hits                      ?     9501           
  Misses                    ?   411890           
  Partials                  ?       84           
Flag Coverage Δ
FmpDevicePkg 9.53% <ø> (?)
MdeModulePkg 1.65% <ø> (?)
MdePkg 5.44% <ø> (?)
NetworkPkg 0.55% <ø> (?)
PolicyServicePkg 30.42% <ø> (?)
SecurityPkg 1.56% <ø> (?)
UefiCpuPkg 4.78% <ø> (?)
UnitTestFrameworkPkg 11.70% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@makubacki makubacki merged commit b8875f9 into microsoft:release/202511 Jun 30, 2026
101 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants