Open Difegue opened 4 years ago
So I'm not sure things are as straight forward as you think unfortunately.
The initialization code in question starts here where we setup some things from our native launcher.
Visual Studio for Mac uses Xamarin.Mac, so it's already setup all of the setup, such as libxammac.dylib.
However, getting past initialization is only the first hurdle. Xamarin iOS and Mac depend runtime support (called toggle ref) to correctly handle memory with the native runtime engine. Mono provides us those APIs, but .NET core does not (yet) to my knowledge.
A member of our community, @filipnavara, did some work at some point looking at the integration and might be able to provide some tails.
As this is at least tangentially related to .NET 5, I'd like to also suggest you take a look at the meta tracking issue.
Please, let me know if that makes sense.
@chamons is right on point. There's currently no way to run Xamarin.Mac applications under .NET Core, or the CoreCLR runtime specifically. Attempts were made to do that but all of them were abandoned for one reason or another.
There is, however, a special "netcore" flavor of Mono runtime. This is currently hosted in the Mono repository (look for the netcore
directory for sample and build scripts) and slated to be moved into dotnet/runtime alongside CoreCLR. This special runtime offers all the classic Mono runtime APIs necessary for loading libxammac.dylib. It also offers the CoreCLR API entrypoints and can act as drop-in replacement for libcoreclr.dylib and System.Private.CoreLib.dll. You can look for the patch-app
(or link-mono
) target in netcore/Makefile.am to see how the replacement is done.
This special runtime is designed to work with Xamarin.Mac eventually but at this point it does not work out of the box yet. There are at least two or three dependencies on the managed side of Xamarin.Mac that rely on private APIs not available on .NET Core (TLS provider initialization, injecting NSAutoreleasePool in thread pool threads, etc.).
Oh, I'm afraid the example project is a bit misleading, my apologies. It uses .NET Core, but that's only to grab the nunit exe from nuget and start processes.
(I wasn't aware of the work on the CoreCLR/Mono hybrid though, very interesting!)
The call to the test runner itself uses mono, so I think it should be fine? Let me know if I'm mistaken :
/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono ~/.nuget/packages/nunit.consolerunner/3.10.0/tools/nunit3-console.exe XamarinMacTestProject/bin/Debug/XamarinMacTestProject.dll --config=Debug --result=TestResults.xml;format=nunit2
I looked into it, and I believe there is a mismatch between how guiunit-ng and nunit is setting things up.
Guiunit-ng: Before loading any test assemblies [setup Xamarin.Mac])(https://github.com/garuma/GuiUnitNg/blob/master/GuiUnitNg/GuiUnit/MonoMacMainLoopIntegration.cs#L34). This appears to make the check pass, as we've setup state.
nuint: I added the same setup before calling NSApplication.Init and it wasn't being hit.
I do not understand why however with my initial research.
Playing nicer with nunit proper and not requiring guiunit-ng is a reasonable enhancement request.
Thanks for looking into it!
I've switched the runner to GuiUnitNg for our Xamarin.Mac tests in the meantime and it seems to work fine.
Steps to Reproduce
NSApplication.Init()
in the test's AssemblySetupFixtureExpected Behavior
The Runtime initializes properly, and the test runs in NUnit.
Actual Behavior
NUnit passes a
null
EntryAssembly when running the test .dll, leading Xamarin.Mac to try guessing one from the dll's path when the runtime gets initialized.The guess is done in the native part here, and stored in the options'
xamarin_entry_assembly_path
field.Said path is then normally unmarshaled here, but that seems to fail and return
null
, leading to a crash during initialization:I feel a simple nullcheck when unmarshalling the
entry_assembly_path
would fix the issue, but it seems weird that the native part would fail like that.Environment
Build Logs
Example Project (If Possible)
XamarinNUnitTestProject.zip
Build the solution, then run the
XamarinTestRunner
project.The test project is
XamarinMacTestProject
and can be ran as-is in VS for Mac.The runner project is in .NET Core and basically just runs the NUnit console runner(provided through the matching nuGet package) with mono.
(I've seen a few forum posts encouraging the use of GuiUnit and the like, but it very much seems the base NUnit console runner would work here if that hurdle with the entryAssembly were to be fixed, since those tests don't need a message loop implementation.)