Skip to content

Xcode links a same-package macro's macOS testable object into an iOS test bundle when SwiftSyntax prebuilts are enabled #1642

Description

@Kyle-Ye

Summary

When a Swift package contains all three targets below in the same package,
Xcode links the macro target's host-only testable object into the iOS Simulator
test bundle when SwiftSyntax prebuilts are enabled:

DemoKitTests (.testTarget) -> DemoKit (.target) -> DemoKitMacros (.macro)

DemoKitTests has no direct dependency on DemoKitMacros. The failure occurs
even when the test does not invoke or reference the macro.

This reproduces with Xcode 26.6 and Xcode 27 beta 4. Moving the macro into a
separate local child package avoids the failure while keeping prebuilts enabled.

Expected behavior

The macro executable and its SwiftSyntax dependencies should be built for and
loaded on the macOS host. Its relocatable/testable macOS object should not be a
link input of the iOS Simulator test bundle.

Actual behavior

The generated target dependency graph makes DemoKitTests-product depend on
DemoKitMacros, and the test bundle's link file list contains the macro's
testable host object:

Target 'DemoKitTests-product' in project 'DemoKit'
    -> Explicit dependency on target 'DemoKitMacros' in project 'DemoKit'
    -> Explicit dependency on target 'DemoKitMacros' in project 'DemoKit'
    -> Explicit dependency on target 'DemoKit' in project 'DemoKit'

The iOS Simulator link then fails:

ld: building for 'iOS-simulator', but linking in object file
(.../Build/Products/Debug/ExecutableModules/
DemoKitMacros--228C090CAA851E1-testable.o) built for 'macOS'

With Xcode 27 beta 4, the log confirms that the SwiftSyntax MacroSupport
prebuilt is selected before the failure:

Downloading package prebuilt
https://download.swift.org/prebuilts/swift-syntax/603.0.2/
swiftlang-6.4.0.27.1-macosx27.0-MacroSupport.zip

Steps to reproduce

  1. Download and extract DemoKit.zip.

  2. From the extracted DemoKit directory, run against any available iOS
    Simulator, starting with clean DerivedData:

    xcodebuild test \
      -scheme DemoKit \
      -destination 'platform=iOS Simulator,name=iPhone 16 Pro' \
      -derivedDataPath /tmp/DemoKitDerivedData \
      -IDEPackageEnablePrebuilts=YES

Controls and workarounds

  • Passing -IDEPackageEnablePrebuilts=NO makes the same-package layout build
    and test successfully, but requires building SwiftSyntax from source.

  • Moving DemoKitMacros into a local child package makes the test pass with
    -IDEPackageEnablePrebuilts=YES.

  • Building the same target graph with the SwiftPM CLI succeeds, including an
    iOS Simulator cross-build of the test targets:

    swift build --build-tests \
      --triple arm64-apple-ios18.0-simulator \
      --sdk "$(xcrun --sdk iphonesimulator --show-sdk-path)" \
      --enable-experimental-prebuilts

This suggests the incorrect testable-object linkage is in the Xcode/Swift
Build package build plan rather than the package's declared dependency graph.

Environment

  • macOS 26.5.2 (25F84), Apple silicon
  • Xcode 26.6 (17F113), Swift 6.3.3
  • Xcode 27 beta 4 (27A5228h), Swift 6.4
  • swift-syntax 603.0.2

Related reports

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions