Skip to content

Commit

Permalink
[runtime] Remove ObjCRuntime.nfloat in favor of System.Runtime.Intero…
Browse files Browse the repository at this point in the history
…pServices.NFloat. (xamarin#14197)

* Remove ObjCRuntime.nfloat (in favor of   System.Runtime.InteropServices.NFloat).
* Automatically add a reference to the System.Runtime.InteropServices.Internal
  package, so that developers get the new NFloat API (with operators) we've
  added post .NET 6 (but don't do this for .NET 7).
* Automatically add a global using alias for
  System.Runtime.InteropServices.NFloat -> nfloat. This is not behind the
  usual `ImplicitUsings` condition our other implicit usings are, because
  they're off by default for existing projects, and the main target for the
  global using alias for nfloat is upgraded projects.
* Automatically generate a global using alias (like above) in the generator
  for all code the generator compiles.
* Update xtro entries to reference System.Runtime.InteropServices.NFloat
  instead of ObjCRuntime.nfloat.
* Add a workaround for a hopefully temporary issue with .NET/CoreCLR where the
  wrong runtime pack is selected otherwise (without the new NFloat API, so
  nothing works at runtime).

Ref: xamarin#13087
  • Loading branch information
rolfbjarne authored and TJ Lambert committed Mar 8, 2022
1 parent 4eb430f commit 5add8c5
Show file tree
Hide file tree
Showing 41 changed files with 236 additions and 64 deletions.
8 changes: 8 additions & 0 deletions Make.config
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,14 @@ DOTNET6_DIR=$(abspath $(TOP)/builds/downloads/$(basename $(basename $(DOTNET6_TA
DOTNET6=$(DOTNET6_DIR)/dotnet
DOTNET6_BCL_DIR:=$(abspath $(TOP)/builds/downloads/microsoft.netcore.app.ref/$(DOTNET6_BCL_VERSION)/ref/net6.0)

# Use the System.Runtime.InteropServices.NFloat.Internal package to get the System.Runtime.InteropServices.dll reference assembly for
# .NET 6. This is no longer needed for .NET 7, when we can switch back to the usual BCL reference assemblies.
ifeq ($(DOTNET_TFM),net6.0)
DOTNET_SYSTEM_RUNTIME_INTEROPSERVICES_REF_ASSEMBLY_DIR:=$(abspath $(TOP)/builds/downloads/system.runtime.interopservices.nfloat.internal/6.0.1/ref/net6.0)
else
DOTNET_SYSTEM_RUNTIME_INTEROPSERVICES_REF_ASSEMBLY_DIR:=$(DOTNET6_BCL_DIR)
endif

# The sdk version band has the last two digits set to 0: https://github.com/dotnet/sdk/blob/22c4860dcb2cf6b123dd641cc4a87a50380759d5/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs#L52-L53
DOTNET_MANIFEST_VERSION_BAND=$(shell echo $(DOTNET6_VERSION_BAND) | sed 's/..$$/00/')
# We must do the same for our version band: the last two digits must be set to 0.
Expand Down
3 changes: 3 additions & 0 deletions builds/package-download/download-packages.proj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<!-- download the reference assemblies -->
<PackageDownload Include="microsoft.netcore.app.ref" Version="[$(ActualPackageVersion)]" />

<!-- download the nfloat reference assembly for .NET 6 (but only for .NET 6, once we switch to .NET 7 this can be removed) -->
<PackageDownload Include="System.Runtime.InteropServices.NFloat.Internal" Version="[6.0.1]" Condition="'$(ActualPackageVersion.Substring(0,1))' == '6'" />

<!-- and get the mono workload as well -->
<PackageDownload Include="Microsoft.NET.Workload.Mono.ToolChain.Manifest-$(ToolChainManifestVersionBand)" Version="[$(ActualPackageVersion)]" />

Expand Down
26 changes: 19 additions & 7 deletions dotnet/BreakingChanges.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,37 @@ favor of the C# 9 `nint` and `nuint` types (these map to `System.IntPtr` and

Reference: https://github.com/xamarin/xamarin-macios/issues/10508
## System.nfloat moved to ObjCRuntime.nfloat
## Removed `System.nfloat`

The `nfloat` type moved from the `System` namespace to the `ObjCRuntime` namespace.
The `System.nfloat` type has been removed in favor of the
`System.Runtime.InteropServices.NFloat` type.

* Code that references the `nfloat` type might not compile unless the `ObjCRuntime` namespace is imported.
In order to make existing code compile as much as possible, we're adding a
global using directive to C# projects, so that using `nfloat` as a type name
continues to work:

Fix: add `using ObjCRuntime` to the file in question.
```csharp
global using nfloat = System.Runtime.InteropServices.NFloat;
```

If this global using directive is undesirable, it can be turned off by setting
a `NoNFloatUsing=true` property in the project file.

* Code that references the full typename, `System.nfloat` won't compile.
There are a few other source code incompatibilities:

Fix: use `ObjCRuntime.nfloat` instead.
* Any code that refers to the full typename (`System.nfloat`) will have to be
modified to just use `nfloat`, or the new full typename
(`System.Runtime.InteropServices.NFloat`).
* The `nfloat.CopyArray` methods don't exist in `NFloat`. The code needs to be
rewritten to use `Buffer.CopyMemory` instead.

## System.NMath moved to ObjCRuntime.NMath

The `NMath` type moved from the `System` namespace to the `ObjCRuntime` namespace.

* Code that uses the `NMath` type won't compile unless the `ObjCRuntime` namespace is imported.

Fix: add `using ObjCRuntime` to the file in question.
Fix: add `using ObjCRuntime` to the file in question, or as a global using directive.

## NSObject.Handle and INativeObject.Handle changed type from System.IntPtr to ObjCRuntime.NativeHandle

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@
<Using Include="Foundation" Platform="MacCatalyst" />
<Using Include="UIKit" Platform="MacCatalyst" />
</ItemGroup>

<!--
Add a 'global using nfloat = System.Runtime.InteropServices.NFloat' to ease migration from Xamarin.
This is not grouped with the other usings, because those are not enabled by default (ImplicitUsings is empty by default, but set in our templates).
However, the main target for this using is upgraded projects, which won't have ImplicitUsings set to anything, so we
use a different condition (NoNFloatUsing) to disable if desired.
-->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'MacCatalyst' And '$(Language)' == 'C#' And '$(NoNFloatUsing)' != 'true'">
<Using Include="System.Runtime.InteropServices.NFloat" Platform="MacCatalyst" Alias="nfloat" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions dotnet/targets/Microsoft.iOS.Sdk.ImplicitNamespaceImports.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@
<Using Include="Foundation" Platform="iOS" />
<Using Include="UIKit" Platform="iOS" />
</ItemGroup>

<!--
Add a 'global using nfloat = System.Runtime.InteropServices.NFloat' to ease migration from Xamarin.
This is not grouped with the other usings, because those are not enabled by default (ImplicitUsings is empty by default, but set in our templates).
However, the main target for this using is upgraded projects, which won't have ImplicitUsings set to anything, so we
use a different condition (NoNFloatUsing) to disable if desired.
-->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'iOS' And '$(Language)' == 'C#' And '$(NoNFloatUsing)' != 'true'">
<Using Include="System.Runtime.InteropServices.NFloat" Platform="iOS" Alias="nfloat" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions dotnet/targets/Microsoft.macOS.Sdk.ImplicitNamespaceImports.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@
<Using Include="CoreGraphics" Platform="macOS" />
<Using Include="Foundation" Platform="macOS" />
</ItemGroup>

<!--
Add a 'global using nfloat = System.Runtime.InteropServices.NFloat' to ease migration from Xamarin.
This is not grouped with the other usings, because those are not enabled by default (ImplicitUsings is empty by default, but set in our templates).
However, the main target for this using is upgraded projects, which won't have ImplicitUsings set to anything, so we
use a different condition (NoNFloatUsing) to disable if desired.
-->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'macOS' And '$(Language)' == 'C#' And '$(NoNFloatUsing)' != 'true'">
<Using Include="System.Runtime.InteropServices.NFloat" Platform="macOS" Alias="nfloat" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions dotnet/targets/Microsoft.tvOS.Sdk.ImplicitNamespaceImports.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@
<Using Include="Foundation" Platform="tvOS" />
<Using Include="UIKit" Platform="tvOS" />
</ItemGroup>

<!--
Add a 'global using nfloat = System.Runtime.InteropServices.NFloat' to ease migration from Xamarin.
This is not grouped with the other usings, because those are not enabled by default (ImplicitUsings is empty by default, but set in our templates).
However, the main target for this using is upgraded projects, which won't have ImplicitUsings set to anything, so we
use a different condition (NoNFloatUsing) to disable if desired.
-->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'tvOS' And '$(Language)' == 'C#' And '$(NoNFloatUsing)' != 'true'">
<Using Include="System.Runtime.InteropServices.NFloat" Platform="tvOS" Alias="nfloat" />
</ItemGroup>
</Project>
32 changes: 32 additions & 0 deletions dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,36 @@
<FrameworkReference Include="Microsoft.$(_PlatformName)" IsImplicitlyDefined="true" Pack="false" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<!-- Add a reference to our custom nfloat reference assembly for .NET 6 (but only for .NET 6, once we switch to .NET 7 this can be removed) -->
<PackageReference Include="System.Runtime.InteropServices.NFloat.Internal" Condition="'$(BundledNETCorePlatformsPackageVersion.Substring(0,1))' == '6'" Version="[6.0.1, )" />
</ItemGroup>

<!--
This a workaround for an issue with the Microsoft.NETCore.App runtime pack
selection. The Microsoft.NETCore.App known framework reference sets
LatestRuntimeFrameworkVersion=6.0.1, which means that when a project is
restored, the 6.0.1 packages (from NuGet) will be selected instead of the
bundled packages (which has version 6.0.3). The problem with this is that
the 6.0.1 packages don't have the new nfloat API. So we try to override
the LatestRuntimeFrameworkVersion=6.0.1 value on the
KnownFrameworkReference by explicitly setting the RuntimeFrameworkVersion
value on the FrameworkReference when LatestRuntimeFrameworkVersion<6.0.3.
Ref: https://github.com/dotnet/sdk/blob/31d4db7dc94bb2f1f4d0ef84ebf158d61f2a7c4f/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs#L587-L594
-->
<ItemGroup Condition="'$(_PlatformName)' == 'macOS'">
<FrameworkReference
Update="Microsoft.NETCore.App"
Condition="
(
@(KnownFrameworkReference->AnyHaveMetadataValue('LatestRuntimeFrameworkVersion', '6.0.1')) Or
@(KnownFrameworkReference->AnyHaveMetadataValue('LatestRuntimeFrameworkVersion', '6.0.2'))
)
"
>
<RuntimeFrameworkVersion>6.0.3</RuntimeFrameworkVersion>
</FrameworkReference>
</ItemGroup>
</Project>
5 changes: 5 additions & 0 deletions dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,11 @@
<_GeneratorAttributeAssembly>$(_XamarinSdkRootDirectory)/tools/lib/Xamarin.Apple.BindingAttributes.dll</_GeneratorAttributeAssembly>
<_DotNetCscCompiler>$(RoslynTargetsPath)/bincore/csc.dll</_DotNetCscCompiler>
</PropertyGroup>

<ItemGroup>
<_BTouchCompileCommand Include="$(DOTNET_HOST_PATH)" />
<_BTouchCompileCommand Include="$(RoslynTargetsPath)/bincore/csc.dll" />
</ItemGroup>
</Target>

<Target Name="_ComputeNativeExecutableInputs" DependsOnTargets="_ComputeVariables">
Expand Down
5 changes: 5 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks.Core/Tasks/BTouchTaskBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public abstract class BTouchTaskBase : XamarinToolTask {

public string Namespace { get; set; }

public bool NoNFloatUsing { get; set; }

public ITaskItem[] NativeLibraries { get; set; }

public string OutputAssembly { get; set; }
Expand Down Expand Up @@ -156,6 +158,9 @@ protected override string GenerateCommandLineCommands ()

cmd.AddQuotedSwitchIfNotNull ("/ns:", Namespace);

if (NoNFloatUsing)
cmd.Add ("/no-nfloat-using:true");

if (!string.IsNullOrEmpty (DefineConstants)) {
var strv = DefineConstants.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var str in strv)
Expand Down
1 change: 1 addition & 0 deletions msbuild/Xamarin.Shared/Xamarin.Shared.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,7 @@ Copyright (C) 2018 Microsoft. All rights reserved.
GeneratedSourcesDir="$(GeneratedSourcesDir)"
GeneratedSourcesFileList="$(_GeneratedSourcesFileList)"
Namespace="$(Namespace)"
NoNFloatUsing="$(NoNFloatUsing)"
OutputAssembly="$(OutputAssembly)"
ProcessEnums="$(ProcessEnums)"
ProjectDir="$(MSBuildProjectDirectory)"
Expand Down
2 changes: 1 addition & 1 deletion runtime/trampolines.m
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,7 @@
#endif
func = to_managed ? (void *) xamarin_nsnumber_to_nuint : (void *) xamarin_nuint_to_nsnumber;
#if DOTNET
} else if (!strcmp (fullname, "ObjCRuntime.nfloat")) {
} else if (!strcmp (fullname, "System.Runtime.InteropServices.NFloat")) {
#else
} else if (!strcmp (fullname, "System.nfloat")) {
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ DOTNET_REFERENCES = \
/r:$(DOTNET6_BCL_DIR)/System.Runtime.dll \
/r:$(DOTNET6_BCL_DIR)/System.Runtime.CompilerServices.Unsafe.dll \
/r:$(DOTNET6_BCL_DIR)/System.Runtime.Extensions.dll \
/r:$(DOTNET6_BCL_DIR)/System.Runtime.InteropServices.dll \
/r:$(DOTNET_SYSTEM_RUNTIME_INTEROPSERVICES_REF_ASSEMBLY_DIR)/System.Runtime.InteropServices.dll \
/r:$(DOTNET6_BCL_DIR)/System.Security.Cryptography.X509Certificates.dll \
/r:$(DOTNET6_BCL_DIR)/System.Text.RegularExpressions.dll \
/r:$(DOTNET6_BCL_DIR)/System.Threading.dll \
Expand Down
7 changes: 3 additions & 4 deletions src/NativeTypes/Primitives.tt
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>

#if NET
#define SKIP_nint
#define SKIP_nuint
#endif
#if !NET

using System;
using System.ComponentModel;
Expand Down Expand Up @@ -454,3 +451,5 @@ namespace System
#endif // !SKIP_<#= type.NSName #>
}
<# } #>

#endif // !NET
7 changes: 7 additions & 0 deletions src/ObjCRuntime/NFloat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#if NET

#if !(MTOUCH || MMP || BUNDLER)
global using nfloat = System.Runtime.InteropServices.NFloat;
#endif

#endif // NET
4 changes: 2 additions & 2 deletions src/ObjCRuntime/Registrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ abstract partial class Registrar {
#endif

#if MMP || MTOUCH || BUNDLER
static string NFloatTypeName { get => Driver.IsDotNet ? "ObjCRuntime.nfloat" : "System.nfloat"; }
static string NFloatTypeName { get => Driver.IsDotNet ? "System.Runtime.InteropServices.NFloat" : "System.nfloat"; }
#elif NET
const string NFloatTypeName = "ObjCRuntime.nfloat";
const string NFloatTypeName = "System.Runtime.InteropServices.NFloat";
#else
const string NFloatTypeName = "System.nfloat";
#endif
Expand Down
8 changes: 7 additions & 1 deletion src/ObjCRuntime/Stret.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,18 @@ static bool IsBuiltInType (Type type, bool is_64_bits, out int type_size)
#if NET
if (type.Namespace == "ObjCRuntime") {
switch (type.Name) {
case "nfloat":
case "NativeHandle":
type_size = is_64_bits ? 8 : 4;
return true;
}
return false;
} else if (type.Namespace == "System.Runtime.InteropServices") {
switch (type.Name) {
case "NFloat":
type_size = is_64_bits ? 8 : 4;
return true;
}
return false;
}
#endif

Expand Down
5 changes: 3 additions & 2 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ We have introduced 6 new types to make this possible:
| `CGRect` | `System.Drawing.RectangleF` | `CoreGraphics.CGRect` |

In the Classic assembly, the `System.Drawing` types are backed by the 32-bit
`System.Single` type. In the Unified assemblies, the `CoreGraphics` types
are backed by 32/64-bit `System.nfloat` type (`ObjCRuntime.nfloat` in .NET).
`System.Single` type. In the Unified assemblies, the `CoreGraphics` types are
backed by 32/64-bit `System.nfloat` type
(`System.Runtime.InteropServices.NFloat` in .NET).

#### Enums ####

Expand Down
2 changes: 1 addition & 1 deletion src/SceneKit/SCNMatrix4_dotnet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#if PFLOAT_SINGLE
using pfloat = System.Single;
#else
using pfloat = ObjCRuntime.nfloat;
using pfloat = System.Runtime.InteropServices.NFloat;
#endif

#nullable enable
Expand Down
2 changes: 1 addition & 1 deletion src/SceneKit/SCNQuaternion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

#if MONOMAC
#if NET
using pfloat = ObjCRuntime.nfloat;
using pfloat = System.Runtime.InteropServices.NFloat;
#else
using pfloat = System.nfloat;
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/SceneKit/SCNVector3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

#if MONOMAC
#if NET
using pfloat = ObjCRuntime.nfloat;
using pfloat = System.Runtime.InteropServices.NFloat;
#else
using pfloat = System.nfloat;
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/SceneKit/SCNVector4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

#if MONOMAC
#if NET
using pfloat = ObjCRuntime.nfloat;
using pfloat = System.Runtime.InteropServices.NFloat;
#else
using pfloat = System.nfloat;
#endif
Expand Down
18 changes: 18 additions & 0 deletions src/btouch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ int Main3 (string [] args)
var defines = new List<string> ();
string? generate_file_list = null;
bool process_enums = false;
bool noNFloatUsing = false;

ErrorHelper.ClearWarningLevels ();

Expand Down Expand Up @@ -316,6 +317,10 @@ int Main3 (string [] args)
}
}
},
{ "no-nfloat-using:", "If a global using alias directive for 'nfloat = System.Runtime.InteropServices.NFloat' should automatically be created.", (v) => {
noNFloatUsing = string.Equals ("true", v, StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty (v);
}
},
new Mono.Options.ResponseFileSource (),
};

Expand Down Expand Up @@ -466,6 +471,14 @@ int Main3 (string [] args)
if (!string.IsNullOrEmpty (Path.GetDirectoryName (baselibdll)))
cargs.Add ("-lib:" + Path.GetDirectoryName (baselibdll));

#if NET
var tmpusing = Path.Combine (tmpdir, "GlobalUsings.g.cs");
if (!noNFloatUsing) {
File.WriteAllText (tmpusing, "global using nfloat = global::System.Runtime.InteropServices.NFloat;\n");
cargs.Add (tmpusing);
}
#endif

Compile (cargs, 2);

universe = new MetadataLoadContext (
Expand Down Expand Up @@ -592,6 +605,11 @@ int Main3 (string [] args)
if (!string.IsNullOrEmpty (Path.GetDirectoryName (baselibdll)))
cargs.Add ("-lib:" + Path.GetDirectoryName (baselibdll));

#if NET
if (!noNFloatUsing)
cargs.Add (tmpusing);
#endif

Compile (cargs, 1000);
} finally {
if (delete_temp)
Expand Down
1 change: 1 addition & 0 deletions src/frameworks.sources
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,7 @@ SHARED_CORE_SOURCES = \
ObjCRuntime/LinkWithAttribute.cs \
ObjCRuntime/NativeAttribute.cs \
ObjCRuntime/NativeHandle.cs \
ObjCRuntime/NFloat.cs \
ObjCRuntime/ObsoleteConstants.cs \
ObjCRuntime/PlatformAvailability.cs \
ObjCRuntime/PlatformAvailability2.cs \
Expand Down
3 changes: 2 additions & 1 deletion src/generator-typemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ public void Initialize (BindingTouch binding_touch, Assembly api, Assembly corli
#if NET
System_nint = Lookup (corlib_assembly, "System", "IntPtr");
System_nuint = Lookup (corlib_assembly, "System", "UIntPtr");
System_nfloat = Lookup (platform_assembly, "ObjCRuntime", "nfloat");
var interop_assembly = binding_touch.universe.LoadFromAssemblyName ("System.Runtime.InteropServices");
System_nfloat = Lookup (interop_assembly, "System.Runtime.InteropServices", "NFloat");
#else
System_nint = Lookup (platform_assembly, "System", "nint");
System_nuint = Lookup (platform_assembly, "System", "nuint");
Expand Down
Loading

0 comments on commit 5add8c5

Please sign in to comment.