dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.68k stars 1.06k forks source link

When building for MacOs on PC, give us an option to Pre-bundle #24467

Open shmellyorc opened 2 years ago

shmellyorc commented 2 years ago

Background and motivation

When developing for MacOs on a PC. I had to make a bundle which can be very annoying to set up. Every time I make a build for mac, I am like, "cmon bundle template, lets get to work".

Give us an option to allow us to prebundle our macOS apps on PC.

When I first published a MacOS build I thought it would bundle it up for me so I could just send it out.

I can set my metadata in my prorject.csproj as in copyright, version, etc but I cannot use that info into bundle or plist file?

API Proposal

Pretty simple.

  1. When setting your app.csprog file as for version, applicationicon, description, copyright, and other metadata tags for build projects, let it make a bundle from that info to generate a MacOs bundle. I thought building for MacOs on my PC would do this automatically.
  2. It would construct a bunch of folders to construct a MacOs bundle that will be descripted below. MacOS Bundle isn't anything special or requires advanced knowledge of how it works. It is just a bunch of folders and normal xml or text files.
  3. I know others may not like this option so don't make it enforced BUT have an option in the publish process for MacOs to allow to prebundle. something like this: "dotnet publish -c Release -r osx-x64 -prebundle"

Bundle file structure looks like this: appname.app(folder): ...Contents(folder) -> ......MacOs(folder) -> All dlls, application, and library dlls go here ......Resources(folder) -> All content, application .icns goes here ......Info.plist(file) -> all the metadata inside app.csprog can be transferred here to what specs plist requires but can be very similar ......Pkginfo(file) -> it is pretty much APPL???? nothing special but required to run the application. It is just metadata telling how this app should run. APPL means its telling macOS that is is a application. So it'll just run it.

API Usage

n/a

Alternative Designs

n/a

Risks

I don't really see any risks, it would be a way speed up production, not slow us down.

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

Joe4evr commented 2 years ago

This is likely not possible due to the requirement of code signing on macOS.

shmellyorc commented 2 years ago

This is likely not possible due to the requirement of code signing on macOS.

Thats not true.

I used: dotnet publish -c Release -r osx-x64 /p:PublishReadyToRun=false /p:TieredCompilation=false --self-contained

and bundled my project myself and it runs. It does required chmod but it does run perfectly.

The application is just a normal dotnet core 6 console application with libraries of MonoGame and Monogame Content Pipeline.

as proof. Those are Pizzamon.app bundle structure (the game has over 500+ files in it) not extracted, etc:

https://user-images.githubusercontent.com/5901214/159249235-cbadf1ed-172a-4f05-8282-b5e5eaed24bb.mp4

filipnavara commented 2 years ago

Code signing is one thing. It's technically possible to do it on Windows but not practical due to the requirement of Apple account and getting the certificates. Visual Studio does that to support some Xamarin scenarios so that part would be doable. However, for anything targeting net6.0-macos TFM you'd need the developer tools that are proprietary and only available on macOS, so at minimum you'd still need the remote macOS machine (just as Xamarin.iOS does for anything beyond the limited Hot Restart technology).

shmellyorc commented 2 years ago

Code signing is one thing. It's technically possible to do it on Windows but not practical due to the requirement of Apple account and getting the certificates. Visual Studio does that to support some Xamarin scenarios so that part would be doable. However, for anything targeting net6.0-macos TFM you'd need the developer tools that are proprietary and only available on macOS, so at minimum you'd still need the remote macOS machine (just as Xamarin.iOS does for anything beyond the limited Hot Restart technology).

Kinda scratching my head... did you look at my previous reply?

filipnavara commented 2 years ago

I did... if you target net6.0-macos instead of net6.0 it does exactly the bundle structure that you ask for. It does depend on the native compiler, resource compilers, code signing tools and other things not available for Windows, often for licensing reasons or lack of non-Apple alternatives.

shmellyorc commented 2 years ago

I did... if you target net6.0-macos instead of net6.0 it does exactly the bundle structure that you ask for. It does depend on the native compiler, resource compilers, code signing tools and other things not available for Windows, often for licensing reasons or lack of non-Apple alternatives.

Ah ok, rip. I guess i'll have to make m own bundler than :D. End of the day I just make games and signing can be VERY expensive so I don't plan on going that route nor do I like MacOs. You know how hard it is to get a previous directory on a MacOs using dotnet6? It is like trying to move a boat with one person.

Anways, I gave it a shot anyways. I'll keep it up, maybe others may like this option for non dotnet6-macos to able to prebundle even if its not code signed. 👯

In my thoughts, "options are always better than none"

filipnavara commented 2 years ago

Distributing unsigned apps is a non-starter since no recent version of macOS allows you to run such apps unless you disable system integrity protection.

Note that the Apple account necessary for code signing can be created for free with certain restrictions. For distributing the apps you may need the $99/year account but there are other ways to enroll (eg. through university). However, that is all beyond scope of the question and there are multiple resources describing Apple policies.

The code signing itself is not technical problem, it can easily be implemented in .NET. Getting the certificates from the Apple developer portal is a bit of a pain though. And for external distribution you'd need to notarize the application after signing. Firstly, that requires Apple tools that are not generally available. Secondly, it may even require encryption keys that not available on non-Apple hardware.

However, beyond anything trivial you need the resource compiler to produce appropriate icon resources and other content in the bundle. These tools are not open source and the Apple ones are not licensed for running on other systems (which is technically possible to very limited extent).

The closest technology to actually achieving the goal is Xamarin Hot Restart. It starts with a prebuilt iOS app bundle which is augmented with user's .NET code and then signed on Windows with certificate from your Apple account. This technology, however, is intended to accelerate the development cycle on Windows machine with locally connected Apple device. It is by no means targeting bundling for end users due to the aforementioned limitations on tools.

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

baronfel commented 2 years ago

Looking at the CreateAppHost task and target in the SDK, and the HostWriter sources that are used by them, it seems like we conflate codesign with bundle generation. Could we break those up into to distinct steps and run them as separate targets, allowing users like @shmellyorc the ability to do their flow with minor modifications, something like <MacOSSignBundle>false</MacOSSignBundle>?

teo-tsirpanis commented 2 years ago

This is not suggesting an API for the BCL. The api-suggestion label should be removed.

vitek-karas commented 1 year ago

Looking at the CreateAppHost task and target in the SDK, and the HostWriter sources that are used by them, it seems like we conflate codesign with bundle generation. Could we break those up into to distinct steps and run them as separate targets, allowing users like @shmellyorc the ability to do their flow with minor modifications, something like false

The signing done by the HostWriter is only for development scenarios. It uses the self-signed default certificate and typically only works on the machine where it was signed. It is explicitly NOT for signing the app with real certificate for store distribution. It needs to be there in order to make it possible to run the compiled app on macOS at all (as the OS will not run unsigned code, any unsigned code).