Swiftで、複数ファイルの扱いがどうなっているのか調べてみた。具体的には、Rubyで言う require みたいのがどうなっているのかよくわからなかったので、調べてみた。
Swift.org
Swiftの仕様等はこちらのサイトに集まっている。
複数ファイルの扱いは、まずはこちらにある。
Swift package manager provides a convention-based system for building libraries and executables, and sharing code across different packages.
詳細は、こちら。
https://swift.org/package-manager
実際に作ってみよう。以下のようにする。
% cd ~/dev
% mkdir PackageManager
% cd PackageManager
% swift package init
Creating library package: PackageManager
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/PackageManager/PackageManager.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/PackageManagerTests/
Creating Tests/PackageManagerTests/PackageManagerTests.swift
Creating Tests/PackageManagerTests/XCTestManifests.swift
ビルドする際には、以下のようにする。
% swift build
コマンドライン実行するようなプログラムの場合は、--type executable
をつける。
% cd ~/dev
% mkdir Hello
% cd Hello
% swift package init --type executable
Creating executable package: Hello
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/Hello/main.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/HelloTests/
Creating Tests/HelloTests/HelloTests.swift
Creating Tests/HelloTests/XCTestManifests.swift
実行する際には、以下のようにする。
% swift run Hello
省略形で、以下のようにもできる。
% swift run
以下のようなファイルを作り、
func sayHello(name: String) {
print("Hello, \(name)!")
}
Sources/Hello/main.swift
を以下のようにする。
if CommandLine.arguments.count != 2 {
print("Usage: hello NAME")
} else {
let name = CommandLine.arguments[1]
sayHello(name: name)
}
すると、main.swift
から、Greeter.swift
のsayHello
を呼び出せるようになる。
% swift run Hello earth
[4/4] Linking Hello
Hello, earth!
% swift run Hello `whoami`
Hello, eto!
main.swiftの冒頭には、require
や#include
等の記述は無い。しかし、同じDirectoryにファイルがあるということで、同じPackageにあるとみなされ、呼び出される。これが、convention-based systemということ。convention-basedというのは、慣例にもとづくということ。単にファイルを置いただけで関連付けられるのは、楽で良さそうと思いつつ、恐いなという気持ちもある。
さて、ここまではわかったが、わからなかったのは、インタープリタで実行する方法だ。実行してみると、
% cd ~/dev/Hello/Sources/Hello
% swift main.swift
main.swift:6:5: error: use of unresolved identifier 'sayHello'
sayHello(name: name)
^~~~~~~~
となる。main.swiftからsayHelloを発見する方法が無いので、当然だ。main.swiftにimport Greeter
を追加しても、
% swift main.swift
main.swift:3:8: error: no such module 'Greeter'
import Greeter
^
となる。 import "Greeter.swift" や import "Greeter" も同様の結果になる。
どうやって読み込めばいいんだろう?