migueldeicaza/SwiftGodot

Windows: Split SwiftGodot in chunks

Opened this issue · 10 comments

SwiftGodot produces too many symbols, and this prevents Windows from compiling the library as a dynamic library.

We could split SwiftGodot in different libraries, separate things by domains (for example, all the XR code could go into SwiftGodotXR). The challenge is the lookupObject that relies on knowing al the possible built-in types to resolve names to types. We would end up requiring a registration system to be added, so that we could resolve new objects surfaced through it.

Another option is to keep all the types in SwiftGodot, but move the implementation of methods to separate assemblies.

So types would be functional only after importing the additional libraries.

Alternative suggestion: The Godot folks told me that the approach they use for Godot C++ is to only generate static libraries, and they only expose the entry point in their extension. I would like to explore what is needed to do that for our extensions and share that guidance.

Alternative suggestion: The Godot folks told me that the approach they use for Godot C++ is to only generate static libraries, and they only expose the entry point in their extension.

How would that work if you have multiple extensions? Do you end up with SwiftGodot statically linked into each one?

We could split SwiftGodot in different libraries, separate things by domains (for example, all the XR code could go into SwiftGodotXR). The challenge is the lookupObject that relies on knowing al the possible built-in types to resolve names to types. We would end up requiring a registration system to be added, so that we could resolve new objects surfaced through it.

Could you not still have a master SwiftGodot library that imports all the sub-domain libraries? So all the domain-specific libraries would be needed at runtime, because the master SwiftGodot would link against them, but each domain's symbols would be exported by its own library, so the master library would export relatively few symbols itself.

Registration of built in types could still be done in the master SwiftGodot library - but it would just need to call a known function in each domain library to add the domain's symbols to the lookup table.

Which is a registration system, I grant you, but it's not much less performant or complicated than having a single prebuilt table; it's just a series of prebuilt tables concatenated at runtime.

Presumably this would be kicked off by the user's extension calling into SwiftGodot, supplying it own table of custom classes, built by the GodotMacro.

What am I missing?

Alternative suggestion: The Godot folks told me that the approach they use for Godot C++ is to only generate static libraries, and they only expose the entry point in their extension.

How would that work if you have multiple extensions? Do you end up with SwiftGodot statically linked into each one?

I suspect that this would be a problem, yes. At least while we figure out a long-term solution.

We could split SwiftGodot in different libraries, separate things by domains (for example, all the XR code could go into SwiftGodotXR). The challenge is the lookupObject that relies on knowing al the possible built-in types to resolve names to types. We would end up requiring a registration system to be added, so that we could resolve new objects surfaced through it.

Could you not still have a master SwiftGodot library that imports all the sub-domain libraries? So all the domain-specific libraries would be needed at runtime, because the master SwiftGodot would link against them, but each domain's symbols would be exported by its own library, so the master library would export relatively few symbols itself.

Registration of built in types could still be done in the master SwiftGodot library - but it would just need to call a known function in each domain library to add the domain's symbols to the lookup table.

Which is a registration system, I grant you, but it's not much less performant or complicated than having a single prebuilt table; it's just a series of prebuilt tables concatenated at runtime.

Presumably this would be kicked off by the user's extension calling into SwiftGodot, supplying it own table of custom classes, built by the GodotMacro.

What am I missing?

I don't think you are missing much. I am not particularly fond of the underlying suggestion I made, and neither am I of having a three-layer cake of libraries. We would end up with something like:

  • SwiftGodotCore: the basic types that are needed by the split libraries
  • SwiftGodotXXXX: the per-feature types that rely on the core
  • SwiftGodot: the entry point that has knowledge of everything

Another option (which we discussed on Slack, but was not captured here) is to define all the types on SwiftGodot, but define the method implementations as extension methods in peer assemblies.

So SwiftGodot contains all the types (and I suspect we need to include here vars, I am not sure), and the peer assemblies contain the method implementations.

I don't think you are missing much. I am not particularly fond of the underlying suggestion I made, and neither am I of having a three-layer cake of libraries.

Yeah, I can see that it's less than ideal, but from the point of view of the consuming user extension, I don't think it would be too bad if the split was logical and functional.

I think the core library is the kicker. It is possible for a library to re-export another import's symbols I think, but I don't know if it's possible to do something like this:

image

such that the client never has to explicitly import SwiftGodotCore.

I could live with having to do

import SwiftGodot
import SwiftGodot3D

I suspect that this wouldn't do the right think in a fully dynamic context. Re-exporting is likely more intended for the situation where your dynamic library wants to static link some other stuff into itself and export its interface to clients.

Mhm, that is a good question.

That is another reason to go with the "Everything-but-methods-in-core".

One thing I was wondering was whether any of the exported symbols are duplicates due to things like #42, where the same pattern is being repeated multiple times.

It might turn out that there's a bunch of symbols that could be eliminated by consolidating some currently generated code into base classes or generics in the way I attempted to do with the signal stuff?

Also just whether there are public things that could be private, although I expect you've been down that road already?

Another option is to keep all the types in SwiftGodot, but move the implementation of methods to separate assemblies.

Are you thinking that the implementations could be extensions? I think there are a few non-obvious things that can't go into extensions (along with stored properties), which might make this messier than one would like.