{"id":2834,"date":"2024-11-15T18:49:09","date_gmt":"2024-11-15T10:49:09","guid":{"rendered":"http:\/\/www.u3d8.com\/?p=2834"},"modified":"2024-11-18T16:22:13","modified_gmt":"2024-11-18T08:22:13","slug":"%e8%ae%b0%e5%bd%95python%e7%bc%96%e5%86%99xcode%e4%b8%80%e9%94%ae%e6%89%93%e5%8c%85","status":"publish","type":"post","link":"http:\/\/www.u3d8.com\/?p=2834","title":{"rendered":"\u8bb0\u5f55python\u7f16\u5199Xcode\u4e00\u952e\u6253\u5305"},"content":{"rendered":"\n<h4>\u524d\u63d0<\/h4>\n\n\n\n<p>\u9884\u5148\u505a\u597d\u6a21\u7248\uff0c\u6211\u8fd9\u91cc\u505a\u4e86\u56db\u4e2a\u6a21\u677f\uff0c\u5206\u522b\u5bf9\u5e94\u56db\u4e2a\u6e20\u9053<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport sys\nimport shutil\nimport logging\nimport plistlib\nimport argparse\nimport subprocess\nimport coloredlogs\nfrom PIL import Image\nfrom pbxproj import XcodeProject\nfrom pbxproj.pbxextensions.ProjectFiles import FileOptions\n\nparser = argparse.ArgumentParser(description='argpase')\nparser.add_argument('--project-folder', '-p', type=str, required=True, help=\"Xcode\u5de5\u7a0b\u76ee\u5f55\")\nparser.add_argument('--replace-assets', '-s', type=int, required=False, default=1, help='\u66ff\u6362\u8d44\u6e90&#91;0:\u4e0d\u66ff\u6362, 1:\u66ff\u6362]')\nparser.add_argument('--pack-ipa', '-i', type=int, required=False, default=0, help='\u6784\u5efaipa&#91;0:\u4e0d\u6784\u5efa, 1:release&amp;develop, 2:release, 3:develop]')\n\nargs = parser.parse_args()\n\ndef group_add_files(project, group, folder, file_options):\n\tfor item in os.listdir(folder):\n\t\tfull_item = os.path.join(folder, item)\n\t\tif os.path.isdir(full_item):\n\t\t\tsub_group = project.get_or_create_group(item, parent=group)\n\t\t\tgroup_add_files(project, sub_group, full_item, file_options)  # \u9012\u5f52\u590d\u5236\u5b50\u76ee\u5f55\n\t\telse:\n\t\t\ttry:\n\t\t\t\tproject.add_file(full_item, parent=group, force=True, target_name='UnityFramework', file_options=file_options)\n\t\t\texcept:\n\t\t\t\tlogging.info('ERROR\u6dfb\u52a0\u6587\u4ef6\u5f15\u7528\u5931\u8d25: ' + full_item)\n\n\n## \u66ff\u6362\u8d44\u6e90\ndef replace_assets(area, sdk_folder, project_folder, tproject_folder):\n\tlogging.info('\u66ff\u6362\u8d44\u6e90: ' + area)\n\tlogging.info('sdk_folder: ' + sdk_folder)\n\tlogging.info('project_folder: ' + project_folder)\n\tlogging.info('tproject_folder: ' + tproject_folder)\n\n\t## \u6e05\u7406\u6784\u5efa\n\tclean_cmd = ('xcodebuild clean -project %s\/Unity-iPhone.xcodeproj -configuration Debug' %(tproject_folder))\n\tprocess = subprocess.Popen(clean_cmd, shell=True, stdin=subprocess.PIPE, stderr=sys.stderr)\n\tprocess.communicate()\n\tif process.returncode != 0:\n\t\tlogging.error('%s clean failed!' %(area))\n\t\treturn\n\tclean_cmd = ('xcodebuild clean -project %s\/Unity-iPhone.xcodeproj -configuration Release' %(tproject_folder))\n\tprocess = subprocess.Popen(clean_cmd, shell=True, stdin=subprocess.PIPE, stderr=sys.stderr)\n\tprocess.communicate()\n\tif process.returncode != 0:\n\t\tlogging.error('%s clean failed!' %(area))\n\t\treturn\n\n\tlogging.info('\u62f7\u8d1dplist\u524d\u7f13\u5b58\u5e76\u5199\u5165\u6b63\u786e\u7684\u7248\u672c\u53f7')\n\tbundle_version_string = ''\n\tbundle_version_number = ''\n\twith open(os.path.join(project_folder, 'Info.plist'), 'rb') as f:\n\t\tplist_data = plistlib.load(f)\n\t\tbundle_version_number = plist_data&#91;'CFBundleVersion']\n\t\tbundle_version_string = plist_data&#91;'CFBundleShortVersionString']\n\n\tplist_data\n\twith open(os.path.join(tproject_folder, 'Info.plist'), 'rb') as f0:\n\t\tplist_data = plistlib.load(f0)\n\t\tplist_data&#91;'CFBundleVersion'] = bundle_version_number\n\t\tplist_data&#91;'CFBundleShortVersionString'] = bundle_version_string\n\twith open(os.path.join(tproject_folder, 'Info.plist'), 'wb') as f1:\n\t\tplistlib.dump(plist_data, f1)\n\n\tlogging.info('bundle_version_number: ' + bundle_version_number)\n\tlogging.info('bundle_version_string: ' + bundle_version_string)\n\n\tlogging.info('\u62f7\u8d1dData\u76ee\u5f55')\n\tshutil.rmtree(os.path.join(tproject_folder, 'Data'))\n\tshutil.copytree(os.path.join(project_folder, 'Data'), os.path.join(tproject_folder, 'Data'))\n\n\tlogging.info('\u62f7\u8d1dClasses\u76ee\u5f55')\n\tshutil.rmtree(os.path.join(tproject_folder, 'Classes'))\n\tshutil.copytree(os.path.join(project_folder, 'Classes'), os.path.join(tproject_folder, 'Classes'))\n\n\tlogging.info('\u62f7\u8d1dLibraries\u76ee\u5f55')\n\tshutil.rmtree(os.path.join(tproject_folder, 'Libraries'))\n\tshutil.copytree(os.path.join(project_folder, 'Libraries'), os.path.join(tproject_folder, 'Libraries'))\n\n\tproject = XcodeProject.load(os.path.join(tproject_folder, 'Unity-iPhone.xcodeproj\/project.pbxproj'))\n\tlogging.info('\u79fb\u9664Data\u76ee\u5f55\u5f15\u7528')\n\tproject.remove_group_by_name('Data')\n\n\tlogging.info('\u79fb\u9664Classes\u76ee\u5f55\u5f15\u7528')\n\tproject.remove_group_by_name('Classes')\n\n\tlogging.info('\u79fb\u9664Libraries\u76ee\u5f55\u5f15\u7528')\n\tproject.remove_group_by_name('Libraries')\n\n\tfile_options = FileOptions(weak=True, ignore_unknown_type=True)\n\tlogging.info('\u6dfb\u52a0Classes\u76ee\u5f55\u5f15\u7528')\n\tproject.add_folder(os.path.join(tproject_folder, 'Data'), create_groups=False, target_name='Unity-iPhone')\n\n\tlogging.info('\u6dfb\u52a0Classes\u76ee\u5f55\u5f15\u7528')\n\tclasses_group = project.get_or_create_group('Classes', make_relative=True)\n\tgroup_add_files(project, classes_group, os.path.join(tproject_folder, 'Classes'), file_options)\n\n\tlogging.info('\u6dfb\u52a0Libraries\u76ee\u5f55\u5f15\u7528')\n\tlibraries_group = project.get_or_create_group('Libraries', make_relative=True)\n\tgroup_add_files(project, libraries_group, os.path.join(tproject_folder, 'Libraries'), file_options)\n\tproject.remove_group_by_name('libil2cpp')\n\n\tproject.save()\n\n\n\t## \u5199\u5165SDK\u521d\u59cb\u5316\u53c2\u6570(\u66ff\u636237\u53ca\u4e2a\u63a8\u53c2\u6570)\n\tlogging.info('\u5199\u516537SDK\u548c\u4e2a\u63a8\u521d\u59cb\u5316\u53c2\u6570\u5230Classes\/UnityAppController.mm')\n\tSQSecret = ''\n\tGTAppId = ''\n\tGTAppKey = ''\n\tGTAppSecret = ''\n\twith open(os.path.join(sdk_folder, '\u5907\u4efd\u6587\u4ef6\/sdk-params.plist'), 'rb') as f:\n\t\tparams = plistlib.load(f)\n\n\t\tif not 'SQSecret' in params:\n\t\t\tlogging.error('\u672c\u5730\u5316SDK\u66ff\u6362\u5931\u8d25: \u672a\u8bfb\u53d6\u5230\u6709\u6548\u7684`SQSecret`,\u8bf7\u68c0\u67e5`\u5907\u4efd\u6587\u4ef6\/sdk-params.plist`\u6587\u4ef6\u7684\u6709\u6548\u6027')\n\t\t\texit()\n\t\telse:\n\t\t\tSQSecret = params&#91;'SQSecret'].strip()\n\n\t\tif not 'GTAppId' in params:\n\t\t\tlogging.error('\u672c\u5730\u5316SDK\u66ff\u6362\u5931\u8d25: \u672a\u8bfb\u53d6\u5230\u6709\u6548\u7684`GTAppId`,\u8bf7\u68c0\u67e5`\u5907\u4efd\u6587\u4ef6\/sdk-params.plist`\u6587\u4ef6\u7684\u6709\u6548\u6027')\n\t\t\texit()\n\t\telse:\n\t\t\tGTAppId = params&#91;'GTAppId'].strip()\n\n\t\tif not 'GTAppKey' in params:\n\t\t\tlogging.error('\u672c\u5730\u5316SDK\u66ff\u6362\u5931\u8d25: \u672a\u8bfb\u53d6\u5230\u6709\u6548\u7684`GTAppKey`,\u8bf7\u68c0\u67e5`\u5907\u4efd\u6587\u4ef6\/sdk-params.plist`\u6587\u4ef6\u7684\u6709\u6548\u6027')\n\t\t\texit()\n\t\telse:\n\t\t\tGTAppKey = params&#91;'GTAppKey'].strip()\n\n\t\tif not 'GTAppSecret' in params:\n\t\t\tlogging.error('\u672c\u5730\u5316SDK\u66ff\u6362\u5931\u8d25: \u672a\u8bfb\u53d6\u5230\u6709\u6548\u7684`GTAppSecret`,\u8bf7\u68c0\u67e5`\u5907\u4efd\u6587\u4ef6\/sdk-params.plist`\u6587\u4ef6\u7684\u6709\u6548\u6027')\n\t\t\texit()\n\t\telse:\n\t\t\tGTAppSecret = params&#91;'GTAppSecret'].strip()\n\n\twith open(os.path.join(tproject_folder, 'Classes\/UnityAppController.mm'), 'r+') as f:\n\t\tlines = f.readlines()\n\t\tindex = -1\n\t\tfor line in lines:\n\t\t\tindex = index + 1\n\t\t\tif line.find('#define SQSecret') != -1:\n\t\t\t\tlines&#91;index] = '#define SQSecret @\"' + SQSecret + '\"\\n'\n\t\t\tif line.find('#define GTAppId') != -1:\n\t\t\t\tlines&#91;index] = '#define GTAppId @\"' + GTAppId + '\"\\n'\n\t\t\tif line.find('#define GTAppKey') != -1:\n\t\t\t\tlines&#91;index] = '#define GTAppKey @\"' + GTAppKey + '\"\\n'\n\t\t\tif line.find('#define GTAppSecret') != -1:\n\t\t\t\tlines&#91;index] = '#define GTAppSecret @\"' + GTAppSecret + '\"\\n'\n\t\t\t'''if area == 'en' and line.find('#import &lt;RVSDK_global\/RVSDK_global.h>') != -1:\n\t\t\t\tlines&#91;index] = '#import &lt;RVSDK\/RVSDK.h>                                 \\n' # \u5982\u679c\u5199\u5165\u7684\u5b57\u7b26\u6570\u5c11\u4e8e\u539f\u6765\u7684\u5b57\u7b26\u6570\uff0c\u4f1a\u5728\u6587\u4ef6\u672b\u5c3e\u5199\u5165\u591a\u4f59\u7684\u884c\n\t\t\t'''\n\t\tf.seek(0)\n\t\tf.writelines(lines)\n\ndef pack(area, project_folder, is_release):\n\tarea = area.lower()\n\tprofiles = ({\n\t\t'en':'b7b8ca4f-6ed5-4ac9-8bd9-2faf01e06802',\n\t\t'kr':'1b0cad1c-7ba7-4143-9024-ed2c58fef657',\n\t\t'tw':'b84438ca-6a91-46d0-9cf1-3b6b5f821109',\n\t\t'vn':'42122714-bb8c-4641-a93a-3c5e132395fd',\n\t\t})\n\tif is_release:\n\t\tprofiles = ({\n\t\t\t'en':'2355228b-4248-404f-b578-f80e6888e59c',\n\t\t\t'kr':'5cd009f4-ea3f-4459-b386-967f8a5577c7',\n\t\t\t'tw':'8d3a705b-c5c6-4728-a028-aea00601b437',\n\t\t\t'vn':'067011a7-3e7e-4799-8436-60ea80dd7157',\n\t\t\t})\n\tif area not in profiles.keys():\n\t\tlogging.error('\u672a\u5b9a\u4e49\u7684\u5730\u533a\u7c7b\u578b:' + area)\n\t\treturn\n\tlogging.info('\u6784\u5efa:' + area)\n\n\tbundle_version_string = ''\n\tbundle_version_number = ''\n\twith open(os.path.join(project_folder, 'Info.plist'), 'rb') as f:\n\t\tplist_data = plistlib.load(f)\n\t\tbundle_version_number = plist_data&#91;'CFBundleVersion']\n\t\tbundle_version_string = plist_data&#91;'CFBundleShortVersionString']\n\n\tarchive_folder = '\/Volumes\/Data\/Xcode\/Archives\/temp\/'\n\tarchive_path = os.path.join(archive_folder, 'Archive.xcarchive')\n\texportOptions = os.path.join(os.getcwd(), ('ExportOptions\/ExportOptions-%s-dev.plist' %(area)))\n\toutput_path = os.path.join('\/Volumes\/Data\/IPA_DEV', '%s&#91;%s]&#91;%s]' %(area.upper(), bundle_version_string, bundle_version_number))\n\tif is_release:\n\t\texportOptions = os.path.join(os.getcwd(), ('ExportOptions\/ExportOptions-%s.plist' %(area)))\n\t\toutput_path = os.path.join('\/Volumes\/Data\/IPA', '%s&#91;%s]&#91;%s]' %(area.upper(), bundle_version_string, bundle_version_number))\n\tif os.path.exists(archive_folder):\n\t\tshutil.rmtree(archive_folder, ignore_errors=True)\n\tif os.path.exists(output_path):\n\t\tshutil.rmtree(output_path, ignore_errors=True)\n\t## \u751f\u6210Archive\n\tcmd1 = ('xcodebuild archive -project %s\/Unity-iPhone.xcodeproj -scheme Unity-iPhone -configuration Release -archivePath %s PROVISIONING_PROFILE=%s -destination \\'generic\/platform=iOS\\'' %(project_folder, archive_path, profiles&#91;area]))\n\t## \u5bfc\u51faipa\n\tcmd2 = ('xcodebuild -exportArchive -archivePath %s -exportPath %s -exportOptionsPlist %s PROVISIONING_PROFILE=%s' %(archive_path, output_path, exportOptions, profiles&#91;area]))\n\tprocess = subprocess.Popen(cmd1, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout, stderr=sys.stderr, close_fds=True, universal_newlines=True, bufsize=1)\n\tprocess.communicate()\n\tif process.returncode == 0:\n\t\tlogging.info('%s archive successful!' %(area))\n\telse:\n\t\tlogging.error('%s archive failed!' %(area))\n\t\treturn\n\tprocess = subprocess.Popen(cmd2, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout, stderr=sys.stderr, close_fds=True, universal_newlines=True, bufsize=1)\n\tprocess.communicate()\n\tif process.returncode == 0:\n\t\tlogging.info('%s pack ipa successful!' %(area))\n\telse:\n\t\tlogging.error('%s pack ipa failed!' %(area))\n\t\treturn\n\ndef main():\n\tcoloredlogs.install(level='INFO', fmt='%(asctime)s %(levelname)s %(message)s')\n\n\tsdk_folders = ({\n\t\t'en':'\/Volumes\/Data\/SDK\/37\u672c\u5730\u5316SDK\/\u5168\u7403\u7248',\n\t\t'kr':'\/Volumes\/Data\/SDK\/37\u672c\u5730\u5316SDK\/\u65e5\u97e9',\n\t\t'tw':'\/Volumes\/Data\/SDK\/37\u672c\u5730\u5316SDK\/\u53f0\u6e7e',\n\t\t'vn':'\/Volumes\/Data\/SDK\/37\u672c\u5730\u5316SDK\/\u8d8a\u5357',\n\t\t})\n\ttproject_folders = ({\n\t\t'en':'\/Volumes\/Data\/Project\/PNC#TMPL#EN',\n\t\t'kr':'\/Volumes\/Data\/Project\/PNC#TMPL#KR',\n\t\t'tw':'\/Volumes\/Data\/Project\/PNC#TMPL#TW',\n\t\t'vn':'\/Volumes\/Data\/Project\/PNC#TMPL#VN',\n\t\t})\n\n\t##\u6d4b\u8bd5\u4ee3\u7801\n\t# replace_assets('en', sdk_folders&#91;'en'], args.project_folder, tproject_folders&#91;'en'])\n\t# return\n\n\tif args.replace_assets == 1:\n\t\tfor key, value in sdk_folders.items():\n\t\t\treplace_assets(key, value, args.project_folder, tproject_folders&#91;key])\n\n\tlogging.info('pack:' + str(args.pack_ipa))\n\tif args.pack_ipa == 1:\n\t\tfor key, value in sdk_folders.items():\n\t\t\tpack(key, tproject_folders&#91;key], False)\n\t\tfor key, value in sdk_folders.items():\n\t\t\tpack(key, tproject_folders&#91;key], True)\n\telif args.pack_ipa == 2:\n\t\tfor key, value in sdk_folders.items():\n\t\t\tpack(key, tproject_folders&#91;key], True)\n\telif args.pack_ipa == 3:\n\t\tfor key, value in sdk_folders.items():\n\t\t\tpack(key, tproject_folders&#91;key], False)\n\n\n\nif __name__ == '__main__':\n\tmain()\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u63d0 \u9884\u5148\u505a\u597d\u6a21\u7248\uff0c\u6211\u8fd9\u91cc\u505a\u4e86\u56db\u4e2a\u6a21\u677f\uff0c\u5206\u522b\u5bf9\u5e94\u56db\u4e2a\u6e20\u9053<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/2834"}],"collection":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2834"}],"version-history":[{"count":4,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/2834\/revisions"}],"predecessor-version":[{"id":2839,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/2834\/revisions\/2839"}],"wp:attachment":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2834"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}