Generating C++ header fails: unable to load standard library for target 'arm64-apple-macosx26.0'

I'm trying to get started with Swift/C++ interoperability by generating C++ headers for my Swift code. The official instructions say Xcode can do it, but I'm working cross-platform so I don't want to go that route. Another page shows how to make swiftc generate headers:

swiftc -frontend -typecheck \
       /sources/a.swift /sources/b.swift -module-name SwiftModule \
       -cxx-interoperability-mode=default \
       -emit-clang-header-path SwiftModule-Swift.h

When I run this (substituting my real source file of course) I just get:

<unknown>:0: error: unable to load standard library for target 'arm64-apple-macosx26.0'

What's wrong? I'm using the standard Xcode 26.5 Swift toolchain (6.3.2) on macOS 26.5.1.

Simply running swiftc -frontend -typecheck /sources/a.swift produces the same error.

If you're invoking frontend mode directly, you usually need to pass the -sdk location explicitly (the driver infers it if not specified).

But in this case, there's no reason to use -frontend here at all; I'm not sure why that page includes it. Does it work if you drop -frontend?

It gets farther, but fails because it can't find the other modules in my project:

error: emit-module command failed with exit code 1 (use -v to see invocation)
Sources/Redacted/Database.swift:8:15: error: no such module '_Common'
  6 | //
  7 | 
  8 | public import _Common
    |               `- error: no such module '_Common'

Do I need to pass every single file in my project on the command line? :grimacing:

If you have other modules (either .swiftmodule files or C .modulemap files) being imported, you need to pass the paths to those to the driver with -I.

I'm just a simple guy who types swift build and it builds my code. This is a bit over my head.

I see there are .swiftmodule files being generated down inside .build/arm64-apple-macosx/debug/ModuleCache ... are those the ones you mean?

It sounds like basic C++ interop is requiring me to construct my own enormous build commands like the ones shown in Xcode build logs. There's no support for this in SwiftPM?

Thus far I've been using Xcode with my SwiftPM package without having to have an xcodeproj file. It's generally very nice (I don't miss messing with huge lists of build settings) but using Xcode to create interop headers requires having a project file, which appears to mean I have to set everything up by hand again, creating targets and adding all my source files manually. I wish there were an upgrade process, i.e. generate an xcodeproj from my existing Package.swift file.

ModuleCache isn't what you want; it has implicitly compiled modules from the system frameworks (which will be generated automatically for you in a temporary directory if needed, when running swiftc yourself). I think the Modules directory in the same location has what you need.

Rather than trying to piece together an invocation from scratch, I wonder if you could just wedge the -emit-clang-header-path flag into the unsafe settings of the target you're interested in. You wouldn't be able to do anything else with that header in a SwiftPM sense AFAIK, but if you're just looking to inspect it, that ought to spit it out.

Thanks for the advice!

Meanwhile I'm reading this extremely depressing series of blog posts by Davide DeRosa about cross-platform Swift, in which he says:

The first advice I can give if you want to build consistently across platforms is to avoid SwiftPM, except for Swift Testing. It’s just not fit for the role yet. XCFrameworks only work on Apple, and binary artifact bundles are on their way, but haven’t been released yet. If you need something that works today, get familiar with swiftc and clang, and switch to CMake with ninja.

... At this point, you may come to realize how SwiftPM could lead you to a complex source hierarchy. The highly granular dependency model encouraged by the manifest is a neat abstraction, and works very well for modular Swift-only systems. But when you have to account for C/C++ targets, modulemaps, DocC, and external non-Swift libraries, it makes you want to jump off the nearest cliff without even a goodbye letter.

I've been very happy to have left CMake behind, but now it's returning from the grave...