Files
obsidian-vault/work/projects/vscode-migration/vscode-migration.md
T

13 KiB
Executable File
Raw Blame History

VSCode/Cursor Builds & Debugging (macOS)

Status: IN PROGRESS · updated 2026-10-04

Asana: Migration to fully VSCode-supported builds&debugging Repo: ~/DuckDuckGo/apple-browsers.git (bare + worktrees) Findings: projects/vscode-migration/findings Tech design (package step): projects/vscode-migration/tech-design-spm-browser-package Editor via Xcode build server (no package needed): projects/vscode-migration/xcode-build-server · projects/vscode-migration/tech-design-xcode-build-server Next: projects/vscode-migration/modularization-roadmap — modularization after the browser package (incl. iOS/macOS sharing)

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

Current decision and evidence (2026-10-04)

  • Code-initialized Core Data models were proposed at Apple Weekly on 2026-09-29, then cancelled after Xcode 27 / Swift 6.4 validation. Asana subtask 1218854852229979 is completed because the conversion became unnecessary, not because the new model code was implemented. Existing .xcdatamodeld files stay as SPM resources and load through Bundle.module; the project documents local Xcode 27.2 verification.
  • Cleanup task 1218987523298563 to remove runtime model compilation test hacks remains open. PR #7080 packages the browser as SwiftPM, is currently Draft, and is separate from the cancelled code-defined model approach. GitHub shows it was temporarily closed and reopened on 2026-10-02.
  • For cross-project focus and career analysis, use personal/projects/personal-os/project-truth-analyzer to distinguish proposals, decisions, implementation, and verification.

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 swiftbuild handles assets, native doesn't. See projects/vscode-migration/findings#Asset catalogs.
  • Re-check whether storyboards still need dropping with Xcode 27.

Plan (next steps)

  1. 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.
  2. 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.
  3. 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).
  4. 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: target DuckDuckGo_Privacy_Browser (same module name as the former app target: storyboards, archived class names, @testable import) with path: "." — files stay in place. Products DuckDuckGoBrowser (static, linked into the app targets) and DuckDuckGoBrowserDynamic (for swift build).
  • Resources stay in the app targets (Bundle.main: strings, JSON, scripts, app icons); asset catalogs (for generated ImageResource/ColorResource) and the 8 Core Data models (codegen entity classes) are processed by the package — models now load from Bundle.module.
  • App targets: only DuckDuckGoApp/main.swift (AppMain.main()), module DuckDuckGoApp; package reference + DuckDuckGoBrowser product added, existing product dependencies kept.
  • SPM_FORCE_DEBUG in Package.swift (same as AppKitExtensions/SyncUI): the CI configuration maps to release for packages.
  • REVIEW compilation 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 Browser Review, unit + integration tests build-for-testing Debug and CI (with SPM_FORCE_DEBUG=1), Xcode-signed Debug app and the VSCode host run without crashes, swift build of the dylib.
  • Open: loc_export.sh / string catalog extraction now that sources are in a package; CI doesn't build the VSCode path; Package.resolved in macOS/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).