Skip to content

[SwiftBuild] Keep macro implementation products as build-time dependencies in SwiftPM PIF generation #776

Description

@kateinoigakukun

Description

Follow-up from #773.

Swift macro implementation products are compile-time tools, but SwiftPM's generated PIF can treat a macro implementation target like a target-side dependency for WASI builds. In the minimum reproducer, ReproMacrosImpl is a macro implementation target and intentionally contains this guard:

#if os(WASI)
#error("ReproMacrosImpl must not be compiled for the WASI target")
#endif

ClientTests depends only on Client, which uses the macro declaration from ReproMacros. The macro implementation should be available as a host build tool for macro expansion, but it should not be compiled as a WASI target-side product.

Updated reproducer zip: https://gist.githubusercontent.com/kateinoigakukun/ba21c654a675032aa77906877c906e53/raw/b457bfba4389d1bacd730f0475020c0ee04844f0/updated-776-macro-build-dependency-linux-2026-06-12.zip

The updated zip preserves the original repro package and original repro.sh, and also includes repro-linux-2026-06-12.sh plus adaptation notes for running the same reproducer with the Linux June 12 snapshot toolchain and Swift SDK.

Expected behavior

Macro implementation targets should remain host/build-time dependencies. SwiftBuild should not build a WASI-side ReproMacrosImpl--...-testable variant for this transitive macro path, and macro implementation artifacts should not contaminate target-side WASI products.

The native and SwiftBuild backends should both build the package tests for the WASI Swift SDK. Macro-dependent tests should still get the direct macro testable variants they need, without pulling the macro implementation into the target-side WASI build.

Actual behavior

With the June 12, 2026 development snapshot and swift-DEVELOPMENT-SNAPSHOT-2026-06-12-a_wasm, the native backend succeeds and SwiftBuild still reproduces the original failure.

Observed in the latest verification:

native exit:     0
swiftbuild exit: 1
swiftbuild testable macro mentions:  24

SwiftBuild plans/compiles a WASI testable macro implementation variant:

ReproMacrosImpl--3E7BE6D87A4DC5F2-testable

and fails with:

Sources/ReproMacrosImpl/ReproMacrosImpl.swift:6:8: error: ReproMacrosImpl must not be compiled for the WASI target
 6 | #error("ReproMacrosImpl must not be compiled for the WASI target")

Steps to reproduce

  1. Download and unzip https://gist.githubusercontent.com/kateinoigakukun/ba21c654a675032aa77906877c906e53/raw/b457bfba4389d1bacd730f0475020c0ee04844f0/updated-776-macro-build-dependency-linux-2026-06-12.zip.

  2. Enter the package directory:

    cd 776-macro-build-dependency
  3. On this Linux verification machine, run the adapted script:

    ./repro-linux-2026-06-12.sh

    The adapted script uses:

    /home/ubuntu/.local/share/swiftly/toolchains/main-snapshot-2026-06-12/usr/bin/swift
    swift-DEVELOPMENT-SNAPSHOT-2026-06-12-a_wasm
    
  4. On a machine matching the original macOS-style repro assumptions, the original script is still available:

    ./repro.sh
  5. The script runs the same comparison for both build systems:

    swift build --package-path "$ROOT" --scratch-path "$WORK/native" --swift-sdk "$SWIFT_SDK_ID" --build-system native --build-tests -v
    swift build --package-path "$ROOT" --scratch-path "$WORK/swiftbuild" --swift-sdk "$SWIFT_SDK_ID" --build-system swiftbuild --build-tests -v
  6. Expected reproducer result for the current bug: native exits 0; SwiftBuild exits nonzero with the WASI-side ReproMacrosImpl #error.

Swift Package Manager version/commit hash

Swift Package Manager - Swift 6.5.0-dev

Swift & OS version (output of swift --version ; uname -a)

Swift version 6.5-dev (LLVM 18d2bfb70c14d89, Swift c13d82e5987aecb)
Target: x86_64-unknown-linux-gnu
Build config: +assertions
Linux swift-dev.fugu.katei.dev 6.8.0-94-generic #96-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan  9 20:36:55 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux

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