diff --git a/Make.versions b/Make.versions
index 7182fdd9abc8..701e10189530 100644
--- a/Make.versions
+++ b/Make.versions
@@ -71,6 +71,12 @@ WATCHOS_NUGET_OS_VERSION=11.0
MACOS_NUGET_OS_VERSION=15.0
MACCATALYST_NUGET_OS_VERSION=18.0
+# The following are the OS versions we first supported with the current .NET version.
+# These versions must *not* change with minor .NET updates, only major .NET releases.
+IOS_TARGET_PLATFORM_VERSION_LIBRARY=18.0
+TVOS_TARGET_PLATFORM_VERSION_LIBRARY=18.0
+MACOS_TARGET_PLATFORM_VERSION_LIBRARY=15.0
+MACCATALYST_TARGET_PLATFORM_VERSION_LIBRARY=18.0
# In theory we should define the default platform version if it's not specified in the TFM. The default should not change for a given .NET version:
# * We release support for iOS 14.5 with .NET 6
@@ -100,6 +106,13 @@ MACCATALYST_NUGET_OS_VERSION=18.0
# So we've made the decision that the default target platform version is
# always the latest target platform version.
+# However, this turns out to be somewhat of a complication for library developers,
+# because they typically don't need Xcode to build their projects, and if we auto-
+# update their TargetPlatformVersion to the latest, then all their customers
+# have to also update their workloads, which for some people end up being a rather
+# nasty surprise (because with the above algorithm it happens without developer
+# action). Thus we follow .NET's default platform version scheme for library projects:
+# it won't change in minor .NET releases.
#
# Here we list all the releases we support for each platform.
diff --git a/dotnet/Makefile b/dotnet/Makefile
index a67f5289fe37..25fb75ee8e1a 100644
--- a/dotnet/Makefile
+++ b/dotnet/Makefile
@@ -119,7 +119,8 @@ targets/Microsoft.$(1).Sdk.Versions.props: targets/Microsoft.Sdk.Versions.templa
-e "s/@PLATFORM@/$(1)/g" \
-e "s/@NUGET_VERSION_NO_METADATA@/$$($(2)_NUGET_VERSION_NO_METADATA)/g" \
-e "s/@NUGET_VERSION_FULL@/$$($(2)_NUGET_VERSION_FULL)/g" \
- -e "s/@TARGET_PLATFORM_VERSION@/$$($(2)_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_EXE@/$$($(2)_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_LIBRARY@/$$($(2)_TARGET_PLATFORM_VERSION_LIBRARY)/g" \
-e "s/@CURRENT_BRANCH@/$$(CURRENT_BRANCH_SED_ESCAPED)/g" \
-e "s/@CURRENT_HASH_LONG@/$$(CURRENT_HASH_LONG)/g" \
-e 's*@VALID_RUNTIME_IDENTIFIERS@*$(foreach rid,$(3),\n\t\t<_XamarinValidRuntimeIdentifier Include="$(rid)" Platform="$(1)" />)*' \
diff --git a/dotnet/targets/Microsoft.Sdk.Versions.template.props b/dotnet/targets/Microsoft.Sdk.Versions.template.props
index d77b1f8d68c0..500353a521ae 100644
--- a/dotnet/targets/Microsoft.Sdk.Versions.template.props
+++ b/dotnet/targets/Microsoft.Sdk.Versions.template.props
@@ -6,7 +6,8 @@
<_ShortPackageVersion>@NUGET_VERSION_NO_METADATA@
<_PackageVersion>@NUGET_VERSION_FULL@
- <_XamarinTargetPlatformVersion>@TARGET_PLATFORM_VERSION@
+ <_XamarinTargetPlatformVersionExecutable>@TARGET_PLATFORM_VERSION_EXE@
+ <_XamarinTargetPlatformVersionLibrary>@TARGET_PLATFORM_VERSION_LIBRARY@
<_XamarinIsPreviewRelease>@XCODE_IS_PREVIEW@
<_XamarinDotNetVersion>@DOTNET_TFM@
<_XamarinPackSuffix>@DOTNET_TFM@_@NUGET_OS_VERSION@
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.TargetFrameworkInference.props b/dotnet/targets/Xamarin.Shared.Sdk.TargetFrameworkInference.props
index 0f585a4db207..3e082daf79fc 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.TargetFrameworkInference.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.TargetFrameworkInference.props
@@ -12,6 +12,7 @@
- $(_XamarinTargetPlatformVersion)
+ $(_XamarinTargetPlatformVersionExecutable)
+ $(_XamarinTargetPlatformVersionLibrary)
diff --git a/tests/dotnet/UnitTests/ApplePlatformExtensions.cs b/tests/dotnet/UnitTests/ApplePlatformExtensions.cs
index b24e66995275..48b6a6ad9707 100644
--- a/tests/dotnet/UnitTests/ApplePlatformExtensions.cs
+++ b/tests/dotnet/UnitTests/ApplePlatformExtensions.cs
@@ -2,10 +2,10 @@
namespace Xamarin.Utils {
public static class ApplePlatformExtensionsWithVersions {
- public static string ToFrameworkWithPlatformVersion (this ApplePlatform @this)
+ public static string ToFrameworkWithPlatformVersion (this ApplePlatform @this, bool isExecutable /* and not library */)
{
var netVersion = Configuration.DotNetTfm;
- var targetPlatformVersion = GetTargetPlatformVersion (@this);
+ var targetPlatformVersion = isExecutable ? GetDefaultTargetPlatformVersionExecutable (@this) : GetDefaultTargetPlatformVersionLibrary (@this);
switch (@this) {
case ApplePlatform.iOS:
return netVersion + "-ios" + targetPlatformVersion;
@@ -20,16 +20,53 @@ public static string ToFrameworkWithPlatformVersion (this ApplePlatform @this)
}
}
- public static string GetTargetPlatformVersion (this ApplePlatform @this)
+ public static string GetDefaultTargetPlatformVersionExecutable (this ApplePlatform @this)
{
switch (@this) {
- case ApplePlatform.iOS: return SdkVersions.TargetPlatformVersioniOS;
- case ApplePlatform.TVOS: return SdkVersions.TargetPlatformVersiontvOS;
- case ApplePlatform.MacOSX: return SdkVersions.TargetPlatformVersionmacOS;
- case ApplePlatform.MacCatalyst: return SdkVersions.TargetPlatformVersionMacCatalyst;
+ case ApplePlatform.iOS: return SdkVersions.TargetPlatformVersionExecutableiOS;
+ case ApplePlatform.TVOS: return SdkVersions.TargetPlatformVersionExecutabletvOS;
+ case ApplePlatform.MacOSX: return SdkVersions.TargetPlatformVersionExecutablemacOS;
+ case ApplePlatform.MacCatalyst: return SdkVersions.TargetPlatformVersionExecutableMacCatalyst;
default:
return "Unknown";
}
}
+
+ public static string GetDefaultTargetPlatformVersionLibrary (this ApplePlatform @this)
+ {
+ switch (@this) {
+ case ApplePlatform.iOS: return SdkVersions.TargetPlatformVersionLibraryiOS;
+ case ApplePlatform.TVOS: return SdkVersions.TargetPlatformVersionLibrarytvOS;
+ case ApplePlatform.MacOSX: return SdkVersions.TargetPlatformVersionLibrarymacOS;
+ case ApplePlatform.MacCatalyst: return SdkVersions.TargetPlatformVersionLibraryMacCatalyst;
+ default:
+ return "Unknown";
+ }
+ }
+ }
+
+ [TestFixture]
+ public class TargetFrameworkTest {
+ [TestCase (ApplePlatform.iOS)]
+ [TestCase (ApplePlatform.MacCatalyst)]
+ [TestCase (ApplePlatform.TVOS)]
+ [TestCase (ApplePlatform.MacOSX)]
+ public void DefaultLibraryTargetPlatformVersion (ApplePlatform platform)
+ {
+ // We might have to change the assert if the first minor OS version we release for a given .NET version is >0 (this happened for both .NET 7 and .NET 8).
+ Assert.That (platform.GetDefaultTargetPlatformVersionLibrary (), Does.EndWith (".0"), "Default TPV for a library must end with .0");
+ }
+
+ [TestCase (ApplePlatform.iOS)]
+ [TestCase (ApplePlatform.MacCatalyst)]
+ [TestCase (ApplePlatform.TVOS)]
+ [TestCase (ApplePlatform.MacOSX)]
+ public void MajorTargetPlatformVersion (ApplePlatform platform)
+ {
+ var vLibrary = Version.Parse (platform.GetDefaultTargetPlatformVersionLibrary ());
+ var vExecutable = Version.Parse (platform.GetDefaultTargetPlatformVersionExecutable ());
+ // We might have to change the assert if we release support for a new major OS version within a .NET releases (this happened for .NET 8)
+ Assert.AreEqual (vExecutable.Major, vLibrary.Major, "The major version must be the same between the default TPV for library and executable projects.");
+ }
}
}
diff --git a/tests/dotnet/UnitTests/MlaunchTest.cs b/tests/dotnet/UnitTests/MlaunchTest.cs
index 76823f08da19..e4a369159473 100644
--- a/tests/dotnet/UnitTests/MlaunchTest.cs
+++ b/tests/dotnet/UnitTests/MlaunchTest.cs
@@ -90,7 +90,7 @@ public void GetMlaunchRunArguments (ApplePlatform platform, string runtimeIdenti
expectedArguments.Append (appPath.Substring (Path.GetDirectoryName (project_path)!.Length + 1)).Append ('/');
if (isSim) {
expectedArguments.Append (" --device \"");
- expectedArguments.Append (device.Replace ("%TPV%", platform.GetTargetPlatformVersion ().Replace ('.', '-')));
+ expectedArguments.Append (device);
expectedArguments.Append ('"');
}
expectedArguments.Append ($" --wait-for-exit:true");
diff --git a/tests/dotnet/UnitTests/PackTest.cs b/tests/dotnet/UnitTests/PackTest.cs
index d6d02b4e69a7..59da47dc18f4 100644
--- a/tests/dotnet/UnitTests/PackTest.cs
+++ b/tests/dotnet/UnitTests/PackTest.cs
@@ -62,6 +62,7 @@ public void BindingFrameworksProject (ApplePlatform platform, bool noBindingEmbe
var archive = ZipFile.OpenRead (nupkg);
var files = archive.Entries.Select (v => v.FullName).ToHashSet ();
+ var tfm = platform.ToFrameworkWithPlatformVersion (isExecutable: false);
var hasSymlinks = noBindingEmbedding && (platform == ApplePlatform.MacCatalyst || platform == ApplePlatform.MacOSX);
if (noBindingEmbedding) {
Assert.That (archive.Entries.Count, Is.EqualTo (hasSymlinks ? 6 : 10), $"nupkg file count - {nupkg}");
@@ -71,17 +72,17 @@ public void BindingFrameworksProject (ApplePlatform platform, bool noBindingEmbe
Assert.That (files, Does.Contain (project + ".nuspec"), "nuspec");
Assert.That (files, Does.Contain ("_rels/.rels"), ".rels");
Assert.That (files, Does.Contain ("[Content_Types].xml"), "[Content_Types].xml");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.dll"), $"{project}.dll");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.dll"), $"{project}.dll");
Assert.That (files, Has.Some.Matches (v => v.StartsWith ("package/services/metadata/core-properties/", StringComparison.Ordinal) && v.EndsWith (".psmdcp", StringComparison.Ordinal)), "psmdcp");
if (noBindingEmbedding) {
if (hasSymlinks) {
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources.zip"), $"{project}.resources.zip");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources.zip"), $"{project}.resources.zip");
} else {
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources/XStaticArTest.framework/XStaticArTest"), $"XStaticArTest.framework/XStaticArTest");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources/XStaticObjectTest.framework/XStaticObjectTest"), $"XStaticObjectTest.framework/XStaticObjectTest");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources/XTest.framework/XTest"), $"XTest.framework/XTest");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources/XTest.framework/Info.plist"), $"XTest.framework/Info.plist");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.resources/manifest"), $"manifest");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources/XStaticArTest.framework/XStaticArTest"), $"XStaticArTest.framework/XStaticArTest");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources/XStaticObjectTest.framework/XStaticObjectTest"), $"XStaticObjectTest.framework/XStaticObjectTest");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources/XTest.framework/XTest"), $"XTest.framework/XTest");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources/XTest.framework/Info.plist"), $"XTest.framework/Info.plist");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{project}.resources/manifest"), $"manifest");
}
}
}
@@ -127,14 +128,15 @@ public void BindingXcFrameworksProject (ApplePlatform platform, bool noBindingEm
var archive = ZipFile.OpenRead (nupkg);
var files = archive.Entries.Select (v => v.FullName).ToHashSet ();
+ var tfm = platform.ToFrameworkWithPlatformVersion (isExecutable: false);
Assert.That (archive.Entries.Count, Is.EqualTo (noBindingEmbedding ? 6 : 5), $"nupkg file count - {nupkg}");
Assert.That (files, Does.Contain (assemblyName + ".nuspec"), "nuspec");
Assert.That (files, Does.Contain ("_rels/.rels"), ".rels");
Assert.That (files, Does.Contain ("[Content_Types].xml"), "[Content_Types].xml");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{assemblyName}.dll"), $"{assemblyName}.dll");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{assemblyName}.dll"), $"{assemblyName}.dll");
Assert.That (files, Has.Some.Matches (v => v.StartsWith ("package/services/metadata/core-properties/", StringComparison.Ordinal) && v.EndsWith (".psmdcp", StringComparison.Ordinal)), "psmdcp");
if (noBindingEmbedding) {
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{assemblyName}.resources.zip"), $"{assemblyName}.resources.zip");
+ Assert.That (files, Does.Contain ($"lib/{tfm}/{assemblyName}.resources.zip"), $"{assemblyName}.resources.zip");
}
}
@@ -164,7 +166,7 @@ public void LibraryProject (ApplePlatform platform)
Assert.That (files, Does.Contain (project + ".nuspec"), "nuspec");
Assert.That (files, Does.Contain ("_rels/.rels"), ".rels");
Assert.That (files, Does.Contain ("[Content_Types].xml"), "[Content_Types].xml");
- Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion ()}/{project}.dll"), $"{project}.dll");
+ Assert.That (files, Does.Contain ($"lib/{platform.ToFrameworkWithPlatformVersion (isExecutable: false)}/{project}.dll"), $"{project}.dll");
Assert.That (files, Has.Some.Matches (v => v.StartsWith ("package/services/metadata/core-properties/", StringComparison.Ordinal) && v.EndsWith (".psmdcp", StringComparison.Ordinal)), "psmdcp");
}
diff --git a/tests/dotnet/UnitTests/XcodeProjectTests.cs b/tests/dotnet/UnitTests/XcodeProjectTests.cs
index 30a7485df8d8..a3a7362f34e5 100644
--- a/tests/dotnet/UnitTests/XcodeProjectTests.cs
+++ b/tests/dotnet/UnitTests/XcodeProjectTests.cs
@@ -179,9 +179,10 @@ public void PackBinding (ApplePlatform platform)
Assert.That (expectedNupkgOutput, Does.Exist, $"Expected pack output '{expectedNupkgOutput}' did not exist.");
List zipContent = ZipHelpers.List (expectedNupkgOutput);
- var expectedFxPath = $"lib/{platform.ToFrameworkWithPlatformVersion ()}/{TestName}.resources/{xcodeProjName}{platform.AsString ()}.xcframework/Info.plist";
+ var tfm = platform.ToFrameworkWithPlatformVersion (isExecutable: false);
+ var expectedFxPath = $"lib/{tfm}/{TestName}.resources/{xcodeProjName}{platform.AsString ()}.xcframework/Info.plist";
if (platform == ApplePlatform.MacOSX || platform == ApplePlatform.MacCatalyst) {
- zipContent = ZipHelpers.ListInnerZip (expectedNupkgOutput, $"lib/{platform.ToFrameworkWithPlatformVersion ()}/{TestName}.resources.zip");
+ zipContent = ZipHelpers.ListInnerZip (expectedNupkgOutput, $"lib/{tfm}/{TestName}.resources.zip");
expectedFxPath = $"{xcodeProjName}{platform.AsString ()}.xcframework/Info.plist";
}
Assert.Contains (expectedFxPath, zipContent, $"Expected xcframework output was not found in '{expectedNupkgOutput}'.");
diff --git a/tools/common/Make.common b/tools/common/Make.common
index 530d21d7e4cd..0a68d8fc8221 100644
--- a/tools/common/Make.common
+++ b/tools/common/Make.common
@@ -50,10 +50,15 @@ $(abspath ../common/SdkVersions.cs): ../common/SdkVersions.in.cs Makefile $(TOP)
-e "s/@MACOS_NUGET_VERSION@/$(MACOS_NUGET_VERSION)/g" \
-e "s/@MACOS_NUGET_REVISION@/$(NUGET_PRERELEASE_IDENTIFIER)$(MACOS_NUGET_COMMIT_DISTANCE)$(NUGET_BUILD_METADATA)/g" \
\
- -e "s/@TARGET_PLATFORM_VERSION_IOS@/$(IOS_NUGET_OS_VERSION)/g" \
- -e "s/@TARGET_PLATFORM_VERSION_TVOS@/$(TVOS_NUGET_OS_VERSION)/g" \
- -e "s/@TARGET_PLATFORM_VERSION_MACOS@/$(MACOS_NUGET_OS_VERSION)/g" \
- -e "s/@TARGET_PLATFORM_VERSION_MACCATALYST@/$(MACCATALYST_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_EXECUTABLE_IOS@/$(IOS_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_EXECUTABLE_TVOS@/$(TVOS_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_EXECUTABLE_MACOS@/$(MACOS_NUGET_OS_VERSION)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_EXECUTABLE_MACCATALYST@/$(MACCATALYST_NUGET_OS_VERSION)/g" \
+ \
+ -e "s/@TARGET_PLATFORM_VERSION_LIBRARY_IOS@/$(IOS_TARGET_PLATFORM_VERSION_LIBRARY)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_LIBRARY_TVOS@/$(TVOS_TARGET_PLATFORM_VERSION_LIBRARY)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_LIBRARY_MACOS@/$(MACOS_TARGET_PLATFORM_VERSION_LIBRARY)/g" \
+ -e "s/@TARGET_PLATFORM_VERSION_LIBRARY_MACCATALYST@/$(MACCATALYST_TARGET_PLATFORM_VERSION_LIBRARY)/g" \
\
-e "s/@PRODUCT_HASH@/$(CURRENT_HASH_LONG)/g" \
\
diff --git a/tools/common/SdkVersions.cs b/tools/common/SdkVersions.cs
index 1413ffbded8b..fdddeec68821 100644
--- a/tools/common/SdkVersions.cs
+++ b/tools/common/SdkVersions.cs
@@ -57,10 +57,15 @@ static class SdkVersions {
public const string MaxWatchDeploymentTarget = "11.0";
public const string MaxTVOSDeploymentTarget = "18.0";
- public const string TargetPlatformVersioniOS = "18.0";
- public const string TargetPlatformVersiontvOS = "18.0";
- public const string TargetPlatformVersionmacOS = "15.0";
- public const string TargetPlatformVersionMacCatalyst = "18.0";
+ public const string TargetPlatformVersionExecutableiOS = "18.0";
+ public const string TargetPlatformVersionExecutabletvOS = "18.0";
+ public const string TargetPlatformVersionExecutablemacOS = "15.0";
+ public const string TargetPlatformVersionExecutableMacCatalyst = "18.0";
+
+ public const string TargetPlatformVersionLibraryiOS = "18.0";
+ public const string TargetPlatformVersionLibrarytvOS = "18.0";
+ public const string TargetPlatformVersionLibrarymacOS = "15.0";
+ public const string TargetPlatformVersionLibraryMacCatalyst = "18.0";
public static Version OSXVersion { get { return new Version (OSX); } }
public static Version iOSVersion { get { return new Version (iOS); } }
diff --git a/tools/common/SdkVersions.in.cs b/tools/common/SdkVersions.in.cs
index 78d07d826860..77761f44bc53 100644
--- a/tools/common/SdkVersions.in.cs
+++ b/tools/common/SdkVersions.in.cs
@@ -57,10 +57,15 @@ static class SdkVersions {
public const string MaxWatchDeploymentTarget = "@MAX_WATCH_DEPLOYMENT_TARGET@";
public const string MaxTVOSDeploymentTarget = "@MAX_TVOS_DEPLOYMENT_TARGET@";
- public const string TargetPlatformVersioniOS = "@TARGET_PLATFORM_VERSION_IOS@";
- public const string TargetPlatformVersiontvOS = "@TARGET_PLATFORM_VERSION_TVOS@";
- public const string TargetPlatformVersionmacOS = "@TARGET_PLATFORM_VERSION_MACOS@";
- public const string TargetPlatformVersionMacCatalyst = "@TARGET_PLATFORM_VERSION_MACCATALYST@";
+ public const string TargetPlatformVersionExecutableiOS = "@TARGET_PLATFORM_VERSION_EXECUTABLE_IOS@";
+ public const string TargetPlatformVersionExecutabletvOS = "@TARGET_PLATFORM_VERSION_EXECUTABLE_TVOS@";
+ public const string TargetPlatformVersionExecutablemacOS = "@TARGET_PLATFORM_VERSION_EXECUTABLE_MACOS@";
+ public const string TargetPlatformVersionExecutableMacCatalyst = "@TARGET_PLATFORM_VERSION_EXECUTABLE_MACCATALYST@";
+
+ public const string TargetPlatformVersionLibraryiOS = "@TARGET_PLATFORM_VERSION_LIBRARY_IOS@";
+ public const string TargetPlatformVersionLibrarytvOS = "@TARGET_PLATFORM_VERSION_LIBRARY_TVOS@";
+ public const string TargetPlatformVersionLibrarymacOS = "@TARGET_PLATFORM_VERSION_LIBRARY_MACOS@";
+ public const string TargetPlatformVersionLibraryMacCatalyst = "@TARGET_PLATFORM_VERSION_LIBRARY_MACCATALYST@";
public static Version OSXVersion { get { return new Version (OSX); } }
public static Version iOSVersion { get { return new Version (iOS); } }