-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to output a shim .exe + .dll for an application (for WinRT activation) #103451
Comments
Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov |
/cc @elinor-fung |
This doesn't seem like it has much utility beyond a WinRT activation scenario and appears to be a typical AppHost scenario. What is the difference here? |
So, there would basically be two different behaviors here depending on CoreCLR vs NativeAOT:
|
At least in theory, this can also be used whenever someone has some shared logic used by their app that they also want to expose in some other way (eg. library native with whatever ABI, be it WinRT, COM or whatever). Using this approach they can compile everything into a single .dll and not bloat their binary size with basically two copies of all the shared code (plus two copies of the whole runtime/GC, at least in the NativeAOT case). |
We had similar problem with iOS apps and NativeAOT. iOS apps have |
I remember Jeremy also mentioning that feature and suggesting we might be able to perhaps reuse it here too. Just so I understand, what part of the work would you imagine this generalized version of that feature would handle? Eg. would the shim .exe also be produced by the runtime/SDK, or would that have to be bundled by something else (eg. CsWinRT)? Another question I have is, how do you imagine the CoreCLR scenario would work? It seems to me that that would essentially have to be some combination of a shim .exe + basically DNNE (host + exports forwarder) + managed .dll(s)..? Just trying to understand how the various pieces would be structured and fit together here 😅 |
I expect that the .NET SDK would just do the minimum to get out of the way. It would be up to the app model specific SDK (e.g. CsWinRT) to produce the custom host and shim. It is how the current solution for iOS works. |
So like, on NativeAOT, the main difference between a fully undocked approach and this would be:
Is the above correct, on NativeAOT? And how would things look like with CoreCLR? Would the output still be a .dll (though managed), and that export be..? |
If we do this the same as iOS/Xamarin, it would mean that We don't currently have the same separation of linker arguments on Windows that we have on iDevices, so we'd need to introduce the same protocol (discussed around #88294 (comment)). |
Mmmh that kinda sounds like more work on CsWinRT itself alone that just doing everything with the fully decoupled approach we also discussed (source generated export + shim .exe both provided by CsWinRT). It's not entirely clear to me whether this additional work (plus what the runtime would need to do to enable this) is worth it just to allow users to not have to remove that single |
You can certainly require OutputType DLL and source generate the secret UnmanagedCallersOnly entrypoint that the shim EXE will call into. That would probably work for native AOT. I don't know how that would look for JIT based deployments, also with respect to VS integration (would need some prototyping). But if OutputType is Library, someone will need to figure out what is Main because the C# compiler will no longer do it. And top level statements won't work. So it's a bit of a UX regression, but could be okay. |
And also generate code to call Assembly.SetEntryAssembly so that the libraries that call |
Right, yeah we were thinking one option could be to try to match this ourselves in some way (eg. assemby name namespace +
Ooh, right 👀
I suppose I was just worried about the cost/complexity of doing all this from CsWinRT, and just thinking about options, is all. It is true though that as I mentioned, support for this is needed by WinUI 3 as well, so it might be worth it. cc. @manodasanW Could you elaborate on how you'd imagine things to work with CoreCLR? Because to me it seems like the NativeAOT scenario here is more straightforward (either with this custom main, or with a decoupled approach), whereas it's not entirely clear to me how things would be structured with CoreCLR (given that we'd presumably also need 2 native binaries there as well, the .exe and the .dll, so that native consumers can use either just like on NativeAOT, and then a managed .dll with the app code..?). And like, presumably we'd also need to use something like DNNE as well here so that the native exports ( |
You can either ship template shim .exe and host .dll, and patch the names in them during the build with the actual app name. It would mirror what .NET SDK does for regular console apps today. This works only if the set of the exports is fixed. Or you can create the shim and host on the fly by compiling C/C++ sources. This is more flexible, but it has a lot more moving parts so it will break more often. |
Right, yeah in our case we're thinking we could just bundle the shim .exe in CsWinRT (like we do our native host) 🤔
@MichalStrehovsky could you clarify why couldn't the runtime/SDK take care of building the native .dll, in the NativeAOT scenario? I mean, wouldn't it be possible for it to do that just like it does when building a shared lib (perhaps behind some flag?). Having to manually invoke the linker and do all that from CsWinRT seems potentially error prone (and complicated), but I would imagine the runtime already has all the necessary setup to do this like it does in other scenarios? |
It should not be that difficult to tweak regular publish of iOS SDK does not use our linker target. They use their own since they want to customize it heavily. So the current |
Yeah I can give it a try! And I can go I have a few more questions on what the general thing would look like:
I guess this was just me saying out loud what my understand is on this. Is this first part correct so far?
Anyway I'll try to put up a draft PR for that .targets and we can go from there I assume. Thank you! 🙂 |
Overview
We're working on enabling more scenarios on modern .NET for WinRT applications (WinUI 3, UWP). One such scenario involves applications that reference one or more WinRT components, and need to both be executed (as an app), as well as act as the implementation binary for those (merged) WinRT components.
To make this clearer, consider this scenario:
MyComponent.csproj
, which is a WinRT component. Common scenarios:IBackgroundTask
typesIBasicVideoEffect
typesWhen publishing your app, you need two different binaries being produced:
Main
from that .dllThis is because there's multiple activation paths for your app:
To make this all work, we need two features:
The latter is described in more detail in this .NET Native blog post:
We basically need to match this for modern .NET as well.
Proposal
Talking with @MichalStrehovsky about this, he suggested we might add some
UseShimExe
property, which would make the build produce these two components. Ideally, this would also make things work as expected when using CoreCLR, and not just NativeAOT.Internal tracking item (MSFT only): microsoft/OS/48896901.
Alternatives
We could do this entirely from the CsWinRT side (adding some source generator to produce a new
[UnmanagedCallersOnly]
method to invoke the user-defined entry point, and then bundle some native host to act as stub .exe, which we could copy to the output folder). The main issues with this approach though are that we'd need to ask users to mark their applications as using a library output type, which is very confusing and counter-intuitive, and that it's not entirely clear how we'd also make this work for CoreCLR.The text was updated successfully, but these errors were encountered: