Skip to content

ci(swift-sdk): prune orphaned FFI header subdirs in build_ios.sh#3666

Merged
QuantumExplorer merged 1 commit into
v3.1-devfrom
fix/ci-xcframework-header-mismatch
May 19, 2026
Merged

ci(swift-sdk): prune orphaned FFI header subdirs in build_ios.sh#3666
QuantumExplorer merged 1 commit into
v3.1-devfrom
fix/ci-xcframework-header-mismatch

Conversation

@llbartekll
Copy link
Copy Markdown
Contributor

@llbartekll llbartekll commented May 19, 2026

Issue being fixed or feature implemented

The Swift SDK CI job (.github/workflows/swift-sdk-build.yml, job Swift SDK and Example build (warnings as errors)) has been failing on PRs that merge v3.1-dev with:

DashSDKFFI.h:10:1: error: umbrella header for module 'DashSDKFFI'
does not include header '/dash-spv-ffi/dash-spv-ffi.h'

The self-hosted macOS ARM64 runner preserves target/ across CI runs (introduced by #3632, git clean -ffdx -e target/ -e target/**). Recently #3644 removed the dash-spv-ffi crate from the unified FFI build and dropped its #include from the umbrella header. cargo never reclaims target/<triple>/<profile>/include/<crate>/ when a crate leaves the dependency tree, so the orphan dash-spv-ffi/dash-spv-ffi.h sits in the cached include directory, xcodebuild -create-xcframework -headers bundles it into the framework, and Clang's umbrella header check fails.

What was done?

Made packages/swift-sdk/build_ios.sh self-correcting against this class of stale-state failure.

  • Introduced a single ordered INCLUDED_CRATES list at the top of the script — the canonical set of FFI crates whose cbindgen output ships in DashSDKFFI.xcframework. Ordering matters because earlier headers define types referenced by later ones.
  • inject_modulemap now:
    1. Prunes any immediate subdirectory of the include dir whose name is not in INCLUDED_CRATES (catches orphans from removed/renamed crates), with safe quoting and a [[ -d "$dir" ]] || continue guard.
    2. Asserts that every crate in INCLUDED_CRATES has its expected header on disk — converts the silent drift case ("array references a crate Cargo.toml doesn't pull in") into a clear script-level error before Clang sees it.
    3. Generates the umbrella DashSDKFFI.h from the same list via a printf loop, replacing the previous hardcoded heredoc.
  • module.modulemap heredoc and the opaque-struct rewrite loop are untouched.

The list is the one source of truth: a future crate removal becomes a one-line edit, and the script self-heals the runner's cache on the next run.

How Has This Been Tested?

Validated locally before pushing.

  • bash -n packages/swift-sdk/build_ios.sh clean.
  • Sourced inject_modulemap against the real stale target/aarch64-apple-ios-sim/release/include/ on this workstation (which contained the same dash-spv-ffi/ orphan the runner has): the orphan was pruned, generated DashSDKFFI.h came out byte-identical to the post-#3644 heredoc shape, module.modulemap unchanged.
  • Hid one of the surviving include dirs (dash-network/) to simulate a Cargo.toml/array drift: existence assertion fired with Missing header: … and exit 1. No silent failure path into Clang.

On CI (this PR): the first run will exercise the bug — the runner's cached target/ still contains the dash-spv-ffi/ subdir from prior builds, the prune step will remove it (look for → pruned orphan header dir: dash-spv-ffi in the logs), the umbrella check passes, and the runner's cache is permanently repaired for every subsequent PR. Re-runs on the same SHA will be a no-op for the prune step.

Out-of-scope: not switching the modulemap from umbrella header "X.h" to umbrella . — that would mask the orphan rather than fix it, and would lose the explicit #include order the framework relies on for transitive type visibility.

Breaking Changes

None. The generated umbrella header is byte-identical to the previous hardcoded heredoc on the no-orphan path, and the script is invoked the same way.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Improved iOS SDK build system with enhanced header organization, validation, and error handling to ensure more reliable builds.

Review Change Stack

…s.sh

cargo doesn't reclaim include/<crate>/ when a crate leaves the dep
tree, so on runners that preserve target/ across runs the orphan gets
bundled into the xcframework and clang's umbrella-header check fails.
Drive umbrella content and a prune step from one ordered
INCLUDED_CRATES list so the script stays correct as crates come and
go, and assert each crate's header exists before emitting the
umbrella.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added this to the v3.1.0 milestone May 19, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b21a63e8-3f26-480c-9063-131e165c51d9

📥 Commits

Reviewing files that changed from the base of the PR and between 798cd25 and 21ff9e3.

📒 Files selected for processing (1)
  • packages/swift-sdk/build_ios.sh

📝 Walkthrough

Walkthrough

The iOS build script now uses a configurable INCLUDED_CRATES list to dynamically generate the DashSDKFFI.h umbrella header, replacing hardcoded includes. The inject_modulemap function was updated to prune orphan header directories, validate required headers exist for each included crate, and emit include statements in dependency order.

Changes

iOS Build Script – Dynamic Crate Header Inclusion

Layer / File(s) Summary
Define included crates configuration
packages/swift-sdk/build_ios.sh
INCLUDED_CRATES ordered array is introduced to specify which crate headers must be shipped in the unified iOS framework.
Implement dynamic header generation and validation
packages/swift-sdk/build_ios.sh
inject_modulemap now prunes header subdirectories not listed in INCLUDED_CRATES, validates that each included crate has its expected $HEADERS_DIR/<crate>/<crate>.h header (failing the build if missing), and generates DashSDKFFI.h by programmatically emitting ordered include statements instead of using a hardcoded heredoc.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • dashpay/platform#3644: Also modifies packages/swift-sdk/build_ios.sh's inject_modulemap umbrella header generation to adjust FFI crate header inclusion.

Suggested reviewers

  • shumkov
  • QuantumExplorer

Poem

🐰 The crates now dance in ordered list,
No hardcoded headers will be missed.
Validation checks and cleanup flow,
Dynamic builds now steal the show!
*~ A grateful rabbit* 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: pruning orphaned FFI header subdirectories in the iOS build script, which is the core issue being fixed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-xcframework-header-mismatch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented May 19, 2026

✅ Review complete (commit 21ff9e3)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 19, 2026

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "75d627d7a59a810436018b19554d1a05491cd085c00540f9c300f6605fc9059b"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

@llbartekll llbartekll marked this pull request as draft May 19, 2026 08:56
@llbartekll llbartekll marked this pull request as ready for review May 19, 2026 09:25
Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

PR is a small, well-scoped CI fix to packages/swift-sdk/build_ios.sh that prunes orphan cbindgen header subdirs before xcframework creation. No FFI surface, ownership, or ABI changes. One nitpick about silent drift in the opposite direction worth surfacing.

Reviewed commit: 21ff9e3

💬 1 nitpick(s)

Comment thread packages/swift-sdk/build_ios.sh
@QuantumExplorer QuantumExplorer merged commit 91859f9 into v3.1-dev May 19, 2026
30 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/ci-xcframework-header-mismatch branch May 19, 2026 11:17
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.

3 participants