[net9.0] Implement multi-targeting for .NET 9.

There are some shortcuts here, because this code will be simplified once .NET
8 has shipped multi-targeting.
This commit is contained in:
Rolf Bjarne Kvinge 2024-02-28 16:52:41 +01:00
Родитель 5ba566179f
Коммит 60ecc7caf1
7 изменённых файлов: 99 добавлений и 57 удалений

Просмотреть файл

@ -142,7 +142,7 @@ SUPPORTED_API_VERSIONS_MACCATALYST=$(DOTNET_TFM)-$(MACCATALYST_NUGET_OS_VERSION)
# Add older versions here!
SUPPORTED_API_VERSIONS_IOS+=$(DOTNET_TFM)-17.0
SUPPORTED_API_VERSIONS_TVOS+=$(DOTNET_TFM)-17.0
SUPPORTED_API_VERSIONS_MACOS+=$(DOTNET_TFM)-14.0
SUPPORTED_API_VERSIONS_MACCATALYST+=$(DOTNET_TFM)-17.0
SUPPORTED_API_VERSIONS_IOS+=net8.0-17.0
SUPPORTED_API_VERSIONS_TVOS+=net8.0-17.0
SUPPORTED_API_VERSIONS_MACOS+=net8.0-14.0
SUPPORTED_API_VERSIONS_MACCATALYST+=net8.0-17.0

Просмотреть файл

@ -181,7 +181,7 @@ Workloads/Microsoft.NET.Sdk.$(1)/WorkloadManifest.json: Makefile $(TOP)/Make.con
Workloads/Microsoft.NET.Sdk.$(1)/WorkloadManifest.targets: Makefile $(TOP)/Make.config.inc $(GIT_DIRECTORY)/HEAD $(GIT_DIRECTORY)/index Makefile generate-workloadmanifest-targets.csharp | Workloads/Microsoft.NET.Sdk.$(1)
$$(Q) rm -f $$@.tmp
$$(Q_GEN) ./generate-workloadmanifest-targets.csharp "$(1)" "$$@.tmp" "$$(DOTNET_WINDOWS_PLATFORMS)" "$(DOTNET_TFM)_$$($(4)_NUGET_OS_VERSION)" "net8.0" "$(DEFAULT_TARGET_PLATFORM_VERSION_$(4))"
$$(Q_GEN) ./generate-workloadmanifest-targets.csharp "$(1)" "$$@.tmp" "$$(DOTNET_WINDOWS_PLATFORMS)" "$(DOTNET_TFM)_$$($(4)_NUGET_OS_VERSION)" "net8.0" "$(SUPPORTED_API_VERSIONS_$(4))"
$$(Q) mv $$@.tmp $$@
Workloads/Microsoft.NET.Sdk.$(1)/LICENSE: $(TOP)/LICENSE | Workloads/Microsoft.NET.Sdk.$(1)

Просмотреть файл

@ -28,6 +28,7 @@ var versionsPropsPath = args [argumentIndex++];
var platformLowerCase = platform.ToLowerInvariant ();
var allApiVersions = new List<string> (supportedApiVersions);
allApiVersions.Add ("net8.0");
allApiVersions = allApiVersions.Select (v => v.Replace ('-', '_')).ToList ();
var versionsPropsTable = File.ReadAllLines (versionsPropsPath).
@ -48,11 +49,13 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
writer.WriteLine ($" \"{platformLowerCase}\": {{");
writer.WriteLine ($" \"description\": \".NET SDK Workload for building {platform} applications.\",");
writer.WriteLine ($" \"packs\": [");
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.{tfm}\",");
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.net8\",");
foreach (var tfm in allApiVersions) {
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.{tfm}\",");
}
if (hasWindows) {
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.{tfm}\",");
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.net8\",");
foreach (var tfm in allApiVersions) {
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.{tfm}\",");
}
}
writer.WriteLine ($" \"Microsoft.{platform}.Ref.{currentApiVersion}\",");
foreach (var rid in runtimeIdentifiers) {
@ -72,37 +75,47 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
writer.WriteLine ($" }},");
writer.WriteLine ($" }},");
writer.WriteLine ($" \"packs\": {{");
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.{tfm}\": {{");
writer.WriteLine ($" \"kind\": \"sdk\",");
writer.WriteLine ($" \"version\": \"{version}\",");
writer.WriteLine ($" }},");
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.net8\": {{");
writer.WriteLine ($" \"kind\": \"sdk\",");
writer.WriteLine ($" \"version\": \"{net8Version}\",");
writer.WriteLine ($" \"alias-to\": {{");
writer.WriteLine ($" \"any\": \"Microsoft.{platform}.Sdk\"");
writer.WriteLine ($" }}");
writer.WriteLine ($" }},");
if (hasWindows) {
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.{tfm}\": {{");
foreach (var tfmVersion in allApiVersions) {
string apiVersion;
var tfm = tfmVersion;
if (tfm == currentApiVersion) {
apiVersion = version;
} else if (tfm == "net8.0") {
apiVersion = net8Version;
} else {
var propsPackageName = $"Microsoft{platform}Sdk" + tfm.Replace ("-", "").Replace (".", "") + "PackageVersion";
if (!versionsPropsTable.TryGetValue (propsPackageName, out apiVersion)) {
Console.Error.WriteLine ($"❌ Unable to find a package version for {platform}/{tfm} in {versionsPropsPath}. Package name: {propsPackageName}");
apiVersion = "?";
failed = true;
}
}
writer.WriteLine ($" \"Microsoft.{platform}.Sdk.{tfm}\": {{");
writer.WriteLine ($" \"kind\": \"sdk\",");
writer.WriteLine ($" \"version\": \"{version}\",");
writer.WriteLine ($" \"alias-to\": {{");
writer.WriteLine ($" \"win-x64\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
writer.WriteLine ($" \"win-x86\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
writer.WriteLine ($" \"win-arm64\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
writer.WriteLine ($" }}");
writer.WriteLine ($" }},");
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.net8\": {{");
writer.WriteLine ($" \"kind\": \"sdk\",");
writer.WriteLine ($" \"version\": \"{net8Version}\",");
writer.WriteLine ($" \"alias-to\": {{");
writer.WriteLine ($" \"win-x64\": \"Microsoft.{platform}.Windows.Sdk\",");
writer.WriteLine ($" \"win-x86\": \"Microsoft.{platform}.Windows.Sdk\",");
writer.WriteLine ($" \"win-arm64\": \"Microsoft.{platform}.Windows.Sdk\",");
writer.WriteLine ($" }}");
writer.WriteLine ($" \"version\": \"{apiVersion}\",");
if (tfm == "net8.0") {
writer.WriteLine ($" \"alias-to\": {{");
writer.WriteLine ($" \"any\": \"Microsoft.{platform}.Sdk\"");
writer.WriteLine ($" }}");
}
writer.WriteLine ($" }},");
if (hasWindows) {
writer.WriteLine ($" \"Microsoft.{platform}.Windows.Sdk.Aliased.{tfm}\": {{");
writer.WriteLine ($" \"kind\": \"sdk\",");
writer.WriteLine ($" \"version\": \"{apiVersion}\",");
writer.WriteLine ($" \"alias-to\": {{");
if (tfm == "net8.0") {
writer.WriteLine ($" \"win-x64\": \"Microsoft.{platform}.Windows.Sdk\",");
writer.WriteLine ($" \"win-x86\": \"Microsoft.{platform}.Windows.Sdk\",");
writer.WriteLine ($" \"win-arm64\": \"Microsoft.{platform}.Windows.Sdk\",");
} else {
writer.WriteLine ($" \"win-x64\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
writer.WriteLine ($" \"win-x86\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
writer.WriteLine ($" \"win-arm64\": \"Microsoft.{platform}.Windows.Sdk.{tfm}\",");
}
writer.WriteLine ($" }}");
writer.WriteLine ($" }},");
}
}
writer.WriteLine ($" \"Microsoft.{platform}.Ref.{currentApiVersion}\": {{");
writer.WriteLine ($" \"kind\": \"framework\",");

Просмотреть файл

@ -26,9 +26,9 @@ var platformLowerCase = platform.ToLowerInvariant ();
var tfm = currentApiVersion;
var supportedTFMs = new List<string> ();
supportedTFMs.AddRange (olderApiVersions.Split (' '));
supportedTFMs.AddRange (supportedApiVersions.Split (' ').Select (v => v.Replace ('-', '_')));
supportedTFMs.Sort ();
supportedTFMs.AddRange (olderApiVersions.Split (' '));
var supportedTFVs = new List<string> ();

Просмотреть файл

@ -20,5 +20,10 @@
<MicrosoftmacOSSdkPackageVersion>14.2.8043</MicrosoftmacOSSdkPackageVersion>
<MicrosoftiOSSdkPackageVersion>17.2.8043</MicrosoftiOSSdkPackageVersion>
<MicrosofttvOSSdkPackageVersion>17.2.8043</MicrosofttvOSSdkPackageVersion>
<!-- This is a subscription to the .NET 8/Xcode 15.0 versions of our packages -->
<MicrosoftMacCatalystSdknet80_170PackageVersion>17.0.8519</MicrosoftMacCatalystSdknet80_170PackageVersion>
<MicrosoftmacOSSdknet80_140PackageVersion>14.0.8519</MicrosoftmacOSSdknet80_140PackageVersion>
<MicrosoftiOSSdknet80_170PackageVersion>17.0.8519</MicrosoftiOSSdknet80_170PackageVersion>
<MicrosofttvOSSdknet80_170PackageVersion>17.0.8519</MicrosofttvOSSdknet80_170PackageVersion>
</PropertyGroup>
</Project>

Просмотреть файл

@ -1152,18 +1152,22 @@ namespace Xamarin.Tests {
[TestCase (ApplePlatform.MacCatalyst, "maccatalyst-x64")]
public void BuildNet7_0App (ApplePlatform platform, string runtimeIdentifiers)
{
var tfm = "net7.0";
var project = "Net7_0SimpleApp";
Configuration.IgnoreIfIgnoredPlatform (platform);
Configuration.AssertRuntimeIdentifiersAvailable (platform, runtimeIdentifiers);
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath, netVersion: "net7.0");
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath, netVersion: tfm);
Clean (project_path);
var properties = GetDefaultProperties (runtimeIdentifiers);
var result = DotNet.AssertBuildFailure (project_path, properties);
var errors = BinLog.GetBuildLogErrors (result.BinLogPath).ToList ();
Assert.AreEqual (1, errors.Count, "Error Count");
Assert.That (errors [0].Message, Does.Contain ("To build this project, the following workloads must be installed: "), "Error message");
// Due to an implementation detail in .NET, the same error message is shown twice.
var targetFramework = $"{tfm}-{platform.AsString ().ToLowerInvariant ()}";
AssertErrorMessages (errors,
$"The workload '{targetFramework}' is out of support and will not receive security updates in the future. Please refer to https://aka.ms/maui-support-policy for more information about the support policy.",
$"The workload '{targetFramework}' is out of support and will not receive security updates in the future. Please refer to https://aka.ms/maui-support-policy for more information about the support policy.");
}
[Test]
@ -1657,7 +1661,6 @@ namespace Xamarin.Tests {
properties [property] = value;
var rv = DotNet.AssertBuildFailure (project_path, properties);
var errors = BinLog.GetBuildLogErrors (rv.BinLogPath).ToArray ();
AssertErrorCount (errors, 1, "Error count");
AssertErrorMessages (errors, $"The property '{property}' is deprecated, please remove it from the project file. Use 'RuntimeIdentifier' or 'RuntimeIdentifiers' instead to specify the target architecture.");
}

Просмотреть файл

@ -415,13 +415,6 @@ namespace Xamarin.Tests {
return false;
}
public static void AssertErrorCount (IList<BuildLogEvent> errors, int count, string message)
{
if (errors.Count == count)
return;
Assert.Fail ($"Expected {count} errors, got {errors.Count} errors: {message}.\n\t{string.Join ("\n\t", errors.Select (v => v.Message?.TrimEnd ()))}");
}
public static void AssertWarningMessages (IList<BuildLogEvent> actualWarnings, params string [] expectedWarningMessages)
{
AssertBuildMessages ("warning", actualWarnings, expectedWarningMessages);
@ -432,20 +425,48 @@ namespace Xamarin.Tests {
AssertBuildMessages ("error", actualErrors, expectedErrorMessages);
}
public static void AssertErrorMessages (IList<BuildLogEvent> actualErrors, Func<string, bool> [] matchesExpectedErrorMessage, Func<string> [] rendersExpectedErrorMessage)
{
AssertBuildMessages ("error", actualErrors, matchesExpectedErrorMessage, rendersExpectedErrorMessage);
}
public static void AssertBuildMessages (string type, IList<BuildLogEvent> actualMessages, params string [] expectedMessages)
{
if (actualMessages.Count != expectedMessages.Length) {
Assert.Fail ($"Expected {expectedMessages.Length} {type}s, got {actualMessages.Count} {type}s:\n\t{string.Join ("\n\t", actualMessages.Select (v => v.Message?.TrimEnd ()))}");
AssertBuildMessages (type, actualMessages,
expectedMessages.Select (v => new Func<string, bool> ((msg) => msg == v)).ToArray (),
expectedMessages.Select (v => new Func<string> (() => v)).ToArray ()
);
}
static string makeSingleLine (string? msg)
{
if (msg is null)
return "";
return msg.TrimEnd ().Replace ("\n", "\\n").Replace ("\r", "\\r");
}
public static void AssertBuildMessages (string type, IList<BuildLogEvent> actualMessages, Func<string, bool> [] matchesExpectedMessage, Func<string> [] rendersExpectedMessage)
{
var expectedCount = matchesExpectedMessage.Length;
if (expectedCount != rendersExpectedMessage.Length)
throw new InvalidOperationException ($"Mismatched function count");
if (actualMessages.Count != expectedCount) {
Assert.Fail ($"Expected {expectedCount} {type}(s), got {actualMessages.Count} {type}(s)\n" +
$"\tExpected:\n" +
$"\t\t{string.Join ("\n\t\t", rendersExpectedMessage.Select (v => makeSingleLine (v ())))}" +
$"\tActual:\n" +
$"\t\t{string.Join ("\n\t\t", actualMessages.Select (v => makeSingleLine (v.Message)))}");
return;
}
var failures = new List<string> ();
for (var i = 0; i < expectedMessages.Length; i++) {
for (var i = 0; i < expectedCount; i++) {
var actual = actualMessages [i].Message ?? string.Empty;
var expected = expectedMessages [i];
if (actual != expected) {
actual = actual.Replace ("\n", "\\n").Replace ("\r", "\\r");
expected = expected.Replace ("\n", "\\n").Replace ("\r", "\\r");
var isExpected = matchesExpectedMessage [i];
if (!isExpected (actual)) {
actual = makeSingleLine (actual);
var expected = makeSingleLine (rendersExpectedMessage [i] ());
failures.Add ($"\tUnexpected {type} message #{i}:\n\t\tExpected: {expected}\n\t\tActual: {actual}");
}
}