Xcode26からPrivateHeadersのモジュールが読めなくなった
問題
Xcode Cloudのバージョンを26にしたら依存ライブラリの影響でCIが失敗した
Unable to find module dependency: 'ExternCModule'
import ExternCModule
^
.swiftinterfaceファイル内でimportしようとした際に、モジュールが見つからないというエラーが発生した、と言っている。
ライブラリのmodule.modulemapを開くとこうなっていた
framework module NormalModule {
umbrella header "NormalModule.h"
export *
module * { export * }
}
module NormalModule.Swift {
header "NormalModule-Swift.h"
requires objc
}
framework module ExternCModule [extern_c]{
umbrella header "ExternCModule.h"
export *
module * { export * }
}
NormalModule.h
とNormalModule-Swift.h
はHeaders
フォルダにあるが、ExternCModule
はPrivateHeaders
フォルダに入っていた。Headers
はPublic、PrivateHeaders
はPrivateという切り分けをしているらしい。
Public and private headers define the API that the target exposes to external clients. Xcode copies these header files into Headers and PrivateHeaders subfolders within the built product. Project headers contain the API that the target uses, but Xcode doesn’t expose the API to external clients.
原因
Xcode26の変更でExplicit Moduleが自動でONになるらしい
Starting from Xcode 26, Swift explicit modules will be the default mode for building all Swift targets.
多分だけど、Xcode 16 まではデフォルトで Swift InterfaceをImplicitに読み込んでいたため、import
を評価するタイミングではすでにPrivateHeaders
の内容が見えていたのだと思う。
一方でExplicit Moduleが有効になると、buildの前段階で依存モジュールをすべて明示的に解決するため、PrivateHeaders
にあるモジュールは読み込めずにエラーになる。正直あまりよくわかってないけど、調べた感じこれが一番納得の行く理由だった。
解決
SWIFT_ENABLE_EXPLICIT_MODULES=NO
にすると解決した人が何人かいた
僕の場合は治らなかったので、ライブラリのPrivateHeaders
のファイルをすべてHeaders
フォルダに入れ、NormalModule.hで読み込んだら一旦はエラーが消えた。
ただNormalModuleにはextern_c
がついていない。またこのライブラリは問題なくなったが、次は他のライブラリで別の理由でbuildがコケるようになった。全部直していてもキリがないので、しばらくはXCode16を使い続けようという結論に至った。
Discussion