この記事でのバージョン
Unity 5.1.0f3 Personal
はじめに
以前、XcodeAPIを使って諸々の設定をするXcodeProjectUpdaterというものを作ったのですが、
文量が多くなってしまったため、XcodeAPIを実際にどう使っているかという説明を省きました。
なので今回は、そのXcodeAPIの説明となります。
説明には上記XcodeProjectUpdaterのコードを使いますので、
そちらを参照しながら読むと分かり易いと思います。
OnPostprocessBuild
XcodeAPIはXcodeプロジェクトを作成した後、そのプロジェクトに対して使います。
Xcodeプロジェクトを作成した後、
つまりビルドが終わった後に処理されるのがOnPostprocessBuildというメソッドです。
(と言うよりPostProcessBuildを上部に付けたメソッド?)
//ビルド後に呼ばれる buildTargetがビルドしたプラットフォーム、プロジェクトを出力したパス [PostProcessBuild (100)] //100の所で実行順を指定、小さい方が先に実行 private static void OnPostprocessBuild(BuildTarget buildTarget, string buildPath){ }
OnPostprocessBuildは複数あっても問題ないので、AssetStoreで買った物など、
複数の設定スクリプトがある場合は実行順序を考慮に入れる必要があります。
その時はPostProcessBuildの後に続く数字で実行順を指定しましょう。(なくても可)
Xcodeプロジェクトの読み込み
XcodeAPIではPBXProjectというクラスでXcodeプロジェクトを編集します。
Unity - Scripting API:PBXProject
Xcodeプロジェクトとは拡張子が.xcodeprojになってるやつの事です。
Xcodeプロジェクトの読み込み方は以下の通りです。
//Xcodeプロジェクトへのパスを取得 buildPathはOnPostprocessBuildの引数 string pbxProjPath = PBXProject.GetPBXProjectPath(buildPath); //インスタンスを作成 PBXProject pbxProject = new PBXProject(); //プロジェクトの読み込み pbxProject.ReadFromString(File.ReadAllText(pbxProjPath));
プロジェクトファイルのパスを作成し、
それをPBXProjectのインスタンスに読み込ませるといった形です。
Xcodeプロジェクトのプロパティ設定
PBXProjectを使ったプロパティの設定方法は以下の通りです。
//プロパティ設定時に必要となるターゲットIDの取得 string targetGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTargetName()); //コンパイラフラグ設定 //fileGuidが設定したいファイルのID compileFlagsが設定するコンパイラフラグ string fileGuid = pbxProject.FindFileGuidByProjectPath(targetPath);//targetPathが設定したいファイルへのパス pbxProject.SetCompileFlagsForFile(string targetGuid, string fileGuid, List<string> compileFlags); //フレームワーク追加 //frameworkにフレームワークの名前を拡張子付きで設定、weak は true だと required、false だと optional になる pbxProject.AddFrameworkToProject(string targetGuid, string framework, bool weak); //その他のプロパティ設定 //nameが変更したいプロパティ名、valueがプロパティに設定する値 pbxProject.AddBuildProperty(string targetGuid, string name, string value); //新規 pbxProject.SetBuildProperty(string targetGuid, string name, string value); //上書き pbxProject.UpdateBuildProperty(string targetGuid, string name, string[] addValues, string[] removeValues); //複数更新 //書き出し //pbxProjPathは読み込んだ時と同じやつ File.WriteAllText(pbxProjPath, pbxProject.WriteToString());
XcodeAPIを使えばこれらのメソッドを使うだけで、
プロジェクトの設定を変えられるわけですね。簡単!
ただし、一つ注意点があり、
valueで真偽値を設定する場合、"true" or "false"では無く、"YES" or "NO"になります。
//BitCodeの設定 pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.ENABLE_BITCODE_KEY, setting.EnableBitCode ? "YES" : "NO");
"YES"という文字列でなければ、全て偽となるようです。
Xcodeプロジェクトのプロパティ名
先ほどXcodeプロジェクトのプロパティを変更する際に、nameでプロパティ名を指定していました。
10.27追記
このプロパティ名の確認方法ですが、以前書いた方法より簡単なものがありました。
画像の通り、項目を選んでQuick Helpという所で確認できます。
10.27追記終わり
このプロパティ名は、プロジェクトファイルを右クリックし、パッケージ内容を表示
した中にあるproject.pbxprojに書いてあります。
このproject.pbxprojをテキストエディタなどで開き、それっぽい単語で検索すると
ENABLE_BITCODEなど、プロパティ名を見つける事ができます。
見ての通りちょっと面倒です。
もしや他に正攻法が……?
ファイル及びディレクトリのコピー
C#でのディレクトリ及びファイルのコピーについては以下の記事をご参照ください。
ファイルをコピーするメソッドはあるけどディレクトリをコピーするメソッドは無いよってだけですが。
また、ここの説明で使うコードはXcodeProjectUpdaterのDirectoryProcessor.csにあります。
Xcodeのプロジェクトへファイル及びディレクトリのコピー するには、
ただファイルをコピーするだけでなく
AddFileToBuildを使ってプロジェクトに追加しなくてはなりません。
//ファイルのコピー //filePathが元あった場所、copyPathがコピーする先 File.Copy(filePath, copyPath); //プロジェクトへファイルの追加(ディレクトリもAddFileToBuildを使う) pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
copyPathとrelativePathは同じ場所を示しているのですが、
copyPathはコピー先への絶対パスで、
relativePathはビルドしたディレクトリからのコピー先への相対パス になります。
例をあげると以下のような感じです。
copyPath
/Users/UserName/Documents/UnityProject/iOS/CopyToXcode/Test1/test1.txt
relativePath
Test1/test1.txt
コピーの方法は以上ですが、コピーの際にいくつか注意点があります。
まず、ディレクトリ内の全ファイルをコピーさせると、
余分なファイルまでXcodeプロジェクトに入ってしまうので、以下のようにするといいかもしれません。
//.metaファイルはコピーしない string extension = Path.GetExtension (filePath); if(extension == ExtensionName.META){ continue; } //隠しファイルはコピーしない .DS_Storeとか if(fileName[0] == '.'){ continue; }
また、ディレクトリ内全コピーだとフレームワークなどもディレクトリ扱いになってしまうので、
.Frameworkや.bundleがついてるディレクトリは内部のファイルを一つずつ追加せず、
全ファイルコピーした後、ディレクトリごと追加する必要があります。
さらにプロジェクトに追加したたけだけでは、
フレームワークパスなどディレクトリへのパスを設定されないので
自力でやる必要があります。
フレームワークサーチパス設定例
pbxProject.AddBuildProperty( targetGuid, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/" + currentDirectoryPath );
Xcode上でのフレームワークサーチパスの場所
ライブラリーサーチパス設定例
pbxProject.AddBuildProperty( targetGuid, "LIBRARY_SEARCH_PATHS" "$(PROJECT_DIR)/" + currentDirectoryPath );
Xcode上でのライブラリーサーチパスの場所
一度作ると便利ですが、結構面倒ですね……。
Info.plist読み込み
PBXProjectではInfo.plist部分の設定は変更できません。
なので、Info.plistの編集にはPlistDocumentを使います。
Unity - Scripting API:PlistDocument
また、ここの説明で使うコードはXcodeProjectUpdaterのInfoPlistProcessor.csにあります。
plistの読み込み方は以下の通りです。
//Xcodeプロジェクトへのパスを取得 buildPathはOnPostprocessBuildの引数 string plistPath = Path.Combine(buildPath, "Info.plist" ); //インスタンスを作成 PlistDocument plist = new PlistDocument() ; //plistの読み込み plist.ReadFromFile(plistPath) ;
流れはXcodeプロジェクトの時と全く同じです。
Info.plist編集
まず、plist.rootでInformation Property Listを取得できます。
Listという名前だけどDictionaryです。
さらにplist.root["Key"]で各要素を取得し、.As◯◯でPlistElement◯◯型に変換します。
例えば、URL typesのURL identifier を取得する場合は以下のようになります。
PlistElementArray urlTypes = plist.root["CFBundleURLTypes"].AsArray(); PlistElementDict itmeDict = urlTypes.values[0].AsDict(); string identifier = itmeDict ["CFBundleURLName"].AsString ();
ただし、要素が存在しないとエラーがでます。
また、ただCreateをすると既にあるデータに上書きしてしまうので、
ContainsKeyを使って要素が存在するかを判断する必要があります。
PlistElementArray urlTypes; //keyがあれば取得 if(plist.root.values.ContainsKey("CFBundleURLTypes")){ urlTypes = plist.root["CFBundleURLTypes"].AsArray(); } //keyが無ければ新規作成 else{ urlTypes = plist.root.CreateArray ("CFBundleURLTypes"); }
最後に、編集が終わったらplist.WriteToFile(plistPath); で書き出します。
Info.plistのkey
10.27追記
各要素のkeyを以前書いた方法より簡単に確認する方法ありました。
画像の通り、項目を選んでQuick Helpという所で確認できます。
10.27追記終わり
各要素のkeyは、Info.plistをテキストエディタで開いて
<key></key>で囲まれている所に記載されています。
Xcodeプロジェクトと比べて、こっちは簡単に確認できます。