Skip to content

Make the CMake build suitable for toolchain builds - #376

Merged
iCharlesHu merged 4 commits into
mainfrom
jake-petroules/cmake
Oct 6, 2026
Merged

iCharlesHu merged 4 commits into
mainfrom
jake-petroules/cmake

Conversation

@jakepetroules

@jakepetroules jakepetroules commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

This makes swift-subprocess's CMake build work as part of a Swift toolchain build. swift-build needs this before it can adopt Subprocess (swiftlang/swift-build#638).

On macOS, swift-build's cmake-smoke-test job currently fails while configuring swift-subprocess. It prints -- Vendoring swift-system and then tries to git clone swift-system without network access. Apple platforms never use swift-system, though: they use the System framework.

Changes

1. Only require swift-system on non-Apple platforms

  • CMake only looks for, vendors, or links SwiftSystem::SystemPackage when NOT APPLE.
  • In Package.swift, the SystemPackage product dependency now has a condition: Linux, Windows, Android, WASI, OpenBSD and FreeBSD. This applies to the Subprocess target and both test targets, which all use the #if canImport(System) pattern. SwiftPM no longer builds SystemPackage on macOS.

2. No silent network fetches

  • New option Subprocess_VENDOR_DEPENDENCIES, default ON.
    • If swift-system isn't found and the option is OFF, configuration fails with a message explaining how to set SwiftSystem_DIR.
    • An explicitly set SwiftSystem_DIR that doesn't contain swift-system is always an error, even with vendoring on. A wrong path never turns into a silent download.
  • The vendored pin moves from 1.4.2 to 1.5.0 (61e4ca4b…), matching from: "1.5.0" in Package.swift.
  • Why the default is ON: it keeps standalone cmake -B build working, and this repo's Linux CMake CI job relies on that. Toolchain builds don't depend on the default:
    • Apple platforms never vendor.
    • build.ps1 already passes SwiftSystem_DIR.
    • CI can pass -DSubprocess_VENDOR_DEPENDENCIES=OFF to fail loudly.

3. SystemPackage is part of the public interface

  • SystemPackage is linked PUBLIC on non-Apple platforms, because FilePath, FileDescriptor and other SystemPackage types appear in the public API (public import SystemPackage).
  • SwiftSubprocessConfig.cmake now locates SwiftSystem itself with find_dependency. The hint points at the swift-system Subprocess was built against, and a client's SwiftSystem_DIR takes precedence. Previously, a client had to define SwiftSystem::SystemPackage before calling find_package(SwiftSubprocess), or generation failed.
  • The targets include is guarded, so loading the config twice works.

4. Enable the SubprocessFoundation trait in CMake builds

  • New option Subprocess_ENABLE_FOUNDATION, default ON, which defines SubprocessFoundation. CMake and SwiftPM builds of the same toolchain now expose the same API (Data input/output, Data(buffer:), etc.).
  • On non-Apple platforms, a Foundation package found via Foundation_DIR is linked, following swift-tools-support-core. Otherwise FoundationEssentials comes from the toolchain or SDK, which is how build.ps1 builds Subprocess today.
  • The CMake build now uses the same language mode and upcoming features as Package.swift: Swift 6, NonisolatedNonsendingByDefault, ExistentialAny, MemberImportVisibility and InternalImportsByDefault. The SubprocessFoundation sources need InternalImportsByDefault to compile. Reviewer note: NonisolatedNonsendingByDefault changes runtime behaviour compared with earlier CMake builds; it now matches SwiftPM builds.

Settings for downstream projects such as swift-build

When building swift-subprocess:

Platform Settings
Apple None needed
Linux / Windows -DSwiftSystem_DIR=<swift-system build>/cmake/modules and, recommended in CI, -DSubprocess_VENDOR_DEPENDENCIES=OFF

When building the consumer:

  • -DSwiftSubprocess_DIR=<swift-subprocess build>/cmake/modules
  • On non-Apple platforms, optionally -DSwiftSystem_DIR=…. The package config finds swift-system without it, but passing it is clearer.

Testing

  • macOS, CMake + Ninja, no SwiftSystem_DIR, network blocked, targeting macOS 13:
    • No vendoring message and no _deps directory.
    • Static and shared builds succeed without warnings.
    • DataOutput symbols are present.
  • Linux, Swift 6.2.4, CMake 3.28:
    • Built swift-system 1.5.0 with CMake first, then Subprocess with SwiftSystem_DIR and vendoring off, static and shared. Nothing was vendored, and DataOutput is in .a and .so.
    • Error cases: vendoring off with no SwiftSystem_DIR, and a wrong SwiftSystem_DIR, both fail with a clear message and fetch nothing.
    • The default vendored build still works and fetches 1.5.0.
    • Subprocess_ENABLE_FOUNDATION=OFF builds and omits DataOutput.
  • Downstream CMake project: uses find_package(SwiftSubprocess), links SwiftSubprocess::Subprocess, imports Subprocess, and runs a process with .data(limit:) output and a FilePath executable. It works on macOS and Linux, static and shared. On Linux it also works with only SwiftSubprocess_DIR set.
  • swift build / swift test on macOS: pass (171 tests) with an SDK newer than Xcode 26.0; see "Known issue" below.
  • Linux SwiftPM: swift build --target Subprocess passes, and SystemPackage is still built and linked.
  • macOS CMake, built for the host OS: builds after the revert.

Not verified locally

  • Linux swift test: couldn't run. My container hit a FileManager copy failure on test resources; this looks environmental. CI covers it.
  • Windows: not built locally. CI here doesn't build the CMake path on Windows, so swift-build's smoke test or a build.ps1 run will be the first real check.
  • Linking FoundationEssentials via an explicit Foundation_DIR: untested.

Known issue, not addressed here: Span.bytes with the Swift 6.2 SDK

This PR doesn't change it; the affected code is identical to main. With the Xcode 26.0 / Swift 6.2 SDK, building for a macOS deployment target below 26 fails:

Sources/Subprocess/API.swift:206:65: error: 'bytes' is only available in macOS 26.0 or newer
  • SwiftPM: always hits this, because it builds for the package's macOS 13 minimum.
  • CMake: only hits it when the Swift target is set explicitly (CMake doesn't pass CMAKE_OSX_DEPLOYMENT_TARGET to swiftc).

The cause: in the Swift 6.2 SDK, Span<BitwiseCopyable>.bytes is @available(macOS 26.0) and not @_alwaysEmitIntoClient. Newer SDKs declare it back-deployable to macOS 10.14.4 and inline it into callers.

Possible fixes, for a follow-up:

  • an internal back-deployable helper (withUnsafeBytes + RawSpan(_unsafeBytes:)), as Array._bytes already does;
  • or require a newer SDK/compiler than Swift 6.2.

@jakepetroules

Copy link
Copy Markdown
Contributor Author

Windows failure is addressed by #377

- Only require swift-system (SystemPackage) on non-Apple platforms. Apple
  platforms use the System framework, so the configure step no longer looks
  for, or vendors, swift-system there.
- Add Subprocess_VENDOR_DEPENDENCIES (default ON). When swift-system is not
  found it is only fetched if this is enabled; otherwise configuration fails
  with a clear diagnostic. An explicitly provided SwiftSystem_DIR that does
  not contain swift-system is always an error, never a silent download.
- Bump the vendored swift-system pin to 1.5.0 to match Package.swift.
- Link SystemPackage PUBLIC, since its types are part of the public API, and
  have SwiftSubprocessConfig.cmake locate SwiftSystem (find_dependency) so
  clients only need SwiftSubprocess_DIR.
- Add Subprocess_ENABLE_FOUNDATION (default ON), which defines the
  SubprocessFoundation trait like SwiftPM's default traits, so CMake and
  SwiftPM builds expose the same API. A Foundation package found via
  Foundation_DIR is linked on non-Apple platforms; otherwise the toolchain or
  SDK provides FoundationEssentials.
- Build with the same language mode and upcoming features as Package.swift
  (Swift 6, NonisolatedNonsendingByDefault, ExistentialAny,
  MemberImportVisibility, InternalImportsByDefault). The SubprocessFoundation
  sources rely on InternalImportsByDefault.
Apple platforms use the System framework (`#if canImport(System)`), so
SystemPackage does not need to be built or linked there.
…w 26

`Span.bytes` is only available on macOS 26 in the Swift 6.2 standard
library (later SDKs back-deploy it). Build the RawSpan from
`withUnsafeBytes`, as is already done for Array.
@jakepetroules

Copy link
Copy Markdown
Contributor Author

@swift-ci build toolchain linux

@jakepetroules

Copy link
Copy Markdown
Contributor Author

@swift-ci build toolchain macos

@jakepetroules

Copy link
Copy Markdown
Contributor Author

@swift-ci build toolchain windows

@jakepetroules

Copy link
Copy Markdown
Contributor Author

@swift-ci build windows toolchain

@jakepetroules

Copy link
Copy Markdown
Contributor Author

@swift-ci Please Build Toolchain Windows Platform

@iCharlesHu
iCharlesHu merged commit 6e0c7b5 into main Oct 6, 2026
91 of 92 checks passed
@jakepetroules
jakepetroules deleted the jake-petroules/cmake branch October 6, 2026 18:26
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