| 1 | #!/bin/sh |
| 2 | set -e |
| 3 | cd "$(dirname "$0")" |
| 4 | |
| 5 | CONFIG=release |
| 6 | APP=Sequencer.app |
| 7 | BIN=Sequencer |
| 8 | |
| 9 | # Signing identity. Override with: SIGN_ID="Some Identity" ./build.sh |
| 10 | SIGN_ID="${SIGN_ID:-Sequencer Dev}" |
| 11 | LOGIN_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. |
| 15 | create_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). |
| 43 | pick_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 | |
| 59 | if [ "$1" = "--create-cert" ]; then |
| 60 | create_cert |
| 61 | shift |
| 62 | fi |
| 63 | |
| 64 | swift build -c "$CONFIG" |
| 65 | |
| 66 | # (Re)build the .app bundle from scratch so stale files never linger. |
| 67 | rm -rf "$APP" |
| 68 | mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" |
| 69 | |
| 70 | cp ".build/$CONFIG/$BIN" "$APP/Contents/MacOS/$BIN" |
| 71 | |
| 72 | cat > "$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> |
| 142 | PLIST |
| 143 | |
| 144 | # Mark the bundle as an app package for Finder/Launch Services. |
| 145 | printf 'APPL????' > "$APP/Contents/PkgInfo" |
| 146 | |
| 147 | IDENTITY=$(pick_identity) |
| 148 | echo "Signing with: $IDENTITY" |
| 149 | codesign --force --deep --sign "$IDENTITY" "$APP" |
| 150 | |
| 151 | echo "Built $APP" |