Skip to content

Emit the swiftmodule at the nested path via CMake's own module properties - #379

Merged
jakepetroules merged 1 commit into
mainfrom
jake-petroules/cmake-module-path
Oct 7, 2026
Merged

jakepetroules merged 1 commit into
mainfrom
jake-petroules/cmake-module-path

Conversation

@jakepetroules

Copy link
Copy Markdown
Contributor

On Windows, building swift-build against swift-subprocess fails at configure time. swift-build's CMake does find_package(SwiftSubprocess) and links SwiftSubprocess::Subprocess (swiftlang/swift-build#638), and configuration stops with:

CMake Error at Sources/SWBUtil/CMakeLists.txt:123 (target_link_libraries):
  Cannot find source file:
    C:/source/.build/plugins/cmake-smoke-test/outputs/swift-subprocess/Sources/Subprocess/Subprocess.swiftmodule/x86_64-unknown-windows-msvc.swiftmodule

The same setup configures and builds on Linux and macOS. swift-build would also hit this in the Windows toolchain build, because build.ps1 already passes SwiftSubprocess_DIR to swift-build.

Cause

emit_swift_interface() asks for the nested <module>.swiftmodule/<triple>.swiftmodule layout by passing its own -emit-module-path. CMake always passes an -emit-module-path of its own as well, so the compiler receives two. It honors the last one, which means the result depends on where CMake puts its flag relative to the target's compile options:

  • Released CMake versions (3.28 through 4.3) put CMake's flag first, so the nested path usually wins.
  • CMake's development branch now appends its flag afterwards.

When CMake's path wins, a plain Subprocess.swiftmodule file is written instead of the nested directory. The existing "Removing regular file …" workaround in this function is there for that same clash.

I couldn't reproduce the Windows build locally, so I haven't directly confirmed which detail makes CMake's path win there. This change removes the dependence on flag order altogether, whatever that detail is.

Change

  • Module path: set Swift_MODULE_DIRECTORY and Swift_MODULE so that the path CMake emits is the nested path itself. When CMP0195 is NEW, keep Swift_MODULE as <module>.swiftmodule and let CMake add the triple.
  • Removed: the extra -emit-module-path, and the add_custom_command(OUTPUT …) that would now be a second rule for CMake's own output. The interface source is marked GENERATED instead.

This also has CMake create the parent directory and track the module as a real build output. .swiftdoc and .swiftsourceinfo now land in the nested directory as well.

Testing (macOS, Swift 6.4)

Each configuration is static and shared, Debug:

CMake Mode
3.28.3 CMP0157 OLD, single-step build
3.31.6 CMP0157 NEW, split build; same version as the Windows runner
4.1.2 default policies, and with CMAKE_POLICY_DEFAULT_CMP0195=NEW

In every configuration:

  • ninja -v shows exactly one -emit-module-path, the nested path.
  • Subprocess.swiftmodule is a directory.
  • A rebuild is a no-op.
  • A separate downstream project using only find_package(SwiftSubprocess) and SwiftSubprocess_DIR imports Subprocess and runs a process.

cmake --install produces lib/swift/macosx/Subprocess.swiftmodule/arm64-apple-macos.{swiftmodule,swiftdoc,swiftsourceinfo}.

Subprocess_ENABLE_LIBRARY_EVOLUTION=YES fails on macOS with availability errors ('FilePath' is only available in macOS 11.0 or newer; clients of 'Subprocess' may have a lower deployment target). That happens on main as well, so this PR doesn't address it.

Windows is being validated through swift-build's Windows cmake-smoke-test (swiftlang/swift-build#638, temporarily pointed at this branch) and through toolchain builds.

…ties

emit_swift_interface() passed its own -emit-module-path for the nested
<module>.swiftmodule/<triple>.swiftmodule layout, in addition to the
-emit-module-path that CMake always adds. The compiler honors whichever comes
last, so the result depends on where CMake places its flag relative to the
target's compile options. When CMake's flag wins, a plain <module>.swiftmodule
file is produced instead of the nested directory, and clients of the exported
SwiftSubprocess::Subprocess target fail at generate time with "Cannot find
source file: .../Subprocess.swiftmodule/<triple>.swiftmodule". This happens
when building swift-build against swift-subprocess on Windows.

Set Swift_MODULE_DIRECTORY and Swift_MODULE so that CMake's own module path
is the nested one (or let CMake nest it when CMP0195 is NEW), and drop the
extra flag and the custom command that would now duplicate CMake's output.
@jakepetroules
jakepetroules merged commit 5eee309 into main Oct 7, 2026
46 checks passed
@jakepetroules
jakepetroules deleted the jake-petroules/cmake-module-path branch October 7, 2026 18:38
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