Skip to content

Add C# iOS support - #82729

Merged
akien-mga merged 1 commit into
godotengine:masterfrom
shana:shana/ios-csharp
Oct 9, 2023
Merged

Add C# iOS support#82729
akien-mga merged 1 commit into
godotengine:masterfrom
shana:shana/ios-csharp

Conversation

@shana

@shana shana commented Oct 3, 2023

Copy link
Copy Markdown
Contributor

This PR adds C# support for iOS targets, using the official .NET Core 8 NativeAOT support. This requires (and has been tested) .NET Core 8 RC 1.

To support iOS+NativeAOT, the csproj gets a lot more complicated than just the two entries it had before, so the generated content is moved to a template, embedded as a resource in the GodotTools.ProjectEditor assembly. It's possible that the release version of dotnet core 8 (around November) will make the csproj template simpler, there's some linker workarounds that are currently required that will likely be fixed by then, so this will need to be revisited when dotnet 8 gets released.

Godot still has a bunch of reflection code which breaks trimming, so the csproj generates an rd.xml whitelisting the godot and project assemblies, so things work out of the box and don't crash at runtime. Once the reflection code gets cleaned up, we can revisit this.

Update/some more notes
The target framework for the user project is set to 8.0 only when the RuntimeIdentifier contains "ios", so in all other cases it should still work fine as is with .net 6 - if I managed to hit all the right buttons, this shouldn't affect any other platforms.

Godot doesn't run on iOS Simulator right now because we're using Vulkan features that it doesn't support, but this PR includes all the needed bits for the simulator (so when #74227 eventually gets fixed, this should Just Work(tm))

Contributed by W4Games

Comment thread modules/mono/mono_gd/gd_mono.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is because open_dynamic_library already does path finding logic to figure out where the file actually is, depending on the platform it's running in. There's no point in doing the check here, as we don't actualliy know what the path actually is at this point.

Comment thread modules/mono/mono_gd/gd_mono.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For NativeAOT, this check isn't right, as we're not actually going to be loading managed assemblies from this particular location. It's not really making anything safer, other parts of the code do path finding to try and find the correct locations for libraries. We don't know whether we're doing nativeaot yet at this point, so we can't even optionally do this only for non-nativeaot. It's going to make it harder to optionally enable nativeaot later for platforms that support both native and managed libraries, so we might want to revisit this check in the future.

@YuriSizov

Copy link
Copy Markdown
Contributor

Just FYI the CI doesn't go past static checks because there appears to be a typo 🙃

./modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs:189: becaue ==> because

@shana

shana commented Oct 3, 2023

Copy link
Copy Markdown
Contributor Author

Just FYI the CI doesn't go past static checks because there appears to be a typo 🙃

./modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs:189: becaue ==> because

gah, and I ran it three times to make sure! jeez 🙈

@shana
shana force-pushed the shana/ios-csharp branch from 1a3ecd4 to 2c28442 Compare October 3, 2023 14:43

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally the path to xcode would come from xcode-select, instead of being hardcoded here. However, we can't easily run xcode-select before this item group is evaluated (we would have to do it as a target before ilccompile and parse the result, etc), AND ideally the dotnet 8 release won't need these anymore, so this is a temporary workaround. If dotnet 8 release still needs this, then we should revisit this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivanpovazan do you know if this is tracked/known somewhere on the dotnet/runtime repo side?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are planning to introduce such changes officially with the support for library mode when targeting iOS with NativeAOT: dotnet/runtime#88737
Although, that is currently marked with a .NET9 milestone. @MichalStrehovsky should we try to get it in sooner?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's discussed in dotnet/runtime#91997
There's actually a better workaround that doesn't involve setting these directly, so I'll fix this up.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although, that is currently marked with a .NET9 milestone. @MichalStrehovsky should we try to get it in sooner?

I'll leave the prioritization on you, depending work/risk/other priorities/etc. There's demand for it from here and from the original issue filer and it might meet the .NET 8 bar ("Blocking key partner scenarios or blocking adoption"). But if there's good workarounds, that could mean .NET 9 is fine. I don't know how much of a problem this is as I don't do mac stuff.

(This discussion can move to dotnet/runtime#88737, just wanted to ask if we have an issue and we do).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI (and I'll add that comment too upstream, but just so it's here as well), it seems like the workaround is only for the -lc++ linker argument, and not for the -isysroot arg, so it would be super great ❤️ ❤️ if (at least) the sysroot path inference bit could be fixed for .NET 8

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've worked around this issue for now by discovering the Xcode path via xcrun xcode-select -p.

@akien-mga

akien-mga commented Oct 3, 2023

Copy link
Copy Markdown
Member

I've made a custom build of 4.2-dev6 (57a6813) + this PR cherrypicked (2c28442989a646acc26c241c8544180e17876429) to ease testing. It includes the macOS editor, and the iOS export templates with C# support enabled.

https://downloads.tuxfamily.org/godotengine/testing/4.2-dev6+pr82729/mono/

Please test and let us know how it works on your C# projects!

Edit: Note: We found out my macOS editor build was borked, I'm making a new build now and will update this link.

Edit 2: The builds have been updated (same link, same names), now it should work™.

Edit 3: More recent build below: #82729 (comment)

Comment thread modules/mono/editor/GodotTools/GodotTools.ProjectEditor/default.csproj.template Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools.ProjectEditor/default.csproj.template Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools.ProjectEditor/default.csproj.template Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivanpovazan do you know if this is tracked/known somewhere on the dotnet/runtime repo side?

Comment thread modules/mono/editor/GodotTools/GodotTools.ProjectEditor/default.csproj.template Outdated
@bruvzg
bruvzg self-requested a review October 4, 2023 07:24

@bruvzg bruvzg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on iPad, M1 Mac and M1 iPhone 15 Simulator, seems to be working fine.

A few issues:

  • Seems like export with C# is always looking for the export template in the default location (and won't run even when custom template is set). It might be a generic iOS export or C# export issue and probably unrelated to the PR.
  • I'm always getting the following error in the export log (it's not happening with non-C# iOS export), but exported project is fully functional:
editor/export/editor_export_platform.h:182 - Xcode Build: Xcode project build failed, see editor log for details.

error: Unexpected duplicate tasks
    note: Command: SignatureCollection ~/Library/Developer/Xcode/DerivedData/ios_mono-bszfhymtdguyrpfslpyhpguifwus/Build/Intermediates.noindex/ArchiveIntermediates/ios_mono/BuildProductsPath/Debug-iphoneos/ios_mono.xcframework-ios.signature
    note: Command: SignatureCollection ~/Library/Developer/Xcode/DerivedData/ios_mono-bszfhymtdguyrpfslpyhpguifwus/Build/Intermediates.noindex/ArchiveIntermediates/ios_mono/BuildProductsPath/Debug-iphoneos/ios_mono.xcframework-ios.signature
** ARCHIVE FAILED **

@bruvzg

bruvzg commented Oct 4, 2023

Copy link
Copy Markdown
Member

Godot doesn't run on iOS Simulator right now because we're using Vulkan features that it doesn't support,

Note for testing: It is possible to run in simulator in the Compatibly/OpenGL mode. Also, with the Apple Silicon powered Mac, you can run the device version by selecting My Mac in the Xcode target list.

@shana

shana commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

Godot doesn't run on iOS Simulator right now because we're using Vulkan features that it doesn't support,

Note for testing: It is possible to run in simulator in the Compatibly/OpenGL mode. Also, with the Apple Silicon powered Mac, you can run the device version by selecting My Mac in the Xcode target list.

Right, I should specify that it won't work for the ios simulator in arm64 mode specifically - besides the vulkan issues, we don't currently ship the ios simulator arm64 template binaries right now because of some issues with the cross-compiler. I haven't tested on my intel mac, so maybe it will work on the simulator there 🤞

@bruvzg

bruvzg commented Oct 4, 2023

Copy link
Copy Markdown
Member

I should specify that it won't work for the ios simulator in arm64 mode specifically

ARM64 simulator works fine, if you build the simulator export template library on macOS (official builds do not have it, but it's OSXCross limitation).

@shana

shana commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

Seems like export with C# is always looking for the export template in the default location (and won't run even when custom template is set). It might be a generic iOS export or C# export issue and probably unrelated to the PR.

I've been testing with custom templates set in the export options and it's been working fine (that's how I iterate locally, I build the templates and package them in a zip file with the rest of the expected contents that the zip file is suppoed to have). For reference, the custom template fields in the export options expect a zip file, and they can be set to the ios.zip file that's included in the tpz linked above.

I'm always getting the following error in the export log (it's not happening with non-C# iOS export), but exported project is fully functional:

editor/export/editor_export_platform.h:182 - Xcode Build: Xcode project build failed, see editor log for details.

error: Unexpected duplicate tasks
    note: Command: SignatureCollection ~/Library/Developer/Xcode/DerivedData/ios_mono-bszfhymtdguyrpfslpyhpguifwus/Build/Intermediates.noindex/ArchiveIntermediates/ios_mono/BuildProductsPath/Debug-iphoneos/ios_mono.xcframework-ios.signature
    note: Command: SignatureCollection ~/Library/Developer/Xcode/DerivedData/ios_mono-bszfhymtdguyrpfslpyhpguifwus/Build/Intermediates.noindex/ArchiveIntermediates/ios_mono/BuildProductsPath/Debug-iphoneos/ios_mono.xcframework-ios.signature
** ARCHIVE FAILED **

Does this happen when the "Only export the project" checkbox is NOT set (so it's trying to generate the ipa)?

@shana

shana commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

I should specify that it won't work for the ios simulator in arm64 mode specifically

ARM64 simulator works fine, if you build the simulator export template library on macOS (official builds do not have it, but it's OSXCross limitation).

Good to know! I couldn't get to work on my M1, but then again I think I was testing the simulator with Xcode 13 and not Xcode 14 at the time, so maybe it's Xcode 13's fault.

@bruvzg

bruvzg commented Oct 4, 2023

Copy link
Copy Markdown
Member

Does this happen when the "Only export the project" checkbox is NOT set (so it's trying to generate the ipa)?

Only happens if Only export the project is unchecked, specifically during creating xcarchive step:

/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project ../../_output/ios_mono.xcodeproj -scheme ios_mono -sdk iphoneos -configuration Debug -destination generic/platform=iOS archive -allowProvisioningUpdates -archivePath ../../_output/ios_mono.xcarchive

I've been testing with custom templates set in the export options and it's been working fine (that's how I iterate locally, I build the templates and package them in a zip file with the rest of the expected contents that the zip file is suppoed to have).

It's using a custom template if it's set, but is still checking if the default one is present and showing a warning message in the export dialog. It seems to be an issue with EditorExportPlatform::exists_export_template which is always setting the error message (so not iOS or C# related, I just have not noticed it before).

@shana

shana commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

Does this happen when the "Only export the project" checkbox is NOT set (so it's trying to generate the ipa)?

Only happens if Only export the project is unchecked, specifically during creating xcarchive step:

I did the same locally, and I didn't get that issue, so it might be something unrelated. I'm on an M1 (Monterey) with Xcode 14.2 and 14.3. It could be an Xcode 15 issue maybe?

@shana

shana commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

Ok, I pushed some updates to this:

  • Moved all the iOS/NativeAOT stuff to the Sdk, so the game csproj is small and simple again. The TargetFramework still needs to be set in the csproj itself for ios to work (because hiding that in the Sdk defaults would be confusing and easy to accidentally override), this is the extra block that gets generated now:
  <PropertyGroup Condition=" '$(GodotTargetPlatform)' == 'ios' ">
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
  • The xcode path is no longer hardcoded, it's found via xcode-select -p. Users can set an XcodePath property to override this behaviour, either in the csproj or in a Directory.Build.props file, like so:
<XCodePath>/Applications/Xcode_14_3.app/Contents/Developer</XCodePath>
  • Redirect the managed export plugin output to the console when running in headless mode (it was previously only being logged to the msbuild panel)
  • Improved detection of GodotPlatform when building from the command line with an rid
  • Applied feedback from review comments

For those testing this, you can still use the export templates that @akien-mga linked above (nothing has changed on those), but you'll need a new build of the editor to get the sdk and build tooling changes. Remember to wipe your nuget package cache (~/.nuget/packages/godot*) so it picks up your local builds!

@raulsntos raulsntos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good. I only have a few concerns about how these iOS-specific changes are intertwined with the rest of the export process.

Comment thread platform/ios/export/export_plugin.cpp Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
@akien-mga

Copy link
Copy Markdown
Member

I made another test build from the last commit of this PR (bfed26e), rebased on top of c2b9167:

https://downloads.tuxfamily.org/godotengine/testing/4.2-dev-pr82729/mono/

It's a full build for all platforms, including non-"mono" builds, as I used this as a pretext to test an update to our build containers. For what's relevant in this PR, this means macOS and iOS builds made with Xcode 15 via latest osxcross/cctools-port.

@shana
shana force-pushed the shana/ios-csharp branch from 7873b61 to ac9d351 Compare October 6, 2023 16:23
Comment thread modules/mono/.editorconfig Outdated
Comment thread platform/ios/export/export_plugin.cpp Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs Outdated
@shana
shana requested a review from raulsntos October 9, 2023 12:11
@shana
shana force-pushed the shana/ios-csharp branch from e682aad to c56f6c4 Compare October 9, 2023 13:54

@raulsntos raulsntos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks for the amazing work!

@akien-mga akien-mga modified the milestones: 4.3, 4.2 Oct 9, 2023
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
Comment thread modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs Outdated
@shana
shana force-pushed the shana/ios-csharp branch from c56f6c4 to 816efa2 Compare October 9, 2023 16:12

@AThousandShips AThousandShips left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style looks good!

This support is experimental and requires .NET 8

Known issues:
- Requires macOS due to use of lipo and xcodebuild
- arm64 simulator templates are not currently included
  in the official packaging
@shana
shana force-pushed the shana/ios-csharp branch from 816efa2 to ee9a735 Compare October 9, 2023 16:23

@akien-mga akien-mga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! Amazing work.

I haven't tested building the very latest iteration but it built fine a couple of days ago, I'm confident it's still the case. Let's get it tested widely in 4.2 beta 1 :)

@akien-mga
akien-mga merged commit 4a5801b into godotengine:master Oct 9, 2023
@akien-mga

Copy link
Copy Markdown
Member

Thanks so much!

@shana
shana deleted the shana/ios-csharp branch October 10, 2023 08:10
@issfire

issfire commented Oct 11, 2023

Copy link
Copy Markdown

Thank you so much for this awesome work!

I'm not super technical, so pardon me if I'm asking something really silly.

Would this in-theory also work with Hotfixing bugs on a Live iOS game?

e.g. I re-compiled all the scripts into a GameLogic.dll and do Assembly.LoadFile("GameLogic.dll")

BendyLand pushed a commit to BendyLand/voltaire that referenced this pull request Aug 2, 2026
BendyLand pushed a commit to BendyLand/voltaire that referenced this pull request Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

9 participants