public static class PostBuildTrigger { // Frameworks Ids - These ids have been generated by creating a project using Xcode then // extracting the values from the generated project.pbxproj. The format of this // file is not documented by Apple so the correct algorithm for generating these // ids is unknown const string CORETELEPHONY_ID = "919BD0C3159C677000C931BE" ; const string CORETELEPHONY_FILEREFID = "919BD0C2159C677000C931BE" ; // List of all the frameworks to be added to the project public struct framework { public string sName ; public string sId ; public string sFileId ; public framework(string name, string myId, string fileid) { sName = name ; sId = myId ; sFileId = fileid ; } } /// Processbuild Function [PostProcessBuild] // <- this is where the magic happens public static void OnPostProcessBuild(BuildTarget target, string path) { // 1: Check this is an iOS build before running #if UNITY_IPHONE { // 2: We init our tab and process our project framework[] myFrameworks = { new framework("CoreTelephony.framework", CORETELEPHONY_ID, CORETELEPHONY_FILEREFID) } ; string xcodeprojPath = Application.dataPath ; xcodeprojPath = xcodeprojPath.Substring(0, xcodeprojPath.Length - 16) ; string device = "iOSandIpad" ; if (PlayerSettings.iOS.targetDevice == iOSTargetDevice.iPadOnly) device = "iPad" ; else if (PlayerSettings.iOS.targetDevice == iOSTargetDevice.iPhoneOnly) device = "iPhone" ; xcodeprojPath = xcodeprojPath + "buildios/"+device+"/Unity-iPhone.xcodeproj" ; // Debug.Log("We found xcodeprojPath to be : "+xcodeprojPath) ; Debug.Log("OnPostProcessBuild - START on: "+device) ; updateXcodeProject(xcodeprojPath, myFrameworks) ; } #else // 3: We do nothing if not iPhone Debug.Log("OnPostProcessBuild - Warning: This is not an iOS build") ; #endif Debug.Log("OnPostProcessBuild - STOP") ; } // MAIN FUNCTION // xcodeproj_filename - filename of the Xcode project to change // frameworks - list of Apple standard frameworks to add to the project public static void updateXcodeProject(string xcodeprojPath, framework[] listeFrameworks) { // STEP 1 : We open up the file generated by Unity and read into memory as // a list of lines for processing string project = xcodeprojPath + "/project.pbxproj" ; string[] lines = System.IO.File.ReadAllLines(project); // STEP 2 : We check if file has already been processed and only proceed if it hasn't, // we'll do this by looping through the build files and see if CoreTelephony.framework // is there int i = 0 ; bool bFound = false ; bool bEnd = false ; while ( !bFound && !bEnd) { if (lines[i].Length > 5 && (String.Compare(lines[i].Substring(3, 3), "End") == 0) ) bEnd = true ; bFound = lines[i].Contains("CoreTelephony.framework") ; ++i ; } if (bFound) Debug.Log("OnPostProcessBuild - ERROR: Frameworks have already been added to XCode project") ; else { // STEP 3 : We'll open/replace project.pbxproj for writing and iterate over the old // file in memory, copying the original file and inserting every extra we need FileStream filestr = new FileStream(project, FileMode.Create); //Create new file and open it for read and write, if the file exists overwrite it. filestr.Close() ; StreamWriter fCurrentXcodeProjFile = new StreamWriter(project) ; // will be used for writing // As we iterate through the list we'll record which section of the // project.pbxproj we are currently in string section = "" ; // We use this boolean to decide whether we have already added the list of // build files to the link line. This is needed because there could be multiple // build targets and they are not named in the project.pbxproj bool bFrameworks_build_added = false ; int iNbBuildConfigSet = 0 ; // can't be > 2 i = 0 ; foreach (string line in lines) { if (line.StartsWith(" GCC_ENABLE_CPP_EXCEPTIONS") || line.StartsWith(" GCC_ENABLE_CPP_RTTI") || line.StartsWith(" GCC_ENABLE_OBJC_EXCEPTIONS") ) { // apparently, we don't copy those lines in our new project } else { ////////////////////////////// // STEP 1 : Build Options // ////////////////////////////// // // TapJoy needs "Enable Object-C Exceptions" to be set to "YES" // ////////////////////////////// // This one is special, we have to replace a line and not write after // if ( section == "XCBuildConfiguration" && line.Trim().StartsWith(" GCC_ENABLE_OBJC_EXCEPTIONS") ) // fCurrentXcodeProjFile.Write(" GCC_ENABLE_OBJC_EXCEPTIONS = YES; ") ; // in any other situation, we'll first copy the line in our new project, then we might do something special regarding that line // else fCurrentXcodeProjFile.WriteLine(line) ; ////////////////////////////////// // STEP 2 : Include Framewoks // ////////////////////////////////// // // TapJoy needs CoreTelephony (in weak-link = "optional") // ////////////////////////////////// // Each section starts with a comment such as : /* Begin PBXBuildFile section */' if ( lines[i].Length > 7 && String.Compare(lines[i].Substring(3, 5), "Begin") == 0 ) { section = line.Split(' ')[2] ; //Debug.Log("NEW_SECTION: "+section) ; if (section == "PBXBuildFile") { foreach (framework fr in listeFrameworks) add_build_file(fCurrentXcodeProjFile, fr.sId, fr.sName, fr.sFileId) ; } if (section == "PBXFileReference") { foreach (framework fr in listeFrameworks) add_framework_file_reference(fCurrentXcodeProjFile, fr.sFileId, fr.sName) ; } if (line.Length > 5 && String.Compare(line.Substring(3, 3), "End") == 0) section = "" ; } // The PBXResourcesBuildPhase section is what appears in XCode as 'Link // Binary With Libraries'. As with the frameworks we make the assumption the // first target is always 'Unity-iPhone' as the name of the target itself is // not listed in project.pbxproj if (section == "PBXFrameworksBuildPhase" && line.Trim().Length > 4 && String.Compare(line.Trim().Substring(0, 5) , "files") == 0 && !bFrameworks_build_added) { foreach (framework fr in listeFrameworks) add_frameworks_build_phase(fCurrentXcodeProjFile, fr.sId, fr.sName) ; bFrameworks_build_added = true ; } // The PBXGroup is the section that appears in XCode as 'Copy Bundle Resources'. if (section == "PBXGroup" && line.Trim().Length > 7 && String.Compare(line.Trim().Substring(0, 8) , "children") == 0 && lines[i-2].Trim().Split(' ').Length > 0 && String.Compare(lines[i-2].Trim().Split(' ')[2] , "CustomTemplate" ) == 0 ) { foreach (framework fr in listeFrameworks) add_group(fCurrentXcodeProjFile, fr.sFileId, fr.sName) ; } ////////////////////////////// // STEP 3 : Build Options // ////////////////////////////// // // AdColony needs "Other Linker Flags" to have "-all_load -ObjC" added to its value // ////////////////////////////// if (section == "XCBuildConfiguration" && line.StartsWith(" OTHER_LDFLAGS") && iNbBuildConfigSet < 2) { //fCurrentXcodeProjFile.Write(" "-all_load", ") ; fCurrentXcodeProjFile.Write(" "-ObjC", ") ; Debug.Log("OnPostProcessBuild - Adding "-ObjC" flag to build options") ; // "-all_load" and ++iNbBuildConfigSet ; } } ++i ; } fCurrentXcodeProjFile.Close() ; } } ///////////////// /////////// // ROUTINES /////////// ///////////////// // Adds a line into the PBXBuildFile section private static void add_build_file(StreamWriter file, string id, string name, string fileref) { Debug.Log("OnPostProcessBuild - Adding build file " + name) ; string subsection = "Frameworks" ; if (name == "CoreTelephony.framework") // CoreTelephony.framework should be weak-linked file.Write(" "+id+" /* "+name+" in "+subsection+" */ = {isa = PBXBuildFile; fileRef = "+fileref+" /* "+name+" */; settings = {ATTRIBUTES = (Weak, ); }; };") ; else // Others framework are normal file.Write(" "+id+" /* "+name+" in "+subsection+" */ = {isa = PBXBuildFile; fileRef = "+fileref+" /* "+name+" */; }; ") ; } // Adds a line into the PBXBuildFile section private static void add_framework_file_reference(StreamWriter file, string id, string name) { Debug.Log("OnPostProcessBuild - Adding framework file reference " + name) ; string path = "System/Library/Frameworks" ; // all the frameworks come from here if (name == "libsqlite3.0.dylib") // except for lidsqlite path = "usr/lib" ; file.Write(" "+id+" /* "+name+" */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "+name+"; path = "+path+"/"+name+"; sourceTree = SDKROOT; }; ") ; } // Adds a line into the PBXFrameworksBuildPhase section private static void add_frameworks_build_phase(StreamWriter file, string id, string name) { Debug.Log("OnPostProcessBuild - Adding build phase " + name) ; file.Write(" "+id+" /* "+name+" in Frameworks */, ") ; } // Adds a line into the PBXGroup section private static void add_group(StreamWriter file, string id, string name) { Debug.Log("OnPostProcessBuild - Add group " + name) ; file.Write(" "+id+" /* "+name+" */, ") ; } }
原文:
Hi !
I'm sorry, I should have replied here days ago, in case someone like you would come here.
So I have ask the question here to prime31. His answer was :
@baz, there is no magic involved. Simply naming the file PostProcessBuildPlayer_Something will most definitely get the script called.
So I was doing everything nice, but it still didn't work !
I forfeit, and tried to do the postProcessing INSIDE Unity, as described in the last link above.
And it worked !
Basically, what I'm doing is opening the Xcode project, reading it and caching it, and then rewrite it line by line, adding or changing lines when special cases happens.
I have append the code here. I know it will look kinda hardcore at first glance, but do copy it in your fav editor, indent it as you want, and iterate through it like 1 or 2 time, and you will understand. In fac it's pretty straighforward. If I have helped anybody then I'm glad
Courage !
传送门:http://forum.unity3d.com/threads/141657-Postprocessbuildplayer-build-options-amp-frameworks