Skip to content

Native Apple Silicon: migrate Carthage → Swift Package Manager, ship a universal binary - #209

Open
StealthWire wants to merge 1 commit into
Mortennn:masterfrom
StealthWire:feat/apple-silicon-spm-migration
Open

Native Apple Silicon: migrate Carthage → Swift Package Manager, ship a universal binary#209
StealthWire wants to merge 1 commit into
Mortennn:masterfrom
StealthWire:feat/apple-silicon-spm-migration

Conversation

@StealthWire

Copy link
Copy Markdown

Why

The only published release (v4.0.0, 2019) ships an Intel-only (x86_64) binary. On Apple Silicon it runs only under Rosetta 2 — which Apple is now phasing out, so Dozer is at risk of stopping working on future macOS. On top of that, Carthage no longer builds cleanly on Apple Silicon with current Xcode (libarclite removed, deprecated AppKit symbols compiled as errors, Sparkle helper-tool codesigning), so the project is effectively unbuildable from a fresh clone today.

This PR migrates all dependencies from Carthage → Swift Package Manager, so the project builds natively on Apple Silicon with no manual patching, and produces a universal (arm64 + x86_64) binary that runs natively on both Apple Silicon and Intel.

What changed

  • All dependencies moved to SPM (resolved automatically by Xcode — no Carthage bootstrap step).
  • Minimum macOS raised 10.13 → 11 (Big Sur). This keeps broad support for older Intel Macs while letting every dependency build on a modern toolchain. ⚠️ It drops users on 10.13–10.15, so this is a breaking change (see "Release version" below).
  • Removed Cartfile, Cartfile.resolved, the Carthage build scripts (SignFrameworks.sh, the old LaunchAtLogin.sh), and the stale Brewfile.lock.json; updated Brewfile, Makefile, README, CONTRIBUTING.

Dependency migration

Dependency From To Notes
Defaults 4.2.2 9.0.9 No source changes.
Preferences 2.2.1 Settings 3.1.2 Renamed upstream: PreferencePaneSettingsPane, PreferencesWindowControllerSettingsWindowController, show(preferencePane:)show(pane:).
Sparkle 1.26.0 2.9.3 SUUpdater.shared() → a shared SPUStandardUpdaterController owned by AppDelegate. The EdDSA-signed, HTTPS appcast feed is unchanged.
MASShortcut (unmaintained) 2.4.0 KeyboardShortcuts 3.0.1 Recorder created programmatically and hosted in an NSView in General.xib (RecorderCocoa can't be loaded from a nib). Hotkey fires on key-down to match the old behavior.
LaunchAtLogin 4.1.0 LaunchAtLogin-Legacy 5.0.2 Same isEnabled API; embeds the login-item helper via a build phase, keeping support for macOS < 13.

Dependency versions are pinned exactly in project.yml (committed and reviewable) — the SPM equivalent of the old Cartfile.resolved.

Backward compatibility

  • Existing users keep their global shortcut. MASShortcut and KeyboardShortcuts use different UserDefaults storage, so on first launch the app migrates the legacy toggleMenuItems {keyCode, modifierFlags} value into KeyboardShortcuts' storage (Cocoa→Carbon modifier conversion). Verified end-to-end (e.g. ⌥⌘D → carbonKeyCode 2, carbonModifiers 2304, legacy key cleaned up, isShortcutSet preserved).
  • All Defaults keys are unchanged, so other settings carry over untouched.

Testing performed

  • Debug and Release builds succeed; Release is universal (x86_64 arm64) for the app, the Sparkle framework, and the login-item helper.
  • ✅ Runtime test of the shortcut migration (above).
  • ✅ Manual: shortcut recorder records/clears; "Check for Updates" works; Launch-at-Login toggles; Settings window opens to the right pane.
  • ✅ SwiftLint passes (0 errors).
  • Note: the repo has no test target, so there are no unit tests to run.

Notes for the maintainer

  • Release version: recommend cutting this as a new major version (5.0.0) since it raises the minimum OS (breaking for 10.13–10.15 users). The build number must also be incremented, and appcast.xml regenerated and re-signed with your EdDSA key — those are release-time steps and intentionally left to you.
  • Settings window activation: opening the window is centralized in AppDelegate.showPreferences(), which calls orderFrontRegardless(). The Settings library uses the cooperative NSApp.activate() on macOS 14+, which doesn't reliably front an accessory (menu-bar) app's window — this restores the always-on-top behavior.
  • ENABLE_USER_SCRIPT_SANDBOXING: NO is set because LaunchAtLogin-Legacy's helper-copy build phase writes into the app bundle. It only affects build-time script phases, not the shipped app.

🤖 Generated with Claude Code

…sal binary

The only published release (v4.0.0, 2019) ships an Intel-only (x86_64) binary,
so it runs on Apple Silicon only under Rosetta 2 — which Apple is removing.
Carthage also no longer builds cleanly on Apple Silicon with current Xcode
(libarclite removed, deprecated AppKit symbols, codesigning of Sparkle's helper
tools), making Dozer effectively unbuildable from a fresh clone.

This migrates all dependencies to Swift Package Manager so the project builds
natively on Apple Silicon with no manual patching, and produces a universal
(arm64 + x86_64) binary that runs natively on both Apple Silicon and Intel.

Dependencies:
- Defaults 4 -> 9: no source changes needed.
- Preferences -> Settings (renamed upstream): PreferencePane -> SettingsPane,
  preferencePaneIdentifier -> paneIdentifier, PreferencesWindowController ->
  SettingsWindowController, show(preferencePane:) -> show(pane:). The settings
  window is now opened via a single AppDelegate.showPreferences() that calls
  orderFrontRegardless(), because Settings' cooperative NSApp.activate() on
  macOS 14+ does not reliably bring an accessory app's window to the front.
- Sparkle 1 -> 2: SUUpdater.shared() -> a shared SPUStandardUpdaterController
  owned by AppDelegate. The EdDSA-signed, HTTPS appcast feed is unchanged.
- MASShortcut (unmaintained) -> KeyboardShortcuts: the recorder is created
  programmatically and hosted in a plain NSView in General.xib, since
  RecorderCocoa cannot be loaded from a nib. The global hotkey fires on
  key-down to match MASShortcut's original behavior. Shortcuts saved by the
  old MASShortcut integration are migrated on first launch (the legacy
  "toggleMenuItems" {keyCode, modifierFlags} dictionary is converted to
  KeyboardShortcuts' storage), so existing users keep their hotkey.
- LaunchAtLogin -> LaunchAtLogin-Legacy (SPM): same isEnabled API; embeds the
  login-item helper via a build phase, keeping support for macOS < 13.

Project:
- Minimum macOS raised from 10.13 to 11 (Big Sur) so older Intel Macs are still
  supported while the binary stays universal. This drops 10.13-10.15 users, so
  it is a breaking change — release as a new major version.
- Dependencies are pinned to exact versions in project.yml (committed and
  reviewable) — the SPM equivalent of the removed Cartfile.resolved.
- Remove Cartfile, Cartfile.resolved, the Carthage build scripts and the now
  stale Brewfile.lock.json; update Brewfile, Makefile, README and CONTRIBUTING.
- .swiftlint.yml: use the current validates_start_with_lowercase syntax so the
  lint phase passes on modern SwiftLint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@andry360

Copy link
Copy Markdown

Considering that @Mortennn is not active in any of the 3 repos he created and didn't respond to any request in this repos since last release, I don't think it's useful to request to maintain this project.

There is a fork https://github.com/callebtc/Dozer-X that updates this app (but drop support for older mac). Maybe you should consider to contribute to this fork?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants