dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.27k stars 4.73k forks source link

Preparing For Removing macIOS dependencies from Binding Tools for Swift #98165

Closed stephen-hawley closed 4 months ago

stephen-hawley commented 9 months ago

In order to integrate Binding Tools for Swift with the runtime, we are accepting that we are not going to include the current support for using the existing types that are bound by Xamarin mac/iOS and instead depend in the future on BTfS to do those bindings. This is not a small task and in order to get there, we need to set forth incremental steps that won't damage the existing infrastructure.

In order to work with the bound types in Mac/iOS with swift, it is necessary to be able to do a bidirectional mapping from Swift type metadata to C# type. The is necessary in marshaling and is heavily needed in managing generics as well as protocols with associated types.

There exists a tool called type-o-matic in the BTfS code space that generates data structures in swift to be built into XamGlue and generates data structures in C# to be built into the runtime library. While we could cut out this step entirely, doing so as it will likely create a fair amount of fallout.

Here's how I would do it to minimize that fallout:

Once this step is working cleanly, then the follow-on work can be done to remove the type-o-matic step entirely.

Other things that will cause us grief: Rather than binding Swift types that are exported as ObjC, we use btouch to do that for us for all ObjC classes and protocols. This is a cheap, quick hack to leverage existing tools and if we want to have no dependencies, we need to consider how to handle this otherwise which will not be a small task. However, one thing to keep in mind is that when you declare a type to be @objc in swift, it is still very much both a swift object and an ObjC object. Every ObjC method is an adapter that calls the swift method, so we should (in theory) be able to bind it as is. But this will of course need time and research.

NewClassCompiler imports all the types from ObjC into the type database through the class BindingImporter. Outside of tests, there is precisely one place where it gets called. We can remove that call. This how the code generated by type-o-matic gets consumed in the the main tool.

ghost commented 9 months ago

Tagging subscribers to this area: @dotnet/area-meta See info in area-owners.md if you want to be subscribed.

Issue Details
In order to integrate Binding Tools for Swift with the runtime, we are accepting that we are *not* going to include the current support for using the existing types that are bound by Xamarin mac/iOS and instead depend in the future on BTfS to do those bindings. This is not a small task and in order to get there, we need to set forth incremental steps that won't damage the existing infrastructure. In order to work with the bound types in Mac/iOS with swift, it is necessary to be able to do a bidirectional mapping from Swift type metadata to C# type. The is necessary in marshaling and is heavily needed in managing generics as well as protocols with associated types. There exists a tool called type-o-matic in the BTfS code space that generates data structures in swift to be built into XamGlue and generates data structures in C# to be built into the runtime library. While we could cut out this step entirely, doing so as it will likely create a fair amount of fallout. Here's how I would do it to minimize that fallout: - Alter type-o-matic to include a new command-line argument like "--generate-empty-tables" - Change Program.cs to spot this flag and skip type aggregation and call a method to generate empty tables instead. - Go through the unit tests and add `[Ignore]` to any any all tests that depend on ObjC types Once this step is working cleanly, then the follow-on work can be done to remove the type-o-matic step entirely. Other things that will cause us grief: Rather than binding Swift types that are exported as ObjC, we use `btouch` to do that for us for all ObjC classes and protocols. This is a cheap, quick hack to leverage existing tools and if we want to have no dependencies, we need to consider how to handle this otherwise which will not be a small task. However, one thing to keep in mind is that when you declare a type to be `@objc` in swift, it is still very much both a swift object and an ObjC object. Every ObjC method is an adapter that calls the swift method, so we should (in theory) be able to bind it as is. But this will of course need time and research. NewClassCompiler imports all the types from ObjC into the type database through the class BindingImporter. Outside of tests, there is precisely one place where it gets called. We can remove that call. This how the code generated by type-o-matic gets consumed in the the main tool.
Author: stephen-hawley
Assignees: kotlarmilos
Labels: `area-Meta`, `tracking`
Milestone: -
kotlarmilos commented 9 months ago

Thanks for bringing this up!

we are accepting that we are not going to include the current support for using the existing types that are bound by Xamarin mac/iOS

We can benefit from the existing bindings, so I suggest we consider including them at a later stage.

There exists a tool called type-o-matic in the BTfS code space that generates data structures in swift to be built into XamGlue and generates data structures in C# to be built into the runtime library

Is the XamGlue framework necessary for cases where Swift wrappers are not required, such as for Swift primitive types?

Rather than binding Swift types that are exported as ObjC, we use btouch to do that for us for all ObjC classes and protocols. This is a cheap, quick hack to leverage existing tools and if we want to have no dependencies, we need to consider how to handle this otherwise which will not be a small task. However, one thing to keep in mind is that when you declare a type to be @objc in swift, it is still very much both a swift object and an ObjC object. Every ObjC method is an adapter that calls the swift method, so we should (in theory) be able to bind it as is. But this will of course need time and research.

Is it possible to consider Objective-C and Swift bindings as two different toolings that work independently? By treating them as distinct tools, we might minimize dependencies between the tooling and the existing Xamarin type registration system (or maybe output of the type registration system?), potentially simplifying maintenance.

/cc: @rolfbjarne @dalexsoto @vitek-karas

stephen-hawley commented 9 months ago

XamGlue is necessary for mundane things like translating strings back and forth between Swift and C# and some other typical type marshaling that is not otherwise available through libswiftCore. This includes:

ghost commented 8 months ago

Tagging subscribers to this area: @dotnet/interop-contrib See info in area-owners.md if you want to be subscribed.

Issue Details
In order to integrate Binding Tools for Swift with the runtime, we are accepting that we are *not* going to include the current support for using the existing types that are bound by Xamarin mac/iOS and instead depend in the future on BTfS to do those bindings. This is not a small task and in order to get there, we need to set forth incremental steps that won't damage the existing infrastructure. In order to work with the bound types in Mac/iOS with swift, it is necessary to be able to do a bidirectional mapping from Swift type metadata to C# type. The is necessary in marshaling and is heavily needed in managing generics as well as protocols with associated types. There exists a tool called type-o-matic in the BTfS code space that generates data structures in swift to be built into XamGlue and generates data structures in C# to be built into the runtime library. While we could cut out this step entirely, doing so as it will likely create a fair amount of fallout. Here's how I would do it to minimize that fallout: - Alter type-o-matic to include a new command-line argument like "--generate-empty-tables" - Change Program.cs to spot this flag and skip type aggregation and call a method to generate empty tables instead. - Go through the unit tests and add `[Ignore]` to any any all tests that depend on ObjC types Once this step is working cleanly, then the follow-on work can be done to remove the type-o-matic step entirely. Other things that will cause us grief: Rather than binding Swift types that are exported as ObjC, we use `btouch` to do that for us for all ObjC classes and protocols. This is a cheap, quick hack to leverage existing tools and if we want to have no dependencies, we need to consider how to handle this otherwise which will not be a small task. However, one thing to keep in mind is that when you declare a type to be `@objc` in swift, it is still very much both a swift object and an ObjC object. Every ObjC method is an adapter that calls the swift method, so we should (in theory) be able to bind it as is. But this will of course need time and research. NewClassCompiler imports all the types from ObjC into the type database through the class BindingImporter. Outside of tests, there is precisely one place where it gets called. We can remove that call. This how the code generated by type-o-matic gets consumed in the the main tool.
Author: stephen-hawley
Assignees: kotlarmilos
Labels: `area-Meta`, `area-System.Runtime.InteropServices`, `tracking`
Milestone: 9.0.0
AaronRobinsonMSFT commented 8 months ago

/cc @jkoritzinsky

kotlarmilos commented 6 months ago

@stephen-hawley Is this still relevant since we decided to iteratively move bits to the runtimelab repository?

jkoritzinsky commented 4 months ago

@stephen-hawley @kotlarmilos given that we've decided to (at least in the .NET 9 time frame) iteratively move bits into runtimelab and bring back pieces as needed, I'm going to close this issue.