Creating an app bundle for GTK applications
This article applies to macOS only.
See also: Multiplatform Programming Guide
│ English (en) │
For macOS you need to create an app bundle for an executable file in order to drop it on the dock or launch it by double-clicking. An app bundle is really just a special folder that can have the same name as the executable, but with an .app extension. Finder doesn't display the .app extension, although you'll see it if you use ls in a Terminal window.
The Carbon and Qt pages both explain how to create an app bundle for apps compiled with those widgetsets. With a GTK app, it's a bit more complicated since X11 always has to be running in order to run the app. Copy and paste the following script to a file named create_gtk_app.sh, use chmod +x on the file so macOS will let you run it, then run it as follows to create an app bundle (substitute the name of your own GUI app compiled with the GTK widgetset):
./create_gtk_app.sh execfile
Now you can drag and drop the resulting app bundle onto the dock just like any other application.
For more information, study the script.
Tip: In the script below, one of the lines is really long and may get chopped off when you print this page (but why would you print this page only to type it in again when you can just copy and paste?) --BigChimp 12:37, 24 November 2013 (CET). Here's the line on two lines. Just be sure it's all one line in your script file.
echo '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">' >>$plistfile
#!/bin/sh
# Force Bourne shell in case another shell is the default.
#
appname=$1
appfolder=$appname.app
macosfolder=$appfolder/Contents/MacOS
plistfile=$appfolder/Contents/Info.plist
if [ $appname = "lazarus" ]
then
appfile=/usr/local/share/lazarus/lazarus
else
appfile=$appname
fi
#
if [ "$appname" = "" ]
then
echo "Usage: $0 executable_file"
echo "Creates .app bundle (folder) for executable file that uses GTK widgetset"
elif ! [ -e $appfile ]
then
echo "$appfile does not exist"
elif [ -e $appfolder ]
then
echo "$appfolder already exists"
else
echo "Creating $appfolder..."
mkdir $appfolder
mkdir $appfolder/Contents
mkdir $appfolder/Contents/MacOS
mkdir $appfolder/Contents/Resources
#
if [ $appname = "lazarus" ]
then
# This is special case for lazarus IDE.
# Create a script file in .app folder that starts X11, then Lazarus.
echo '#!/bin/sh' >$macosfolder/$appname.sh
echo '# This script starts X11, then Lazarus.' >>$macosfolder/$appname.sh
echo 'open -a x11' >>$macosfolder/$appname.sh
echo "export DISPLAY=':0.0'" >>$macosfolder/$appname.sh
echo 'open -a '$appfile >>$macosfolder/$appname.sh #IMPORTANT! If you're running TCSH, or other,
chmod +x $macosfolder/$appname.sh # "open -a" doesn't work. Use "open" instead
else
# Instead of copying executable into .app folder after each compile,
# simply create a symbolic link to executable.
ln -s ../../../$appname $macosfolder/$appname
# Create a little script file in .app folder that opens executable with X11.
echo '#!/bin/sh' >$macosfolder/$appname.sh
echo '# This script opens the executable file with X11.' >>$macosfolder/$appname.sh
echo 'open ${0/%.sh}' >>$macosfolder/$appname.sh
chmod +x $macosfolder/$appname.sh
fi
#
# Create PkgInfo file.
echo "APPL????" >$appfolder/Contents/PkgInfo
#
# Create information property list file (Info.plist).
echo '<?xml version="1.0" encoding="UTF-8"?>' >$plistfile
echo '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' >>$plistfile
echo '<plist version="1.0">' >>$plistfile
echo '<dict>' >>$plistfile
echo ' <key>CFBundleDevelopmentRegion</key>' >>$plistfile
echo ' <string>English</string>' >>$plistfile
echo ' <key>CFBundleExecutable</key>' >>$plistfile
echo ' <string>'$appname'.sh</string>' >>$plistfile
echo ' <key>CFBundleInfoDictionaryVersion</key>' >>$plistfile
echo ' <string>6.0</string>' >>$plistfile
echo ' <key>CFBundlePackageType</key>' >>$plistfile
echo ' <string>APPL</string>' >>$plistfile
echo ' <key>CFBundleSignature</key>' >>$plistfile
echo ' <string>????</string>' >>$plistfile
echo ' <key>CFBundleVersion</key>' >>$plistfile
echo ' <string>1.0</string>' >>$plistfile
echo ' <key>CSResourcesFileMapped</key>' >>$plistfile
echo ' <true/>' >>$plistfile
echo '</dict>' >>$plistfile
echo '</plist>' >>$plistfile
fi