1#!/bin/sh
2set -e
3cd "$(dirname "$0")"
4
5CONFIG=release
6APP=Sequencer.app
7BIN=Sequencer
8
9# Signing identity. Override with: SIGN_ID="Some Identity" ./build.sh
10SIGN_ID="${SIGN_ID:-Sequencer Dev}"
11LOGIN_KEYCHAIN="$HOME/Library/Keychains/login.keychain-db"
12
13# Create a self-signed code-signing identity named "$SIGN_ID" in the login
14# keychain, so codesign works on a machine that has no dev certificate.
15create_cert() {
16 name="$SIGN_ID"
17 echo "Creating self-signed code-signing identity \"$name\"…"
18 tmp=$(mktemp -d)
19 openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \
20 -keyout "$tmp/key.pem" -out "$tmp/cert.pem" \
21 -subj "/CN=$name" \
22 -addext "basicConstraints=critical,CA:false" \
23 -addext "keyUsage=critical,digitalSignature" \
24 -addext "extendedKeyUsage=critical,codeSigning" >/dev/null 2>&1
25 openssl pkcs12 -export -legacy -out "$tmp/id.p12" \
26 -inkey "$tmp/key.pem" -in "$tmp/cert.pem" -passout pass: >/dev/null 2>&1 \
27 || openssl pkcs12 -export -out "$tmp/id.p12" \
28 -inkey "$tmp/key.pem" -in "$tmp/cert.pem" -passout pass: >/dev/null 2>&1
29 security import "$tmp/id.p12" -k "$LOGIN_KEYCHAIN" -P "" \
30 -T /usr/bin/codesign -T /usr/bin/security
31 # Trust it for signing, and let codesign use the key without a GUI prompt.
32 # Both are best-effort (may need the keychain password); a one-time
33 # "codesign wants to sign" prompt on first build is harmless — click Always Allow.
34 security add-trusted-cert -r trustRoot -p codeSign -k "$LOGIN_KEYCHAIN" \
35 "$tmp/cert.pem" >/dev/null 2>&1 || true
36 security set-key-partition-list -S apple-tool:,apple:,codesign: -s \
37 -k "" "$LOGIN_KEYCHAIN" >/dev/null 2>&1 || true
38 rm -rf "$tmp"
39}
40
41# Choose a signing identity: honour $SIGN_ID if present, else the first available
42# codesigning identity, else fall back to ad-hoc ("-", no certificate needed).
43pick_identity() {
44 if security find-identity -v -p codesigning 2>/dev/null | grep -qF "\"$SIGN_ID\""; then
45 printf '%s' "$SIGN_ID"; return
46 fi
47 first=$(security find-identity -v -p codesigning 2>/dev/null \
48 | sed -n 's/^[[:space:]]*[0-9][0-9]*)[[:space:]]*[0-9A-Fa-f]*[[:space:]]*"\(.*\)"$/\1/p' \
49 | head -n1)
50 if [ -n "$first" ]; then
51 echo "Identity \"$SIGN_ID\" not found; using \"$first\"." >&2
52 printf '%s' "$first"; return
53 fi
54 echo "No code-signing identity found — using ad-hoc signing (-)." >&2
55 echo " Run './build.sh --create-cert' to make a reusable self-signed \"$SIGN_ID\"." >&2
56 printf '%s' "-"
57}
58
59if [ "$1" = "--create-cert" ]; then
60 create_cert
61 shift
62fi
63
64swift build -c "$CONFIG"
65
66# (Re)build the .app bundle from scratch so stale files never linger.
67rm -rf "$APP"
68mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources"
69
70cp ".build/$CONFIG/$BIN" "$APP/Contents/MacOS/$BIN"
71
72cat > "$APP/Contents/Info.plist" <<'PLIST'
73<?xml version="1.0" encoding="UTF-8"?>
74<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
75<plist version="1.0">
76<dict>
77 <key>CFBundleName</key>
78 <string>Sequencer</string>
79 <key>CFBundleDisplayName</key>
80 <string>Clover Sequencer</string>
81 <key>CFBundleExecutable</key>
82 <string>Sequencer</string>
83 <key>CFBundleIdentifier</key>
84 <string>net.paperclover.Sequencer</string>
85 <key>CFBundlePackageType</key>
86 <string>APPL</string>
87 <key>CFBundleShortVersionString</key>
88 <string>1.0</string>
89 <key>CFBundleVersion</key>
90 <string>1</string>
91 <key>LSMinimumSystemVersion</key>
92 <string>14.0</string>
93 <key>NSHighResolutionCapable</key>
94 <true/>
95 <key>NSPrincipalClass</key>
96 <string>Sequencer.SeqApplication</string>
97 <key>CFBundleDocumentTypes</key>
98 <array>
99 <dict>
100 <key>CFBundleTypeName</key>
101 <string>Sequencer Project</string>
102 <key>CFBundleTypeRole</key>
103 <string>Editor</string>
104 <key>LSHandlerRank</key>
105 <string>Owner</string>
106 <key>LSTypeIsPackage</key>
107 <true/>
108 <key>NSDocumentClass</key>
109 <string>Sequencer.ProjectDocument</string>
110 <key>LSItemContentTypes</key>
111 <array>
112 <string>net.paperclover.sequencer.project</string>
113 </array>
114 <key>CFBundleTypeExtensions</key>
115 <array>
116 <string>sq</string>
117 </array>
118 </dict>
119 </array>
120 <key>UTExportedTypeDeclarations</key>
121 <array>
122 <dict>
123 <key>UTTypeIdentifier</key>
124 <string>net.paperclover.sequencer.project</string>
125 <key>UTTypeDescription</key>
126 <string>Sequencer Project</string>
127 <key>UTTypeConformsTo</key>
128 <array>
129 <string>com.apple.package</string>
130 </array>
131 <key>UTTypeTagSpecification</key>
132 <dict>
133 <key>public.filename-extension</key>
134 <array>
135 <string>sq</string>
136 </array>
137 </dict>
138 </dict>
139 </array>
140</dict>
141</plist>
142PLIST
143
144# Mark the bundle as an app package for Finder/Launch Services.
145printf 'APPL????' > "$APP/Contents/PkgInfo"
146
147IDENTITY=$(pick_identity)
148echo "Signing with: $IDENTITY"
149codesign --force --deep --sign "$IDENTITY" "$APP"
150
151echo "Built $APP"