Skip to content

[Build] Skip XamlC when no XAML files need XamlC processing#34972

Draft
davidnguyen-tech wants to merge 5 commits intodotnet:net11.0from
davidnguyen-tech:feature/xamlc-skip-empty-sg-xc
Draft

[Build] Skip XamlC when no XAML files need XamlC processing#34972
davidnguyen-tech wants to merge 5 commits intodotnet:net11.0from
davidnguyen-tech:feature/xamlc-skip-empty-sg-xc

Conversation

@davidnguyen-tech
Copy link
Copy Markdown
Member

Summary

Skip the XamlC MSBuild target when both _MauiXaml_SG and _MauiXaml_XC item groups are empty — meaning no XAML files use the SourceGen or XamlC inflator.

Motivation

In Debug builds, XamlC runs in ValidateOnly=True mode, loading the compiled assembly via Cecil, parsing all XAML, validating it, then discarding the result. When all XAML files use the SourceGen inflator (the default), this validation is redundant because the Source Generator already validates XAML at compile time.

Changes

  • Microsoft.Maui.Controls.targets: Added AND ('@(_MauiXaml_SG)' != '' OR '@(_MauiXaml_XC)' != '') to the XamlC target condition
  • MSBuildTests.cs: Added two tests:
    • XamlCSkippedWhenRuntimeInflatorOnly — verifies XamlC is skipped when all XAML uses Runtime inflator
    • XamlCRunsWhenXamlCInflatorUsed — verifies XamlC still runs when XamlC inflator is used

Target Ordering

_MauiXamlComputeInflator (which populates _MauiXaml_SG/_MauiXaml_XC) runs before Compile via PrepareResourcesDependsOn. XamlC runs AfterTargets="AfterCompile", so MSBuild evaluates XamlC's condition after the item groups are fully populated.

Impact

This primarily benefits builds where all XAML uses the Runtime inflator (deprecated path). The default SourceGen path still runs XamlC for validation. A follow-up optimization could skip XamlC's validate-only pass for SourceGen files, since SourceGen already self-validates.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34972

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34972"

@davidnguyen-tech davidnguyen-tech changed the base branch from main to net11.0 April 15, 2026 09:47
@davidnguyen-tech davidnguyen-tech force-pushed the feature/xamlc-skip-empty-sg-xc branch 3 times, most recently from b38cbcf to 00912c6 Compare April 21, 2026 11:13
@davidnguyen-tech davidnguyen-tech force-pushed the feature/xamlc-skip-empty-sg-xc branch 3 times, most recently from b1aff52 to 28daf7d Compare April 22, 2026 11:45
XamlC's validate-only pass (Debug default) is the only build-time
XAML validation for files using the Runtime or XamlC inflators.
SourceGen-only files are validated by XSG itself, so XamlC is
redundant for them.

Gate the XamlC target on '@(_MauiXaml_XC)' != '' OR '@(_MauiXaml_RT)' != ''
(equivalent to '@(_MauiXaml_AsEmbeddedResource)' != ''). Projects
using SourceGen exclusively — the default in net11.0 — now skip
XamlC entirely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@davidnguyen-tech davidnguyen-tech force-pushed the feature/xamlc-skip-empty-sg-xc branch from 28daf7d to 921a0c2 Compare April 22, 2026 13:35
davidnguyen-tech and others added 4 commits April 22, 2026 18:13
Tests that don't care about XamlC now lock in the SourceGen default:
they assert the build still succeeds and XamlC.stamp is absent.

Tests whose subject is the XamlC target itself (incrementality,
Clean, DesignTimeBuild contrast, AddNewFile) opt in via
-p:MauiXamlInflator=XamlC -p:NoWarn=MAUI1001 so the existing contract
is verifiable. Plan originally called for the SourceGen,XamlC combo,
but for these synthesised projects the source generator emits a
duplicate InitializeComponent (CS0111) when both inflators are
active, so the bare XamlC form with NoWarn=MAUI1001 is used instead
to silence the deprecation warning under the repo-wide
TreatWarningsAsErrors setting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract XamlC opt-in args + rationale to a single const so the
'why bare XamlC, not SourceGen,XamlC' explanation lives in one
place. Apply the same opt-in to TouchXamlFile's body for
future-proofing. Reword the misleading inline comment on the
DesignTimeBuild precondition.

Note: the prior commit message's TreatWarningsAsErrors rationale
for NoWarn=MAUI1001 is slightly inaccurate — the synthesized
projects under tempDirectory write a fresh Directory.Build.props
that does not chain in the repo-root TWAE setting. NoWarn is
kept anyway for noise reduction and to be robust if the chain
ever changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The XamlC target is gated to SourceGen-default-empty projects in
this PR's targets change. Tests that simulated XamlC running on the
synthesised single-project scaffold (TargetsShouldSkip, Clean,
DesignTimeBuild, AddNewFile, TouchXamlFile) were exercising a code
path that no longer executes by default. Delete them along with the
XamlCOptIn constant. The contract that XamlC does not run by default
is already locked in by BuildAProject, LinkedFile, RandomXml,
RandomEmbeddedResource (AssertDoesNotExist on XamlC.stamp), and by
NoXamlFiles (log-scrape that the target isn't scheduled).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the single-line header comment with a block that makes explicit the contract the surviving tests protect: SourceGen is the net11.0 default and the XamlC target must not run on default builds. Addresses reviewer feedback on dotnet#34972 that future contributors had no in-file guidance that these are negative tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant