How to debug Mac OS X pkg? - macos

I built a Mac OS X bundle Frequon Invaders.app, and it runs fine. The executable was created with Go. Then I packaged it like this:
$ pkgbuild --component 'Frequon Invaders.app' --install-location /Applications FrequonInvaders.pkg
pkgbuild: Adding component at /Users/Dad/Documents/projects/Frequon-Invaders-2.2/installer-macos/Frequon Invaders.app
pkgbuild: Wrote package to FrequonInvaders.pkg
When I open FrequonInvaders.pkg in Finder, I get a "install Frequon Invaders" window that lets me go through the motions of installing it, and the Summary part says "Installation was successful". But when I look in /Applications, it's not there. Indeed none of the files in the bundle were installed.
[Updated] After looking around, I found that the package appears to have been installed right on top of the original place that Frequon Invaders.app was originally built. It seems that the --install-location /Applications was completely ignored!
Question:
How do I use pkgbuild to build a package that is really installed where install-location said to install it?

How to debug Mac OS X pkg?
Debugging .pkg files is tricky because there's no easy way to get verbose output.
sudo installer -pkg my_package.pkg -target / -verbose
This may help understand the step that's failing but it really doesn't help narrow the problem down...
Next, you can use a utility like The Unarchiver to extract the .pkg file. Your scripts will need to be extracted twice by this utility.
Note: If you prefer the command line:
xar -xf my_package.pkg # extract pkg
tar -xf Scripts # extract scripts
From there, you can attempt to troubleshoot what's going wrong with the scripts.
But in my case, the only way I was able to debug the scripts were to run the package over and over echoing debug statements to a file.
For example:
# preinstall
echo "here!" >> /Users/Tom/Desktop/debug.txt

for such simple installers it is always better to use a tool to do the work for you. I usually use the Packages tool
http://s.sudre.free.fr/Software/Packages/about.html
which is free and really really good.

Related

Installing without package manager, why does executable binary fail with "command not found" unless I make the commands start with "./"?

I'm learning to use GNU/Linux and I want to know how to install programs that cannot be installed with the package manager.
I downloaded the tarball with the Linux 64-bit Binaries (including one called "haxelib"), extracted it, changed directory in the terminal to their location (~/Downloads/things/haxe_20201231082044_5e33a78aa/), and used chmod to make them executable.
If I try a command such as haxelib list, then the terminal returns
haxelib: command not found
If I try ./haxelib list (the same command but with ./ at the start) instead, then the command works as expected.
Why can't I use it without the ./? Programs installed with the package manager can be used without the ./.
Edit: I should probably also ask: where should I put the files from the tarball? Should they all go together in the same place? I have a feeling that a folder named "things" in my Downloads folder is not the best place for them.

Mac installer overwrites ALL copies of file

I’m having an odd issue where my installer properly overwrites the previously installed app, but then overwrites the app in my build directory.
My installer build looks like this:
mkdir /tmp/foo
cp -R ~/Projects/MyApp/Builds/MacOSX/build/Release/MyApp.app /tmp/foo
pkgbuild --quiet --analyze --root /tmp/foo/ MyApp.plist
pkgbuild --quiet --root /tmp/foo/ \
--component-plist MyApp.plist \
--identifier com.mycompany.myapp \
--version $VERSION \
--install-location "/Applications" \
MyApp.pkg
productbuild --quiet --distribution "./Distribution.xml" \
--package-path "./" --resources "./Resources" \
--sign "Developer ID Installer: My LLC" "MyApp Installer.pkg"
Now, this works…it installs the app in the /Applications folder as I’d expect. But I was noticing some issues with my next Xcode build. After some investigating, I noticed that my build folder looked like this after the Xcode build and before running the installer:
drwxr-xr-x# 3 me staff 96 Jul 11 23:15 My.app
…and like this, AFTER running the installer:
drwxr-xr-x 3 root wheel 96 Jul 11 23:44 My.app
Somehow, the owner of my app had changed. I double checked everything and didn’t see anything that touched my build folder. But then I checked the installer log and found this mysterious line:
PackageKit: Applications/MyApp.app relocated to
Users/me/Projects/MyApp/Builds/MacOSX/build/Release/MyApp.app
After some googling, others have speculated that the installer overwrites ANY copy of the app it finds anywhere on the drive…not just the one in the folder you tell it. It makes some sense…if I delete that copy of my app in the build folder, the installer doesn’t create a new one. It only overwrites it if it’s there.
While this isn’t a huge problem, it’s somewhat problematic as it changes the owner of the file which prevents the next build from working.
Has anyone else run into this issue? Is there some option for the installer to NOT overwrite EVERY copy of the installed app?
The Installer has a few features that allow it to locate application bundles that have moved in the file system. Inside your compiled .pkg, have a look at the PackageInfo and Distribution files, and see if you see any <locator> tags. The <locator> tag is defined at the link below, and is one of the main ways to enable this sort of thing.
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html#//apple_ref/doc/uid/TP40005370-CH100-SW15
Another possibility is that you may have a <bundle> element with the search property set, as documented here:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html#//apple_ref/doc/uid/TP40005370-CH100-SW36
If you want to easily inspect the internal structure of your compiled package, you can use Pacifist to do that fairly easily. (disclaimer: I'm the author of Pacifist)
It's just a hunch, but I wonder if this can be solved by forgetting the current installs of your app by dropping the installation receipts like this:
sudo pkgutil --forget com.mycompany.myapp.pkg
You can get a list of all package receipts on your machine like this:
sudo pkgutil --pkgs
The reason I have this hunch is because I think the install locations might be stored in the receipts. Therefore causing the machine to "forget" (delete) where the packages are might make it so the installer has to install at the specified location specified by the package. I fully admit this is a WAG (wild-ass guess).

How to package a standalone xulrunner app for OS X?

I'm trying to create a xulrunner app for OS X 10.9+. I need it to be standalone, i.e. to not require any extra additional software (including Firefox) to be installed on the box along with the app.
I was not able to google up an up-to-date guide on how to do that. It seems that I've hit every issue described here: https://bugzilla.mozilla.org/show_bug.cgi?id=923979
One of the last ones is:
$ open MyApp.app
LSOpenURLsWithRole() failed with error -10810 for the file /Path/To/MyApp.app.
Here is an what I have so far:
https://drive.google.com/file/d/0BxRquYs2Nx92ZTZaVjk0QThMN2c/view?usp=sharing
How can I create an OS X .app for a modern (v36+) xulrunner application?
You are on the right track, there is just one major issue you are facing.
If you were to run you application by the command line, you would get some output like this.
$ SampleApplication.app/Contents/MacOS/xulrunner
Mozilla XULRunner 33.0
Usage: xulrunner [OPTIONS]
xulrunner APP-FILE [APP-OPTIONS...]
OPTIONS
--app specify APP-FILE (optional)
-h, --help show this message
-v, --version show version
--gre-version print the GRE version string on stdout
APP-FILE
Application initialization file.
APP-OPTIONS
Application specific options
As we can see, the executable did not automatically run the Contents/Resources/application.ini like the tutorials say it will. This is a known issue, and the popular workaround among XULRunner users is to create a stub shell script to pass the required argument to the xulrunner binary.
Here is a script I've whipped up to do just that.
#!/bin/sh
runpath="`dirname "$0"`"
contentsdir="`cd "$runpath"/.. > /dev/null && pwd`"
exec "$runpath/xulrunner" --app "$contentsdir/Resources/application.ini"
Save this text to a file in your MacOS directory and give it executable permissions. For sake of example, I will use sampleapplication. Here is the command to set executable permissions.
chmod +x sampleapplication
Now, modify your Info.plist to execute this script instead of executing xulrunner directly by setting the CFBundleExecutable entry to match your stub shell script.
<key>CFBundleExecutable</key>
<string>sampleapplication</string>
Now when you run your application, it should work. If you are getting an error saying "The application cannot be opened because its executable is missing", you may want to rename the application bundle, or follow the advice in that question to avoid the caching issue.
Bonus Info
You can remove the Contents/Frameworks/XUL.framework directory, it is no longer used and placing the XUL.framework contents in the MacOS folder is now the correct place to put them.
You should also copy the dependentlibs.list file from the Contents/MacOS to the Contents/Resources directory, although XULRunner 33 seems to be getting on fine without it.

OpenAFS install, packagemaker not found

I have tried to install openAFS directly from source code. This is for a MAC with OS Yosemite and I followed the instructions from an earlier question of mine:
https://stackoverflow.com/questions/26959675/afs-and-yosemite-on-mac
However I can do everything until: sudo make packages, were I get the error:
packagemaker not found
make: *** [packages] Error 1
I looked into where this error occurs and it wants something in:
/Developer/usr/bin/packagemaker
Do I need another piece of software to finish this installation?
thanks,
Alex.
Yes, you need PackageMaker installed. Note that this isn't technically required to build OpenAFS, but it is required to build the installer packages, which you probably want to do.
To install PackageMaker:
Download "Auxiliary Tools for Xcode - Late July 2012" from somewhere in developer.apple.com. I think this is somewhere in here.
Copy PackageMaker.app into /Applications/Utilities
Run:
$ sudo ln -s /Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker /Developer/usr/bin/PackageMaker
Then you should be able to make packages in the OpenAFS source tree.
References:
https://lists.openafs.org/pipermail/port-darwin/2013-November/001436.html
https://lists.openafs.org/pipermail/port-darwin/2013-November/001444.html
http://mid.gmane.org/CALCW7iK1jGarc+RNMu=3255FrOK3tk1aO75YWO0BCjPh6dggjA#mail.gmail.com
http://mid.gmane.org/201311200208.rAK28uH8028025#hedwig.cmf.nrl.navy.mil

How to use pkgbuild to create a kext installer from within Xcode

I understand PackageMaker is now deprecated. We're now supposed to use pkgbuild/productbuild.
However, I can't seem to find an example for creating an installer for a kext. I was hoping to build the package as part of a build step from my kext Xcode project. So any bash/script files would be great.
This answer is a seriously good guide for the general case.
For a kext specifically, after the Product -> Archive step, to generate the component plist, I found that I needed to 'cd' into the built archive package directory:
cd ~/Library/Developer/Xcode/Archives/2013-12-22/my-kext\ 22-12-2013\ 22.57.xcarchive
Then, the pkgbuild --analyze step looks like this:
pkgbuild --analyze --root ./Products/ my-kext.plist
The produced plist should contain a sensible-looking install destination for your kext under the RootRelativeBundlePath key. (typically /System/Library/Extensions/my.kext, or if codesigned and for 10.9+ it should be /Library/Extensions/my.kext) If not, fix the install location for your kext target in Xcode.
The main thing to watch out for when installing kexts is to get permissions right and to refresh the kext cache. pkgbuild seems to install the kext as root by default, so that's good. To force refreshing the kext cache, you need to update the modified time on /System/Library/Extensions (or /Library/Extensions if that's where you're installing to). You want to do this after your kext has been fully installed, so you'll need a postinstall script. Create a directory for it, e.g. ./scripts and create a file called 'postinstall' with the contents:
#!/bin/sh
touch /System/Library/Extensions
Then make it executable:
chmod +x postinstall
You can now build a generic package for your kext using:
pkgbuild --root ./Products/ --scripts ./scripts/ --component-plist my-kext.plist my-kext.pkg
For customisation, codesigning, etc., follow the instructions in catlan's linked answer - you can't beat them!

Resources