Skip to content

Harden SwiftUsdShell C++ interop exposure for downstream re-export targets #3

@elkraneo

Description

@elkraneo

Context

During the OpenUSDKit modularization/client-live split, downstream aggregate live targets such as OpenUSDKitVariantsLive and OpenUSDKitMaterialsLive started failing in Xcode with:

Clang dependency scanning failure: .../_OpenUSD_SwiftBindingHelpers/include/module.modulemap:22:8: error: module '_OpenUSD_SwiftBindingHelpers' requires feature 'cplusplus'
Unable to resolve module dependency: 'std'

The immediate fix in OpenUSDKit 0.2.22 was to add .interoperabilityMode(.Cxx) to the aggregate live re-export targets, even though those targets are only tiny modules that @_exported import their concrete live client modules.

That works, but it is a smell: C++ interop requirements from SwiftUsdShellOpenUSD are leaking through re-export/aggregate targets and forcing package consumers to know more about the implementation graph than they should.

Why this matters

OpenUSDKit is moving toward a pick-and-match SDK shape:

  • contract/client modules should stay pure Swift
  • concrete live modules may bridge to Shell/OpenUSD
  • aggregate live products should be ergonomic and boring to import
  • app/package authors should not have to chase transitive C++ interop settings on re-export-only targets

If every aggregate module that re-exports a live implementation must enable C++ interop, the SDK boundary becomes harder to reason about and easy to break when modules are split further.

Current workaround

OpenUSDKit 0.2.22 added C++ interop settings to:

  • OpenUSDKitVariantsLive
  • OpenUSDKitMaterialsLive

The concrete live targets already had C++ interop enabled where they directly import SwiftUsdShellOpenUSD.

Requested follow-up

Investigate whether SwiftUsdShell can reduce or better contain this exposure.

Questions to answer:

  1. Should SwiftUsdShellOpenUSD avoid exposing any public signatures or re-exported symbols that force downstream importers/re-exporters into C++ interop mode?
  2. Can the pure Swift SwiftUsdShell product remain the only product visible to most SDK live aggregation layers, with OpenUSD-specific runtime implementation hidden behind narrower modules?
  3. Is there a packaging/target arrangement that prevents _OpenUSD_SwiftBindingHelpers and std module dependencies from appearing in downstream aggregate-target dependency scans?
  4. If this is unavoidable with Swift/Xcode's current C++ interop scanner, should we document a hard rule: any target that imports or re-exports a module depending on SwiftUsdShellOpenUSD must opt into .interoperabilityMode(.Cxx)?

Acceptance criteria

  • Reproduce or explain why re-export-only targets need C++ interop when they depend on a live module that imports SwiftUsdShellOpenUSD.
  • Either reduce the leakage through target/API changes, or document the exact package authoring rule with examples.
  • Add a lightweight guard or manifest audit if possible so future OpenUSDKit/Preflight module splits fail early before Xcode emits dependency-scanner errors.

Related commits

  • OpenUSDKit fb280da / tag 0.2.22: enabled C++ interop for aggregate live targets as a workaround.
  • Preflight b6d8a905: bumped OpenUSDKit to consume the workaround.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions