From c567bd94191ae2197f44885d14b6f3ad52fa2df9 Mon Sep 17 00:00:00 2001 From: qingmo Date: Wed, 10 Jun 2026 10:36:15 +0800 Subject: [PATCH 1/5] Fix Carthage build failures on modern Xcode The pinned dependencies (GCDWebServer 3.4.1, JSONModel, KeePassHTTPKit) date from ~2019 and fail to build with current Xcode for two reasons: 1. Their deployment targets (macOS 10.7 / iOS 8.0) are below the supported minimum, so linking fails with "SDK does not contain 'libarclite'" because Apple removed libarclite_*.a in Xcode 14.3+. 2. GCDWebServer and JSONModel each ship several shared schemes that build a framework with the same product name (e.g. both "JSONModel" and "JSONModel-mac" produce JSONModel.framework). Carthage builds them in parallel and they race to write the same path in Carthage/Build/Mac, so the macOS framework is intermittently clobbered by an iOS build ("building for macOS, but linking in dylib built for iOS") or an arm64-only iOS-device slice (arch-mismatch link errors). Fixes: - Add carthage-deployment-target.xcconfig that raises the deployment targets to the supported minimums (macOS 10.13 / iOS 12.0) and pins ARCHS to arm64 (native arch on Apple Silicon; matches MacPass). - Add build-deps.sh that injects the xcconfig via XCODE_XCCONFIG_FILE and runs checkout -> prune -> build, deleting the duplicate non-macOS schemes so exactly one scheme per framework remains. This makes the build deterministic (verified across repeated clean and incremental runs). The fix lives in the script/xcconfig because carthage re-checks-out and overwrites the dependency projects on every run. - Update README to document the build-deps.sh workflow. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 27 ++++++++- build-deps.sh | 88 +++++++++++++++++++++++++++++ carthage-deployment-target.xcconfig | 27 +++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100755 build-deps.sh create mode 100644 carthage-deployment-target.xcconfig diff --git a/README.md b/README.md index eb00596..debbb99 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,33 @@ cd MacPassHTTP * Install [Carthage](https://github.com/Carthage/Carthage#installing-carthage) * Fetch and build dependencies for MacPassHTTP ```bash -carthage bootstrap --platform macOS +./build-deps.sh ``` + + > **Note:** Use `./build-deps.sh` instead of calling `carthage bootstrap` directly. + > The pinned dependencies (GCDWebServer 3.4.1, JSONModel, KeePassHTTPKit) date from + > ~2019 and need two workarounds on modern Xcode, both handled by the script: + > + > 1. **Deployment targets** (macOS 10.7 / iOS 8.0) are below what modern Xcode + > supports, so linking fails with `SDK does not contain 'libarclite'` (Apple + > removed `libarclite_*.a` in Xcode 14.3+). The script injects + > `carthage-deployment-target.xcconfig` via `XCODE_XCCONFIG_FILE`, raising the + > targets to the supported minimums and pinning `ARCHS = arm64`. + > 2. **Duplicate schemes:** GCDWebServer and JSONModel each ship several shared + > schemes that build a framework with the *same* product name (e.g. both + > `JSONModel` and `JSONModel-mac` produce `JSONModel.framework`). Carthage + > builds them in parallel and they race to write the same path in + > `Carthage/Build/Mac`, so you intermittently get an iOS framework + > (`building for macOS, but linking in dylib built for iOS`) or an arm64-only + > iOS slice where the macOS framework should be. The script splits the build + > into `checkout → prune → build`, deleting the duplicate non-macOS schemes so + > exactly one scheme per framework remains. + > + > The build is arm64-only (matches MacPass running natively on Apple Silicon). + > The script forwards arguments to `carthage`, e.g. `./build-deps.sh update`. + > Editing the dependency Xcode projects directly does not stick — `carthage` + > re-checks-out and overwrites them on every run, which is why the fixes live in + > the script and xcconfig. * Clone MacPass and fetch and build dependencies ```bash cd .. diff --git a/build-deps.sh b/build-deps.sh new file mode 100755 index 0000000..8257a19 --- /dev/null +++ b/build-deps.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# +# build-deps.sh — fetch and build MacPassHTTP's Carthage dependencies. +# +# Two problems make a plain `carthage bootstrap --platform macOS` fail with the +# pinned, ~2019-era dependencies on modern Xcode: +# +# 1. Deployment targets (macOS 10.7 / iOS 8.0) are below what modern Xcode +# supports, so the link step fails with "SDK does not contain 'libarclite'" +# (Apple removed libarclite_*.a in Xcode 14.3+). Fixed by +# carthage-deployment-target.xcconfig, injected via XCODE_XCCONFIG_FILE, +# which raises the targets to the supported minimums and pins ARCHS. +# +# 2. GCDWebServer and JSONModel each ship several shared schemes that build a +# framework with the SAME product name (e.g. both "JSONModel" and +# "JSONModel-mac" produce JSONModel.framework; "GCDWebServers (iOS)" and +# "GCDWebServers (Mac)" produce GCDWebServers.framework). Carthage builds all +# macOS-eligible schemes in parallel and they race to write the same path in +# Carthage/Build/Mac. Depending on which build wins the race you intermittently +# get an iOS framework ("building for macOS, but linking in dylib built for +# iOS") or an arm64-only iOS-device slice (arch-mismatch link errors) in place +# of the real macOS framework. We split bootstrap into checkout -> prune -> build +# and delete the duplicate non-macOS schemes so exactly one scheme per +# framework remains, making the build deterministic. +# +# Usage: +# ./build-deps.sh # checkout, prune duplicate schemes, build (macOS) +# ./build-deps.sh update # carthage update (re-resolve), then prune + build +# ./build-deps.sh # forwarded verbatim to carthage (with xcconfig) + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +XCCONFIG="$SCRIPT_DIR/carthage-deployment-target.xcconfig" +CHECKOUTS="$SCRIPT_DIR/Carthage/Checkouts" + +if ! command -v carthage >/dev/null 2>&1; then + echo "error: carthage not found. Install it: https://github.com/Carthage/Carthage#installing-carthage" >&2 + exit 1 +fi +if [ ! -f "$XCCONFIG" ]; then + echo "error: missing $XCCONFIG" >&2 + exit 1 +fi + +run_carthage() { + echo "==> XCODE_XCCONFIG_FILE=$XCCONFIG" + echo "==> carthage $*" + XCODE_XCCONFIG_FILE="$XCCONFIG" carthage "$@" +} + +# Keep exactly one macOS scheme per framework so Carthage's parallel builds can't +# race two same-named frameworks into Carthage/Build/Mac. Safe to re-run; missing +# files are ignored. +prune_duplicate_schemes() { + echo "==> pruning duplicate non-macOS schemes from checkouts" + local removed=0 f + # JSONModel: keep JSONModel-mac, drop the iOS/tvOS/watchOS schemes. + for f in "JSONModel" "JSONModel-tvOS" "JSONModel-watchOS"; do + local p="$CHECKOUTS/jsonmodel/JSONModel.xcodeproj/xcshareddata/xcschemes/$f.xcscheme" + if [ -f "$p" ]; then rm -f "$p"; echo " removed jsonmodel scheme: $f"; removed=$((removed+1)); fi + done + # GCDWebServer: keep "GCDWebServers (Mac)", drop iOS/tvOS. + for f in "GCDWebServers (iOS)" "GCDWebServers (tvOS)"; do + local p="$CHECKOUTS/GCDWebServer/GCDWebServer.xcodeproj/xcshareddata/xcschemes/$f.xcscheme" + if [ -f "$p" ]; then rm -f "$p"; echo " removed GCDWebServer scheme: $f"; removed=$((removed+1)); fi + done + echo " pruned $removed scheme(s)" +} + +mode="${1:-bootstrap}" +case "$mode" in + bootstrap) + run_carthage checkout + prune_duplicate_schemes + run_carthage build --platform macOS + ;; + update) + shift + run_carthage update --no-build "$@" + prune_duplicate_schemes + run_carthage build --platform macOS + ;; + *) + # Anything else: forward verbatim (still with the xcconfig). + run_carthage "$@" + ;; +esac diff --git a/carthage-deployment-target.xcconfig b/carthage-deployment-target.xcconfig new file mode 100644 index 0000000..299f262 --- /dev/null +++ b/carthage-deployment-target.xcconfig @@ -0,0 +1,27 @@ +// Build overrides for `carthage bootstrap`, injected via XCODE_XCCONFIG_FILE. +// +// The pinned dependencies (GCDWebServer 3.4.1, JSONModel, KeePassHTTPKit) date +// from ~2019 and declare deployment targets (macOS 10.7 / iOS 8.0) that modern +// Xcode no longer supports. ARC code at those targets links against +// libarclite_*.a, which Apple removed in Xcode 14.3+, so the link step fails: +// clang: error: SDK does not contain 'libarclite' ...; try increasing the +// minimum deployment target +// Raising the deployment targets to the supported minimums fixes this. +// +// Architecture: build arm64 only (the native arch on Apple Silicon, where +// MacPass also runs natively). The duplicate-scheme race that used to produce +// the wrong framework in Carthage/Build/Mac is handled separately by +// build-deps.sh (see its header); pinning a single arch here additionally keeps +// the output deterministic and matches the host. If you need to run on Intel +// Macs, build universal instead (e.g. carthage --use-xcframeworks or a +// post-build lipo) rather than this single-arch pin. +// +// Usage: prefer ./build-deps.sh, which injects this file. To invoke carthage +// directly: +// XCODE_XCCONFIG_FILE="$(pwd)/carthage-deployment-target.xcconfig" \ +// carthage bootstrap --platform macOS + +MACOSX_DEPLOYMENT_TARGET = 10.13 +IPHONEOS_DEPLOYMENT_TARGET = 12.0 +ARCHS = arm64 +ONLY_ACTIVE_ARCH = NO From 57a40ba7d8728787641273d336e8d30a83834a78 Mon Sep 17 00:00:00 2001 From: qingmo Date: Wed, 10 Jun 2026 11:31:00 +0800 Subject: [PATCH 2/5] Add full build.sh that builds and installs the plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build-deps.sh only handled MacPassHTTP's own Carthage dependencies. The plugin also requires MacPass's dependencies and several modern-Xcode workarounds, none of which were scripted. Add build.sh to do the whole chain end to end. The plugin compiles against MacPass headers (HEADER_SEARCH_PATHS = ../MacPass/**) and links HNHUi/KeePassKit, so MacPass's own Carthage dependencies must be built first. build.sh: 1. Builds MacPass's dependencies (sibling ../MacPass checkout): inits submodules, prunes iOS/tvOS/watchOS schemes (same same-named-framework race as MacPassHTTP's deps), and builds only HNHUi, KeePassKit and KissXML — TransformerKit fails to compile on a modern SDK (removed Darwin 'xlocale' module) and the plugin does not need it. 2. Builds MacPassHTTP's dependencies via build-deps.sh. 3. Compiles the plugin with the overrides it needs on modern Xcode: MACOSX_DEPLOYMENT_TARGET=10.13 (project's 10.10 hits libarclite), ARCHS=arm64, MacPass's build dir added to FRAMEWORK_SEARCH_PATHS, and CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES=YES (the recursive header search path pulls source headers into framework modules, which -Werror rejects). 4. Stamps CFBundleVersion (the project's Versioning phase no-ops on clean builds, leaving "UNKNOWN") and embeds KeePassHTTPKit's transitive frameworks (GCDWebServers, JSONModel) into the installed plugin so it can load. Installs to ~/Library/Application Support/MacPass/MacPassHTTP.mpplugin. Update README to document the full and manual build paths. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 57 +++++++++++++++++++++++---- build.sh | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 8 deletions(-) create mode 100755 build.sh diff --git a/README.md b/README.md index debbb99..aa68dae 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,29 @@ Download the latest release from the [Releases page](https://github.com/MacPass/ ### Building from source +The dependencies and the MacPass plugin SDK predate current Xcode, so a plain +`carthage bootstrap` + `xcodebuild` no longer works out of the box. Two helper +scripts encapsulate the required workarounds (explained in the notes below): + +* `build.sh` — **full build**: builds MacPass's dependencies, MacPassHTTP's + dependencies, then compiles and installs the plugin. +* `build-deps.sh` — just MacPassHTTP's own Carthage dependencies. + +#### Quick build (recommended) + +```bash +git clone https://github.com/MacPass/MacPassHTTP +git clone https://github.com/mstarke/MacPass # sibling checkout, see layout below +cd MacPassHTTP +./build.sh +``` + +This installs the plugin to `~/Library/Application Support/MacPass/MacPassHTTP.mpplugin` +(arm64; restart MacPass to load it). The build is arm64-only, matching MacPass +running natively on Apple Silicon. + +#### Manual steps + * Clone the repository ```bash git clone https://github.com/MacPass/MacPassHTTP @@ -51,15 +74,23 @@ cd MacPassHTTP > Editing the dependency Xcode projects directly does not stick — `carthage` > re-checks-out and overwrites them on every run, which is why the fixes live in > the script and xcconfig. -* Clone MacPass and fetch and build dependencies +* Clone MacPass (as a sibling directory) and build the dependencies the plugin + needs. On modern Xcode the non-macOS schemes must be pruned first, and + TransformerKit fails to compile (removed Darwin `xlocale` module) but isn't + needed by the plugin, so build only the required dependencies: ```bash cd .. git clone https://github.com/mstarke/MacPass cd MacPass -git checkout 0.7.4 git submodule update --init --recursive -carthage bootstrap --platform macOS +carthage checkout +# remove iOS/tvOS/watchOS schemes so Carthage doesn't race same-named frameworks +find Carthage/Checkouts -path "*/xcshareddata/xcschemes/*.xcscheme" \ + \( -iname "*iOS*" -o -iname "*tvOS*" -o -iname "*watchOS*" \) -delete +XCODE_XCCONFIG_FILE="$(pwd)/../MacPassHTTP/carthage-deployment-target.xcconfig" \ + carthage build HNHUi KeePassKit KissXML --platform macOS ``` + (`build.sh` does all of the above for you.) * If your folder structure isn't like the following, you need to adjust the ````HEADER_SEARCH_PATHS```` to point to the MacPass folder ```` @@ -68,15 +99,25 @@ carthage bootstrap --platform macOS └─ MacPassHTTP ```` -* Change back to the MacPassHTTP folder, compile and install +* Change back to the MacPassHTTP folder, compile and install. The plugin's own + deployment target (10.10) is too low for modern Xcode, it must build arm64 to + match the dependencies, and it needs MacPass's built frameworks on the + framework search path: ```bash -cd .. -cd MacPassHTTP -xcodebuild +cd ../MacPassHTTP +XCODE_XCCONFIG_FILE="$(pwd)/carthage-deployment-target.xcconfig" xcodebuild \ + -scheme MacPassHTTP -configuration Release \ + MACOSX_DEPLOYMENT_TARGET=10.13 ARCHS=arm64 ONLY_ACTIVE_ARCH=NO \ + "FRAMEWORK_SEARCH_PATHS=\$(inherited) \$(PROJECT_DIR)/../MacPass/Carthage/Build/Mac" \ + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES=YES ``` + After the build, KeePassHTTPKit's own dependencies (GCDWebServers, JSONModel) + must be embedded into the installed plugin so it can load — `build.sh` does + this automatically. Again, prefer `./build.sh` over running these by hand. -The Plugin is moved to the plugin folder of MacPass automacially. +The plugin is installed automatically to MacPass's plugin folder: ````~/Library/Application Support/MacPass/MacPassHTTP.mpplugin```` +Restart MacPass to load it. ## License diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..cc45b32 --- /dev/null +++ b/build.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# +# build.sh — full build of the MacPassHTTP plugin on modern Xcode (Apple Silicon). +# +# Orchestrates the whole chain and installs the plugin to +# ~/Library/Application Support/MacPass/MacPassHTTP.mpplugin +# +# 1. MacPass (sibling repo) dependencies — the plugin compiles against MacPass +# headers (HEADER_SEARCH_PATHS = ../MacPass/**) and links HNHUi/KeePassKit, +# so MacPass's own Carthage deps must be checked out and built first. +# 2. MacPassHTTP's own Carthage deps — via ./build-deps.sh. +# 3. The plugin itself — xcodebuild, with the overrides explained below. +# 4. Embed KeePassHTTPKit's transitive frameworks (GCDWebServers, JSONModel) +# into the installed plugin so it can load (see step 4 for why). +# +# Requirements: +# - Xcode + carthage installed. +# - MacPass checked out as a sibling directory (../MacPass). Clone with: +# git clone https://github.com/mstarke/MacPass ../MacPass +# +# Usage: ./build.sh + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MACPASS="$(cd "$ROOT/.." && pwd)/MacPass" +XCCONFIG="$ROOT/carthage-deployment-target.xcconfig" +CONFIG="Release" +PLUGIN="$HOME/Library/Application Support/MacPass/MacPassHTTP.mpplugin" + +log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } +die() { printf '\033[1;31merror: %s\033[0m\n' "$*" >&2; exit 1; } + +command -v carthage >/dev/null 2>&1 || die "carthage not found. See https://github.com/Carthage/Carthage#installing-carthage" +command -v xcodebuild >/dev/null 2>&1 || die "xcodebuild not found. Install Xcode and run xcode-select." +[ -f "$XCCONFIG" ] || die "missing $XCCONFIG" +[ -d "$MACPASS/.git" ] || die "MacPass not found at $MACPASS. Clone it: git clone https://github.com/mstarke/MacPass \"$MACPASS\"" + +# Delete shared schemes for platforms we don't build (iOS/tvOS/watchOS). These +# old projects ship several schemes that emit a same-named framework; Carthage +# builds them in parallel for --platform macOS and they race to write the same +# path in Carthage/Build/Mac, intermittently leaving an iOS or arm64-only build +# where the macOS framework should be. Removing them leaves one macOS scheme per +# framework. Re-run safe; runs again after each checkout restores the schemes. +prune_non_macos_schemes() { + local checkouts="$1" + log "pruning iOS/tvOS/watchOS schemes under $checkouts" + find "$checkouts" -path "*/xcshareddata/xcschemes/*.xcscheme" \ + \( -iname "*iOS*" -o -iname "*tvOS*" -o -iname "*watchOS*" \) -print -delete || true +} + +# --------------------------------------------------------------------------- +log "1/4 Building MacPass dependencies ($MACPASS)" +# Submodule (DDHotKey) + Carthage deps. We build only what the plugin needs +# (HNHUi, KeePassKit and its KissXML dep); TransformerKit fails to compile on a +# modern SDK (removed Darwin 'xlocale' module) and the plugin doesn't need it. +git -C "$MACPASS" submodule update --init --recursive +XCODE_XCCONFIG_FILE="$XCCONFIG" carthage checkout --project-directory "$MACPASS" +prune_non_macos_schemes "$MACPASS/Carthage/Checkouts" +XCODE_XCCONFIG_FILE="$XCCONFIG" carthage build HNHUi KeePassKit KissXML \ + --platform macOS --project-directory "$MACPASS" + +# --------------------------------------------------------------------------- +log "2/4 Building MacPassHTTP dependencies" +"$ROOT/build-deps.sh" + +# --------------------------------------------------------------------------- +log "3/4 Building the MacPassHTTP plugin ($CONFIG)" +# Command-line settings (highest precedence) override the project's stale values: +# MACOSX_DEPLOYMENT_TARGET=10.13 project sets 10.10, too low -> libarclite link error +# ARCHS=arm64 match the arm64-only Carthage frameworks +# FRAMEWORK_SEARCH_PATHS += MacPass build dir, so , +# resolve to the built frameworks, not source headers +# CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES=YES +# the recursive HEADER_SEARCH_PATHS=../MacPass/** +# pulls source headers into framework modules, which +# -Werror would otherwise reject +XCODE_XCCONFIG_FILE="$XCCONFIG" xcodebuild \ + -project "$ROOT/MacPassHTTP.xcodeproj" -scheme MacPassHTTP -configuration "$CONFIG" \ + MACOSX_DEPLOYMENT_TARGET=10.13 ARCHS=arm64 ONLY_ACTIVE_ARCH=NO \ + "FRAMEWORK_SEARCH_PATHS=\$(inherited) \$(PROJECT_DIR)/../MacPass/Carthage/Build/Mac" \ + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES=YES + +[ -d "$PLUGIN" ] || die "build reported success but $PLUGIN is missing" + +# The project's "Versioning" build phase stamps CFBundleVersion from the git +# commit count, but on a clean build it runs before Info.plist exists in the +# output and silently no-ops, leaving the "UNKNOWN" placeholder. Stamp it here +# (same logic as the build phase: Release = commit count) so it's deterministic. +BUILD_NUMBER="$(git -C "$ROOT" rev-list --count HEAD 2>/dev/null || echo 0)" +/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUILD_NUMBER" "$PLUGIN/Contents/Info.plist" 2>/dev/null \ + || /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string $BUILD_NUMBER" "$PLUGIN/Contents/Info.plist" 2>/dev/null || true + +# --------------------------------------------------------------------------- +log "4/4 Embedding transitive frameworks into the plugin" +# The project embeds only KeePassHTTPKit.framework, but it dynamically links +# GCDWebServers and JSONModel (@rpath). KeePassHTTPKit declares an rpath of +# @loader_path/Frameworks, so place its deps there; otherwise the plugin fails +# to load. HNHUi/KeePassKit are NOT embedded on purpose — they resolve from the +# host MacPass.app via @executable_path/../Frameworks. +NESTED="$PLUGIN/Contents/Frameworks/KeePassHTTPKit.framework/Versions/A/Frameworks" +mkdir -p "$NESTED" +for fw in GCDWebServers JSONModel; do + rm -rf "$NESTED/$fw.framework" + cp -R "$ROOT/Carthage/Build/Mac/$fw.framework" "$NESTED/" +done + +log "Done. Installed plugin:" +echo " $PLUGIN" +echo " arch: $(lipo -info "$PLUGIN/Contents/MacOS/MacPassHTTP" 2>/dev/null | sed 's/.*: //')" +echo " version: $(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$PLUGIN/Contents/Info.plist" 2>/dev/null)" +echo "Restart MacPass to load it." From cca7552b85255ba0a6822e93834f4152c14b9276 Mon Sep 17 00:00:00 2001 From: qingmo Date: Wed, 10 Jun 2026 11:34:59 +0800 Subject: [PATCH 3/5] Bump MacPassHTTP version to 0.3.3 Raise CURRENT_PROJECT_VERSION (drives CFBundleShortVersionString) from 0.3.2 to 0.3.3 in both the Debug and Release configurations. Co-Authored-By: Claude Opus 4.8 (1M context) --- MacPassHTTP.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MacPassHTTP.xcodeproj/project.pbxproj b/MacPassHTTP.xcodeproj/project.pbxproj index 936f1ce..e85c01c 100644 --- a/MacPassHTTP.xcodeproj/project.pbxproj +++ b/MacPassHTTP.xcodeproj/project.pbxproj @@ -372,7 +372,7 @@ buildSettings = { BUNDLE_LOADER = ""; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.3.2; + CURRENT_PROJECT_VERSION = 0.3.3; DEPLOYMENT_LOCATION = YES; DSTROOT = "$(HOME)"; FRAMEWORK_SEARCH_PATHS = ( @@ -400,7 +400,7 @@ buildSettings = { BUNDLE_LOADER = ""; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.3.2; + CURRENT_PROJECT_VERSION = 0.3.3; DEPLOYMENT_LOCATION = YES; DSTROOT = "$(HOME)"; FRAMEWORK_SEARCH_PATHS = ( From 8f4ddae7ab019e0b480b7facae6b5baecfacd723 Mon Sep 17 00:00:00 2001 From: qingmo Date: Wed, 10 Jun 2026 11:46:27 +0800 Subject: [PATCH 4/5] Code sign the plugin at the end of build.sh MacPass runs `codesign --verify` on plugins and shows "Plugin is not properly signed" when it fails. xcodebuild leaves the bundle with only the arm64 linker's ad-hoc signature (no sealed resources), and the post-build Info.plist edit and framework copy would invalidate any real signature anyway. Add a final inside-out signing pass (nested frameworks deepest-first, then the outer bundle) plus a verify step. Defaults to ad-hoc, which MacPass accepts since it pins no signing anchor; override with CODESIGN_IDENTITY for a distributable build. Co-Authored-By: Claude Opus 4.8 (1M context) --- build.sh | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index cc45b32..bae41d2 100755 --- a/build.sh +++ b/build.sh @@ -12,6 +12,8 @@ # 3. The plugin itself — xcodebuild, with the overrides explained below. # 4. Embed KeePassHTTPKit's transitive frameworks (GCDWebServers, JSONModel) # into the installed plugin so it can load (see step 4 for why). +# 5. Code sign the bundle (inside-out) so MacPass will load it — MacPass runs +# `codesign --verify` and refuses unsigned plugins (see step 5 for why). # # Requirements: # - Xcode + carthage installed. @@ -27,6 +29,10 @@ MACPASS="$(cd "$ROOT/.." && pwd)/MacPass" XCCONFIG="$ROOT/carthage-deployment-target.xcconfig" CONFIG="Release" PLUGIN="$HOME/Library/Application Support/MacPass/MacPassHTTP.mpplugin" +# Signing identity for the final codesign pass. Defaults to ad-hoc ("-"), which +# is enough for MacPass to load the plugin (it doesn't pin a signing anchor). +# Export CODESIGN_IDENTITY="Developer ID Application: ..." for a distributable build. +SIGN_ID="${CODESIGN_IDENTITY:--}" log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } die() { printf '\033[1;31merror: %s\033[0m\n' "$*" >&2; exit 1; } @@ -50,7 +56,7 @@ prune_non_macos_schemes() { } # --------------------------------------------------------------------------- -log "1/4 Building MacPass dependencies ($MACPASS)" +log "1/5 Building MacPass dependencies ($MACPASS)" # Submodule (DDHotKey) + Carthage deps. We build only what the plugin needs # (HNHUi, KeePassKit and its KissXML dep); TransformerKit fails to compile on a # modern SDK (removed Darwin 'xlocale' module) and the plugin doesn't need it. @@ -61,11 +67,11 @@ XCODE_XCCONFIG_FILE="$XCCONFIG" carthage build HNHUi KeePassKit KissXML \ --platform macOS --project-directory "$MACPASS" # --------------------------------------------------------------------------- -log "2/4 Building MacPassHTTP dependencies" +log "2/5 Building MacPassHTTP dependencies" "$ROOT/build-deps.sh" # --------------------------------------------------------------------------- -log "3/4 Building the MacPassHTTP plugin ($CONFIG)" +log "3/5 Building the MacPassHTTP plugin ($CONFIG)" # Command-line settings (highest precedence) override the project's stale values: # MACOSX_DEPLOYMENT_TARGET=10.13 project sets 10.10, too low -> libarclite link error # ARCHS=arm64 match the arm64-only Carthage frameworks @@ -92,7 +98,7 @@ BUILD_NUMBER="$(git -C "$ROOT" rev-list --count HEAD 2>/dev/null || echo 0)" || /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string $BUILD_NUMBER" "$PLUGIN/Contents/Info.plist" 2>/dev/null || true # --------------------------------------------------------------------------- -log "4/4 Embedding transitive frameworks into the plugin" +log "4/5 Embedding transitive frameworks into the plugin" # The project embeds only KeePassHTTPKit.framework, but it dynamically links # GCDWebServers and JSONModel (@rpath). KeePassHTTPKit declares an rpath of # @loader_path/Frameworks, so place its deps there; otherwise the plugin fails @@ -105,6 +111,25 @@ for fw in GCDWebServers JSONModel; do cp -R "$ROOT/Carthage/Build/Mac/$fw.framework" "$NESTED/" done +# --------------------------------------------------------------------------- +log "5/5 Code signing the plugin (id: $SIGN_ID)" +# MacPass refuses to load plugins that fail `codesign --verify` (the UI shows +# "Plugin is not properly signed"; see MPPluginHost.m -_isSignedPluginURL:). +# xcodebuild leaves the bundle with only the arm64 linker's ad-hoc signature, +# which has no sealed resources, and the steps above (Info.plist edit, framework +# copy) would invalidate any real signature anyway — so we sign LAST, inside-out: +# nested frameworks deepest-first, then the outer bundle, which seals everything +# into Contents/_CodeSignature/CodeResources. MacPass doesn't pin a signing +# anchor, so an ad-hoc signature is accepted. +while IFS= read -r fw; do + codesign --force --sign "$SIGN_ID" "$fw" || die "failed to sign $fw" +done < <(find "$PLUGIN/Contents/Frameworks" -name "*.framework" -depth) + +codesign --force --sign "$SIGN_ID" "$PLUGIN" || die "failed to sign $PLUGIN" + +# Verify exactly as MacPass does before it loads the plugin. +codesign --verify --verbose "$PLUGIN" || die "codesign --verify failed for $PLUGIN" + log "Done. Installed plugin:" echo " $PLUGIN" echo " arch: $(lipo -info "$PLUGIN/Contents/MacOS/MacPassHTTP" 2>/dev/null | sed 's/.*: //')" From f6095ea9860b316c26dc288b527e59e3b89f32b9 Mon Sep 17 00:00:00 2001 From: qingmo Date: Wed, 10 Jun 2026 12:15:16 +0800 Subject: [PATCH 5/5] Fix collapsed Interface box in plugin settings UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two NSBoxes in MacPassHTTPSettings.xib are laid out with Auto Layout but their content views still use autoresizing masks, so the checkbox constraints inside never give the boxes an intrinsic height. The boxes were pinned only top/leading/trailing — no height or bottom — leaving box height an unconstrained free variable. This was harmless at the xib's fixed design size, but MacPass embeds the view and stretches it via Auto Layout (MPPluginPreferencesController), so the ambiguous height collapsed the Interface box and its checkboxes overlapped. Pin each box to its design height (Interface 90, Advanced 168) to remove the ambiguity. ibtool compiles with no errors or warnings. Co-Authored-By: Claude Opus 4.8 (1M context) --- MacPassHTTP/Base.lproj/MacPassHTTPSettings.xib | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MacPassHTTP/Base.lproj/MacPassHTTPSettings.xib b/MacPassHTTP/Base.lproj/MacPassHTTPSettings.xib index 964e8ff..da74007 100644 --- a/MacPassHTTP/Base.lproj/MacPassHTTPSettings.xib +++ b/MacPassHTTP/Base.lproj/MacPassHTTPSettings.xib @@ -88,6 +88,9 @@ + + + @@ -120,6 +123,9 @@ + + +