How to generate an installer package for Mac app? - macos

How can I create a single installer package for an OS X binary as well as a few configuration and script files?
Final folders should look like this:
Any help would be appreciated. Thanks.

Installers are great if you want various things to be placed in different spots – app here, documentation there, support files over here, etc. They're also great for providing configurability of the installation experience (optional extras), or hand-holding for an unusual type of installation that the user might not otherwise understand, or extra work (configuration scripts, permissions modifications, authentication, compatibility checking, etc.) that need to run during the installation process. There is nothing wrong with installers, contrary to the answer from #d00dle, although there is also nothing wrong with distributing your app through the App Store, or as a dmg.
For setting up your own installers, I highly recommend a program called Packages (http://s.sudre.free.fr/Software/Packages/about.html). I am in no way connected to it, but I use it to build the installer for an app that I work on. It greatly smoothes the process of making a complex installer, and has an excellent GUI interface.

There's also macOS Installer Builder, which is a CLI you can use to create an installer wizard for your .pkg: https://github.com/KosalaHerath/macos-installer-builder

macOS does not normally use installers. Applications are packaged in app containers with the extension .app. This container is "executable" but you're also able to dig in and see what is inside. This is also the format distributed through App Store.
You can create .pkg or .dmg "installers" if necessary, however this is clearly not something apple aims to be standard. I would advise to use the .app pattern and any scripts needed should be self contained and executed on first run.
You can use .dmg to distribute your application outside of App Store (this is still fairly normal).
macOS also includes a terminal program called productbuild that builds a product archive for the macOS Installer or the Mac App Store. Enter man productbuild into the Terminal on a Mac for the manual page.

Related

Uninstalling items installed by an .app when user deletes it, including SMJobBless helpers

The short version: is it possible to delete helper tools which were set up by the app (SMJobBless() etc.) when the app is deleted? If so, how?
The long version:
The Mac app we are developing unfortunately requires admin privileges to perform an occasional operation, and it also requires a background task to be live for other apps' plugins to connect to even when the app itself isn't running (this one can be unprivileged). The app will be signed with a Developer ID certificate, and distributed only outside the App Store.
We'd like the app to be a "good citizen" as far as possible, also on uninstall.
For the background task, we're using a login item, created using SMLoginItemSetEnabled(). This isn't amazing, because XPC messaging doesn't seem to work (we're using CFMessagePort instead - alternative suggestions welcome), but if the user deletes the app, the login item at least doesn't get loaded anymore on next login. I suspect there's still a trace of it somewhere in the system, but the executable inside the .app bundle is used, and when that disappears, the login item no longer runs.
For the occasional operation requiring admin rights, we've got a privileged helper tool which our app installs using SMJobBless(), and which implements a named XPC service, so the task spins up on demand when it receives a message from the main app. This is what Apple recommends and describes in its Even Better Authorization Sample.
The helper executable is copied to /Library/PrivilegedHelperTools/ by SMJobBless(), and the embedded launchd.plist ends up in /Library/LaunchDaemons/. Even though the OS has the information on which app "owns" the helper, it doesn't seem to uninstall it when the user deletes the app. Apple's sample is silent on uninstalling, other than the uninstall.sh script which is apparently intended to be used during development only. We don't need this helper while the app isn't running, so installing it as a full-blown launch daemon is slightly overkill, but we'd also like to avoid repeatedly annoying the user with the password prompt too. Besides, Apple advises against other forms of running code with admin privileges than SMJobBless() these days - for example SMJobSubmit() is marked deprecated.
So how do we clean up after ourselves?
I've found SMJobRemove(), but (a) when would we call that in our case - you can't run code on .app bundle deletion, or can you? and (b) it doesn't actually seem to clean up.
The only 2 things I can think of are not terribly satisfying:
Some kind of uninstaller app or script. But that seems pretty ugly too.
Don't worry about it and just leave a mess behind when the user deletes our app.
Update:
There have been some changes in this area with macOS 13.0 Ventura; there's an introduction to the new mechanism in the WWDC22 session 'What’s new in privacy'. The new SMAppService APIs support automatic cleanup for daemons, agents and login items. Unfortunately you'll of course still have to find a workaround for any older macOS versions you support.
Original answer:
There has been a similar question on the Apple Developer Forums at https://forums.developer.apple.com/thread/66821 - the recommendation by Apple is a manual uninstall mechanism, and consuming as few resources as possible if the user does not do this.
Apple DTS staff further recommended implementing a self-uninstall mechanism in the privileged launch daemon, to be triggered from the app via XPC. This is what we're going with.
I think the only solution you have right now is to use the uninstall shell code that you mentioned in order to physically remove the privileged helper from disk or to build an uninstaller for it. Either way you will have to ask the user to enter his/her password. This what all installers / uninstallers that require privileged access to the system do, and for a very good reason. That's why I avoid like the plague to use privileged helpers, but I understand that sometimes you really have to. I don't think it is good that you leave such a helper in the user's system, because it will reload next time the user starts up the computer.
I just checked ServiceManagement.h header and they state that SMJobRemove will be replaced by an API that will be made available through libxpc in the future. (Sometimes you really need to go to the headers to get extra info that the documentation does not give you.) Hopefully this promised replacement will uninstall it for us. However, I'd file a bug report and ask for that enhancement.
One solution you could consider is to include an uninstaller script or program in your .app bundle.
You can then pass the path of this small tool to your helper tool (via IPC) and have the execute the the uninstaller, thereby deleting itself. You will have to be careful that components are removed in the right order but it can be made to work.
You're correct that Apple does not provide an API to uninstall a helper tool installed with SMJobBless nor do they do so automatically. As for why macOS doesn't automatically do an uninstall, my educated guess is because macOS fundamentally doesn't have a unified concept of "install". While it's convention for apps to be located in /Applications (and a few other locations), it's perfectly valid for apps to be located and run from anywhere on the system including external drives and network drives. For example should macOS uninstall helper tools when apps disappear because the drive they're on is disconnected?
In terms of how to uninstall, doing so requires root permission and so realistically have the helper tool itself do the uninstall is the easiest option. You can have your app via XPC tell the helper to uninstall itself. Here's an example in Swift of how to do this; it's part of SwiftAuthorizationSample. The basic idea is:
Use the launchctl command line tool to unload the helper tool
Delete the helper tool executable
Delete the helper tool launchd plist
But there's a bit of additional complexity involved because launchctl won't let you unload a running process.

How to create application to launch wine and Windows application

I'm trying to use "wine" on MAC osX Sierra version 10.12, wine is version 1.9.19
In the terminal I can launch Windows applications, however its a pain to have to keep typing in:
/Applications/Wine\ Staging.app/Contents/MacOS/wine ~/.wine/drive_c/Program\ Files/HeidiSQL/heidisql.exe
I've searched around for a post on how to create shortcuts/applications to add to the launchpad, but so far none of the information has led me to a working end result. Either the locations of wine is different or it just doesn't work.
I've tried creating an application script:
do shell script "/Applications/Wine Staging.app/Contents/MacOS/wine ~/.wine/drive_c/Program Files/HeidiSQL/heidisql.exe"
But this won't run either.
For anyone having the same problem, in the end I created scripts which reside in my home folder:
Launch vi, create a file called HeidiSQL, insert:
wine ~/.wine/drive_c/Program\ Files/HeidiSQL/heidisql.exe
Save and exit file, grant file execute permissions:
chmod +x HeidiSQL
Launch wine terminal and type in ./HeidiSQL to launch, I then did the same for PSPad.exe:
wine ~/.wine/drive_c/Program\ Files\ \(x86\)/PSPad\ editor/PSPad.exe
I know this thread is a little old but I was just looking for something like this to launch HeidiSQL and I came up with these three solutions which I have tried and all of them work. I am putting my findings down here for it may help someone:
Wineskin (http://wineskin.urgesoftware.com), Playonmac (https://www.playonmac.com/en) and Winebottler
(http://winebottler.kronenberg.org)
Wineskin is a mac app that download and install (and manages, updates, etc) "wine" for you. It then creates a HeidiSQL.app (any name you want with any icon you want - but you need to configure it) around the windows.exe that includes the wine version selected and is completely self contained (does not need wine installed separately). Personally this is the neatest solution and my preferred even though there its a little more technical than Playonmac and similar to Winebottler. You need to read the instructions (which are very good) and you have choices to make as to the wine version to use and to configure the app. Noteworthy is that you need to change the windows version to XP rather than 7 or some buttons won't work.
Playonmac on the other hand is very user friendly. It has HeidiSQL listed on its website as compatible and its almost a single click install. You just select HeidiSQL from the list of programs and it will download everything you need for you. The only reason I prefer Wineskin is that it does not create a true self contained HeidiSQL.app. You can create a shortcut for it in your Applications folder but this will launch Playonmac and the app needs to be installed inside Playonmac. On the plus side, Playonmac will chose all the right settings for you to run the app correctly, the correct windows and wine version etc which is something you need to fiddle with with with Wineskin.
Winebottler again makes an app like Wineskin. The only real difference I could see is that with Wineskin the configuration app is actually part of the package whereas in Winebottler you have to recreate the package each time you make a change. I stuck with Wineskin. YMMV.

Installers and productbuild on OSX for Mac App Store

I have a product that I would like to distribute on the Mac App Store. For context, this is a Qt (5.3) app written in C++ on OSX 10.9 with Xcode 5.1.1. I have two questions:
1) When I use productbuild like such:
productbuild --component /path/to/my/Program.app /Applications Product-Installer.pkg
I get the Product-Installer.pkg as expected (this took some effort since the man pages made no mention that the bundle has to be signed before this will work) but when I run the installer, I do not see my app in /Applications. Even though the installer says it installed successfully, I am unable to find any evidence that Program.app was installed anywhere on my system. I am wondering if there is something I'm missing, similar to how not signing the bundle caused productbuild to give me a "The component [component] is not a bundle error?
2) My program has configuration files and I'm not sure what the best way is to handle these on install. For example, in the Windows-world, I would just install a config.ini file (for example) into the user's data folder during install. However, the way the docs read regarding Mac Store Apps, my take is that that's really not done...? I'm wondering then if the best way to handle this is to just generate the config.ini upon the first run of the app? How is this typically handled with App Store apps?
Thank you!
2) you would install them in the Application Support directory in your sandbox container.
Typically the configuration is called User Defaults and implemented with CFPreferences in plain old C or NSUserDefaults with Objective C. You would ship your UserDefaults.plist inside your package/bundle and register it on each launch of the app with registerDefaults:.

How do I include one application inside another?

Our .app download includes a tool (another, smaller, app) with it that we'd like to allow users to run from the "Applications" folder, but we don't want them to have to download more than one file.
Is there a way to include one .app inside another that will result in the OS automatically adding both of them to the Applications folder when the user drags and drops it in there from the dmg file we distribute? Or would we have to use a package that extracts two separate applications?
Thanks for your help.
I don't think that apps bundled inside other apps (i.e. helper apps) would show up in Mac OS X's (Lion) Launch Pad. Much less from the Finder for end-users.
Apple distributes Xcode through the Mac App Store and it has many apps : Xcode, Intruments, Quartz Composer, etc. Perhaps downloading an installer from the Store (as is done with Xcode) would be an option for you.
I realize it's an extra step for the user but I don't see how you can bundle multiple distinct apps in the App Store.
Aside from that, perhaps offer each software as a seperate download. Or revisite if the apps actually do need to be their own islands. Good luck!

How do I package a Mac OS application for install?

I know on windows there are a bunch of installer tools you can use to create an installer, but on Mac OS I've seen two ways to install apps:
A DMG file which you download, double-click, then run an application inside - the application typically has you drag an icon to another icon (representing the Applications folder) to install the app
Another type of file which launches an apparently standard installer, which sometimes brings up a warning like "This installer may run a program to determine if you can go ahead with the install"
What's the "standard" way of packaging an app for install on Mac OS? Is one of the above the Apple-recommended way?
Thanks.
Apple is very clearly making the "standard" to be downloading a program from the App Store. This has the benefit of making application installation transparent to the normal user. And, believe it or not, normal people have a lot of trouble with the concept of installing a program. Of course that benefit comes with some costs, but this isn't the place for that debate–there are plenty of other places for that.
Assuming you don't want to or can't go the App Store route, both PKG and DMG are common ways to distribute a program. Use a PKG if you need to install files aside from your application bundle (which should not be a common use case). In all other cases use a DMG that prompts the user to copy the application into the Applications folder. But a lot of your users will not understand that they need to do that (unless your target audience is solely knowledgeable computer users). They will run your application from the disk image. Ideally in this case, your program will detect that it is running from a disk image and offer to copy itself into the Applications folder.
Packages works well. If your deployment process must be kept simple, it is great.
The Quick build consists of dragging your .app onto Package and it is done.
For advanced packaging, you can also provide a certificate.
http://s.sudre.free.fr/Software/Packages/about.html
We're discussing two things:
first and most importantly, the standard method by which the bits of an executable get laid on the disk in a way that's accessible and properly registered by the system
second, the mechanism for preparing the .app, as recommended by Apple
An older marketing page on Apple's site says it's recommended to create packages (so the Installer application can move the bits in place) with the PackageMaker application.
Its usage is described here: mactech.com/articles/mactech/Vol.25/25.03/2503MacEnterprise-PackagingforSystemAdministrators/index.html.
But as others have mentioned, the elephant in the room is the MacAppStore(MAS for short). Until it's debut, what was standard for large companies was their own custom scripts rolled into an older-style 'bundle' package or using an executable like the VISE installer. Smaller developers usually tried to make their app installable via drag-drop, distributed in zip archives or disk images(for simplicity's sake).
The MAS is different: as of 10.7 it uses a package format (which debuted in 10.5) referred to as a flat package (really a xar archive, explanation here)
which is transferred over http to a hidden folder, installs directly to Applications(after which the temporary folder it is downloaded to is deleted). It drops its receipt and a bill or materials file into /private/var/db, and is therefore audit-able by the built-in command line pkgutil tool, described here: mactech.com/articles/mactech/Vol.25/25.12/2512MacEnterprise-PackagesReceiptsandSnow/index.html
A benefit of using the flat package format is you can pull things over the network more safely and efficiently, but it isn't as easy to work with as bundle packages if you are testing and modifying the package regularly, or iterating to ensure scripts that perform actions or checks work well. Even when flat, putting the pkg in a archive or disk image is recommended for flexibility. More distribution tools expect DMG's than zip's, so there's that as well.
Besides what Apple recommends and what is standard, common practice, there's this article: https://www.afp548.com/2010/06/03/the-commandments-of-packaging-in-os-x/ which discusses the why's and hows (although mainly for system administrators) of packaging for wider distribution. It is greatly recommended to get more of a feel of how and why things go wrong, and what to avoid.
Try Iceberg!
Another one package creator.
In OS X, many applications are just created as a Relocatable
application bundles that the user just need to copy to the
/Application folder (or any other location). In other cases, when you
need to perform some operations over the machine (such as adding users
or changing permissions) you can use a PKG installer (for example built using PackageMaker), which allows
executing some pre and post install scripts and support some basic
installation configuration, like selecting the installation drive.
Sometimes, as with complex server software, you need more flexibility, for example to show custom pages to
the end user requesting information required to install your
application, like the MySQL port and password or proxy information to
download requirements on the fly (or simply to make it look fancier
:)). For this cases there are other installer solutions like our BitRock
InstallBuilder (disclaimer, I'm one of the developers).
InstallBuilder also has the advantage of generating multiplatform
installers using the same project with very little customization per
platform.

Resources