60500


Xcode 11.2.1 の環境にて、`import Parchment` と記載されたところに

> Module compiled with Swift 5.1 cannot be imported by the Swift 5.1.2

というエラーが出ました。

[Xcodeをアップデートしてビルドしたら Module compiled with Swift 5.0.1 cannot be imported by
the Swift 5.1.2 compiler というエラーが出た](https://www.nk3-dev.net/archives/8584)

上記ページを参考に

`$ carthage update --platform ios --cache-builds`

すると、無事コンパイルが通りました。

`ABI Stability`になったので、`Swift 5.1` でコンパイルされたモジュールが `Swift 5.1.2`
にインポートできない理由がわかりません。

なぜなのでしょうか？

（エラーが出たのは `import
Parchment`の部分ですが、おそらくコンパイルのタイミングでこのライブラリが一番始めにインポートされただけで、どのライブラリでもこのエラーが出てもおかしくなかったと推測しています）


CC BY-SA 4.0
2019-11-14T03:46:36.740
60498
2019-11-14T17:05:16.897
2019-11-14T04:05:16.443
3060
9008
question
swift xcode carthage
ABI Stability なのになぜ Module compiled with Swift 5.1 cannot be imported by the Swift 5.1.2 というエラーが起こるのでしょうか？


そのライブラリのビルド設定において、 **Module Stabilityが有効になっていない** からです。

Swift 5におけるABI Stabilityというのは２つのパートに分かれていて、１つは **ABI Stability** でもう一つは
**Module Stability** です。

ABI StabilityはSwift
5.0で実現されました。これは異なるバージョンのコンパイラから生成されたバイナリ同士を「リンクできる」というものです。  
これにより、Standard Libraryをアプリごとに同梱する必要がなくなりました。

一方Module StabilityはSwift
5.1で実現されました。これは異なるバージョンのコンパイラから生成されたモジュール（≒フレームワーク、ライブラリ）を「インポートできる」というものです。

Swiftがフレームワーク、ライブラリを利用可能にする（＝インポートする）ためには「モジュール」が必要で、これまでは`*.swiftmodule`というファイルがそれを担っていました。

ソースコードから別のライブラリのオブジェクトや関数を利用するには「インポート」してPublicなAPIを通じて機能を呼び出す必要があります。  
このPublicなインターフェースを記述してインポート可能にするものが`*.swiftmodule`（＝モジュール）です。  
（`*.swiftmodule`ファイルはCやObjective-Cにおけるヘッダファイルです。モジュールと同等なものとしてCやObjective-
CのライブラリをSwiftにインポートする際にはヘッダファイルをモジュールに変換できるmodulemapファイルを使いますが、今回の件には関係ないので省略します。）

この`*.swiftmodule`ファイルは生成したコンパイラのバージョン間に互換性がありません（今もありません）。  
そのためSwift
5.1ではコンパイラのバージョン間で互換性を保持できる`*.swiftinterface`ファイルというテキストベースのモジュール記述ファイルが採用されました。

つまり、Swift 5.0ではABI Stabilityによって
**異なるバージョンのコンパイラが生成したライブラリをリンクできますが、インポートできないので実質的にサードパーティのライブラリに対してはABI
Stabilityの恩恵を受けることはできません** 。  
（インポートの段階で失敗するのでリンクの段階まで到達しないため）

**Swift 5.1のModule
Stabilityと合わせて、ようやく任意のライブラリにおいてビルドしたコンパイラのバージョンを気にせず利用できるようになりました。**

ただし、Module
Stabilityに必要な`*.swiftinterface`はそれぞれのライブラリ側が設定を有効にしてビルドしなければ生成されません。  
`*.swiftinterface`を出力するには`BUILD_LIBRARY_FOR_DISTRIBUTION`というフラグを`YES`にする必要があります。

ほとんどのライブラリはまだその設定が有効になっていないので普通にCarthageでビルドすると`*.swiftinterface`ファイルが生成されません。

これがSwift 5.1でコンパイルされたモジュールがSwift 5.1.2でインポートできない理由です。  
（Swift Standard LibraryがSwift 5.0の頃からEmbedせずに済むようになっていたのは、私たちがModule
Stabilityを利用できるようになる前にApple提供のモジュールについてはPrivate機能としてModule
Stabilityが有効になっていたためです）

参考:  
<https://swift.org/blog/abi-stability-and-more/>  
<https://forums.swift.org/t/plan-for-module-stability/14551>


CC BY-SA 4.0
2019-11-14T05:01:38.297
60500
2019-11-14T17:05:16.897
2019-11-14T17:05:16.897
5519
5519
60498
answer