Skip to content

Add AOT compatibility for net8.0 TFM#197

Merged
BenjaminMichaelis merged 4 commits into
mainfrom
agents/aot-compliance-research-multitool
May 13, 2026
Merged

Add AOT compatibility for net8.0 TFM#197
BenjaminMichaelis merged 4 commits into
mainfrom
agents/aot-compliance-research-multitool

Conversation

@BenjaminMichaelis
Copy link
Copy Markdown
Member

Summary

Makes IntelliTect.Multitool AOT-compatible so that consumers on .NET 8+ can publish with NativeAOT or trimming without warnings originating from this library. Older consumers on netstandard2.1 are unaffected.

Changes

Multi-target netstandard2.1;net8.0

NuGet automatically selects the best matching TFM — net8.0+ consumers get the AOT-annotated assembly; older consumers fall back to netstandard2.1.

IsAotCompatible for net7.0+ TFMs

<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>

Enables the AOT, trim, and single-file analyzers for net8.0 (and any future TFMs added). Uses IsTargetFrameworkCompatible instead of a hardcoded equality check so it automatically applies to net10.0, etc.

Fix non-generic reflection in ReleaseDateAttribute.GetReleaseDate

// Before — non-generic, causes IL2070 trim warning
object[]? attribute = assembly?.GetCustomAttributes(typeof(ReleaseDateAttribute), false);

// After — generic, trimmer can statically resolve the type
return assembly?.GetCustomAttribute<ReleaseDateAttribute>()?.ReleaseDate;

Null guard in RepositoryPaths.GetDefaultRepoRoot

Added && projectPath is not null to guard against the dictionary returning a null value — required for correctness under net8.0's stricter nullable annotations with TreatWarningsAsErrors.

Verification

  • ✅ Build passes with zero warnings across netstandard2.1, net8.0, and net10.0 (test project)
  • TreatWarningsAsErrors=true — all AOT/trim analyzers ran clean
  • ✅ 30/32 tests pass; 2 pre-existing failures are unrelated worktree path tests

- Multi-target netstandard2.1;net8.0 so existing consumers still work
  and net8.0+ consumers get a properly annotated AOT-compatible assembly
- Add IsAotCompatible conditionally for net7.0+ TFMs using
  MSBuild.IsTargetFrameworkCompatible, which also enables the trim and
  AOT Roslyn analyzers for that build slice
- Replace non-generic GetCustomAttributes(typeof(T), false) in
  ReleaseDateAttribute.GetReleaseDate() with the generic
  GetCustomAttribute<ReleaseDateAttribute>() extension — the generic
  overload lets the AOT linker statically resolve the type and removes
  the IL2070/IL2077 trim warning
- Fix pre-existing nullable correctness bug in RepositoryPaths.cs:
  TryGetValue on ReadOnlyDictionary<string, string?> can legitimately
  yield a null value; guard the FileInfo constructor call with an
  explicit null check. This latent bug was invisible under the
  netstandard2.1 build because the BCL lacked full nullable annotations
  there; it became a hard error (CS8604/TreatWarningsAsErrors) once the
  net8.0 TFM was added.
- Fix IsAotCompatible condition floor from net7.0 to net8.0 per MS docs
- Add IntelliTect.Multitool.AotTest console app with PublishAot=true
- Add AOT publish+run CI job (ubuntu-latest, linux-x64)
- Add AotTest project to solution
- Add TreatWarningsAsErrors to AotTest.csproj (ensures AOT analyzer
  warnings are errors, not just warnings, completing C coverage)
- Override aot-test CI job to use bash shell instead of inherited pwsh
- Add aot-test to automerge needs so Dependabot can't bypass AOT CI
- Fix misleading comment: GetCustomAttribute<T> uses AOT-safe reflection
- Add comment explaining RepositoryPaths exclusion from AOT test
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR multi-targets IntelliTect.Multitool for netstandard2.1 and net8.0 and adds AOT/trimming compatibility improvements, along with a CI-published NativeAOT smoke test to ensure the library stays warning-free under AOT tooling.

Changes:

  • Multi-target netstandard2.1;net8.0 and enable IsAotCompatible conditionally for the modern TFM.
  • Replace non-generic reflection usage in ReleaseDateAttribute with GetCustomAttribute<T> to avoid trim/AOT warnings.
  • Add a new IntelliTect.Multitool.AotTest project and CI job to publish/run it with NativeAOT on Linux.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
IntelliTect.Multitool/RepositoryPaths.cs Adds a null guard when reading ProjectPath from build variables.
IntelliTect.Multitool/ReleaseDateAttribute.cs Switches to generic custom-attribute retrieval for trimming/AOT friendliness.
IntelliTect.Multitool/IntelliTect.Multitool.csproj Multi-targets netstandard2.1 + net8.0 and enables IsAotCompatible under a TFM-compat condition.
IntelliTect.Multitool.slnx Includes the new AOT test project in the solution.
IntelliTect.Multitool.AotTest/Program.cs Adds a small runtime verification harness for AOT publishing.
IntelliTect.Multitool.AotTest/IntelliTect.Multitool.AotTest.csproj New AOT publishable console project referencing the library.
.github/workflows/build-and-test.yml Adds an AOT publish/run job and gates automerge on it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread IntelliTect.Multitool/RepositoryPaths.cs Outdated
Comment thread IntelliTect.Multitool/IntelliTect.Multitool.csproj
A trimmed-empty string passes 'is not null' but throws in new FileInfo().
IsNullOrWhiteSpace covers both cases.
@BenjaminMichaelis BenjaminMichaelis merged commit fdac6a8 into main May 13, 2026
5 checks passed
@BenjaminMichaelis BenjaminMichaelis deleted the agents/aot-compliance-research-multitool branch May 13, 2026 07:12
intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request May 13, 2026
Updated
[IntelliTect.Multitool](https://github.com/IntelliTect/Multitool) from
2.0.0 to 2.1.0.

<details>
<summary>Release notes</summary>

_Sourced from [IntelliTect.Multitool's
releases](https://github.com/IntelliTect/Multitool/releases)._

## 2.1.0

## Features

Add AOT compatibility for net8.0 TFM (and later) by @​BenjaminMichaelis
in IntelliTect/Multitool#197

## What's Changed
* chore(deps): bump actions/download-artifact from 7 to 8 by
@​dependabot[bot] in IntelliTect/Multitool#184
* chore(deps): bump actions/upload-artifact from 6 to 7 by
@​dependabot[bot] in IntelliTect/Multitool#183
* Bump Microsoft.Build from 18.3.3 to 18.4.0 by @​dependabot[bot] in
IntelliTect/Multitool#186
* Bump Microsoft.NET.Test.Sdk from 18.0.1 to 18.3.0 by @​dependabot[bot]
in IntelliTect/Multitool#185
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.103 to 10.0.201 by
@​dependabot[bot] in IntelliTect/Multitool#187
* Bump Microsoft.SourceLink.GitHub from 10.0.103 to 10.0.201 by
@​dependabot[bot] in IntelliTect/Multitool#188
* chore(deps): bump fastify/github-action-merge-dependabot from 3.11.2
to 3.12.0 by @​dependabot[bot] in
IntelliTect/Multitool#189
* Bump Microsoft.NET.Test.Sdk from 18.3.0 to 18.4.0 by @​dependabot[bot]
in IntelliTect/Multitool#191
* chore(deps): bump softprops/action-gh-release from 2 to 3 by
@​dependabot[bot] in IntelliTect/Multitool#190
* Bump Microsoft.SourceLink.GitHub from 10.0.201 to 10.0.202 by
@​dependabot[bot] in IntelliTect/Multitool#193
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.201 to 10.0.202 by
@​dependabot[bot] in IntelliTect/Multitool#192
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.202 to 10.0.203 by
@​dependabot[bot] in IntelliTect/Multitool#194
* Bump Microsoft.SourceLink.GitHub from 10.0.202 to 10.0.203 by
@​dependabot[bot] in IntelliTect/Multitool#195
* Bump Microsoft.NET.Test.Sdk from 18.4.0 to 18.5.1 by @​dependabot[bot]
in IntelliTect/Multitool#196
* Add AOT compatibility for net8.0 TFM by @​BenjaminMichaelis in
IntelliTect/Multitool#197


**Full Changelog**:
IntelliTect/Multitool@v2.0.0...v2.1.0

## What's Changed
* chore(deps): bump actions/download-artifact from 7 to 8 by
@​dependabot[bot] in IntelliTect/Multitool#184
* chore(deps): bump actions/upload-artifact from 6 to 7 by
@​dependabot[bot] in IntelliTect/Multitool#183
* Bump Microsoft.Build from 18.3.3 to 18.4.0 by @​dependabot[bot] in
IntelliTect/Multitool#186
* Bump Microsoft.NET.Test.Sdk from 18.0.1 to 18.3.0 by @​dependabot[bot]
in IntelliTect/Multitool#185
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.103 to 10.0.201 by
@​dependabot[bot] in IntelliTect/Multitool#187
* Bump Microsoft.SourceLink.GitHub from 10.0.103 to 10.0.201 by
@​dependabot[bot] in IntelliTect/Multitool#188
* chore(deps): bump fastify/github-action-merge-dependabot from 3.11.2
to 3.12.0 by @​dependabot[bot] in
IntelliTect/Multitool#189
* Bump Microsoft.NET.Test.Sdk from 18.3.0 to 18.4.0 by @​dependabot[bot]
in IntelliTect/Multitool#191
* chore(deps): bump softprops/action-gh-release from 2 to 3 by
@​dependabot[bot] in IntelliTect/Multitool#190
* Bump Microsoft.SourceLink.GitHub from 10.0.201 to 10.0.202 by
@​dependabot[bot] in IntelliTect/Multitool#193
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.201 to 10.0.202 by
@​dependabot[bot] in IntelliTect/Multitool#192
* Bump Microsoft.CodeAnalysis.NetAnalyzers from 10.0.202 to 10.0.203 by
@​dependabot[bot] in IntelliTect/Multitool#194
* Bump Microsoft.SourceLink.GitHub from 10.0.202 to 10.0.203 by
@​dependabot[bot] in IntelliTect/Multitool#195
* Bump Microsoft.NET.Test.Sdk from 18.4.0 to 18.5.1 by @​dependabot[bot]
in IntelliTect/Multitool#196
* Add AOT compatibility for net8.0 TFM by @​BenjaminMichaelis in
IntelliTect/Multitool#197


**Full Changelog**:
IntelliTect/Multitool@v2.0.0...v2.1.0

Commits viewable in [compare
view](IntelliTect/Multitool@v2.0.0...v2.1.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=IntelliTect.Multitool&package-manager=nuget&previous-version=2.0.0&new-version=2.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@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.

2 participants