Dear friends,
on MacOS, I have noticed a few problems with Lazarus 4.6 and I would like to share some workaround.
First issue is the management of icons. Mac uses a format .icns that contains several versions of the icon.
The workaround proposed by Claude (it works but the size is interpreted as 0x0 and it does not display if Project Options -> Application):
# 1. Convert .ico to .png as needed
sips -s format png MyIcon.ico --out MyIcon.png
# 2. Create the iconset directory
mkdir MyIcon.iconset
# 3. Produce icons of different sizes from the png
sips -z 16 16 MyIcon.png --out MyIcon.iconset/icon_16x16.png
sips -z 32 32 MyIcon.png --out MyIcon.iconset/icon_16x16@2x.png
sips -z 32 32 MyIcon.png --out MyIcon.iconset/icon_32x32.png
sips -z 64 64 MyIcon.png --out MyIcon.iconset/icon_32x32@2x.png
sips -z 128 128 MyIcon.png --out MyIcon.iconset/icon_128x128.png
sips -z 256 256 MyIcon.png --out MyIcon.iconset/icon_128x128@2x.png
sips -z 256 256 MyIcon.png --out MyIcon.iconset/icon_256x256.png
sips -z 512 512 MyIcon.png --out MyIcon.iconset/icon_256x256@2x.png
sips -z 512 512 MyIcon.png --out MyIcon.iconset/icon_512x512.png
sips -z 1024 1024 MyIcon.png --out MyIcon.iconset/icon_512x512@2x.png
# 4. Create the .icns
iconutil -c icns MyIcon.iconset -o MyIcon.icns
Then, the bundle produced by Lazarus does not work because it is not signed, the executable is not copied in the MacOS directrory of the bundle and the icon is not properly located in the Resource directory. And of course, the Info.plist must be updated accordingly. To solve these issues I propose the following post-build script -thanks to Claude:
#!/bin/bash
# Usage: ./MacPostBuild.sh <ProjPath> <TargetFile> <IconFile> <BundleIdentifier>
# Example: ./MacPostBuild.sh "$ProjPath" "$TargetFile" "MyIcon" "com.mycompany.myapp"
set -e
export ProjPath=${1%/}
export TargetFile=${2%/}
export IconFile=$3
export BundleID=$4
cp "$ProjPath/$IconFile.icns" "$TargetFile.app/Contents/Resources/" || { echo "ERROR: copy of the icon failed"; exit 1; }
# Replace the symbolic link with a true copy
rm "$TargetFile.app/Contents/MacOS/$(basename $TargetFile)"
cp "$TargetFile" "$TargetFile.app/Contents/MacOS/" || { echo "ERROR: copy of the executable code failed"; exit 1; }
/usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string $BundleID" "$TargetFile.app/Contents/Info.plist" 2>/dev/null || \
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BundleID" "$TargetFile.app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Add :CFBundleIconFile string $IconFile" "$TargetFile.app/Contents/Info.plist" 2>/dev/null || \
/usr/libexec/PlistBuddy -c "Set :CFBundleIconFile $IconFile" "$TargetFile.app/Contents/Info.plist"
codesign --force --deep -s - "$TargetFile.app" 2>/dev/null || { echo "ERROR: signing app failed"; exit 1; }
# Force refresh of the icon display
touch "$TargetFile.app"
The last touch command will force the refresh of the icon in Finder, so the compiled .app display correctly.
The script have to be called as post-build :
/bin/bash $(ProjPath)/MacPostBuild.sh "$(ProjPath)" "$(TargetFile)" "MyIcon" "com.mycompany.myapp"
I hope this can be of some help to Mac users and sorry if it is a duplicate in another place of the forum.
Ciao,
Gilles Marcou