Browse Source

Add AOT flag to worker template (#47721)

* Add AOT flag to worker template

Fix #46541

* Update Worker template tests for NativeAOT.

Fix Api template tests for NativeAOT to pass locally.
Eric Erhardt 2 years ago
parent
commit
cd711c22f4
42 changed files with 190 additions and 26 deletions
  1. 1 7
      src/ProjectTemplates/Shared/AspNetProcess.cs
  2. 46 8
      src/ProjectTemplates/Shared/Project.cs
  3. 1 1
      src/ProjectTemplates/TestInfrastructure/Directory.Build.targets.in
  4. 4 0
      src/ProjectTemplates/Web.ProjectTemplates/Worker-CSharp.csproj.in
  5. 4 0
      src/ProjectTemplates/Web.ProjectTemplates/Worker-FSharp.fsproj.in
  6. 4 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/dotnetcli.host.json
  7. 4 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/ide.host.json
  8. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.cs.json
  9. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.de.json
  10. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.en.json
  11. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.es.json
  12. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.fr.json
  13. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.it.json
  14. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ja.json
  15. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ko.json
  16. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.pl.json
  17. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.pt-BR.json
  18. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ru.json
  19. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.tr.json
  20. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.zh-Hans.json
  21. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.zh-Hant.json
  22. 7 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/template.json
  23. 4 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/dotnetcli.host.json
  24. 7 1
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/ide.host.json
  25. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.cs.json
  26. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.de.json
  27. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.en.json
  28. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.es.json
  29. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.fr.json
  30. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.it.json
  31. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ja.json
  32. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ko.json
  33. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.pl.json
  34. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.pt-BR.json
  35. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ru.json
  36. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.tr.json
  37. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.zh-Hans.json
  38. 2 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.zh-Hant.json
  39. 7 0
      src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/template.json
  40. 12 0
      src/ProjectTemplates/scripts/Run-WorkerNativeAot-Locally.ps1
  41. 9 4
      src/ProjectTemplates/test/Templates.Tests/ApiTemplateTest.cs
  42. 24 5
      src/ProjectTemplates/test/Templates.Tests/WorkerTemplateTest.cs

+ 1 - 7
src/ProjectTemplates/Shared/AspNetProcess.cs

@@ -1,15 +1,10 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System;
-using System.Collections.Generic;
 using System.Diagnostics;
-using System.IO;
-using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Net.Security;
-using System.Threading.Tasks;
 using AngleSharp.Dom.Html;
 using AngleSharp.Parser.Html;
 using Microsoft.AspNetCore.Internal;
@@ -18,7 +13,6 @@ using Microsoft.Extensions.CommandLineUtils;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging.Abstractions;
 using Microsoft.Playwright;
-using Xunit;
 using Xunit.Abstractions;
 
 namespace Templates.Test.Helpers;
@@ -66,7 +60,7 @@ public class AspNetProcess : IDisposable
         {
             if (usePublishedAppHost)
             {
-                // When publishingu used the app host to run the app. This makes it easy to consistently run for regular and single-file publish
+                // When publishing, use the app host to run the app. This makes it easy to consistently run for regular and single-file publish
                 process = Path.ChangeExtension(dllPath, OperatingSystem.IsWindows() ? ".exe" : null);
                 arguments = null;
             }

+ 46 - 8
src/ProjectTemplates/Shared/Project.cs

@@ -1,23 +1,16 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System;
-using System.Collections.Generic;
 using System.Diagnostics;
-using System.IO;
-using System.Linq;
 using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
 using Microsoft.AspNetCore.Internal;
 using Microsoft.AspNetCore.Testing;
 using Microsoft.Extensions.CommandLineUtils;
 using Microsoft.Extensions.Logging;
-using Xunit;
 using Xunit.Abstractions;
 using Xunit.Sdk;
-using static Templates.Test.Helpers.ProcessLock;
 
 namespace Templates.Test.Helpers;
 
@@ -363,6 +356,51 @@ public class Project : IDisposable
         Assert.Contains($"<{propertyName}>{expectedValue}</{propertyName}>", projectFileContents);
     }
 
+    public void SetCurrentRuntimeIdentifier()
+    {
+        RuntimeIdentifier = GetRuntimeIdentifier();
+
+        static string GetRuntimeIdentifier()
+        {
+            // we need to use the "portable" RID (win-x64), not the actual RID (win10-x64)
+            return $"{GetOS()}-{GetArchitecture()}";
+        }
+
+        static string GetOS()
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                return "win";
+            }
+            if (OperatingSystem.IsLinux())
+            {
+                return "linux";
+            }
+            if (OperatingSystem.IsMacOS())
+            {
+                return "osx";
+            }
+            throw new NotSupportedException();
+        }
+
+        static string GetArchitecture()
+        {
+            switch (RuntimeInformation.ProcessArchitecture)
+            {
+                case Architecture.X86:
+                    return "x86";
+                case Architecture.X64:
+                    return "x64";
+                case Architecture.Arm:
+                    return "arm";
+                case Architecture.Arm64:
+                    return "arm64";
+                default:
+                    throw new NotSupportedException();
+            }
+        }
+    }
+
     public string ReadFile(string path)
     {
         AssertFileExists(path, shouldExist: true);

+ 1 - 1
src/ProjectTemplates/TestInfrastructure/Directory.Build.targets.in

@@ -4,6 +4,6 @@
   <PropertyGroup>
     <RestoreAdditionalProjectSources>${RestoreAdditionalProjectSources}</RestoreAdditionalProjectSources>
     <!-- This sets an option which prevents the tests from rolling forward into a newer shared framework. -->
-    <UserRuntimeConfig>$(MSBuildThisFileDirectory)runtimeconfig.norollforward.json</UserRuntimeConfig>
+    <UserRuntimeConfig Condition="'$(PublishAot)' != 'true'">$(MSBuildThisFileDirectory)runtimeconfig.norollforward.json</UserRuntimeConfig>
   </PropertyGroup>
 </Project>

+ 4 - 0
src/ProjectTemplates/Web.ProjectTemplates/Worker-CSharp.csproj.in

@@ -5,6 +5,10 @@
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
     <InvariantGlobalization>true</InvariantGlobalization>
+    <!--#if (NativeAot) -->
+    <PublishAot>true</PublishAot>
+    <StripSymbols>true</StripSymbols>
+    <!--#endif -->
     <UserSecretsId>dotnet-Company.Application1-53bc9b9d-9d6a-45d4-8429-2a2761773502</UserSecretsId>
     <NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
     <RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.Application1</RootNamespace>

+ 4 - 0
src/ProjectTemplates/Web.ProjectTemplates/Worker-FSharp.fsproj.in

@@ -4,6 +4,10 @@
     <TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
     <UserSecretsId>dotnet-Company.Application1-53bc9b9d-9d6a-45d4-8429-2a2761773502</UserSecretsId>
     <InvariantGlobalization>true</InvariantGlobalization>
+    <!--#if (NativeAot) -->
+    <PublishAot>true</PublishAot>
+    <StripSymbols>true</StripSymbols>
+    <!--#endif -->
     <NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
     <RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.Application1</RootNamespace>
   </PropertyGroup>

+ 4 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/dotnetcli.host.json

@@ -15,6 +15,10 @@
     "UseProgramMain": {
       "longName": "use-program-main",
       "shortName": ""
+    },
+    "NativeAot": {
+      "longName": "publish-native-aot",
+      "shortName": "aot"
     }
   },
   "usageExamples": [

+ 4 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/ide.host.json

@@ -9,6 +9,10 @@
       "isVisible": true,
       "persistenceScope": "shared",
       "persistenceScopeName": "Microsoft"
+    },
+    {
+      "id": "NativeAot",
+      "isVisible": true
     }
   ]
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.cs.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Pokud se tato možnost zadá, přeskočí automatické obnovení projektu při vytvoření.",
   "symbols/UseProgramMain/displayName": "Nepoužívat _příkazy nejvyšší úrovně",
   "symbols/UseProgramMain/description": "Určuje, jestli se má místo příkazů nejvyšší úrovně generovat explicitní třída Program a metoda Main.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Obnoví balíčky NuGet vyžadované tímto projektem.",
   "postActions/restore/manualInstructions/default/text": "Spustit dotnet restore"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.de.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Wenn angegeben, wird die automatische Wiederherstellung des Projekts beim Erstellen übersprungen.",
   "symbols/UseProgramMain/displayName": "Keine Anweisungen_der obersten Ebene verwenden",
   "symbols/UseProgramMain/description": "Gibt an, ob anstelle von Anweisungen der obersten Ebene eine explizite Programmklasse und eine Main-Methode generiert werden soll.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "„NuGet-Pakete“ wiederherstellen, die für dieses Projekt erforderlich sind.",
   "postActions/restore/manualInstructions/default/text": "„dotnet restore“ ausführen"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.en.json

@@ -10,6 +10,8 @@
   "symbols/UseProgramMain/displayName": "Do not use _top-level statements",
   "_symbols/UseProgramMain/displayName.comment": "Use '_' as accelerator key when translating.",
   "symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restore NuGet packages required by this project.",
   "postActions/restore/manualInstructions/default/text": "Run 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.es.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Si se especifica, se omite la restauración automática del proyecto durante la creación.",
   "symbols/UseProgramMain/displayName": "No usar instrucciones de _nivel superior",
   "symbols/UseProgramMain/description": "Indica si se debe generar una clase Program explícita y un método Main en lugar de instrucciones de nivel superior.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaure los paquetes NuGet necesarios para este proyecto.",
   "postActions/restore/manualInstructions/default/text": "Ejecutar \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.fr.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "S’il est spécifié, ignore la restauration automatique du projet lors de la création.",
   "symbols/UseProgramMain/displayName": "N’utilisez pas _d’instructions de niveau supérieur.",
   "symbols/UseProgramMain/description": "Indique s’il faut générer une classe Programme explicite et une méthode Main au lieu d’instructions de niveau supérieur.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaurez les packages NuGet requis par ce projet.",
   "postActions/restore/manualInstructions/default/text": "Exécuter « dotnet restore »"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.it.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Se specificato, ignora il ripristino automatico del progetto durante la creazione.",
   "symbols/UseProgramMain/displayName": "Non usare_istruzioni di primo livello",
   "symbols/UseProgramMain/description": "Indica se generare una classe Program esplicita e un metodo Main anziché istruzioni di primo livello.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Ripristina i pacchetti NuGet richiesti da questo progetto.",
   "postActions/restore/manualInstructions/default/text": "Esegui 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ja.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "指定した場合、作成時にプロジェクトの自動復元がスキップされます。",
   "symbols/UseProgramMain/displayName": "最上位レベルのステートメントを使用しない(_T)",
   "symbols/UseProgramMain/description": "最上位レベルのステートメントではなく、明示的な Program クラスと Main メソッドを生成するかどうか。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "このプロジェクトに必要な NuGet パッケージを復元します。",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' を実行する"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ko.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "지정된 경우, 프로젝트 생성 시 자동 복원을 건너뜁니다.",
   "symbols/UseProgramMain/displayName": "최상위 문 사용 안 함(_T)",
   "symbols/UseProgramMain/description": "최상위 문 대신 명시적 Program 클래스 및 Main 메서드를 생성할지 여부입니다.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "이 프로젝트에 필요한 NuGet 패키지를 복원합니다.",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' 실행"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.pl.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Jeśli ta opcja jest określona, pomija automatyczne przywracanie projektu podczas tworzenia.",
   "symbols/UseProgramMain/displayName": "Nie używaj ins_trukcji najwyższego poziomu",
   "symbols/UseProgramMain/description": "Określa, czy wygenerować jawną klasę Program i metodę Main zamiast instrukcji najwyższego poziomu.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Przywróć pakiety NuGet wymagane przez ten projekt.",
   "postActions/restore/manualInstructions/default/text": "Uruchom polecenie \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.pt-BR.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Se especificado, ignora a restauração automática do projeto sendo criado.",
   "symbols/UseProgramMain/displayName": "Não use ins_truções de nível superior",
   "symbols/UseProgramMain/description": "Se deve gerar uma classe de Programa explícita e um método principal em vez de instruções de nível superior.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaure os pacotes NuGet exigidos por este projeto.",
   "postActions/restore/manualInstructions/default/text": "Executar 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.ru.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Если установлено, автоматическое восстановление проекта при создании пропускается.",
   "symbols/UseProgramMain/displayName": "Не использовать _операторы верхнего уровня",
   "symbols/UseProgramMain/description": "Следует ли создавать явный класс Program и метод Main вместо операторов верхнего уровня.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Восстановление пакетов NuGet, необходимых для этого проекта.",
   "postActions/restore/manualInstructions/default/text": "Выполнить команду \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.tr.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "Belirtilirse, oluşturma sırasında projenin otomatik geri yüklenmesini atlar.",
   "symbols/UseProgramMain/displayName": "_Üst düzey deyimler kullanmayın",
   "symbols/UseProgramMain/description": "Üst düzey deyimler yerine açık bir Program sınıfı ve Ana yöntem oluşturup oluşturulmayacağını belirtir.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Bu projenin gerektirdiği NuGet paketlerini geri yükleyin.",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' çalıştır"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.zh-Hans.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "如果指定,则在创建时跳过项目的自动还原。",
   "symbols/UseProgramMain/displayName": "不使用顶级语句(_T)",
   "symbols/UseProgramMain/description": "是否生成显式程序类和主方法,而不是顶级语句。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "还原此项目所需的 NuGet 包。",
   "postActions/restore/manualInstructions/default/text": "运行 \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/localize/templatestrings.zh-Hant.json

@@ -8,6 +8,8 @@
   "symbols/skipRestore/description": "若指定,會在建立時跳過專案的自動還原。",
   "symbols/UseProgramMain/displayName": "不要使用最上層陳述式(_T)",
   "symbols/UseProgramMain/description": "是否要產生明確的 Program 類別和 Main 方法,而非最上層語句。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "還原此專案所需的 NuGet 套件。",
   "postActions/restore/manualInstructions/default/text": "執行 'dotnet restore'"
 }

+ 7 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/template.json

@@ -89,6 +89,13 @@
       "defaultValue": "false",
       "displayName": "Do not use _top-level statements",
       "description": "Whether to generate an explicit Program class and Main method instead of top-level statements."
+    },
+    "NativeAot" : {
+      "type": "parameter",
+      "datatype": "bool",
+      "defaultValue": "false",
+      "displayName": "Enable _native AOT publish",
+      "description": "Whether to enable the project for publishing as native AOT."
     }
   },
   "primaryOutputs": [

+ 4 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/dotnetcli.host.json

@@ -11,6 +11,10 @@
     "ExcludeLaunchSettings": {
       "longName": "exclude-launch-settings",
       "shortName": ""
+    },
+    "NativeAot": {
+      "longName": "publish-native-aot",
+      "shortName": "aot"
     }
   },
   "usageExamples": [

+ 7 - 1
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/ide.host.json

@@ -2,5 +2,11 @@
   "$schema": "http://json.schemastore.org/ide.host",
   "order": 300,
   "icon": "ide/Worker.png",
-  "supportsDocker": true
+  "supportsDocker": true,
+  "symbolInfo": [
+    {
+      "id": "NativeAot",
+      "isVisible": true
+    }
+  ]
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.cs.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Cílová architektura pro projekt",
   "symbols/Framework/choices/net8.0/description": "Cílový net8.0",
   "symbols/skipRestore/description": "Pokud se tato možnost zadá, přeskočí automatické obnovení projektu při vytvoření.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Obnoví balíčky NuGet vyžadované tímto projektem.",
   "postActions/restore/manualInstructions/default/text": "Spustit dotnet restore"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.de.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Das Zielframework für das Projekt.",
   "symbols/Framework/choices/net8.0/description": "Ziel net8.0",
   "symbols/skipRestore/description": "Wenn angegeben, wird die automatische Wiederherstellung des Projekts beim Erstellen übersprungen.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "„NuGet-Pakete“ wiederherstellen, die für dieses Projekt erforderlich sind.",
   "postActions/restore/manualInstructions/default/text": "„dotnet restore“ ausführen"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.en.json

@@ -7,6 +7,8 @@
   "symbols/Framework/choices/net8.0/description": "Target net8.0",
   "_symbols/Framework/choices/net8.0/description.comment": "{Locked='net8.0'}",
   "symbols/skipRestore/description": "If specified, skips the automatic restore of the project on create.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restore NuGet packages required by this project.",
   "postActions/restore/manualInstructions/default/text": "Run 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.es.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Marco de destino del proyecto.",
   "symbols/Framework/choices/net8.0/description": "net8.0 de destino",
   "symbols/skipRestore/description": "Si se especifica, se omite la restauración automática del proyecto durante la creación.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaure los paquetes NuGet necesarios para este proyecto.",
   "postActions/restore/manualInstructions/default/text": "Ejecutar \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.fr.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Framework cible du projet.",
   "symbols/Framework/choices/net8.0/description": "Cible net8.0",
   "symbols/skipRestore/description": "S’il est spécifié, ignore la restauration automatique du projet lors de la création.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaurez les packages NuGet requis par ce projet.",
   "postActions/restore/manualInstructions/default/text": "Exécuter « dotnet restore »"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.it.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Il framework di destinazione per il progetto.",
   "symbols/Framework/choices/net8.0/description": "Destinazione net8.0",
   "symbols/skipRestore/description": "Se specificato, ignora il ripristino automatico del progetto durante la creazione.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Ripristina i pacchetti NuGet richiesti da questo progetto.",
   "postActions/restore/manualInstructions/default/text": "Esegui 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ja.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "プロジェクトのターゲット フレームワークです。",
   "symbols/Framework/choices/net8.0/description": "ターゲット net8.0",
   "symbols/skipRestore/description": "指定した場合、作成時にプロジェクトの自動復元がスキップされます。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "このプロジェクトに必要な NuGet パッケージを復元します。",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' を実行する"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ko.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "프로젝트에 대한 대상 프레임워크입니다.",
   "symbols/Framework/choices/net8.0/description": "대상 net8.0",
   "symbols/skipRestore/description": "지정된 경우, 프로젝트 생성 시 자동 복원을 건너뜁니다.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "이 프로젝트에 필요한 NuGet 패키지를 복원합니다.",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' 실행"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.pl.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Platforma docelowa dla tego projektu.",
   "symbols/Framework/choices/net8.0/description": "Docelowa platforma net8.0",
   "symbols/skipRestore/description": "Jeśli ta opcja jest określona, pomija automatyczne przywracanie projektu podczas tworzenia.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Przywróć pakiety NuGet wymagane przez ten projekt.",
   "postActions/restore/manualInstructions/default/text": "Uruchom polecenie \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.pt-BR.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "A estrutura de destino do projeto.",
   "symbols/Framework/choices/net8.0/description": "net8.0 de destino",
   "symbols/skipRestore/description": "Se especificado, ignora a restauração automática do projeto sendo criado.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Restaure os pacotes NuGet exigidos por este projeto.",
   "postActions/restore/manualInstructions/default/text": "Executar 'dotnet restore'"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.ru.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Целевая платформа для проекта.",
   "symbols/Framework/choices/net8.0/description": "Целевая net8.0",
   "symbols/skipRestore/description": "Если установлено, автоматическое восстановление проекта при создании пропускается.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Восстановление пакетов NuGet, необходимых для этого проекта.",
   "postActions/restore/manualInstructions/default/text": "Выполнить команду \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.tr.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "Projenin hedef çerçevesi.",
   "symbols/Framework/choices/net8.0/description": "Hedef net8.0",
   "symbols/skipRestore/description": "Belirtilirse, oluşturma sırasında projenin otomatik geri yüklenmesini atlar.",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "Bu projenin gerektirdiği NuGet paketlerini geri yükleyin.",
   "postActions/restore/manualInstructions/default/text": "'dotnet restore' çalıştır"
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.zh-Hans.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "项目的目标框架。",
   "symbols/Framework/choices/net8.0/description": "目标 net8.0",
   "symbols/skipRestore/description": "如果指定,则在创建时跳过项目的自动还原。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "还原此项目所需的 NuGet 包。",
   "postActions/restore/manualInstructions/default/text": "运行 \"dotnet restore\""
 }

+ 2 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/localize/templatestrings.zh-Hant.json

@@ -6,6 +6,8 @@
   "symbols/Framework/description": "專案的目標 Framework。",
   "symbols/Framework/choices/net8.0/description": "目標 net8.0",
   "symbols/skipRestore/description": "若指定,會在建立時跳過專案的自動還原。",
+  "symbols/NativeAot/displayName": "Enable _native AOT publish",
+  "symbols/NativeAot/description": "Whether to enable the project for publishing as native AOT.",
   "postActions/restore/description": "還原此專案所需的 NuGet 套件。",
   "postActions/restore/manualInstructions/default/text": "執行 'dotnet restore'"
 }

+ 7 - 0
src/ProjectTemplates/Web.ProjectTemplates/content/Worker-FSharp/.template.config/template.json

@@ -67,6 +67,13 @@
       "datatype": "bool",
       "description": "If specified, skips the automatic restore of the project on create.",
       "defaultValue": "false"
+    },
+    "NativeAot" : {
+      "type": "parameter",
+      "datatype": "bool",
+      "defaultValue": "false",
+      "displayName": "Enable _native AOT publish",
+      "description": "Whether to enable the project for publishing as native AOT."
     }
   },
   "primaryOutputs": [

+ 12 - 0
src/ProjectTemplates/scripts/Run-WorkerNativeAot-Locally.ps1

@@ -0,0 +1,12 @@
+#!/usr/bin/env pwsh
+#requires -version 4
+
+[CmdletBinding(PositionalBinding = $false)]
+param()
+
+Set-StrictMode -Version 2
+$ErrorActionPreference = 'Stop'
+
+. $PSScriptRoot\Test-Template.ps1
+
+Test-Template "worker" "worker -aot" "Microsoft.DotNet.Web.ProjectTemplates.8.0.8.0.0-dev.nupkg" $false

+ 9 - 4
src/ProjectTemplates/test/Templates.Tests/ApiTemplateTest.cs

@@ -35,7 +35,7 @@ public class ApiTemplateTest : LoggedTest
         await ApiTemplateCore(languageOverride: null);
     }
 
-    [ConditionalFact(Skip = "Unskip when there are no more build or publish warnings for native AOT.")]
+    [ConditionalFact(Skip = "Unskip when Helix supports native AOT. https://github.com/dotnet/aspnetcore/pull/47247/")]
     public async Task ApiTemplateNativeAotCSharp()
     {
         await ApiTemplateCore(languageOverride: null, args: new[] { ArgConstants.PublishNativeAot });
@@ -47,7 +47,7 @@ public class ApiTemplateTest : LoggedTest
         await ApiTemplateCore(languageOverride: null, args: new[] { ArgConstants.UseProgramMain });
     }
 
-    [ConditionalFact(Skip = "Unskip when there are no more build or publish warnings for native AOT.")]
+    [ConditionalFact(Skip = "Unskip when Helix supports native AOT. https://github.com/dotnet/aspnetcore/pull/47247/")]
     public async Task ApiTemplateProgramMainNativeAotCSharp()
     {
         await ApiTemplateCore(languageOverride: null, args: new[] { ArgConstants.UseProgramMain, ArgConstants.PublishNativeAot });
@@ -55,11 +55,16 @@ public class ApiTemplateTest : LoggedTest
 
     private async Task ApiTemplateCore(string languageOverride, string[] args = null)
     {
+        var nativeAot = args?.Contains(ArgConstants.PublishNativeAot) ?? false;
+
         var project = await ProjectFactory.CreateProject(Output);
+        if (nativeAot)
+        {
+            project.SetCurrentRuntimeIdentifier();
+        }
 
         await project.RunDotNetNewAsync("api", args: args, language: languageOverride);
 
-        var nativeAot = args?.Contains(ArgConstants.PublishNativeAot) ?? false;
         var expectedLaunchProfileNames = nativeAot
             ? new[] { "http" }
             : new[] { "http", "IIS Express" };
@@ -92,7 +97,7 @@ public class ApiTemplateTest : LoggedTest
             await AssertEndpoints(aspNetProcess);
         }
 
-        using (var aspNetProcess = project.StartPublishedProjectAsync(noHttps: true))
+        using (var aspNetProcess = project.StartPublishedProjectAsync(noHttps: true, usePublishedAppHost: nativeAot))
         {
             Assert.False(
                 aspNetProcess.Process.HasExited,

+ 24 - 5
src/ProjectTemplates/test/Templates.Tests/WorkerTemplateTest.cs

@@ -1,10 +1,8 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Threading.Tasks;
 using Microsoft.AspNetCore.Testing;
 using Templates.Test.Helpers;
-using Xunit;
 using Xunit.Abstractions;
 
 namespace Templates.Test;
@@ -32,17 +30,38 @@ public class WorkerTemplateTest : LoggedTest
 
     [ConditionalTheory]
     [InlineData("C#", null)]
-    [InlineData("C#", new [] { ArgConstants.UseProgramMain })]
+    [InlineData("C#", new[] { ArgConstants.UseProgramMain })]
     [InlineData("F#", null)]
     public async Task WorkerTemplateAsync(string language, string[] args)
     {
+        await WorkerTemplateCoreAsync(language, args);
+
+    }
+
+    [ConditionalTheory(Skip = "Unskip when Helix supports native AOT. https://github.com/dotnet/aspnetcore/pull/47247/")]
+    [InlineData("C#")]
+    [InlineData("F#")]
+    public async Task WorkerTemplateNativeAotAsync(string language)
+    {
+        await WorkerTemplateCoreAsync(language, args: new[] { ArgConstants.PublishNativeAot });
+    }
+
+    private async Task WorkerTemplateCoreAsync(string language, string[] args)
+    {
+        var nativeAot = args?.Contains(ArgConstants.PublishNativeAot) ?? false;
+
         var project = await ProjectFactory.CreateProject(Output);
+        if (nativeAot)
+        {
+            project.SetCurrentRuntimeIdentifier();
+        }
 
         await project.RunDotNetNewAsync("worker", language: language, args: args);
 
         await project.VerifyHasProperty("InvariantGlobalization", "true");
 
-        await project.RunDotNetPublishAsync();
+        // Force a restore if native AOT so that RID-specific assets are restored
+        await project.RunDotNetPublishAsync(noRestore: !nativeAot);
 
         // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
         // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
@@ -57,7 +76,7 @@ public class WorkerTemplateTest : LoggedTest
                 ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
         }
 
-        using (var aspNetProcess = project.StartPublishedProjectAsync(hasListeningUri: false))
+        using (var aspNetProcess = project.StartPublishedProjectAsync(hasListeningUri: false, usePublishedAppHost: nativeAot))
         {
             Assert.False(
                 aspNetProcess.Process.HasExited,