zoukankan      html  css  js  c++  java
  • 转:Postprocessbuildplayer自動連接Framework文件

    原文:  http://blog.sina.com.cn/s/blog_4a628f030101b411.html

    自用筆記,口胡莫怪

    最近鼓搗用Unity開發IOS app,對每次生成Project都要在Xcode下手動添加Framework文件甚煩,查了下,可以用Postprocessbuildplayer解決

    Postprocessbuildplayer(無後綴名),放在工程文件下Assets/Editor下,Unity在編譯最後會自動執行這個腳本文件

    以下以ARToolKit所需添加的Framework文件為例:(參看這裡

    ——————————————————————————————————————————————

    #!/usr/bin/python

    import sys
    import os


    # Constants
    FRAMEWORK_NAME = 0
    FRAMEWORK_ID = 1
    FRAMEWORK_FILEREFID = 2

    RESFILE_NAME = 0
    RESFILE_ID = 1
    RESFILE_FILEREFID = 2
    RESFILE_LASTKNOWNTYPE = 3

    # 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

    ACCELERATE_ID = '4A24A46A17244C9F00953BF8'
    ACCELERATE_FILEREFID = '4A24A46917244C9F00953BF8'

    AUDIOTOOLBOX_ID = '567B626A114A9F340000AA1F'
    AUDIOTOOLBOX_FILEREFID = '8358D1B70ED1CC3700E3A684'

    AVFOUNDATION_ID = '7F36C11313C5C673007FBDD9'
    AVFOUNDATION_FILEREFID = '7F36C11013C5C673007FBDD9'

    COREGRAPHICS_ID = '56B7959B1442E0F20026B3DD'
    COREGRAPHICS_FILEREFID = '56B7959A1442E0F20026B3DD'

    COREMEDIA_ID = '7F36C11113C5C673007FBDD9'
    COREMEDIA_FILEREFID = '7F36C10E13C5C673007FBDD9'

    COREVIDEO_ID = '7F36C11213C5C673007FBDD9'
    COREVIDEO_FILEREFID = '7F36C10F13C5C673007FBDD9'

    OPENGLES_ID = '567B6265114A9F340000AA1F'
    OPENGLES_FILEREFID = '83B256E10E62FEA000468741'

    QUARTZCORE_ID = '567B6266114A9F340000AA1F'
    QUARTZCORE_FILEREFID = '83B2570A0E62FF8A00468741'

    # List of all the frameworks to be added to the project
    frameworks = [["Accelerate.framework", ACCELERATE_ID, ACCELERATE_FILEREFID], \
                  ["AudioToolbox.framework", AUDIOTOOLBOX_ID, AUDIOTOOLBOX_FILEREFID], \
                  ["AVFoundation.framework", AVFOUNDATION_ID, AVFOUNDATION_FILEREFID], \
                  ["CoreGraphics.framework", COREGRAPHICS_ID,COREGRAPHICS_FILEREFID], \
                  ["CoreMedia.framework", COREMEDIA_ID, COREMEDIA_FILEREFID], \
                  ["CoreVideo.framework", COREVIDEO_ID, COREVIDEO_FILEREFID], \
                  ["OpenGLES.framework", OPENGLES_ID, OPENGLES_FILEREFID], \
                  ["QuartzCore.framework", QUARTZCORE_ID, QUARTZCORE_FILEREFID]]

    # List of data files to be added to the app bundle
    resfiles = []



    # Adds a line into the PBXBuildFile section
    def add_build_file(pbxproj, id, name, fileref):
        subsection = 'Resources'
        if name[-9:] == 'framework':
            subsection = 'Frameworks'
        print "Adding build file " + name + '\n'
        pbxproj.write('\t\t' + id + ' = {isa = PBXBuildFile; fileRef = ' + fileref +  ' ; };\n')

    #Adds a line to the PBXFileReference to add a resource file
    def add_res_file_reference(pbxproj, id, name, last_known_file_type):
        print "Adding data file reference " + name + "\n"
        pbxproj.write('\t\t' + id + ' = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = ' + last_known_file_type + '; name = ' + name + '; path = Data/Raw/' + name + '; sourceTree = SOURCE_ROOT; };\n')

    # Adds a line into the PBXFileReference section to add a framework
    def add_framework_file_reference(pbxproj, id, name):
        print "Adding framework file reference " + name + '\n'
        pbxproj.write('\t\t' + id + ' = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ' + name + '; path = System/Library/Frameworks/' + name + '; sourceTree = SDKROOT; };\n')

    # Adds a line into the PBXFrameworksBuildPhase section
    def add_frameworks_build_phase(pbxproj, id, name):
        print "Adding build phase " + name + '\n'
        pbxproj.write('\t\t\t\t' + id + ' ,\n')

    # Adds a line into the PBXResourcesBuildPhase section
    def add_resources_build_phase(pbxproj, id, name):
        print "Adding build phase " + name + '\n'
        pbxproj.write('\t\t\t\t' + id + ' ,\n')

    # Adds a line into the PBXGroup section
    def add_group(pbxproj, id, name):
        print "Add group " + name + '\n'
        pbxproj.write('\t\t\t\t' + id + ' ,\n')

    # Returns a list of all the files already in a pbxproj
    #    lines - a list of all the lines read in from a pbxproj
    def read_existing_files(lines):
        begin_pbxbuildfile_section = False
        existing_files = []
        i = 0
        line = lines[i]
        while line[3:6] != 'End':
            if not begin_pbxbuildfile_section:
                begin_pbxbuildfile_section = (line[3:21] == 'Begin PBXBuildFile')
            else:
                existing_files.append(line.split()[2])
            i = i + 1
            line = lines[i]

        return existing_files


    # Processes the given xcode project to add or change the supplied parameters
    #   xcodeproj_filename - filename of the Xcode project to change
    #   frameworks - list of Apple standard frameworks to add to the project
    #   resfiles - list resource files added to the project
    def process_pbxproj(xcodeproj_filename, frameworks, resfiles):

        # Open up the file generated by Unity and read into memory as
        # a list of lines for processing
        pbxproj_filename = xcodeproj_filename + '/project.pbxproj'
        pbxproj = open(pbxproj_filename, 'r')
        lines = pbxproj.readlines()
        pbxproj.close()

        # Work out which of the resfiles exist and remove them if they don't, this
        # is because if using frame markers there may not be a qcar-resources.dat
        resfiles = [x for x in resfiles if os.path.exists(xcodeproj_filename + '/../Data/Raw/' + x[RESFILE_NAME])]

        # Next open up an empty project.pbxproj for writing and iterate over the old
        # file copying the original file and inserting anything extra we need
        pbxproj = open(pbxproj_filename, 'w')

        # As we iterate through the list we'll record which section of the
        # project.pbxproj we are currently in
        section = ''

        # We use these booleans 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
        frameworks_build_added = False
        res_build_added = False

        # Build a list of the files already added to the project.  Then use it to
        # avoid adding anything to the project twice
        existing_files = read_existing_files(lines)
        filtered_frameworks = []
        for framework in frameworks:
            if framework[0] not in existing_files:
                filtered_frameworks.append(framework)
        frameworks = filtered_frameworks
        for resfile in resfiles:
            if resfile[0] in existing_files:
                resfiles.remove(resfile)
       
      
        # Now iterate through the project adding any new lines where needed
        i = 0
        for i in range(0, len(lines)):
            line = lines[i]
            pbxproj.write(line)

            # Each section starts with a comment such as
            # '
            if line[3:8] == 'Begin':
                section = line.split(' ')[2]
                if section == 'PBXBuildFile':
                    for framework in frameworks:
                        add_build_file(pbxproj, framework[FRAMEWORK_ID], framework[FRAMEWORK_NAME], framework[FRAMEWORK_FILEREFID])
                    for resfile in resfiles:
                        add_build_file(pbxproj, resfile[RESFILE_ID], resfile[RESFILE_NAME], resfile[RESFILE_FILEREFID])

                if section == 'PBXFileReference':
                    for framework in frameworks:
                        add_framework_file_reference(pbxproj, framework[FRAMEWORK_FILEREFID], framework[FRAMEWORK_NAME])
                    for resfile in resfiles:
                        add_res_file_reference(pbxproj, resfile[RESFILE_FILEREFID], resfile[RESFILE_NAME], resfile[RESFILE_LASTKNOWNTYPE])
       
            if line[3:6] == 'End':
                section = ''
      
            if section == 'PBXFrameworksBuildPhase':
                if line.strip()[0:5] == 'files':
                    if not frameworks_build_added:
                        for framework in frameworks:
                            add_frameworks_build_phase(pbxproj, framework[FRAMEWORK_ID], framework[FRAMEWORK_NAME])
                        frameworks_build_added = True

            # 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 == 'PBXResourcesBuildPhase':
                if line.strip()[0:5] == 'files':
                    if not res_build_added:
                        for resfile in resfiles:
                            add_resources_build_phase(pbxproj,resfile[RESFILE_ID], resfile[RESFILE_NAME])
                        res_build_added = True

            # The PBXGroup is the section that appears in XCode as 'Copy Bundle Resources'.
            if section == 'PBXGroup':
                if (line.strip()[0:8] == 'children') and (lines[i-2].strip().split(' ')[2] == 'CustomTemplate'):
                    for resfile in resfiles:
                        add_group(pbxproj, resfile[RESFILE_FILEREFID], resfile[RESFILE_NAME])
                    for framework in frameworks:
                        add_group(pbxproj, framework[FRAMEWORK_FILEREFID], framework[FRAMEWORK_NAME])



        pbxproj.close()


    # Script start
    print "Starting PostProcessBuildPlayer with the following arguments..."

    i = 0
    for args in sys.argv:
        print str(i) +': ' + args
        i += 1

    # Check this is an iOS build before running
    if sys.argv[2] == "iPhone":

        xcodeproj_full_path_name = sys.argv[1] + '/Unity-iPhone.xcodeproj'
        process_pbxproj(xcodeproj_full_path_name, frameworks, resfiles)


    —————————————————————————————————————————————
    說明:文件的ID和FILEREFID需要用Xcode先正確生成一次工程,之後找到工程文件夾下的 Unity-iPhone.xcodeproj,右鍵 Show Package Contents ,用 TextEdit 打開其下的 project.pbxproj ,尋找要添加的文件名即可

    上面的程序就是通過腳本直接生成 project.pbxproj 以達成直接添加所需文件和庫的目的

    蛇足提示:ID和FILEREFID長得像但其實不一樣。。。某人二逼兮兮一晚上都運行不對就是因為眼瞎了。。。

    以上

  • 相关阅读:
    Java 函数式编程—@FunctionalInterface----functional interface
    人月神话的博客
    如何度量复杂度
    泛型沉思录:创建模版与使用模版生成代码
    ioc与bean管理
    模式(思维)匹配是什么
    简析散光的成因,以及什么是散光的度数和轴位?
    概括是什么?
    思维与模型、世界观
    抽象、维度、层次与分析、综合
  • 原文地址:https://www.cnblogs.com/qqqeeebbb/p/3271853.html
Copyright © 2011-2022 走看看