11 KiB
Executable File
VSCode/Cursor Builds & Debugging (macOS)
Status: IN PROGRESS · updated 2026-10-01
Asana: Migration to fully VSCode-supported builds&debugging
Repo: ~/DuckDuckGo/apple-browsers.git (bare + worktrees)
Findings: projects/vscode-migration/findings
Goal
Build, run and debug the macOS app from VSCode/Cursor: make most of the app
SPM-compatible, so swift build + SourceKit-LSP work, and configure
.vscode (tasks, launch).
Status
| Step | Status |
|---|---|
| Move non-Swift code to local packages | ✅ Jun 2025 |
| Missing imports, unused files cleanup | ✅ Jun 2025 |
| Initial VSCode config | ✅ Jun 2025 (stale: sweetpad worktree) |
| Unify WebKit private methods (Sparkle/AppStore) | ✅ Feb 2026 |
Drop #if SPARKLE/APPSTORE |
✅ Mar 2026 — DMG and App Store targets now compile the same 1398 files |
Drop dead target flags (SANDBOX_TEST_TOOL, ALPHA, NETWORK_EXTENSION in shared files) |
✅ #6983 |
Replace sandbox-test-tool with App Store UI tests (AppStoreSandboxUITests, CI leg along full DMG runs) |
✅ #6980 |
| Split app files shared with helper targets | 🔄 A+B in review (#7029), C ready, G done; the rest stays shared by path — see Target split stages |
| Asset resource initializers instead of asset symbol extensions | ✅ committed, alex/asset-resource-symbols (needs a PR) |
| Drop storyboards | ✅ last one (NavigationBar) is alex/drop-navigationbar-storyboard (PR open); Feedback #6866, PasswordManager #6950 merged |
| Browser code as a SwiftPM package | 🔄 builds and runs from Xcode and VSCode — alex/spm-browser-package, see Browser package |
| Core Data models in code | ❌ Cancelled 2026-10-01 — Xcode 27 builds these in SPM |
Asset catalogs for swift build |
❌ Cancelled 2026-10-01 — Xcode 27 builds these in SPM |
| swift-build fork (Provisional Inputs) | ⏸ not started; may be unnecessary |
| Remote debugging (VMs, old hardware) | ⏸ not started |
| AI instructions, GitHub MCP subtasks | ⏸ not started |
Open items after the cancellation
- Closed PR #6976 (AssetCatalogPlugin) and the Core Data PR; their worktrees are removed.
- Check what Xcode 27 actually does for
swift build(native) and SourceKit-LSP: asset symbols,.car,.momd, storyboards? Earlier finding on Xcode 26: only--build-system swiftbuildhandles assets, native doesn't. See projects/vscode-migration/findings#Asset catalogs. - Re-check whether storyboards still need dropping with Xcode 27.
Plan (next steps)
- PRs in order: #7029 (A+B) → C (
move-vpn-pixel-event) / G (move-helper-only-files) →alex/asset-resource-symbols→alex/drop-navigationbar-storyboard→alex/spm-browser-package. - Browser package PR follow-ups — see Browser package: localization export (
loc_export.sh), CI checks for the VSCode setup, dropping the duplicated app-target package product dependencies. - Helper-target split, later: D, E1, E2+H, F aren't needed for the package (helpers keep compiling the shared files by path); do them when there's a reason (F with the KeyedStoring migration).
- VSCode tasks with cached helper targets (extensions/login items built by Xcode only when their inputs change) — the host app already contains them; revisit if host rebuilds are too slow. See projects/vscode-migration/findings#Extensions in VSCode tasks.
Browser package
Worktree spm-browser-package, branch alex/spm-browser-package (on top of alex/move-helper-only-files + alex/asset-resource-symbols + alex/drop-navigationbar-storyboard; package work uncommitted).
macOS/DuckDuckGo/Package.swift: targetDuckDuckGo_Privacy_Browser(same module name as the former app target: storyboards, archived class names,@testable import) withpath: "."— files stay in place. ProductsDuckDuckGoBrowser(static, linked into the app targets) andDuckDuckGoBrowserDynamic(forswift build).- Resources stay in the app targets (
Bundle.main: strings, JSON, scripts, app icons); asset catalogs (for generatedImageResource/ColorResource) and the 8 Core Data models (codegen entity classes) are processed by the package — models now load fromBundle.module. - App targets: only
DuckDuckGoApp/main.swift(AppMain.main()), moduleDuckDuckGoApp; package reference +DuckDuckGoBrowserproduct added, existing product dependencies kept. SPM_FORCE_DEBUGinPackage.swift(same as AppKitExtensions/SyncUI): the CI configuration maps to release for packages.REVIEWcompilation condition can't reach the package → Browser Tools Panel debug menu item is gated at runtime (isDebugBuild || isReviewBuild).- VSCode/Cursor: open
macOS/DuckDuckGo;.vscode/has tasks (host app →swift build --build-system swiftbuild→ sign),launch.json,make-host-app.sh,sign-dylib.sh,launcher/launcher.c. - Verified (Xcode 27.2, offline): all product schemes Debug,
macOS BrowserReview, unit + integration testsbuild-for-testingDebug and CI (withSPM_FORCE_DEBUG=1), Xcode-signed Debug app and the VSCode host run without crashes,swift buildof the dylib. - Open:
loc_export.sh/ string catalog extraction now that sources are in a package; CI doesn't build the VSCode path;Package.resolvedinmacOS/DuckDuckGo(copied from the project) — keep in sync or generate.
Target split stages
Goal: no file in macOS/DuckDuckGo/ is compiled into a helper target (VPN agent, PIR agent, NetP extensions), so the app directory can become one SPM target. InputFilesChecker tracks the remaining files in temporarilyAllowedMisplacedFiles (one block per stage); a stale entry fails the build, so each stage PR must remove its block.
| Stage | Files | Used by | Home | New deps / project changes | Size & blockers | PR |
|---|---|---|---|---|---|---|
| A | ApplicationBuildType, BuildFlags, DuckDuckGoUserAgent |
app + all 6 helpers | AppKitExtensions |
none (all targets already link it) | 46 imports | #7029 |
| B | DBPFeatureFlagger, DataBrokerAuthenticationManagerBuilder, DataBrokerProtectionSettings+Environment, WebViewUserAgentProvider, SafariVersionReader, WebKitVersionProvider |
app + PIR agent | DataBrokerProtection-macOS |
none (Subscription comes transitively, like elsewhere in the package) |
5 imports | #7029 |
| C | NetworkProtectionPixelEvent (569 loc) |
app, VPN agent, 3 extensions | NetworkProtectionMac → VPNPixels (new library product) |
VPNPixels += VPN, Configuration; BSK package dep; product linked to 7 targets |
9 imports. Ready, uncommitted (move-vpn-pixel-event) |
own PR, on top of #7029 |
| D | SubscriptionPixel, SubscriptionPixelHandler, SubscriptionEnvironment+Default, WideEventFeatureFlagAdapter, SubscriptionFunnelOrigin (836 loc) |
app, VPN agent, PIR agent, 3 extensions | new local package (no existing one is linked by all consumers) | Subscription, PixelKit, Networking, PrivacyConfig, WideEvent, AppKitExtensions; product linked to ~8 targets |
used in ~134 files — biggest diff | own PR (new package, Subscription reviewers) |
| E1 | TipKit ×4, VPNIPCResources, VPNOperationErrorRecorder, NetworkProtectionVPNCountryLabelsModel, VPNSettings+Environment (~470 loc) |
app + VPN agent | NetworkProtectionMac (IPC / UI, or a small TipKitSupport target) |
Subscription for VPNSettings+Environment |
moderate, no strings | combine with G |
| G | 10 helper-only sources living in DuckDuckGo/ (Bundle+VPN, NetworkProtectionOptionKeyExtension, NetworkProtectionControllerErrorStore, NetworkProtectionTunnelController, MacPacketTunnelProvider, MacTransparentProxyProvider, NetworkProtectionNotificationsPresenterFactory, VPNFailureRecoveryPixel, Bundle+NetworkProtectionExtensions, SubscriptionManager+StandardConfiguration) |
helpers only, never the app | DuckDuckGoVPN/, new HelperTargetsShared/ (allowed for helper targets in InputFilesChecker) |
git mv + pbxproj group paths only |
done | ✅ alex/move-helper-only-files |
| E2 | UserText+NetworkProtection+Shared, DefaultVPNLocationFormatter |
app + VPN agent | NetworkProtectionUI (has Localizable.xcstrings) |
strings → Bundle.module with translations; app and VPN agent each have their own UserText |
blocked on the strings/resources decision | combine with H |
| H | 4 app icons, macos-config.json, 7 VPN Lottie JSONs, 2 NetP .xcstrings |
app + helpers | package resources or per-target copies | resource bundles / Bundle.module |
same decision as E2 and the app-package tech design | with E2 |
| F | UserDefaultsWrapper (415 loc) + UserDefaults+NetworkProtectionShared |
app, VPN agent, all extensions; ~51 app files | don't move — deprecated in favour of KeyedStoring |
follows the KeyedStoring migration | blocked on that migration (owner/timeline TBD) | after the migration |
| X (optional) | NETP_SYSTEM_EXTENSION in MacPacketTunnelProvider, MacTransparentProxyProvider, NetworkProtectionNotificationsPresenterFactory |
extensions only | runtime check Bundle.main.bundleURL.pathExtension == "systemextension" |
removes the last FEATURE_FLAGS from xcconfigs |
changes keychain service / defaults selection — needs VPN team review | optional, separate |
Order: C → D → E1+G → strings/resources tech design → E2+H → F after KeyedStoring. X any time if the VPN team agrees.
Worktrees
| Worktree | Branch | What |
|---|---|---|
trim-target-memberships |
alex/trim-target-memberships |
Stages A+B + membership trim, PR #7029 |
move-vpn-pixel-event |
alex/move-vpn-pixel-event |
Stage C, uncommitted, on top of #7029 |
move-helper-only-files |
alex/move-helper-only-files |
Stage G (committed): helper-only sources → DuckDuckGoVPN/, HelperTargetsShared/ |
asset-resource-symbols |
alex/asset-resource-symbols |
Asset resource initializers (committed) |
spm-browser-package |
alex/spm-browser-package |
Browser code as a SwiftPM package + VSCode setup (WIP, uncommitted) |
drop-sb-navigationbar |
alex/drop-navigationbar-storyboard |
Last storyboard (PR open, merged into spm-browser-package) |
drop-sb-feedback |
alex/drop-feedback-storyboard |
Merged (#6866); follow-up commits after the squash? |
coredata-spm-hacks-cleanup |
alex/coredata-spm-hacks-cleanup |
no commits ahead of main yet |
netp-dependencies |
alex/align-netp-dependencies |
Old draft: move files by target (superseded by the stages above) |
vscode, vscode2 |
alex/fix-imports-cleanup, alex/vscode2 |
Old: SwiftGenPlugin draft (uncommitted), root Package.swift |
sweetpad |
alex/cursor-fix-build |
Old .vscode (SweetPad) config |
Gone: spm-asset-symbols-plugin, coredata-code-models*, drop-sb-bookmarksbar* (BookmarksBar storyboard + xib are on main), appstore-sandbox-ui-tests (#6980), drop-dead-target-flags (#6983), split-shared-target-files.
Demo project for the (cancelled) asset approach: ~/Developer/SPMAssetSymbolsDemo (./verify.sh).