[swift] swiftcコマンド まとめ

# 環境
* OS: MacOS Sierra
* swiftc --version

  ```
  Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37)
  Target: x86_64-apple-macosx10.9
  ```

# 書いたこと
* モジュールとライブラリについて
* モジュールファイルの作成
* 静的ライブラリーの作成
* 動的ライブラリーの作成
* 実行ファイルの作成  


# Swiftのモジュールとライブラリについて
Swiftソースファイルをモジュール化するには、swiftmoduleファイルを作成する必要がある。
このswiftmoduleファイルは、C言語のヘッダーファイルに相当する。

従って、Pythonなどのようなスクリプト言語におけるモジュールとは異なり、実行ファイル生成時もしくは、swiftコマンドで直接ソースファイルを実行時に、別途ライブラリやソースファイルを指定する必要がある。

swiftコンパイラは、モジュールとライブラリーを単独でそれぞれ出力する事ができる。
またライブラリは静的ライブラリと動的ライブラリどちらも作ることができるが、
実行ファイルの作成時においてライブラリをリンクする際、動的ライブラリと静的ライブラリで違いはない。

# 前提とするディレクトリ階層

```ファイル階層
Main/-*-main.swift
      |
      *-Foo/-*-Foo.swift
```

以下、Fooを外部モジュールとみたてて、Main.swiftファイルの実行ファイルを作成する方法を説明する。

# モジュールファイルの作成

```terminal
$ swiftc -emit-module -module-name Foo Foo.swift
```
Foo.swiftmoduleファイルが生成される。

**NOTE: 指定しているオプションについて**

|option|description|
|:-----|:----------|
|-emit-module|モジュールを出力するように指定|
|-module-name|出力するモジュール名を指定|

main.swiftファイル内で、Fooモジュールがimportされている場合は以下のようにしてmain.swiftファイルのコンパイルが可能になる。

```
$ swiftc -I ../Foo ../Foo/Foo.swift main.swift -o a.out
$ ./a.out # 実行
```

**NOTE: 指定しているオプションについて**

|option|description|
|:-----|:----------|
|-I|モジュール検索パス|

# 静的ライブラリーの作成

##### 1. オブジェクトファイルを作る  

```
$ swiftc -emit-object -parse-as-library Foo.swift
```
Foo.oファイルが生成される。

**NOTE: 指定しているオプションについて**

|option           |description                             |
|:----------------|:---------------------------------------|
|-emit-object     |オブジェクトファイルを出力するように指定|
|-parse-as-library|指定されたソースファイルをライブラリとして解析するように指定。この指定がないと実行ファイル生成時に、_mainシンボルが重複しているエラーが出力される|

##### 2. 静的ライブラリーの作成　　

```terminal
$ ar r libFoo.a Foo.o ...
```
...には、他にもオブジェクトファイルがある場合は指定する

---
**MEMO:**
オブジェクトファイル作成時に、`-parse-as-library` を指定しないと、実行ファイル生成時に_mainシンボルが重複しているエラーが表示される。

```warning
$ swiftc -I ./Foo -L ./Foo -lFoo main.swift 
ld: warning: ignoring file .//libFoo.a, file was built for archive which is not the architecture being linked (x86_64): .//libFoo.a
Undefined symbols for architecture x86_64:
  "__T03FooAAVABSS4name_tcfC", referenced from:
      _main in main-c86a13.o
ld: symbol(s) not found for architecture x86_64
```

静的ライブラリの機能（関数など）はswiftコマンドで読み込むことはできない。
一旦swiftcコマンドで実行ファイルを生成する必要がある。

# 動的ライブラリの作成

動的ライブラリは直接swiftcコマンドで作成出来る。
  
```terminal
$ swiftc -emit-library Foo.swift
```

libFoo.dylibが生成される。

**NOTE: 指定しているオプションについて**

|option|description|
|:-----|:----------|
|-emit-object|オブジェクトファイルを出力するように指定|

また以下のように直接モジュールとライブラリーを作ることも可能
ex: 動的ライブラリの場合

```
$ swiftc -emit-library -emit-module -module-name Foo Foo.swift
```


---
**MEMO:**
動的ライブラリは、`-parse-as-library` を指定する必要はない。
また動的ライブラリはswiftコマンドで直接ライブラリ内の機能をロード出来る。

# 実行ファイルの作成

Main実行ファイルを作成する
   
 ```terminal
 $ swiftc -I ./Foo -L ./Foo -lFoo main.swift
 ```
 
**NOTE: 指定しているオプションについて**

|option|description|
|:-----|:----------|
|-I|モジュール検索パス|
|-L|ライブラリ検索パス|
|-lXXX|libXXXライブラリをリンクするように指定|
 

main実行ファイルの実行

```
$ ./Main
```

# swiftソースファイルを直接実行
Fooモジュールが、動的ライブラリの場合はswiftコマンドでmain.swiftをそのまま実行できる。
しかしながら、静的ライブラリは実行エラーになる。

```
$ swift -I ./Foo -L ./Foo -lFoo main.swift
```


# 関連
* clangモジュールについて 
https://qiita.com/ysn551/items/6f783af2b65c2c4d4631] 
こちらはObjective-Cで開発時に私がまとめたものです。
このモジュール機能を調べていなければ、Swiftのモジュールは理解できなかっただろうと思いました。
<br>

* [C言語] 共有ライブラリと静的ライブラリを整理する 
https://qiita.com/edo_m18/items/b9765ff3313d5a13f82f 
ライブラリの作成方法で参照にさせていただきました。
オブジェクトファイルから静的ライブラリを作る方法がC言語とまったく同じってところがswiftの凄さですよね。