Swift 2.2.1から3.0に更新したらSegmentation faultが多発するようになった話

Ubuntu 14.04.5にAppleのSwiftを入れて遊ぼうとしていたのだが、Swift 2.2.1から3.0に差し掛かえたらSegmentation faultが多発するようになった。

$ swift
Welcome to Swift version 3.0 (swift-3.0-RELEASE). Type :help for assistance.
  1> 1 + 3
Segmentation fault (コアダンプ)
$ _

REPLで式を入力したらSegmentation faultとか、現象として直面すると――「そんな品質でリリースするようなプロジェクト・チームだなんて考えられないよなあ」という常識の壁との衝突ゆえに、非常に当惑するものである。

実のところ3.0-RCの頃から同じ現象が起きていたのだが、「リリース版じゃないからなあ」と軽く考えて、2.2.1に差し戻していた。これが、リリース版でも起きる(しかもネット上で騒ぎになっていない)となると、少々問題である。

解決の鍵となる情報は意外なところから得られた。Swiftプロジェクトの公式サイトのドキュメントを参考にhello, worldをビルドしようとしたところ、こんなエラーが発生した。

$ mkdir -p Hello
$ pushd Hello/
$ swift package init --type executable
Creating executable package: Hello
Creating Package.swift
Creating Sources/
Creating Sources/main.swift
Creating Tests/
$ swift build
<unknown>:0: error: cannot open file '/opt/apple/swift-3.0-RELEASE-ubuntu14.04/usr/lib/swift/CoreFoundation/module.modulemap': Permission denied
Can't parse Package.swift manifest file because it contains invalid format. Fix Package.swift file format and try again.
error: invalidManifestFormat
$ _

実はSwiftをホームディレクトリではなく/opt/apple配下にroot権限で手動インストールしていたのだが:

$ sudo mkdir -p /opt/apple
$ sudo tar xf swift-3.0-RELEASE-ubuntu14.04.tar.gz -C /opt/apple
$ sudo ln -s /opt/apple/swift-3.0-RELEASE-ubuntu14.04 /opt/apple/swift
$ _

どうも展開されたファイルの読み込み権限がオーナーとグループにしか付いていないようだ。

$ ls -l /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap 
-rw-r----- 1 root root 200  9月 14 06:17 /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap
$ _

オーナーとグループのどちらもrootのため、root以外のユーザでは、パッケージで提供されているモジュールなどのファイルを読み込むことができない。

どうもそれが原因ではないかと考えて、安直に全ファイルに読み込み権限を付加したところ、どうやら動くようになったようだ。

$ sudo chmod -R +r /opt/apple/swift
$ ls -l /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap 
-rw-r--r-- 1 root root 200  9月 14 06:17 /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap
$ swift build
Compile Swift Module 'Hello' (1 sources)
Linking ./.build/debug/Hello
$ swift
Welcome to Swift version 3.0 (swift-3.0-RELEASE). Type :help for assistance.
  1> 1 + 2
$R0: Int = 3
  2> :q
$ _

まあでも現状では、UbuntuにSwiftを入れる時にホームディレクトリ以外を選択する人は少ないだろうから、この問題にハマる人なんていないだろう。