🔥 【C#】コンパイルが必要な言語はダメらしいので「NativeAOT」について紹介 2024/09/14 に公開 2025/03/03 .NET C# コンパイル ネイティブ NativeAOT tech NativeAOTって? 最近のC#/.NETは結構早い gRPCベンチマークだとマルチコアでトップになることも 「C#は遅くて~」というのは古い情報。情報のアップデートを! </span><a href="https://x.com/Dave_DotNet/status/1673393475507867649" style="" target="_blank" rel="nofollow noopener noreferrer">https://x.com/Dave_DotNet/status/1673393475507867649</a></p> <p data-line="8" class="code-line">早い理由の一つは <strong>NativeAOT</strong></p> <li data-line="9" class="code-line">※他には<code>Span<T></code>やSIMD対応、DynamicPGOとか色々</li> <p data-line="11" class="code-line"><strong>NativeAOT</strong>って?</p> <li data-line="12" class="code-line">ネイティブバイナリ向けに事前(Ahead-Of-Time)コンパイルする仕組み</li> <li data-line="13" class="code-line">「C#はJITコンパイルで~」というのは古い情報。情報のアップデートを!</li> <details><summary>monoと言えば…</summary><div class="details-content"> <p data-line="43" class="code-line">「<a href="https://i.gzn.jp/img/2024/08/28/mono-microsoft-wine/00.png" target="_blank" rel="nofollow noopener noreferrer">Microsoftが「Mono」をWineチームに寄贈、Microsoftの手を離れることでMonoが再び活気を取り戻すと期待する声も - GIGAZINE</a>」というニュースがありましたが、</p> <p data-line="45" class="code-line">Microsoftの手を離れたMono</p> <p data-line="47" class="code-line">というのは誤報で、単に(もう更新がほとんどされなくなった)「<a href="https://github.com/mono/mono" target="_blank" rel="nofollow noopener noreferrer">mono/mono</a>」のリポジトリの管理がWineに移管されるだけ、とのことです。</p> <p data-line="49" class="code-line">mono自体の開発のメインストリームは「<a href="https://github.com/dotnet/runtime/tree/main/src/mono" target="_blank" rel="nofollow noopener noreferrer">dotnet/runtime/mono</a>」にあり、引き続き.NET SDK/ランタイムの中でmonoの開発は進行していくそうです。</p> <p data-line="51" class="code-line">Microsoft maintains a modern fork of Mono runtime in the dotnet/runtime repo and has been progressively moving workloads to that fork. That work is now complete, and we recommend that active Mono users and maintainers of Mono-based app frameworks migrate to .NET which includes work from this fork.<br/> <a href="https://github.com/mono/mono/issues/21796" target="_blank" rel="nofollow noopener noreferrer">https://github.com/mono/mono/issues/21796</a></p> <a class="header-anchor-link" href="#nativeaot" aria-hidden="true"/> NativeAOT</h3> <li data-line="58" class="code-line">Win/macOS/Linuxで使えるAOT</li> <li data-line="59" class="code-line">モバイル・WASMはexperimental <li data-line="60" class="code-line">.NET 9+で<a href="https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ios-like-platforms/" target="_blank" rel="nofollow noopener noreferrer">iOS向けは正式に</a> <li data-line="61" class="code-line">.NET 7.0 SDKから正式に使えるように <li data-line="62" class="code-line">徐々に制限が少なくなったり、機能が増えたりしている</li> <details><summary>参考:Avalonia UIでNativeAOTを使ったモバイル・WASM向け比較実験</summary><div class="details-content"> <p data-line="66" class="code-line"><span class="embed-block zenn-embedded zenn-embedded-tweet"><iframe id="zenn-embedded__f76386a38db4e" src="https://embed.zenn.studio/tweet#zenn-embedded__f76386a38db4e" data-content="https%3A%2F%2Fx.com%2FAvaloniaUI%2Fstatus%2F1808477753856909756" frameborder="0" scrolling="no" loading="lazy"/></span><a href="https://x.com/AvaloniaUI/status/1808477753856909756" style="" target="_blank" rel="nofollow noopener noreferrer">https://x.com/AvaloniaUI/status/1808477753856909756</a></p> <p data-line="68" class="code-line"><span class="embed-block zenn-embedded zenn-embedded-tweet"><iframe id="zenn-embedded__9391a69aeeb7b" src="https://embed.zenn.studio/tweet#zenn-embedded__9391a69aeeb7b" data-content="https%3A%2F%2Fx.com%2FAvaloniaUI%2Fstatus%2F1830836925227552810" frameborder="0" scrolling="no" loading="lazy"/></span><a href="https://x.com/AvaloniaUI/status/1830836925227552810" style="" target="_blank" rel="nofollow noopener noreferrer">https://x.com/AvaloniaUI/status/1830836925227552810</a></p> <a class="header-anchor-link" href="#%E3%81%84%E3%81%84%E3%81%A8%E3%81%93%E3%82%8D%E3%83%BB%E3%82%8F%E3%82%8B%E3%81%84%E3%81%A8%E3%81%93%E3%82%8D" aria-hidden="true"/> いいところ・わるいところ</h2> <p data-line="74" class="code-line">いいところ</p> <li data-line="75" class="code-line">起動時間が早い</li> <li data-line="76" class="code-line">そのまま動く</li> <li data-line="77" class="code-line">サイズも比較的小さい</li> <li data-line="78" class="code-line">ネイティブライブラリも作れる</li> <li data-line="79" class="code-line">難読化になってる</li> <p data-line="81" class="code-line">悪いところ</p> <li data-line="82" class="code-line">モバイル・WASMはまだ試験対応</li> <li data-line="83" class="code-line">クロスコンパイルできない</li> <li data-line="84" class="code-line">使えないコードがある</li> <li data-line="85" class="code-line">ライブラリが対応してないことがまだ多い</li> <li data-line="86" class="code-line">コンパイルが通っても動かないことがある</li> <a class="header-anchor-link" href="#%E3%83%93%E3%83%AB%E3%83%89%E8%A8%AD%E5%AE%9A(csproj)" aria-hidden="true"/> ビルド設定(csproj)</h3> <p data-line="174" class="code-line">NativeAOTを有効にするだけなら<code>PublishAot</code>の設定一つだけで済みますが、実際にはcsproj内で細かく設定を調整していく必要があります。<br/> (特にTrimming設定)</p> <p data-line="177" class="code-line">ノウハウがそんなに多くないので、この辺りの細かい調整をなんども試す必要があります…!!!!</p> <div class="code-block-filename-container"><span class="code-block-filename">csproj PropertyGroup</span></div> <pre class="language-xml"><code class="language-xml code-line" data-line="180"><span class="token comment"><!-- 必須 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>PublishAot</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>PublishAot</span><span class="token punctuation">></span></span> <span class="token comment"><!-- NativeAOT対応と宣言する --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IsAotCompatible</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IsAotCompatible</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 判定だけ有効にするなら --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>EnableTrimAnalyzer</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>EnableTrimAnalyzer</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 速度とサイズどちらを優先にするか(Size/Speed) --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>OptimizationPreference</span><span class="token punctuation">></span></span>Size<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>OptimizationPreference</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 追加のCPU限定命令を有効に出来るオプション --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcInstructionSet</span><span class="token punctuation">></span></span>native<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcInstructionSet</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcMaxVectorTBitWidth</span><span class="token punctuation">></span></span>512<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcMaxVectorTBitWidth</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 次のTrim設定は自動で有効になるので指定不要 --></span> <span class="token comment"><!-- <PublishTrimmed>true</PublishTrimmed> --></span> <span class="token comment"><!-- <EnableTrimAnalyzer>true</EnableTrimAnalyzer> --></span> <span class="token comment"><!-- 同時に有効になるTrimmingの設定(full/partial) --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TrimMode</span><span class="token punctuation">></span></span>partial<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>TrimMode</span><span class="token punctuation">></span></span> <span class="token comment"><!-- .NET8.0以降はこの設定は指定不可 --></span> <span class="token comment"><!-- <TrimMode>copyused</TrimMode> --></span> <span class="token comment"><!-- サイズを小さくする追加設定(以下2つは常に有効でもOK) --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>InvariantGlobalization</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>InvariantGlobalization</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>StripSymbols</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>StripSymbols</span><span class="token punctuation">></span></span> <span class="token comment"><!-- Trimming警告有効 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>SuppressTrimAnalysisWarnings</span><span class="token punctuation">></span></span>false<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>SuppressTrimAnalysisWarnings</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 監視・テレメトリ系ライブラリを使うときはtrue --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>EventSourceSupport</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>EventSourceSupport</span><span class="token punctuation">></span></span> <span class="token comment"><!-- フレームワークによっては必須設定 --></span> <span class="token comment"><!-- 例:Avalonia UI は BuiltInComInteropSupportをtrueにする必要あり --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>BuiltInComInteropSupport</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>BuiltInComInteropSupport</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 例:ASP.NET Core --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>EnableConfigurationBindingGenerator</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>EnableConfigurationBindingGenerator</span><span class="token punctuation">></span></span> <code>PublishAot=true</code>で有効</li> <code>OptimizationPreference</code>で速度orサイズの優先を変えられる <li data-line="225" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/native-aot/optimizing#optimize-for-size-or-speed" target="_blank" rel="nofollow noopener noreferrer">サイズまたは速度を最適化する</a></li> <li data-line="226" class="code-line">CPU限定命令を追加で有効に出来るオプションがある <li data-line="227" class="code-line"><a href="https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/optimizing.md" target="_blank" rel="nofollow noopener noreferrer">Optimizing programs targeting Native AOT</a></li> <code>PublishTrimmed</code>もNativeAOTで自動で有効になる</li> <code>TrimMode</code>はデフォは<code>full</code> <li data-line="230" class="code-line">なのでtrimmingし過ぎで動かない、が良く起きる</li> <code>partial</code>指定して、ちゃんとアセンブリを一つ一つ指定してあげる必要あり</li> <li data-line="232" class="code-line">Trimmingのオプションはたくさんある <li data-line="233" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/trimming-options#trim-framework-library-features" target="_blank" rel="nofollow noopener noreferrer">フレームワーク ライブラリの機能をトリミングする</a></li> <li data-line="234" class="code-line"><strong>フレームワークやライブラリによってはこの追加設定が必須</strong></li> <p data-line="238" class="code-line">NativeAOTで動くようにする、の大きなところはTrimming設定です。</p> <div class="code-block-filename-container"><span class="code-block-filename">csproj</span></div> <pre class="language-xml"><code class="language-xml code-line" data-line="242"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ItemGroup</span><span class="token punctuation">></span></span> <span class="token comment"><!-- TrimMode=partialの時の指定 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TrimmableAssembly</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>【使ってるDLL(アセンブリ)】<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token comment"><!-- ルートアセンブリの指定 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TrimmerRootAssembly</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MyAssembly<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token comment"><!-- xmlで書いて指定することもできる --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TrimmerRootDescriptor</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>./path/to/trd.xml<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ItemGroup</span><span class="token punctuation">></span></span> </div><p data-line="255" class="code-line"><code>TrimmableAssembly</code>で指定すると、その指定されたものが対象になります。<br/> <code>TrimmerRootAssembly</code>で指定すると、そこから繋がってるコードを参照してくれるそうです。</p> <p data-line="258" class="code-line">"ルート" アセンブリとは、トリマーがライブラリ内のすべての呼び出しを分析し、そのアセンブリを起点とするすべてのコード パスを横断することを意味します。</p> <p data-line="260" class="code-line"><code>TrimmerRootDescriptor</code>でxmlで指定すると、メソッドとかプロパティの単位で指定できます。<br/> 動的に呼び出してるような場合は、この方法が必要なよう?です。</p> <div class="code-block-filename-container"><span class="code-block-filename">TrimmerRootDescriptor XML</span></div> <pre class="language-xml"><code class="language-xml code-line" data-line="263"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>linker</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>assembly</span> <span class="token attr-name">fullname</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MyAssembly<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>type</span> <span class="token attr-name">fullname</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MyAssembly.MyClass<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>method</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>DynamicallyAccessedMethod<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>type</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>assembly</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>linker</span><span class="token punctuation">></span></span> </div><details><summary>参考:Rd.xmlについて</summary><div class="details-content"> <p data-line="276" class="code-line">NativeAOT関連で「<code>Rd.xml</code>」についての情報が出てくることがあります。</p> <li data-line="278" class="code-line"><a href="https://qiita.com/skitoy4321/items/4e8960db0c7ddb4fe586" target="_blank" rel="nofollow noopener noreferrer">NativeAOT(元corert)のrd.xmlについて - Qiita</a></li> <li data-line="279" class="code-line"><a href="https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/rd-xml-format.md" target="_blank" rel="nofollow noopener noreferrer">Rd.xml File Format</a></li> <p data-line="281" class="code-line"><code>TrimmerRootDescriptor</code>に似ていますが、<code>TrimmerRootDescriptor</code>で解決できないものも解決できるようになる…そうです。<br/> <strong>ただし、公式にはこれはサポートされていない</strong>ようです。<br/> テンプレートの中で使われていたりもしますが、ちゃんと動くか保証ないので注意です!</p> <li data-line="286" class="code-line"><a href="https://github.com/kant2002/RdXmlLibrary" target="_blank" rel="nofollow noopener noreferrer">https://github.com/kant2002/RdXmlLibrary</a></li> <li data-line="287" class="code-line"><a href="https://github.com/hez2010/EFCore.NativeAOT.RdGenerator" target="_blank" rel="nofollow noopener noreferrer">https://github.com/hez2010/EFCore.NativeAOT.RdGenerator</a></li> <a class="header-anchor-link" href="#%E3%83%91%E3%83%96%E3%83%AA%E3%83%83%E3%82%B7%E3%83%A5" aria-hidden="true"/> パブリッシュ</h3> <p data-line="294" class="code-line">NativeAOTが有効になるにはpublishする必要があります。</p> <div class="code-block-container"><pre class="language-cmd"><code class="language-cmd code-line" data-line="297">dotnet publish -c Release -r <runtime_id_here> <strong>runtime id(RID)の指定は必須</strong> <li data-line="302" class="code-line">指定可能:<a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/native-aot/?tabs=net8plus%2CmacOS#platformarchitecture-restrictions" target="_blank" rel="nofollow noopener noreferrer">Platform/architecture restrictions</a> <li data-line="303" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/rid-catalog" target="_blank" rel="nofollow noopener noreferrer">.NET Runtime Identifier (RID) カタログ - .NET | Microsoft Learn</a></li> <a class="header-anchor-link" href="#%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E5%81%B4%E3%81%AE%E5%AF%BE%E5%BF%9C%EF%BC%88c%23%EF%BC%89" aria-hidden="true"/> ソースコード側の対応(C#)</h3> <p data-line="323" class="code-line">ソース側の対応は、ライブラリの差し替えやソースジェネレータベースの処理に書き換えが中心になります。定番ライブラリもまだダメだったりするので選定は大変です。</p> <p data-line="325" class="code-line">アプリじゃなくてライブラリの場合は、警告対応の属性をあちこちに付ける必要があります。指定漏れがあるとどんどん警告が連鎖するのでとても大変です。</p> <a class="header-anchor-link" href="#%E8%AD%A6%E5%91%8A%E5%AF%BE%E5%BF%9C%E3%81%8C%E5%BF%85%E8%A6%81" aria-hidden="true"/> 警告対応が必要</h4> <li data-line="330" class="code-line">ILxxx っていう警告がでまくる</li> <code>[RequiresUnreferencedCode]</code> / <code>[RequiresDynamicCode]</code>属性 <li data-line="332" class="code-line">NativeAOTに互換性がないところ(メソッド等)に付ける属性</li> <li data-line="333" class="code-line">怒られなくなるだけで<strong>使えるようになるわけじゃない</strong>ので注意</li> <code>[UnconditionalSuppressMessage]</code>属性 <li data-line="335" class="code-line">NativeAOT非対応だけど、呼び出しても問題ない時に付ける属性</li> <li data-line="336" class="code-line">処理が分岐されてて何も起きない、とか</li> <li data-line="337" class="code-line">.NET8.0以前の古いTargetFrameworkに対応するためにPolySharpとかのpolyfillを入れる</li> <a class="header-anchor-link" href="#%E3%83%88%E3%83%AA%E3%83%9F%E3%83%B3%E3%82%B0%E8%AD%A6%E5%91%8A%E5%AF%BE%E5%BF%9C%E3%82%82%E5%BF%85%E8%A6%81" aria-hidden="true"/> トリミング警告対応も必要</h4> <li data-line="341" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/prepare-libraries-for-trimming" target="_blank" rel="nofollow noopener noreferrer">トリミング用に .NET ライブラリを準備する - .NET | Microsoft Learn</a></li> <code>[DynamicallyAccessedMembers]</code>属性</li> <code>[UnconditionalSuppressMessage]</code>属性</li> <code>[DynamicDependency]</code> 属性</li> <li data-line="345" class="code-line">.NET8.0以前の古いTargetFrameworkに対応するためにPolySharpとかのpolyfillを入れる</li> <a class="header-anchor-link" href="#nativeaot%E5%AF%BE%E5%BF%9C%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E4%BD%BF%E3%81%86" aria-hidden="true"/> NativeAOT対応ライブラリを使う</h4> <p data-line="350" class="code-line"><strong>NativeAOT対応ライブラリの見極めは難しい</strong>です。</p> <p data-line="352" class="code-line">ソースジェネレータを使っているかどうか、は一つの基準になりますが、ソースジェネレータを使っていてもNativeAOTに対応していないこともあるので注意が必要です。</p> <a href="https://github.com/CommunityToolkit/dotnet" target="_blank" rel="nofollow noopener noreferrer">CommunityToolkit.MVVM</a> - ver 8.3で対応</li> <a href="https://github.com/Cysharp/ConsoleAppFramework" target="_blank" rel="nofollow noopener noreferrer">ConsoleAppFramework</a> - ver 5で対応</li> <li data-line="357" class="code-line">Dapper -> <a href="https://www.nuget.org/packages/Dapper.AOT" target="_blank" rel="nofollow noopener noreferrer">Dapper.AOT</a> <p data-line="361" class="code-line">ソースジェネレータに対応した.NETライブラリは以下のリストなどがあります。</p> <p data-line="363" class="code-line"><a href="https://github.com/amis92/csharp-source-generators" target="_blank" rel="nofollow noopener noreferrer">https://github.com/amis92/csharp-source-generators</a></p> <a class="header-anchor-link" href="#nativeaot%E5%AF%BE%E5%BF%9C%E3%81%AE%E5%87%A6%E7%90%86%E3%81%AB%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B" aria-hidden="true"/> NativeAOT対応の処理にソースコードを書き換える</h4> <p data-line="370" class="code-line"><code>IsAotCompatible</code>の警告や、<code>SuppressTrimAnalysisWarnings=False</code>の警告、「<a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/native-aot/?tabs=net8plus%2Cwindows#limitations-of-native-aot-deployment" target="_blank" rel="nofollow noopener noreferrer">Limitations of Native AOT deployment</a>」「<a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/incompatibilities" target="_blank" rel="nofollow noopener noreferrer">既知のトリミングの非互換性</a>」の情報をもとにコードを書き換えていきます。</p> <p data-line="372" class="code-line">どうしても対応できない場合は、<strong>諦めることも大事!</strong></p> <p data-line="375" class="code-line"><span class="embed-block zenn-embedded zenn-embedded-card"><iframe id="zenn-embedded__79fa7e3a10d8b" src="https://embed.zenn.studio/card#zenn-embedded__79fa7e3a10d8b" data-content="https%3A%2F%2Flearn.microsoft.com%2Fja-jp%2Fdotnet%2Fcore%2Fdeploying%2Ftrimming%2Fincompatibilities" frameborder="0" scrolling="no" loading="lazy"/></span><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/incompatibilities" style="" target="_blank" rel="nofollow noopener noreferrer">https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/incompatibilities</a></p> <li data-line="377" class="code-line">json処理はSystem.Text.Jsonのソースジェネレータベースの処理に書き換える</li> <li data-line="378" class="code-line">リフレクションは使わないか、SGベースのライブラリを使う処理にする <li data-line="379" class="code-line"><a href="https://github.com/byme8/Apparatus.AOT.Reflection" target="_blank" rel="nofollow noopener noreferrer">Apparatus.AOT.Reflection</a></li> <li data-line="380" class="code-line"><a href="https://github.com/axzxs2001/AOTReflection/blob/main/README_en.md" target="_blank" rel="nofollow noopener noreferrer">AOTReflection</a></li> <li data-line="381" class="code-line"><a href="https://github.com/SourceGeneration/Reflection" target="_blank" rel="nofollow noopener noreferrer">Reflection</a></li> <p data-line="384" class="code-line">リフレクションがすべてNativeAOTに対応していない訳ではないです。</p> <li data-line="387" class="code-line">正規表現は<code>GeneratedRegex</code>にする <li data-line="388" class="code-line">Codefixで自動修正可能</li> <p data-line="391" class="code-line">C#13.0で追加の <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#more-partial-members" target="_blank" rel="nofollow noopener noreferrer">partial property(部分プロパティ)</a> を使うと、プロパティに対してソースジェネレータで処理を追加できるようになります。</p> <div class="code-block-container"><pre class="language-csharp"><code class="language-csharp code-line" data-line="393"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">GeneratedRegex</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">@"\d{4}"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">partial</span> <span class="token return-type class-name">Regex</span> FourDigits <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <li data-line="400" class="code-line"><code>[GeneratedComInterface]</code></li> <li data-line="401" class="code-line">動的なdll読込は避ける <code>[DllImport]</code> -> <code>[LibraryImport]</code> <li data-line="403" class="code-line">.NET9.0では<code>Microsoft.Extensions.DependencyInjection</code>も対応が良くなるらしい</li> <a class="header-anchor-link" href="#nativeaot%E5%AF%BE%E5%BF%9C%E3%82%A2%E3%82%B7%E3%82%B9%E3%83%88%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%83%BB%E3%83%84%E3%83%BC%E3%83%AB%E3%82%82%E4%BD%BF%E3%81%86" aria-hidden="true"/> NativeAOT対応アシストライブラリ・ツールも使う</h4> <p data-line="408" class="code-line">ほとんど試していないので紹介ONLY!!!!</p> <li data-line="411" class="code-line"><a href="https://github.com/MichalStrehovsky/PublishAotCompressed" target="_blank" rel="nofollow noopener noreferrer">PublishAotCompressed</a></li> <li data-line="412" class="code-line"><a href="https://github.com/ionite34/CompiledExpressions" target="_blank" rel="nofollow noopener noreferrer">CompiledExpressions: Create Compiled Delegates from Expressions with nested member support and binding accessibility checking. AOT compatible with no run-time reflection.</a></li> <li data-line="413" class="code-line"><a href="https://github.com/ascpixi/dotnet-ilc" target="_blank" rel="nofollow noopener noreferrer">ascpixi/dotnet-ilc: 🛠 A .NET tool wrapper to manually run ilc - the IL compiler.</a></li> <li data-line="414" class="code-line"><a href="https://github.com/kant2002/winformscominterop" target="_blank" rel="nofollow noopener noreferrer">WinFormsComInterop: ComWrappers required to run NativeAOT and WinForms</a></li> <li data-line="415" class="code-line"><a href="https://www.nuget.org/packages/SourceGear.Bridge.NativeAOT.Rust" target="_blank" rel="nofollow noopener noreferrer">SourceGear.Bridge.NativeAOT.Rust</a></li> <li data-line="416" class="code-line"><a href="https://github.com/MichalStrehovsky/PublishAotCross" target="_blank" rel="nofollow noopener noreferrer">PublishAotCross: NuGet package to help you cross-compile Native AOT to different OSes/architectures</a></li> <a class="header-anchor-link" href="#%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B" aria-hidden="true"/> デバッグできるようにする</h3> <p data-line="421" class="code-line">この辺りはよく分かってないので、参考情報で!</p> <p data-line="424" class="code-line">ふつうの.NETアプリのデバッグだと、NativeAOT対応で動かない理由はわからない</p> <p data-line="425" class="code-line">WinDbg や gdb をつかってネイティブデバッグする必要がある</p> <li data-line="426" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/native-aot/diagnostics#native-debugging" target="_blank" rel="nofollow noopener noreferrer">ネイティブ デバッグ</a></li> <p data-line="428" class="code-line">csprojに追加の設定を加えるとNativeAOTのデバッグが少し色々できるようになる</p> <li data-line="429" class="code-line"><a href="https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/troubleshooting.md" target="_blank" rel="nofollow noopener noreferrer">Troubleshooting NativeAOT compiler</a></li> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcSingleThreaded</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcSingleThreaded</span><span class="token punctuation">></span></span> <span class="token comment"><!-- メタデータ ログの生成 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcGenerateMetadataLog</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcGenerateMetadataLog</span><span class="token punctuation">></span></span> <span class="token comment"><!-- オブジェクトのレイアウトを記述するログ ファイルを生成 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcGenerateMapFile</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcGenerateMapFile</span><span class="token punctuation">></span></span> <span class="token comment"><!-- IL生成のdumpを生成 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcDumpGeneratedIL</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcDumpGeneratedIL</span><span class="token punctuation">></span></span> <span class="token comment"><!-- サイズ情報を含む mstat形式ファイルの生成 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcGenerateMstatFile</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcGenerateMstatFile</span><span class="token punctuation">></span></span> <span class="token comment"><!-- DGML 形式のログの生成 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>IlcGenerateDgmlFile</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>IlcGenerateDgmlFile</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>PropertyGroup</span><span class="token punctuation">></span></span> <li data-line="449" class="code-line">上の情報を元に解析ツールなどでさらに調べられる <a href="https://github.com/hez2010/sizoscopeX" target="_blank" rel="nofollow noopener noreferrer">sizoscopeX</a> :<code>IlcGenerateMstatFile</code>/<code>IlcGenerateDgmlFile</code>のデータからサイズ削減の調査ができるようになる</li> <li data-line="480" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/native-aot/?tabs=net7%2Cwindows" target="_blank" rel="nofollow noopener noreferrer">Native AOT deployment overview - .NET | Microsoft Learn</a></li> <li data-line="481" class="code-line"><a href="https://learn.microsoft.com/ja-jp/dotnet/core/deploying/trimming/trim-self-contained" target="_blank" rel="nofollow noopener noreferrer">自己完結型アプリケーションのトリミング - .NET | Microsoft Learn</a></li> <li data-line="482" class="code-line"><a href="https://github.com/dotnet/runtime/tree/main/src/coreclr/nativeaot/docs" target="_blank" rel="nofollow noopener noreferrer">Using Native AOT</a></li> <li data-line="483" class="code-line"><a href="https://devblogs.microsoft.com/dotnet/creating-aot-compatible-libraries/" target="_blank" rel="nofollow noopener noreferrer">How to make libraries compatible with native AOT - .NET Blog</a></li> <a href="https://github.com/ascpixi/smolsharp/tree/main" target="_blank" rel="nofollow noopener noreferrer">ascpixi/smolsharp: 🐜 Extremely small standalone C# executables using NativeAOT</a> <li data-line="485" class="code-line">いろんな裏技を駆使してめちゃくちゃ小さいサイズを実現するサンプル</li> <li data-line="486" class="code-line"><a href="https://github.com/bflattened/bflat" target="_blank" rel="nofollow noopener noreferrer">bflattened/bflat: C# as you know it but with Go-inspired tooling (small, selfcontained, and native executables)</a></li> <li data-line="487" class="code-line"><a href="https://blog.ndepend.com/net-native-aot-explained/" target="_blank" rel="nofollow noopener noreferrer">.NET Native AOT Explained - NDepend Blog</a></li> <li data-line="488" class="code-line"><a href="https://github.com/microsoft/CsWin32/discussions/1169" target="_blank" rel="nofollow noopener noreferrer">AOT Support? · microsoft/CsWin32 · Discussion #1169</a></li> <li data-line="489" class="code-line"><a href="https://github.com/dotnet/runtime/discussions/95244" target="_blank" rel="nofollow noopener noreferrer">AOT with Reflection · dotnet/runtime · Discussion #95244</a></li> <li data-line="490" class="code-line"><a href="https://bytecodealliance.org/articles/simplifying-components-for-dotnet-developers-with-componentize-dotnet" target="_blank" rel="nofollow noopener noreferrer">componentize-dotnet</a></li>