feat: migrate to current upstream idb — Device Hub works via DTUHID transport auto-selection#68
Open
onevcat wants to merge 8 commits into
Open
feat: migrate to current upstream idb — Device Hub works via DTUHID transport auto-selection#68onevcat wants to merge 8 commits into
onevcat wants to merge 8 commits into
Conversation
Migrate the idb pin from 76639e4d (2025-05-29) to main @ 1f6943f8 (2026-07-23). Upstream moved its build to XcodeGen-generated projects producing STATIC frameworks, so the packaging pipeline changes shape: - scripts/build.sh generates FBSimulatorControl.xcodeproj with XcodeGen (new build-time dependency: `brew install xcodegen`), builds CompanionUtilities first (FBSimulator.h imports CompanionUtilities-Swift.h and a bare xcodebuild does not order the generated header), then FBControlCore / XCTestBootstrap / FBSimulatorControl. FBDeviceControl is dropped — nothing in sim-use ever imported it. XCFrameworks are created with -allow-internal-distribution: no library evolution (upstream's Swift 6 code rejects non-frozen-enum exhaustiveness), so build_products/ is locked to the producing toolchain — re-run `build.sh dev` after switching Xcode versions. - The idb PrivateHeaders modules (Clang module maps + headers + .tbd stubs) are staged under build_products/PrivateHeaders: the FB* Swift modules import them, and the static archives defer their CoreSimulator / AccessibilityPlatformTranslation class references to the final link. - Package.swift wires those module maps into every FB-consuming target (-Xcc -fmodule-map-file, absolute via Context.packageDirectory) and links the executable/test bundle with -ObjC plus the weak .tbd stubs. The binary target set swaps FBDeviceControl for CompanionUtilities. - Static linking dissolves the SwiftBuild-backend dlopen problem the rpath machinery existed for: the Package.swift slice rpaths, scripts/stage-fb-frameworks.sh, and the release-time build_products-rpath stripping are all retired. Framework strip/sign steps are gone too (static archives have no nested frameworks; their signatures are irrelevant at runtime). - CI caches build_products/PrivateHeaders alongside the XCFrameworks, keys purely on scripts/build.sh + the Xcode version (the patches/ glob is gone), and installs XcodeGen on cache miss. - All four patches/idb/ patches are retired: xcode27-simulatorkit-sharedframeworks and multi-touch-spike are superseded upstream; headerpad-shims targeted the removed checked-in project's shim build phase; fbprocess-runtime-rename renamed a class that no longer exists upstream and was never referenced by sim-use. Note: this commit does not build on its own — the Swift-side API migration lands in the following commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
…ust work Adapt sim-use to the Swiftified FBSimulatorControl surface at 1f6943f8 and retire the stopgaps it supersedes: - HID events are Swift enums: touchDownAt/keyDown/buttonDown-style factories become .touch/.keyboard/.button(direction:...), composites become .composite([...]), and events are sent with the native async `hid.send(event:logger:)` (FBFuture bridging deleted: FutureBridge, BridgeQueues). - HID connections construct `FBSimulatorHID(for:transport:)` directly — deliberately NOT `simulator.connectToHID()`, whose upstream-side cache has no boot-identity gate and would resurrect exactly the stale handles issue #55 guards against. Discarded cache entries are now disconnect()ed explicitly. - Transport selection is upstream's automatic per-boot rule: DTUHID on dtuhidd-suppressed simulators (booted while Device Hub was open), legacy Indigo otherwise. The DeviceHubHIDSuppression guard and its SIM_USE_SKIP_DTUHIDD_CHECK escape hatch are removed — the state the guard refused is now simply functional; verified live on iOS 27.0 / Beta 4, where a poisoned-boot simulator delivers tap and type via DTU. SIM_USE_HID_TRANSPORT=indigo|dtuhid is the new debug override (forcing indigo on a suppressed simulator fail-louds with upstream's keyboardSuppressedByActiveDTUHIDD). - The explicit xcodeFrameworks preload stays in GlobalSetup / HIDInteractor: facebook/idb#941 (Indigo transport constructs its client before SimulatorKit loads) is still open, and the preload is also what surfaces a clean error when SimulatorKit is absent. - Accessibility consumption goes through the typed FBAccessibilityElement + serialize API via a legacy-shape bridge (LegacyAccessibilityBridge): upstream's serializer output shapes are unchanged, so the downstream pipeline (outline, collapsed-children recovery, orientation calibration) is untouched. - Multi-touch rides upstream's native `.twoFingerTouch` primitive; the whole trajectory is assembled into one composite event so the transport is drained exactly once per gesture, as DTUHID requires. The local spike primitive (sendMultiTouch) is gone with the patch. - Video streaming uses the async `createStream(configuration:to:)` / awaitCompletion / stopStreaming lifecycle; screenshots use `takeScreenshot(format:)`; FBEventReporter/EmptyEventReporter now come from CompanionUtilities. Verified: 1116 unit tests green; full make e2e-ios 21/21 suites green (Beta 4); manual pinch-out recognized on the gesture playground; live Xcode 27 matrix (clean boot via Indigo, poisoned boot via DTU) passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
With the FB* code statically linked into the binary, the release payload shrinks to the executable plus the two SwiftPM resource bundles: - release-payload.sh / release-artifacts.sh stop copying and verifying a Frameworks/ directory (the executable arch checks cover the linked code); the homebrew formula installs and post_install-resigns the binary only. - local-release.sh / dev-install.sh check for build_products/XCFrameworks + PrivateHeaders (the swift build inputs) instead of build_products/Frameworks, drop the framework signing steps, and lose the framework loops from their smoke tests. The --build-frameworks path maps to `build.sh frameworks install xcframeworks` (strip/sign-frameworks no longer exist). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
- CHANGELOG: Unreleased entry for the idb bump (DTU transport auto-selection, static linking, retired patches/guard, new SIM_USE_HID_TRANSPORT override, XcodeGen build dependency). - README / AGENTS.md: xcodegen prerequisite, toolchain-locked build_products note, and a rewritten Xcode 27 section — Device Hub workflows are now supported, the reboot-dance guidance is gone. - Skill: drop the Device-Hub-poisoned-simulator pitfall from SKILL.md and references/pitfalls.md; the shipped binary no longer has that failure mode. - docs/ai/xxxx-xcode27-support: phase-1 re-validation addendum (harness zero-drift at 1f6943f8, facebook/idb#941 still open, keyboard-only suppression observed headlessly — the full touch kill likely needs Device Hub's device view actively attached) and the migration-executed addendum recording the shape of the change and the live verification matrix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
The FB* swiftmodules are toolchain-locked (no library evolution), and two betas of the same marketing version ship incompatible Swift compilers — keying the cache on "27.0" alone would serve one beta's build to another. Spotted in AXe's equivalent migration (PR #61 keys on the build id). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
Upstream does not expose which transport its auto-selection resolved to, so log the inputs instead: the SIM_USE_HID_TRANSPORT override when forced, otherwise the dtuhidd-presence fact the selection keys on (reusing the sysctl process-table probe the boot-identity token already pays for). Presence is reported as a fact rather than a claimed selection, so the line cannot drift out of sync with upstream's predicate. Note: SimUseLogger currently writes to no sink by default, so the line surfaces only once a debug logging path is wired up — tracked with the transport-race follow-up issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
The Xcode 26.5 leg of the toolchain matrix caught both failure modes of the blanket flag: - With -ObjC (the spike-recipe default), 26.5-built binaries abort with "freed pointer was not the last allocation" — a Swift task-allocator LIFO trap — in unrelated async code (deterministic from the first ViewerAPIHandlers.run call). Per-archive bisection attributes it to force-loading CompanionUtilities; Beta 4 builds of identical source never trip it, and neither +load side effects nor cross-archive member duplication explain it (both checked). - Without any force-load, category-only members are dropped by the archive link and the first runtime use dies with "+[FBControlCoreLoggerFactory osLoggerWithLevel:]: unrecognized selector" (FBControlCoreLogger+OSLog.o). Thread the needle: -force_load FBControlCore, FBSimulatorControl, and XCTestBootstrap (their ObjC categories must survive), ordinary archive link for CompanionUtilities (pure Swift — everything it provides is pulled in by symbol references). 1116 unit tests + 21/21 E2E suites green on both Xcode 26.5 and 27 Beta 4 with this shape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
The Xcode 26.5 compiler flags two non-Sendable captures in the send-deadline @sendable closure that Beta 4 stays quiet about (both are errors in Swift 6 language mode): - FBSimulatorHIDEvent gets a retroactive @unchecked Sendable — it is a pure value tree (coordinates, key codes, delays, nested composites) that upstream simply never declared conformant, public enums getting no implicit conformance. - The closure captures the @unchecked-Sendable FBSimulatorHID handle instead of the whole Session, which carries the non-Sendable FBSimulator. (@preconcurrency import does not silence closure-capture diagnostics — verified before reaching for the conformance.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Executes step 2 of the Xcode 27 plan (
docs/ai/xxxx-xcode27-support/README.md): the pinned idb ref moves from76639e4d(2025-05-29) to upstream main @1f6943f8(2026-07-23). This is a migration, not a version bump — upstream Swiftified the HID layer, moved to XcodeGen-generated static frameworks, and rewrote the video layer — and it buys the headline feature:Simulators booted while Device Hub is open now just work. The HID transport is selected automatically per boot (DTUHID through dtuhidd's CoreDevice service when the legacy HID is suppressed, classic Indigo otherwise), so the state that v0.11.0's guard could only refuse now delivers
tap/type/swipenormally.What changed
scripts/build.sh): pins1f6943f8, generates the Xcode project with XcodeGen (new build dep:brew install xcodegen), packages static XCFrameworks with-allow-internal-distribution, stages the idbPrivateHeadersmodules for consumers, and drops FBDeviceControl (never imported). No library evolution →build_products/is toolchain-locked; re-runbuild.sh devafter switching Xcode.patches/idb/patches retired — superseded upstream or targeting deleted code.Package.swift: private-module maps via-Xcc -fmodule-map-file; per-archive-force_loadfor the three ObjC-bearing frameworks + weak-linked CoreSimulator/APT tbds. The entire SwiftBuild-rpath machinery (slice rpaths,stage-fb-frameworks.sh, release rpath stripping) is deleted — static linking dissolves the dlopen problem it existed for. Deliberately NOT-ObjC: blanket force-loading makes Xcode 26.5-built binaries trip a Swift task-allocator abort (bisected to CompanionUtilities), while no force-load at all drops category-only members (+[FBControlCoreLoggerFactory osLoggerWithLevel:]unrecognized selector — both reproduced, see the linking addendum in the work record).hid.send(event:logger:); connections constructFBSimulatorHID(for:transport:)directly (upstream'sconnectToHID()cache has no boot-identity gate and would resurrect iOS daemon holds a stale HID connection across simulator reboot — tap reports success but is not delivered #55); accessibility consumes the typedFBAccessibilityElementAPI through a legacy-shape bridge (serializer shapes unchanged → outline/recovery/calibration pipelines untouched); video uses the asynccreateStream(configuration:to:)lifecycle; multi-touch rides upstream's native.twoFingerTouch, assembled as one composite so the DTUHID transport drains once per gesture.DeviceHubHIDSuppression+SIM_USE_SKIP_DTUHIDD_CHECKremoved;SIM_USE_HID_TRANSPORT=indigo|dtuhidadded as a debug override, and connection creation logs the dtuhidd-presence signal the auto-selection keys on. The Indigo HID transport constructs the HID client before SimulatorKit is loaded — clientClassUnavailable for library consumers facebook/idb#941 mitigation (explicitxcodeFrameworkspreload) is kept.Frameworks/, no framework codesigning); formula/staging/dev-install updated accordingly.PrivateHeadersalongside the XCFrameworks, keys on the Xcode build id (betas share a marketing version but ship incompatible toolchain-locked swiftmodules), installs XcodeGen on cache miss.Verification
Both toolchains, full regression: Xcode 26.5 and 27 Beta 4 each run 1116 unit tests + 21/21 E2E suites, zero warnings, zero failures.
Live 4-case matrix (deterministic judges: Playground tap counter, Settings navigation, Safari URL field):
Plus: forced-transport A/B in the poisoned state (forced
dtuhiddelivers; forcedindigokeyboard fail-louds with upstream's diagnostic), manual pinch-out recognized on the gesture playground (multi-touch has no scripted iOS E2E suite), and the standalone-harness re-validation recorded in the work-record addenda.Follow-ups
.traits-triggered empty hierarchies — are recorded in the work record with their reference fixes.Work record with full investigation trail:
docs/ai/xxxx-xcode27-support/README.md.🤖 Generated with Claude Code