Skip to content

Derive private framework exports from client link graphs - #3039

Open
karim-alweheshy wants to merge 2 commits into
bazelbuild:mainfrom
karim-alweheshy:codex/derive-private-framework-exports
Open

Derive private framework exports from client link graphs#3039
karim-alweheshy wants to merge 2 commits into
bazelbuild:mainfrom
karim-alweheshy:codex/derive-private-framework-exports

Conversation

@karim-alweheshy

@karim-alweheshy karim-alweheshy commented Aug 2, 2026

Copy link
Copy Markdown

Summary

Adds an opt-in apple_exported_symbols_list rule for closed-world, app-private dynamic frameworks assembled from static libraries.

The rule:

  • derives the required Swift export surface from explicit client CcInfo link graphs;
  • conservatively preserves non-Swift definitions by default for Objective-C runtime lookup and dlsym;
  • supports authored runtime roots and an optional custom llvm-nm executable;
  • emits a deterministic JSON audit report describing selected and missing symbols;
  • generates and consumes export lists independently for each Apple architecture.

Motivation

Private dynamic frameworks can publish implementation-detail symbols even when only a closed set of applications and extensions load them. Restricting the exported ABI reduces that surface without requiring a manually maintained list of every statically referenced Swift symbol.

Bazel cannot discover reverse consumers, so callers provide the complete client link roots explicitly. This rule is intended for app-private frameworks with a closed client set, not public frameworks whose current consumers do not define a stable ABI.

Architecture and runtime-symbol handling

exported_symbols_lists follows the same Apple split configuration as the corresponding link action. Each architecture therefore analyzes its own framework and client inputs and passes only its matching generated list to the linker.

Authored entries from additional_exported_symbols_lists are retained only when the current architecture's framework inputs define them. Missing authored entries are omitted from the linker input and listed in the target's report output group.

preserve_all_non_swift_exports defaults to True. Projects should disable it only after auditing Objective-C runtime and dlsym usage and declaring all runtime-discovered roots explicitly.

Validation

  • Independent release-readiness re-review: SHIP, with no remaining blocking findings.
  • Stable patch identity confirmed after rebasing onto current main.
  • Buildifier, Python compilation, git diff --check, and pre-commit checks passed.
  • Python export-analysis tests and all exported-symbol Starlark integration tests passed.
  • Linker Stardoc consistency check passed.
  • Multi-architecture aquery confirmed the arm64 and x86_64 link actions each consume the generated export list from their own split configuration.

@karim-alweheshy
karim-alweheshy marked this pull request as ready for review August 5, 2026 05:22
@karim-alweheshy

karim-alweheshy commented Aug 5, 2026

Copy link
Copy Markdown
Author

CI audit: the currently red Bazel 8.x, Bazel 9.x, and last-green lanes all stopped before checkout after repeated pull-ref fetches ended with a mirror bus error. The Bazel 8.0.1 lane did check out the same head and completed the full public test matrix, including all five exported-symbol-list tests. I found no code failure in this run; the remaining red statuses need an infrastructure retry.

@karim-alweheshy

Copy link
Copy Markdown
Author

@adincebic, could you rerun the failed Buildkite lanes when convenient? Bazel 8.x, 9.x, and last-green all stopped before checkout on repeated mirror fetch bus errors; the Bazel 8.0.1 lane checked out this same head and passed the full public suite, including all five new exported-symbol-list tests. Once the infrastructure lanes are green, a review of the linker/export aspect would be appreciated.

@adincebic

Copy link
Copy Markdown
Contributor

@adincebic, could you rerun the failed Buildkite lanes when convenient? Bazel 8.x, 9.x, and last-green all stopped before checkout on repeated mirror fetch bus errors; the Bazel 8.0.1 lane checked out this same head and passed the full public suite, including all five new exported-symbol-list tests. Once the infrastructure lanes are green, a review of the linker/export aspect would be appreciated.

Sure.

@karim-alweheshy
karim-alweheshy marked this pull request as draft August 6, 2026 11:52
@karim-alweheshy
karim-alweheshy force-pushed the codex/derive-private-framework-exports branch from bcc926c to 4ac300b Compare September 5, 2026 08:26
@karim-alweheshy

Copy link
Copy Markdown
Author

Rebased this onto current main and completed the architecture-specific correction before publishing the new head:

  • exported_symbols_lists now follows the Apple split configuration and selects the generated export list for the matching link action only.
  • Authored symbols are validated against each architecture's framework definitions; missing entries are omitted from the linker input and reported in the audit output.
  • Added asymmetric arm64/x86_64 integration coverage and verified via aquery that each link action consumes only its own split-generated list.

Current local verification passes the Python export-analysis tests, all exported-symbol Starlark integration tests, linker Stardoc consistency, Buildifier/lint, Python compilation, git diff --check, and pre-commit. An independent final re-review found no remaining blocker. Marking this ready for the fresh CI and linker/export review cycle.

@karim-alweheshy
karim-alweheshy marked this pull request as ready for review September 5, 2026 08:26
@adincebic adincebic changed the title feat: derive private framework exports from client link graphs Derive private framework exports from client link graphs Sep 5, 2026
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