xamarin-macios/versions-check.csharp

99 строки
3.8 KiB
Plaintext
Исходник Обычный вид История

#!/usr/bin/env /Library/Frameworks/Mono.framework/Commands/csharp -s
// this script is to make sure our versions.plist files are not out of date with our min/max supported OS versions.
// arguments are: plistPath iOSMinVersion iOSMaxVersion tvOSMinVersion tvOSMaxVersion watchOSMinVersion watchOSMaxVersion macOSMinVersion macOSMaxVersion MacCatalystOSMinVersion MacCatalystOSMaxVersion
using System.IO;
using System.Xml;
try {
var args = Args;
var expectedArgumentCount = 11;
if (args.Length != expectedArgumentCount) {
Console.WriteLine ("Need 11 arguments, got {0}", args.Length);
Environment.Exit (1);
return;
}
var plistPath = args [0];
var iOSMin = args [1];
var iOSMax = args [2];
var tvOSMin = args [3];
var tvOSMax = args [4];
var watchOSMin = args [5];
var watchOSMax = args [6];
var macOSMin = args [7];
var macOSMax = args [8];
var MacCatalystMin = args [9];
var MacCatalystMax = args [10];
var doc = new System.Xml.XmlDocument ();
doc.Load (plistPath);
var failed = false;
var check = new Action<string, string, string> ((product, min, max) =>
{
var minVersion = Version.Parse (min);
var maxVersion = Version.Parse (max);
var foundMax = false;
var foundMin = false;
var versions = doc.SelectNodes ($"/plist/dict/key[text()='KnownVersions']/following-sibling::dict[1]/key[text()='{product}']/following-sibling::array[1]/string");
if (versions.Count == 0) {
// Skip this (iOS/tvOS/watchOS versions for macOS, or vice versa)
return;
}
[dotnet] Differentiate between "OS version we support as TargetPlatformVersion" and "OS version we support or have supported". (#19882) The `SdkSupportedTargetPlatformVersion` item group is used for (at least) two things: 1. Generate the `_OR_GREATER` preprocessing symbols: https://github.com/dotnet/sdk/blob/bfd2919bc446cad68d11de90cec4025d3683591c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets#L230-L237 2. Validate the TargetPlatformVersion: https://github.com/dotnet/sdk/blob/bfd2919bc446cad68d11de90cec4025d3683591c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.TargetFrameworkInference.targets#L233-L246 The problem is that these two uses aren't equivalent. Take for example the following scenario: We release bindings for iOS 10, and a library developer takes advantage of the bindings for the new iOS version, while at the same time supporting multi-targeting to older platforms: ```csharp #if IOS10_0_OR_GREATER UseNewApi (); #else UseOldApi (); #endif ``` Time passes, iOS 11 comes out, and we stop shipping bindings specifically for iOS 10 (the APIs themselves would be included in the bindings for iOS 11). The code above should continue to work, but iOS 10 is not a valid TargetPlatformVersion anymore. However, with the current situation there's no way to express this, because the moment we remove the "10.0" version from SdkSupportedTargetPlatformVersion, the IOS10_0_OR_GREATER define isn't generated anymore. We discussed this in a meeting internally, and the suggestion that came up was to use metadata to handle this situation, and we've decided to add the "DefineConstantsOnly=true" metadata to items in SdkSupportedTargetPlatformVersion that are "OS versions we support or have supported", but not "OS versions we support as TargetPlatformVersion". Note: we're adding this to .NET 8, but .NET will not understand the new metadata until .NET 9, which means this won't be a breaking change until .NET 9. In a different PR I'll add logic to warn if a project uses a TargetPlatformVersion that is no longer valid (so that people will start getting a warning in .NET 8 instead of getting surprised by a build error in .NET 9). Ref: https://github.com/dotnet/sdk/issues/38016
2024-01-23 21:17:25 +03:00
var versionsHashSet = new HashSet<string> (versions.Cast<XmlNode> ().Select (v => v.InnerText));
foreach (XmlNode node in versions) {
// Console.WriteLine ($"{product}: checking: {node.InnerText}");
var v = node.InnerText;
var version = Version.Parse (v);
if (version < minVersion) {
Console.Error.WriteLine ($"Found the {product} version {v} in {Path.GetFileName (plistPath)}, but it's smaller than the supported min {product} version we support ({min}).");
failed = true;
} else if (version > maxVersion) {
Console.Error.WriteLine ($"Found the {product} version {v} in {Path.GetFileName (plistPath)}, but it's higher than the supported max {product} version we support ({max}).");
failed = true;
}
if (version == maxVersion)
foundMax = true;
if (version == minVersion)
foundMin = true;
}
if (!foundMax) {
Console.Error.WriteLine ($"Could not find the max {product} version {max} in {Path.GetFileName (plistPath)}.");
failed = true;
}
if (!foundMin) {
Console.Error.WriteLine ($"Could not find the min {product} version {min} in {Path.GetFileName (plistPath)}.");
failed = true;
}
[dotnet] Differentiate between "OS version we support as TargetPlatformVersion" and "OS version we support or have supported". (#19882) The `SdkSupportedTargetPlatformVersion` item group is used for (at least) two things: 1. Generate the `_OR_GREATER` preprocessing symbols: https://github.com/dotnet/sdk/blob/bfd2919bc446cad68d11de90cec4025d3683591c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets#L230-L237 2. Validate the TargetPlatformVersion: https://github.com/dotnet/sdk/blob/bfd2919bc446cad68d11de90cec4025d3683591c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.TargetFrameworkInference.targets#L233-L246 The problem is that these two uses aren't equivalent. Take for example the following scenario: We release bindings for iOS 10, and a library developer takes advantage of the bindings for the new iOS version, while at the same time supporting multi-targeting to older platforms: ```csharp #if IOS10_0_OR_GREATER UseNewApi (); #else UseOldApi (); #endif ``` Time passes, iOS 11 comes out, and we stop shipping bindings specifically for iOS 10 (the APIs themselves would be included in the bindings for iOS 11). The code above should continue to work, but iOS 10 is not a valid TargetPlatformVersion anymore. However, with the current situation there's no way to express this, because the moment we remove the "10.0" version from SdkSupportedTargetPlatformVersion, the IOS10_0_OR_GREATER define isn't generated anymore. We discussed this in a meeting internally, and the suggestion that came up was to use metadata to handle this situation, and we've decided to add the "DefineConstantsOnly=true" metadata to items in SdkSupportedTargetPlatformVersion that are "OS versions we support or have supported", but not "OS versions we support as TargetPlatformVersion". Note: we're adding this to .NET 8, but .NET will not understand the new metadata until .NET 9, which means this won't be a breaking change until .NET 9. In a different PR I'll add logic to warn if a project uses a TargetPlatformVersion that is no longer valid (so that people will start getting a warning in .NET 8 instead of getting surprised by a build error in .NET 9). Ref: https://github.com/dotnet/sdk/issues/38016
2024-01-23 21:17:25 +03:00
var supportedTPVNodes = doc.SelectNodes ($"/plist/dict/key[text()='SupportedTargetPlatformVersions']/following-sibling::dict[1]/key[text()='{product}']/following-sibling::array[1]/string").Cast<XmlNode> ().ToArray ();
var supportedTPVs = supportedTPVNodes.Select (v => v.InnerText).ToArray ();
if (supportedTPVs?.Any () == true) {
var supportedTPVSet = new HashSet<string> (supportedTPVs);
var missingTPVs = versionsHashSet.Except (supportedTPVSet);
if (missingTPVs.Any ()) {
Console.Error.WriteLine ($"The array SupportedTargetPlatformVersions are missing the following entries (they're in the KnownVersions array): {string.Join (", ", missingTPVs)}");
failed = true;
}
} else if (plistPath.Contains ("/builds/")) {
Console.Error.WriteLine ($"No SupportedTargetPlatformVersions array found in the plist: {plistPath}");
failed = true;
}
});
check ("iOS", iOSMin, iOSMax);
check ("tvOS", tvOSMin, tvOSMax);
check ("watchOS", watchOSMin, watchOSMax);
check ("macOS", macOSMin, macOSMax);
check ("MacCatalyst", MacCatalystMin, MacCatalystMax);
Environment.Exit (failed ? 1 : 0);
} catch (Exception e) {
Console.WriteLine (e);
Environment.Exit (1);
}