As a former Linux user, I love macOS for its UX but also hate how strong-handy Apple likes being in comparison to that and Windows. I decided to try and build my app, Tag Hierarchy Manager, for use on macOS by bundling it as an app. Avalonia Parcel can do a lot of the bulk work in compiling it as a .app bundle and packaging it in whatever (installer, ZIP, DMG). However, trying to get the app to work at this state results in the app being forcefully quit by macOS sending a SIGABRT.
The reason? The app hasn’t been signed properly, and Mac strongly enforces code-signing on packages to the point that you can’t even execute a .app bundle without at least ad-hoc signing the app. Ad-hoc signing still results in error messages from Gatekeeper telling you the app is damaged (it is not, Apple is just bullshitting you) – you’ll have to go into the settings to allow the app to run, or use the Terminal to remove the quarantine flag. A lot of hobbyist and free + open-source software relies on this sort of signing over what Apple wants, and in my opinion this is hostile to both parties, especially given that the Apple developer account costs nearly a hundred bucks a year and doxes personal developers.
For the record, Windows also does this with SmartScreen, and Microsoft is trying to enforce this with Windows 11 S or whatever they enforce on the PCs you get from Best Buy or Currys or whatever. Linux of course doesn’t have this, but that also means running Linux with all its associated jank and incompatibilities. For us who want to use Mac, here’s what I did:
Running apps from anywhere
To run apps from anywhere, you’ll need the terminal. Run this command and type your password in when the terminal asks for it.
sudo spctl --master-disable
Then, you’ll have to go into System Settings. Do not close it at all until this is done. Go to Privacy & Security, scroll all the way down to Security, and under “Allow Applications From”, choose Anywhere. macOS will nag you about how this is a bad idea and whatnot, if you’re doing this you probably already know the implications of doing so. Type your password in (or, uh, approve the change with your Apple Watch) and now apps downloaded anywhere should just work.
I don’t know if Apple will try to strong-hand you and change it behind your back. Who knows. But this should allow you to run apps from anywhere as normal.
Signing your own apps
This one I needed to consult Claude for, and I’m glad I did now. Firstly, package the app as you normally would. If you’re packaging a .NET app, you’ll need to have “Publish Single File” enabled because otherwise it’s not going to work.
Then, you’ll need to add the following entitlements into a file named entitlements.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
Save that into the same directory as your packaged app (you can move it, just change the location of entitlements.plist below). Then, in the terminal:
codesign --force --deep --options runtime --entitlements entitlements.plist --sign - ./yourapp.app
Hopefully then, your app should run!