[Unity] PostProcessBuildで*.tbdを追加する (Xcode Manipulation API)

Xcode7から**.dylib**ファイルが**.tbd**に変わりましたが、.tdbライブラリを
Xcode Manipulation API で追加するのがなかなかうまくいかなかったため、その方法です。
Unity5.2.2f1で確認しています。

**[追記]
Unity5.3.2p1からは.tbdの追加に対応され、.dylib同様に以下のコードだけでOKになりました**

```csharp
proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.tbd", "Frameworks/libsqlite3.tbd", PBXSourceTree.Sdk));
```


# コード
先にコードを全部載せます。

```csharp:Assets/Editor/PostBuildProcess.cs
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Collections.Generic;
using System.Text;
using System.IO;

public class PostBuildProcess {

	[PostProcessBuild]
	public static void OnPostProcessBuild (BuildTarget buildTarget, string path) {
		if (buildTarget == BuildTarget.iOS) {
			processForiOS (path);
		}
	}


	private static void processForiOS (string path) {
		string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";

		PBXProject proj = new PBXProject ();
		proj.ReadFromString (File.ReadAllText (projPath));

		string target = proj.TargetGuidByName ("Unity-iPhone");

		// tbd追加
		string tbdName = "libsqlite3.tbd";
		proj.AddFileToBuild(target, proj.AddFile("usr/lib/" + tbdName, "Frameworks/" + tbdName, PBXSourceTree.Sdk));
		string projText = addTbdLibrary (target, proj.WriteToString (), tbdName);

		File.WriteAllText(projPath, projText);
	}


	// .pbxprojファイルのtbdの記述を修正して返却
	private static string addTbdLibrary(string target, string projText, string tbdName) {

		string[] lines = projText.Split ('\n');
		List<string> newLines = new List<string> ();

		string refId = null;
		bool editFinish = false;

		for (int i = 0; i < lines.Length; i++) {

			string line = lines [i];

			if (editFinish) {
				newLines.Add (line);

			} else if (line.IndexOf (tbdName) > -1) {
				if (refId == null && line.IndexOf ("PBXBuildFile") > -1) {
					refId = line.Substring (0, line.IndexOf ("/*")).Trim ();
				} else if (line.IndexOf ("lastKnownFileType") > -1) {
					line = line.Replace ("lastKnownFileType = file;", "lastKnownFileType = \"sourcecode.text-based-dylib-definition\";");
				}
				newLines.Add (line);

			} else if (line.IndexOf ("isa = PBXFrameworksBuildPhase;") > -1) {
				do {
					newLines.Add (line);
					line = lines [++i];
				} while (line.IndexOf("files = (") == -1);

				while (true) {
					if (line.IndexOf (")") > -1) {
						newLines.Add (refId + ",");
						newLines.Add (line);
						break;
					} else if (line.IndexOf (refId) > -1) {
						newLines.Add (line);
						break;
					} else {
						newLines.Add (line);
						line = lines [++i];
					}
				}
				editFinish = true;

			} else {
				newLines.Add (line);
			}
		}

		return string.Join ("\n", newLines.ToArray ());
	}
}

```

# 説明

dylibの場合は、以下の方法でいけるっぽいです。

```csharp
// dylib追加
proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.dylib", "Frameworks/libsqlite3.dylib", PBXSourceTree.Sdk));
```

**[追記]
Unity5.3.2p1からは、.tbdでも上記の書き方だけででOKになってます。**


tbdで同じように書いたところ、Xcode上で「Project navigator」には追加されますが、
「Link Binary With Libraries」に追加されず、リンクが完全ではない状態でした。

そこでXcode上の操作で追加した場合と比較してみると、以下の箇所が違っているようでした。

```text:PostProcessBuildで追加
                XXXXXXXXXXXXXXXXXXXXXXXX /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = file; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };

... 省略 ...

/* Begin PBXFrameworksBuildPhase section */
		XXXXXXXXXXXXXXXXXXXXXXXX /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
... 省略 ...
				XXXXXXXXXXXXXXXXXXXXXXXX /* libsqlite3.tbd in Resources */,
			);

```



```text:Xcodeで追加
		XXXXXXXXXXXXXXXXXXXXXXXX /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };

... 省略 ...

/* Begin PBXFrameworksBuildPhase section */
		XXXXXXXXXXXXXXXXXXXXXXXX /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
... 省略 ...
			);


```

1つ目の違いが「lastKnownFileType = file」が「"sourcecode.text-based-dylib-definition"」になっている点、
もう１つがPBXFrameworksBuildPhaseのfilesリストに追加されていない点です。

そのためこの２つを無理矢理変更しているコードが上に書いたものです。

そのうちこんなことをしなくても、もっと簡単に.tbdを追加できるようになるとは思いますが、
それまでの繋ぎで使えれば良いかと思います。


# 補足
PBXProjectオブジェクトをメソッドの引数に渡して処理をしようとすると、
以下のようなエラーが出ます。

> FileNotFoundException: Could not load file or assembly 'UnityEditor.iOS.Extensions.Xcode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.

```csharp:コードの例
private static void test(PBXProject proj) {
	proj.WriteToString ();
}
```

そのためPBXProjectの操作は、newしたメソッドの中で完結させる必要があるようです。（謎）


以上