Skip to content

Commit 8a092ac

Browse files
committed
Makefile: add MacOS packaging targets
Add support for creating MacOS .pkg packages in the Makefile. Similar to the Debian packaging routine, this is broken into four steps: 1. Build the executables. 2. Copy executables & 'uninstall.sh' into the appropriate file structure to build the .pkg file. 3. Build the component package with 'pkgbuild' and the full package with 'productbuild'. Signed-off-by: Victoria Dye <[email protected]>
1 parent dbe05e1 commit 8a092ac

File tree

7 files changed

+213
-0
lines changed

7 files changed

+213
-0
lines changed

.vscode/settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"*.md": "markdown",
2525
"*.sh": "shellscript",
2626
"prerm": "shellscript",
27+
"postinstall": "shellscript",
2728
"Makefile": "makefile"
2829
}
2930
}

Makefile

+29
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ $(DEB_FILENAME): check-version $(DEBDIR)/root
6767
.PHONY: package
6868
package: $(DEB_FILENAME)
6969

70+
else ifeq ($(GOOS),darwin)
71+
# MacOS .pkg file
72+
# Steps:
73+
# 1. Layout files in _dist/pkg/payload/ as they'll be installed (including
74+
# uninstall.sh script).
75+
# 2. Create the product archive in _dist/.
76+
77+
# Platform-specific variables
78+
PKGDIR := $(DISTDIR)/pkg
79+
PKG_FILENAME := $(DISTDIR)/$(NAME)_$(VERSION)-$(PACKAGE_REVISION)_$(PACKAGE_ARCH).pkg
80+
81+
# Targets
82+
$(PKGDIR)/payload: check-arch build
83+
@echo
84+
@echo "======== Formatting package contents ========"
85+
@build/package/layout-unix.sh --bindir="$(BINDIR)" \
86+
--uninstaller="$(CURDIR)/build/package/pkg/uninstall.sh" \
87+
--output="$(PKGDIR)/payload"
88+
89+
$(PKG_FILENAME): check-version $(PKGDIR)/payload
90+
@echo
91+
@echo "======== Creating product archive package ========"
92+
@build/package/pkg/pack.sh --version="$(VERSION)" \
93+
--payload="$(PKGDIR)/payload" \
94+
--output="$(PKG_FILENAME)"
95+
96+
.PHONY: package
97+
package: $(PKG_FILENAME)
98+
7099
else
71100
# Packaging not supported for platform, exit with error.
72101
.PHONY: package

build/package/layout-unix.sh

100644100755
+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ case "$i" in
1212
BINDIR="${i#*=}"
1313
shift # past argument=value
1414
;;
15+
--uninstaller=*)
16+
UNINSTALLER="${i#*=}"
17+
shift # past argument=value
18+
;;
1519
--include-symlinks)
1620
INCLUDE_SYMLINKS=1
1721
shift # past argument
@@ -51,6 +55,12 @@ mkdir -p "$INSTALL_TO"
5155
echo "Copying binaries..."
5256
cp -R "$BINDIR/." "$INSTALL_TO/bin"
5357

58+
# Copy uninstaller script
59+
if [ -n "$UNINSTALLER" ]; then
60+
echo "Copying uninstall script..."
61+
cp "$UNINSTALLER" "$INSTALL_TO"
62+
fi
63+
5464
# Create symlinks
5565
if [ -n "$INCLUDE_SYMLINKS" ]; then
5666
LINK_TO="$DEBROOT/usr/local/bin/"

build/package/pkg/entitlements.xml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.security.cs.allow-jit</key>
6+
<true/>
7+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
8+
<true/>
9+
<key>com.apple.security.cs.disable-library-validation</key>
10+
<true/>
11+
</dict>
12+
</plist>

build/package/pkg/pack.sh

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/bin/bash
2+
die () {
3+
echo "$*" >&2
4+
exit 1
5+
}
6+
7+
# Directories
8+
THISDIR="$( cd "$(dirname "$0")" ; pwd -P )"
9+
10+
# Product information
11+
IDENTIFIER="com.github.gitbundleserver"
12+
INSTALL_LOCATION="/usr/local/git-bundle-server"
13+
14+
# Parse script arguments
15+
for i in "$@"
16+
do
17+
case "$i" in
18+
--version=*)
19+
VERSION="${i#*=}"
20+
shift # past argument=value
21+
;;
22+
--payload=*)
23+
PAYLOAD="${i#*=}"
24+
shift # past argument=value
25+
;;
26+
--output=*)
27+
PKGOUT="${i#*=}"
28+
shift # past argument=value
29+
;;
30+
*)
31+
die "unknown option '$i'"
32+
;;
33+
esac
34+
done
35+
36+
# Perform pre-execution checks
37+
if [ -z "$VERSION" ]; then
38+
die "--version was not set"
39+
fi
40+
if [ -z "$PAYLOAD" ]; then
41+
die "--payload was not set"
42+
elif [ ! -d "$PAYLOAD" ]; then
43+
die "Could not find '$PAYLOAD'. Did you run layout-unix.sh first?"
44+
fi
45+
if [ -z "$PKGOUT" ]; then
46+
die "--output was not set"
47+
fi
48+
49+
# Exit as soon as any line fails
50+
set -e
51+
52+
# Cleanup any old component
53+
if [ -e "$PKGOUT" ]; then
54+
echo "Deleting old component '$PKGOUT'..."
55+
rm -f "$PKGOUT"
56+
fi
57+
58+
# Ensure the parent directory for the component exists
59+
mkdir -p "$(dirname "$PKGOUT")"
60+
61+
# Build the component package
62+
PKGTMP="$PKGOUT.tmp"
63+
64+
# Remove any unwanted .DS_Store files
65+
echo "Removing unnecessary files..."
66+
find "$PAYLOAD" -name '*.DS_Store' -type f -delete
67+
68+
# Set full read, write, execute permissions for owner and just read and execute permissions for group and other
69+
echo "Setting file permissions..."
70+
/bin/chmod -R 755 "$PAYLOAD"
71+
72+
# Remove any extended attributes (ACEs)
73+
echo "Removing extended attributes..."
74+
/usr/bin/xattr -rc "$PAYLOAD"
75+
76+
# Build component package
77+
echo "Building core component package..."
78+
/usr/bin/pkgbuild \
79+
--root "$PAYLOAD/" \
80+
--install-location "/" \
81+
--scripts "$THISDIR/scripts" \
82+
--identifier "$IDENTIFIER" \
83+
--version "$VERSION" \
84+
"$PKGTMP"
85+
86+
echo "Component pack complete."
87+
88+
# Build product installer
89+
echo "Building product package..."
90+
/usr/bin/productbuild \
91+
--package "$PKGTMP" \
92+
--identifier "$IDENTIFIER" \
93+
--version "$VERSION" \
94+
"$PKGOUT"
95+
96+
echo "Product build complete."

build/package/pkg/scripts/postinstall

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
set -e
3+
4+
PACKAGE=$1
5+
INSTALL_DESTINATION=$2
6+
7+
# Directories
8+
INSTALL_TO="$INSTALL_DESTINATION/usr/local/git-bundle-server/"
9+
LINK_TO="$INSTALL_DESTINATION/usr/local/bin/"
10+
RELATIVE_LINK_TO_INSTALL="../git-bundle-server"
11+
mkdir -p "$LINK_TO"
12+
13+
# Create symlinks
14+
for program in "$INSTALL_TO"/bin/*
15+
do
16+
/bin/ln -Fs "$RELATIVE_LINK_TO_INSTALL/bin/$(basename $program)" "$LINK_TO/$(basename $program)"
17+
done
18+
19+
exit 0

build/package/pkg/uninstall.sh

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
set -e
3+
4+
THISDIR="$( cd "$(dirname "$0")" ; pwd -P )"
5+
PATH_TO_SYMLINKS="$THISDIR/../bin"
6+
7+
8+
# Ensure we're running as root
9+
if [ $(id -u) != "0" ]
10+
then
11+
sudo "$0" "$@"
12+
exit $?
13+
fi
14+
15+
# Get the current logged-in user from the owner of /dev/console
16+
LOGGED_IN_USER=$(stat -f "%Su" /dev/console)
17+
echo "Stopping the web server daemon for user '$LOGGED_IN_USER'..."
18+
sudo -u $LOGGED_IN_USER \
19+
"$THISDIR/bin/git-bundle-server" web-server stop --remove
20+
21+
# Remove symlinks
22+
for program in "$THISDIR"/bin/*
23+
do
24+
symlink="$PATH_TO_SYMLINKS/$(basename $program)"
25+
if [ -L "$symlink" ]
26+
then
27+
echo "Deleting '$symlink'..."
28+
rm -f "$symlink"
29+
else
30+
echo "No symlink found at path '$symlink'."
31+
fi
32+
done
33+
34+
# Remove application files
35+
if [ -d "$THISDIR" ]
36+
then
37+
echo "Deleting application files in '$THISDIR'..."
38+
rm -rf "$THISDIR"
39+
else
40+
echo "No application files found."
41+
fi
42+
43+
# Forget package installation/delete receipt
44+
echo "Removing installation receipt..."
45+
pkgutil --forget com.github.gitbundleserver || echo "Could not remove package receipt. Exiting..."
46+
exit 0

0 commit comments

Comments
 (0)