Skip to content

[Driver] Recognize embedded stdlib layout when picking plugin paths#2150

Merged
hnrklssn merged 2 commits into
swiftlang:mainfrom
hnrklssn:embedded-stdlib-macros
Jun 10, 2026
Merged

[Driver] Recognize embedded stdlib layout when picking plugin paths#2150
hnrklssn merged 2 commits into
swiftlang:mainfrom
hnrklssn:embedded-stdlib-macros

Conversation

@hnrklssn

@hnrklssn hnrklssn commented Jun 9, 2026

Copy link
Copy Markdown
Member

For embedded noneOS targets the stdlib lives at
<resource-dir>/embedded/<triple>/Swift.swiftmodule, but the existing hasToolchainStdlib probe only checked <resource-dir>/<platform>/, which is <resource-dir>/Swift.swiftmodule (no platform subdir) for noneOS because Triple.platformName() returns nil. The probe always returned false, so the conditional swap in
addCommonFrontendOptions placed the SDK's -external-plugin-path ahead of the toolchain's -plugin-path. The first-emplace race in PluginLoader then registered the bootstrap Xcode SDK's (potentially stale) libSwiftMacros.dylib as SwiftMacros, shadowing the freshly-built one and producing
"type 'SwiftMacros.SwiftifyImportMacro' could not be found" errors when the embedded headers used macros that post-date the bootstrap platform (and some CI machines run a pretty old host OS, so they lack _SwiftifyImport). This should mostly be an issue when bootstrapping.

Branch the probe on triple.os == .noneOS so the embedded layout is checked directly, with a single fileSystem.exists call. Covers Apple *-apple-none-macho (the visible failure), plus Wasm *-unknown-none-wasm, ARM/RISC-V/x86 *-none-*-eabi|elf, and AVR.

Add 8 regression tests in ToolchainTests (4 Apple macho + 4 non-Apple noneOS), each gated with requireFrontendSupportsTarget so they self-skip on toolchains lacking the relevant LLVM backend.

rdar://178814859

Assisted-by: Claude Opus 4.7

For embedded `noneOS` targets the stdlib lives at
`<resource-dir>/embedded/<triple>/Swift.swiftmodule`, but the existing
`hasToolchainStdlib` probe only checked `<resource-dir>/<platform>/`,
which is `<resource-dir>/Swift.swiftmodule` (no platform subdir) for
`noneOS` because `Triple.platformName()` returns nil. The probe always
returned false, so the conditional swap in
`addCommonFrontendOptions` placed the SDK's `-external-plugin-path`
ahead of the toolchain's `-plugin-path`. The first-emplace race in
`PluginLoader` then registered the bootstrap Xcode SDK's (potentially
stale) `libSwiftMacros.dylib` as `SwiftMacros`, shadowing the
freshly-built one and producing
"type 'SwiftMacros.SwiftifyImportMacro' could not be found" errors when
the embedded headers used macros that post-date the bootstrap platform
(and some CI machines run a pretty old host OS, so they lack
`_SwiftifyImport`). This should mostly be an issue when bootstrapping.

Branch the probe on `triple.os == .noneOS` so the embedded layout is
checked directly, with a single `fileSystem.exists` call. Covers Apple
`*-apple-none-macho` (the visible failure), plus Wasm
`*-unknown-none-wasm`, ARM/RISC-V/x86 `*-none-*-eabi|elf`, and AVR.

Add 8 regression tests in `ToolchainTests` (4 Apple macho + 4 non-Apple
`noneOS`), each gated with `requireFrontendSupportsTarget` so they
self-skip on toolchains lacking the relevant LLVM backend.

rdar://178814859
@hnrklssn hnrklssn force-pushed the embedded-stdlib-macros branch from 840eddd to 6763ab5 Compare June 9, 2026 05:56

@DougGregor DougGregor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks reasonable, thank you!

@hnrklssn

hnrklssn commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

@swift-ci please test


// Check that we pass the toolchain plugin path before the external plugin
// path for embedded targets.
@Test(.requireFrontendSupportsTarget("armv6-apple-none-macho"))

@cachemeifyoucan cachemeifyoucan Jun 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a perfect case to use parameterized tests?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was not familiar with that feature so I looked it up, but it doesn't seem like that would be compatible with .requireFrontendSupportsTarget since that's only evaluated once (unless I'm missing something). I could add a guard inside the test function if you want, but then it would show up as passing instead of unsupported. Maybe that's still preferable?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You don't need to use requireFrontendSupportsTarget in your Test trait. You just need to construct Collection to be passed as argument: and you can construct this collection with supported target.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ahh yeah that works, thanks!

@hnrklssn

hnrklssn commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

@swift-ci please test

@hnrklssn

hnrklssn commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

@swift-ci please test windows platform

@hnrklssn hnrklssn merged commit 96ab393 into swiftlang:main Jun 10, 2026
26 checks passed
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