LoginSignup
21
17

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-10-29

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

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

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

コード

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

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の場合は、以下の方法でいけるっぽいです。

// 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上の操作で追加した場合と比較してみると、以下の箇所が違っているようでした。

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 */,
            );

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"」になっている点、
もう1つがPBXFrameworksBuildPhaseのfilesリストに追加されていない点です。

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

そのうちこんなことをしなくても、もっと簡単に.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.

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

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

以上

21
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
17