├── .DS_Store ├── .idea ├── .gitignore ├── UnityiOSExporter.iml ├── misc.xml ├── modules.xml └── vcs.xml ├── Doc ├── .DS_Store ├── doc1.png ├── doc2.png ├── doc3.png ├── doc4.png ├── doc5.png └── doc6.png ├── IpaExporter.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ ├── a4399.xcuserdatad │ │ ├── IDEFindNavigatorScopes.plist │ │ ├── UserInterfaceState.xcuserstate │ │ ├── WorkspaceSettings.xcsettings │ │ └── xcdebugger │ │ │ └── Expressions.xcexplist │ │ ├── apple.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── xcdebugger │ │ │ └── Expressions.xcexplist │ │ └── hezunzu.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── xcdebugger │ │ └── Expressions.xcexplist ├── xcshareddata │ └── xcschemes │ │ └── IpaExporter.xcscheme └── xcuserdata │ ├── a4399.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── apple.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── IpaExporter.xcscheme │ │ └── xcschememanagement.plist │ └── hezunzu.xcuserdatad │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── IpaExporter ├── .DS_Store ├── App │ ├── .DS_Store │ ├── AppMain.h │ ├── AppMain.m │ ├── Defs.h │ ├── Logic │ │ ├── .DS_Store │ │ ├── Cammond │ │ │ ├── PackCammond.h │ │ │ └── PackCammond.m │ │ ├── CodeTester.h │ │ ├── CodeTester.m │ │ ├── DetailsInfoData.h │ │ ├── DetailsInfoData.m │ │ ├── ExportInfoManager.h │ │ ├── ExportInfoManager.m │ │ ├── LogicManager.h │ │ ├── LogicManager.m │ │ ├── NSMutableDictionary+ArraySupport.h │ │ ├── NSMutableDictionary+ArraySupport.m │ │ ├── NSObject+LogicBase.h │ │ ├── NSObject+LogicBase.m │ │ ├── PreferenceData.h │ │ ├── PreferenceData.m │ │ ├── Unity │ │ │ ├── BuilderCSFileEdit.h │ │ │ ├── BuilderCSFileEdit.m │ │ │ ├── UnityAssetManager.h │ │ │ └── UnityAssetManager.m │ │ ├── VersionInfo.h │ │ └── VersionInfo.m │ └── View │ │ ├── DetailsInfoSetting.h │ │ ├── DetailsInfoSetting.m │ │ ├── DetailsInfoView.h │ │ ├── DetailsInfoView.m │ │ ├── GeneralView.h │ │ ├── GeneralView.m │ │ ├── PreferenceView.h │ │ ├── PreferenceView.m │ │ ├── SceneSelectView.h │ │ ├── SceneSelectView.m │ │ ├── ViewMain.h │ │ └── ViewMain.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-1.png │ │ ├── icon-2.png │ │ ├── icon-3.png │ │ ├── icon-4.png │ │ ├── icon-5.png │ │ ├── icon-6.png │ │ ├── icon-7.png │ │ ├── icon-8.png │ │ ├── icon-9.png │ │ └── icon.png ├── Base.lproj │ └── Main.storyboard ├── Common │ ├── .DS_Store │ ├── Alert.h │ ├── Alert.m │ ├── Common.h │ ├── CustomLog.h │ ├── CustomLog.m │ ├── DragDropView.h │ ├── DragDropView.m │ ├── EventManager.h │ ├── EventManager.m │ ├── EventTypeDef.h │ ├── LocalDataSave.h │ ├── LocalDataSave.m │ ├── MobileprovisionParser.h │ ├── MobileprovisionParser.m │ ├── NSFileManager+Extern.h │ ├── NSFileManager+Extern.m │ ├── NSString+Emoji.h │ ├── NSString+Emoji.m │ ├── NSString+RKMatch.h │ └── NSString+RKMatch.m ├── English.lproj │ └── Main.storyboard ├── ExporterMain.h ├── ExporterMain.m ├── Info.plist ├── Libs │ ├── .DS_Store │ ├── CodeTest │ │ ├── .DS_Store │ │ ├── CodeTest.sh │ │ └── Test │ │ │ ├── _TestBuilder.cs │ │ │ └── _TestConfig.json │ ├── TempCode │ │ ├── .DS_Store │ │ └── Builder │ │ │ ├── .DS_Store │ │ │ ├── LitJson │ │ │ ├── .DS_Store │ │ │ ├── IJsonWrapper.cs │ │ │ ├── JsonData.cs │ │ │ ├── JsonException.cs │ │ │ ├── JsonMapper.cs │ │ │ ├── JsonMockWrapper.cs │ │ │ ├── JsonReader.cs │ │ │ ├── JsonWriter.cs │ │ │ ├── Lexer.cs │ │ │ ├── Netstandard15Polyfill.cs │ │ │ └── ParserToken.cs │ │ │ ├── Users │ │ │ ├── .DS_Store │ │ │ ├── _CustomBuilder.cs │ │ │ ├── _CustomConfig.plist │ │ │ └── _CustomShell.sh │ │ │ └── _Builder.cs │ └── Xcodeproj │ │ ├── .DS_Store │ │ ├── EditXcode.sh │ │ ├── ExportIpa.sh │ │ ├── ExportOptions.plist │ │ ├── ExportXcode.sh │ │ ├── Main(Deprecated).sh │ │ ├── Main.rb │ │ ├── VERSION │ │ ├── XcodeProjectUpdater.rb │ │ ├── XcodeSigningEdit.rb │ │ ├── XcodeSigningEdit.sh │ │ ├── lib │ │ ├── .DS_Store │ │ ├── atomos.rb │ │ ├── atomos │ │ │ └── version.rb │ │ ├── claide.rb │ │ ├── claide │ │ │ ├── ansi.rb │ │ │ ├── ansi │ │ │ │ ├── cursor.rb │ │ │ │ ├── graphics.rb │ │ │ │ └── string_escaper.rb │ │ │ ├── argument.rb │ │ │ ├── argv.rb │ │ │ ├── command.rb │ │ │ ├── command │ │ │ │ ├── argument_suggester.rb │ │ │ │ ├── banner.rb │ │ │ │ └── plugin_manager.rb │ │ │ ├── help.rb │ │ │ └── informative_error.rb │ │ ├── colored2.rb │ │ ├── colored2 │ │ │ ├── ascii_decorator.rb │ │ │ ├── codes.rb │ │ │ ├── numbers.rb │ │ │ ├── object.rb │ │ │ ├── strings.rb │ │ │ └── version.rb │ │ ├── nanaimo.rb │ │ ├── nanaimo │ │ │ ├── object.rb │ │ │ ├── plist.rb │ │ │ ├── reader.rb │ │ │ ├── unicode.rb │ │ │ ├── unicode │ │ │ │ ├── next_step_mapping.rb │ │ │ │ └── quote_maps.rb │ │ │ ├── version.rb │ │ │ ├── writer.rb │ │ │ └── writer │ │ │ │ ├── pbxproj.rb │ │ │ │ └── xml.rb │ │ ├── xcodeproj.rb │ │ └── xcodeproj │ │ │ ├── command.rb │ │ │ ├── command │ │ │ ├── config_dump.rb │ │ │ ├── project_diff.rb │ │ │ ├── show.rb │ │ │ ├── sort.rb │ │ │ └── target_diff.rb │ │ │ ├── config.rb │ │ │ ├── config │ │ │ └── other_linker_flags_parser.rb │ │ │ ├── constants.rb │ │ │ ├── differ.rb │ │ │ ├── gem_version.rb │ │ │ ├── helper.rb │ │ │ ├── plist.rb │ │ │ ├── project.rb │ │ │ ├── project │ │ │ ├── case_converter.rb │ │ │ ├── object.rb │ │ │ ├── object │ │ │ │ ├── build_configuration.rb │ │ │ │ ├── build_file.rb │ │ │ │ ├── build_phase.rb │ │ │ │ ├── build_rule.rb │ │ │ │ ├── configuration_list.rb │ │ │ │ ├── container_item_proxy.rb │ │ │ │ ├── file_reference.rb │ │ │ │ ├── group.rb │ │ │ │ ├── helpers │ │ │ │ │ ├── build_settings_array_settings_by_object_version.rb │ │ │ │ │ ├── file_references_factory.rb │ │ │ │ │ └── groupable_helper.rb │ │ │ │ ├── native_target.rb │ │ │ │ ├── reference_proxy.rb │ │ │ │ ├── root_object.rb │ │ │ │ ├── swift_package_product_dependency.rb │ │ │ │ ├── swift_package_remote_reference.rb │ │ │ │ └── target_dependency.rb │ │ │ ├── object_attributes.rb │ │ │ ├── object_dictionary.rb │ │ │ ├── object_list.rb │ │ │ ├── project_helper.rb │ │ │ └── uuid_generator.rb │ │ │ ├── scheme.rb │ │ │ ├── scheme │ │ │ ├── abstract_scheme_action.rb │ │ │ ├── analyze_action.rb │ │ │ ├── archive_action.rb │ │ │ ├── build_action.rb │ │ │ ├── buildable_product_runnable.rb │ │ │ ├── buildable_reference.rb │ │ │ ├── command_line_arguments.rb │ │ │ ├── environment_variables.rb │ │ │ ├── launch_action.rb │ │ │ ├── macro_expansion.rb │ │ │ ├── profile_action.rb │ │ │ ├── remote_runnable.rb │ │ │ ├── test_action.rb │ │ │ └── xml_element_wrapper.rb │ │ │ ├── user_interface.rb │ │ │ ├── workspace.rb │ │ │ ├── workspace │ │ │ ├── file_reference.rb │ │ │ ├── group_reference.rb │ │ │ └── reference.rb │ │ │ └── xcodebuild_helper.rb │ │ ├── packer.sublime-project │ │ └── packer.sublime-workspace ├── LuaLib │ ├── .DS_Store │ ├── include │ │ ├── lauxlib.h │ │ ├── lua.h │ │ ├── lua.hpp │ │ ├── luaconf.h │ │ └── lualib.h │ └── liblua.a ├── README.md ├── en.lproj │ └── Main.strings ├── zh-HK.lproj │ └── Main.strings └── zh-Hans.lproj │ ├── .DS_Store │ └── Main.strings ├── IpaExporterTests ├── Info.plist └── IpaExporterTests.m ├── IpaExporterUITests ├── Info.plist └── IpaExporterUITests.m └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/.DS_Store -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/UnityiOSExporter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Doc/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/.DS_Store -------------------------------------------------------------------------------- /Doc/doc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc1.png -------------------------------------------------------------------------------- /Doc/doc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc2.png -------------------------------------------------------------------------------- /Doc/doc3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc3.png -------------------------------------------------------------------------------- /Doc/doc4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc4.png -------------------------------------------------------------------------------- /Doc/doc5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc5.png -------------------------------------------------------------------------------- /Doc/doc6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/Doc/doc6.png -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/a4399.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/a4399.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/a4399.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/a4399.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/hezunzu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/hezunzu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/project.xcworkspace/xcuserdata/hezunzu.xcuserdatad/xcdebugger/Expressions.xcexplist: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 10 | 11 | 13 | 14 | 16 | 17 | 18 | 19 | 21 | 22 | 24 | 25 | 26 | 27 | 29 | 30 | 32 | 33 | 34 | 35 | 37 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/xcuserdata/a4399.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/xcuserdata/a4399.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IpaExporter.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1837800C1D766C84004E3BAD 16 | 17 | primary 18 | 19 | 20 | 183780221D766C84004E3BAD 21 | 22 | primary 23 | 24 | 25 | 1837802D1D766C85004E3BAD 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IpaExporter.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1837800C1D766C84004E3BAD 16 | 17 | primary 18 | 19 | 20 | 183780221D766C84004E3BAD 21 | 22 | primary 23 | 24 | 25 | 1837802D1D766C85004E3BAD 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /IpaExporter.xcodeproj/xcuserdata/hezunzu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /IpaExporter/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/App/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/App/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/App/AppMain.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/8/31. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]); 12 | 13 | @interface AppDelegate : NSObject 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /IpaExporter/App/AppMain.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/8/31. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | 12 | #import "AppMain.h" 13 | #import "Defs.h" 14 | #import "LogicManager.h" 15 | 16 | int printf(const char * __restrict format, ...) 17 | { 18 | va_list args; 19 | va_start(args, format); 20 | NSLogv([NSString stringWithUTF8String:format], args); 21 | va_end(args); 22 | return 1; 23 | } 24 | 25 | int main(int argc, const char * argv[]) 26 | { 27 | @autoreleasepool 28 | { 29 | if(![[NSFileManager defaultManager] fileExistsAtPath:SETTING_FOLDER]){ 30 | [[NSFileManager defaultManager] createDirectoryAtPath:SETTING_FOLDER withIntermediateDirectories:YES attributes:nil error:nil]; 31 | } 32 | 33 | [[LogicManager defaultManager] startUp]; 34 | 35 | return NSApplicationMain(argc, argv); 36 | } 37 | } 38 | 39 | @implementation AppDelegate 40 | 41 | - (void)applicationWillFinishLaunching:(NSNotification *)notification 42 | { 43 | [[LogicManager defaultManager] applicationDelegateCallBack:ApplicationWillFinishLaunching withNotification:notification]; 44 | } 45 | 46 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 47 | { 48 | [[LogicManager defaultManager] applicationDelegateCallBack:ApplicationDidFinishLaunching withNotification:aNotification]; 49 | } 50 | 51 | - (void)applicationWillTerminate:(NSNotification *)aNotification 52 | { 53 | [[LogicManager defaultManager] applicationDelegateCallBack:ApplicationWillTerminate withNotification:aNotification]; 54 | } 55 | 56 | - (void)applicationDidBecomeActive:(NSNotification *)notification 57 | { 58 | [[LogicManager defaultManager] applicationDelegateCallBack:ApplicationDidBecomeActive withNotification:notification]; 59 | } 60 | 61 | - (void)applicationWillResignActive:(NSNotification *)notification 62 | { 63 | [[LogicManager defaultManager] applicationDelegateCallBack:ApplicationWillResignActive withNotification:notification]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/App/Logic/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/App/Logic/Cammond/PackCammond.h: -------------------------------------------------------------------------------- 1 | // 2 | // RubyCommand.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 5/28/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NSNumber* CammondResult; 12 | #define CAMM_EXIT @100 13 | #define CAMM_SUCCESS @101 14 | #define CAMM_CONTINUE @102 15 | #define CAMM_BREAK @103 16 | 17 | typedef NSNumber* CammondCode; 18 | #define CODE_EXPORT_XCODE @1 19 | #define CODE_EDIT_XCODE @2 20 | #define CODE_EXPORT_IPA @4 21 | #define CODE_GEN_RESFOLDER @8 22 | #define CODE_RUN_CUSTOM_SHELL @16 23 | #define CODE_ACTIVE_WND_TOP @32 24 | #define CODE_BACKUP_XCODE @64 25 | #define CODE_XCODE_SIGN @128 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @interface PackCammond : NSObject 30 | { 31 | @private 32 | __block BOOL _isExporting; 33 | NSMutableDictionary *_cammondCode; 34 | } 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/CodeTester.h: -------------------------------------------------------------------------------- 1 | // 2 | // CodeTester.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 6/24/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LogicManager.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface CodeTester : NSObject 15 | { 16 | @private 17 | ExportInfoManager* _manager; 18 | UnityAssetManager* _dataInst; 19 | } 20 | - (void)run; 21 | - (void)copyTestFolderToProject; 22 | - (void)saveAndRemoveTestFolder; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/DetailsInfoData.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsInfoData.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/11/3. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailsInfoData : NSObject 12 | 13 | @property(nonatomic, readonly) NSMutableDictionary *dict; 14 | 15 | @property(nonatomic, readonly) NSString *appName; 16 | @property(nonatomic, readonly) NSString *productName; 17 | @property(nonatomic, readonly) NSString *bundleIdentifier; 18 | @property(nonatomic, readonly) NSString *appidRelease;//bundleIdentifier release 19 | @property(nonatomic, readonly) NSString *codeSignIdentity; 20 | @property(nonatomic, readonly) NSString *provisioningProfile; 21 | @property(nonatomic, readonly) NSString *frameworks; 22 | @property(nonatomic, readonly) NSString *isSelected;//是否已经选择 23 | @property(nonatomic, readonly) NSString *customSDKPath;//自定义资源路径 24 | @property(nonatomic, readonly) NSString *libkerFlag; 25 | @property(nonatomic, readonly) NSString *libs; 26 | @property(nonatomic, readonly) NSString *debugProfileName; 27 | @property(nonatomic, readonly) NSString *debugDevelopTeam; 28 | @property(nonatomic, readonly) NSString *releaseProfileName; 29 | @property(nonatomic, readonly) NSString *releaseDevelopTeam; 30 | @property(nonatomic, readonly) NSMutableArray *frameworkNames; 31 | @property(nonatomic, readonly) NSMutableArray *frameworkIsWeaks; 32 | @property(nonatomic, readonly) NSMutableArray *libNames; 33 | @property(nonatomic, readonly) NSMutableArray *linkerFlag; 34 | @property(nonatomic, readonly) NSMutableArray *embedFramework; 35 | @property(nonatomic, readonly) NSMutableArray *customSDKChild; 36 | @property(nonatomic, readonly) NSString *uidStr; 37 | 38 | + (id)initWithJsonString:(NSString *)string; 39 | - (id)initWithInfoDict:(NSDictionary*) dic; 40 | - (void)setValueForKey:(NSString*)key withObj:(id)obj; 41 | - (id)getValueForKey:(NSString*)key; 42 | - (NSString*)toJson; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/ExportInfoManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExportInfoManager.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/28. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | // 唯一能与界面逻辑直接交互的逻辑类 用于读取和存储界面的数据 9 | // 10 | 11 | #import 12 | #import "DetailsInfoData.h" 13 | #import "Common.h" 14 | #import "Defs.h" 15 | 16 | #define SAVE_DETAIL_ARRARY_KEY @"detailArray" 17 | #define SAVE_PROJECT_PATH_KEY @"projectPath" 18 | #define SAVE_CODE_SAVE_PATH_KEY @"codeSavePath" 19 | #define SAVE_EXPORT_PATH_KEY @"exportPath" 20 | #define SAVE_SCENE_ARRAY_KEY @"scenePath" 21 | #define SAVE_IS_RELEASE_KEY @"isRelease" 22 | #define SAVE_IS_EXPORT_XCODE @"isExportKey" 23 | #define SAVE_IS_EXPORT_IPA @"isExportIpa" 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | @interface ExportInfoManager : NSObject 27 | { 28 | @private 29 | LocalDataSave *_userData; 30 | NSDictionary *_saveTpDict; 31 | } 32 | 33 | @property(nonatomic, readwrite) ExportInfo *info; 34 | @property(nonatomic, readonly) NSMutableArray *unityProjPathArr; 35 | @property(nonatomic, readonly) NSMutableArray *exportPathArr; 36 | @property(nonatomic, readonly) NSString *codeBackupPath; 37 | @property(nonatomic, readonly, getter=getDetailArray) NSMutableArray *detailArray; 38 | @property(nonatomic, readonly, getter=getSceneArray) NSMutableArray *sceneArray; 39 | 40 | - (void)saveDataForKey:(NSString*)key withData:(id) data; 41 | 42 | - (BOOL)addNewUnityProjPath:(NSString*)path; 43 | - (void)replaceUnityProjPath:(NSString*)path; 44 | - (BOOL)addNewExportProjPath:(NSString*)path; 45 | - (void)replaceExportProjPath:(NSString*)path; 46 | 47 | //路径配置 48 | - (void)reload; 49 | - (void)reloadPaths; 50 | 51 | //包配置 信息表格数据部分 52 | - (NSMutableArray*)reLoadDetails:(NSString*)saveKey; 53 | - (void)addDetail:(id)data withKey:(NSString*)saveKey; 54 | - (void)removeDetail:(NSUInteger)index withKey:(NSString*)saveKey; 55 | - (void)updateDetail:(NSUInteger)index withObject:(id)object withKey:(NSString*)saveKey; 56 | 57 | //设置备份存储路径 58 | - (void)setCodeSavePath:(NSString*)path; 59 | - (NSArray*)getAllUnityScenePath; 60 | 61 | NS_ASSUME_NONNULL_END 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/LogicManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // LogicMain.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/4/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | #import "PackCammond.h" 14 | #import "ExportInfoManager.h" 15 | #import "UnityAssetManager.h" 16 | #import "BuilderCSFileEdit.h" 17 | #import "PreferenceData.h" 18 | #import "VersionInfo.h" 19 | #import "CodeTester.h" 20 | #import "NSObject+LogicBase.h" 21 | 22 | #define get_instance(instanceName) [[LogicManager defaultManager] getInstByClassName:instanceName error:nil] 23 | #define inst_method_call(instanceName, methodName) \ 24 | objc_msgSend([[LogicManager defaultManager] getInstByClassName:instanceName error:nil], @selector(methodName)) 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @interface LogicManager : NSObject 29 | { 30 | NSArray *_instanceArray; 31 | NSMutableDictionary *_instanceDict; 32 | } 33 | 34 | + (instancetype)defaultManager; 35 | - (void)startUp; 36 | - (id)getInstByClassName:(NSString*)className error:(NSError**)err; 37 | - (void)applicationDelegateCallBack:(AppDelegateType)tp 38 | withNotification:(NSNotification *)notification; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/LogicManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // LogicMain.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/4/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "LogicManager.h" 10 | #import "NSMutableDictionary+ArraySupport.h" 11 | 12 | @implementation LogicManager 13 | 14 | + (instancetype)defaultManager 15 | { 16 | Class cls = [self class]; 17 | //动态去取属性方法 18 | id instance = objc_getAssociatedObject(cls, @"instance"); 19 | if(!instance) 20 | { 21 | instance = [[self allocWithZone:NULL] init]; 22 | objc_setAssociatedObject(cls, @"instance", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | } 24 | return instance; 25 | } 26 | 27 | - (void)startUp 28 | { 29 | _instanceArray = @[[[CodeTester alloc] init], 30 | [[PackCammond alloc] init], 31 | [[ExportInfoManager alloc] init], 32 | [[UnityAssetManager alloc] init], 33 | [[BuilderCSFileEdit alloc] init], 34 | [[PreferenceData alloc] init], 35 | [[VersionInfo alloc] init] 36 | ]; 37 | 38 | _instanceDict = [NSMutableDictionary dictionaryWithArray:_instanceArray]; 39 | 40 | for(int i = 0; i < [_instanceArray count]; i++){ 41 | NSObject* item = _instanceArray[i]; 42 | [item initialize]; 43 | } 44 | 45 | EVENT_REGIST(EventViewWillAppear, @selector(viewDidAppear)); 46 | EVENT_REGIST(EventViewDidDisappear, @selector(viewDidDisappear)); 47 | } 48 | 49 | - (id)getInstByClassName:(NSString*)className error:(NSError**)err 50 | { 51 | err = nil; 52 | id obj = [_instanceDict objectForKey:className]; 53 | if(obj == nil){ 54 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat: @"%@不存在,请到startUp进行初始化", className] 55 | forKey:NSLocalizedDescriptionKey]; 56 | *err = [NSError errorWithDomain:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"] code:999 userInfo:userInfo]; 57 | } 58 | 59 | return obj; 60 | } 61 | 62 | - (void)viewDidAppear 63 | { 64 | for(int i = 0; i < [_instanceArray count]; i++){ 65 | NSObject* item = _instanceArray[i]; 66 | [item updateData]; 67 | } 68 | } 69 | 70 | - (void)viewDidDisappear 71 | { 72 | for(int i = 0; i < [_instanceArray count]; i++){ 73 | NSObject* item = _instanceArray[i]; 74 | [item clear]; 75 | } 76 | } 77 | 78 | - (void)applicationDelegateCallBack:(AppDelegateType)tp 79 | withNotification:(NSNotification *)notification 80 | { 81 | switch (tp) 82 | { 83 | case ApplicationWillFinishLaunching: 84 | case ApplicationDidFinishLaunching: 85 | case ApplicationWillTerminate: 86 | case ApplicationDidBecomeActive: 87 | case ApplicationWillResignActive: 88 | default: 89 | break; 90 | } 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/NSMutableDictionary+ArraySupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+ArraySupport.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/6/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSMutableDictionary (ArraySupport) 14 | 15 | /** 16 | 根据数组进行初始化 17 | 18 | @param array 需要初始化的数组(注意会根据classnName作为key) 19 | @return 返回转换后的字典 20 | */ 21 | +(nullable NSMutableDictionary *)dictionaryWithArray:(NSArray*)array; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/NSMutableDictionary+ArraySupport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+ArraySupport.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/6/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+ArraySupport.h" 10 | 11 | @implementation NSMutableDictionary (ArraySupport) 12 | 13 | + (NSMutableDictionary *)dictionaryWithArray:(NSArray *)array 14 | { 15 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 16 | for(int i = 0; i < [array count]; i++){ 17 | id item = array[i]; 18 | [dict setObject:item forKey:[item className]]; 19 | } 20 | return dict; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/NSObject+LogicBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+LogicBase.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/6/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSObject (LogicBase) 14 | 15 | /** 16 | 逻辑类初始化方法,应用开启调用一次 17 | */ 18 | -(void)initialize; 19 | 20 | 21 | /** 22 | 更新数据方法,每次界面打开时候调用一次 23 | */ 24 | -(void)updateData; 25 | 26 | 27 | /** 28 | 清除数据方法,每次关闭界面时候调用一次 29 | */ 30 | -(void)clear; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/NSObject+LogicBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+LogicBase.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 8/6/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "NSObject+LogicBase.h" 10 | 11 | @implementation NSObject (LogicBase) 12 | 13 | -(void)initialize{} 14 | -(void)updateData{} 15 | -(void)clear{} 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/PreferenceData.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreferenceData.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/1/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Common.h" 11 | #import "LogicManager.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | #define OPEN_CODE_APP_SAVE_KEY @"openCodeAppKey" 16 | #define OPEN_SIMPLE_SEARCH @"openSimpleSearch" 17 | 18 | @interface PreferenceData : NSObject 19 | { 20 | @private 21 | LocalDataSave *_saveData; 22 | NSMutableArray *_codeAppArray; 23 | NSString *_openSimpleSearch; 24 | } 25 | 26 | - (void)backUpCustomCode; 27 | - (void)restoreCustomCode; 28 | - (NSMutableArray*)addAndSave:(NSString*)data withKey:(NSString*)key; 29 | - (NSMutableArray*)getCodeAppArray; 30 | - (void)setOpenSimpleSearch:(BOOL)state; 31 | 32 | @property(nonatomic, readonly, getter=getCodeFilePath) NSString *codeFilePath; 33 | @property(nonatomic, readonly, getter=getJsonFilePath) NSString *jsonFilePath; 34 | @property(nonatomic, readonly, getter=getIsOpenSimpleSearch) BOOL isSimpleSearch; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/Unity/BuilderCSFileEdit.h: -------------------------------------------------------------------------------- 1 | // 2 | // BuilderCSFileEdit.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/10/12. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LogicManager.h" 11 | 12 | 13 | /// 编辑修改C#里面的TempCode/Builder/_Builder.cs文件 14 | @interface BuilderCSFileEdit : NSObject 15 | { 16 | @private 17 | NSString* _path; 18 | NSFileHandle* _fileHandle; 19 | NSMutableString* _content; 20 | ExportInfoManager* _view; 21 | } 22 | 23 | - (void)startWithDstPath:(NSString*)dstPath; 24 | 25 | @property (nonatomic, readonly) NSArray* lines; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/Unity/UnityAssetManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DataControlBase.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/10/9. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | // 用于拷贝文件夹以及文件夹下所有文件 9 | 10 | #import 11 | #import "Common.h" 12 | #import "Defs.h" 13 | 14 | 15 | @interface UnityAssetManager : NSObject 16 | { 17 | @private 18 | NSString *_unityProjPath; 19 | NSFileManager* _fileManager; 20 | int _startingCount; 21 | } 22 | 23 | - (void)start:(ExportInfo*)info; 24 | - (void)appendingFolder:(NSString*)path; 25 | - (void)end; 26 | 27 | @property (readonly) NSString *rootPath; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/VersionInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // VersionInfo.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/30/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(int, VersionFailCode){ 12 | ContentIllegal = -10000 13 | }; 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | @interface VersionInfo : NSObject 17 | { 18 | NSString *_localVersion; 19 | BOOL _isUpdate; 20 | } 21 | 22 | @property (nonatomic, readonly)NSString *version; 23 | @property (nonatomic, readonly)NSString *build; 24 | 25 | - (BOOL)isUpdate; 26 | 27 | @end 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /IpaExporter/App/Logic/VersionInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // VersionInfo.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/30/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "VersionInfo.h" 10 | #import "Defs.h" 11 | 12 | @implementation VersionInfo 13 | 14 | - (void)initialize 15 | { 16 | [self checkVersionInfo]; 17 | } 18 | 19 | - (BOOL)isUpdate 20 | { 21 | return _isUpdate; 22 | } 23 | 24 | - (void)checkVersionInfo 25 | { 26 | NSString *localVerFile = [NSString stringWithFormat:@"%@/version.txt", SETTING_FOLDER]; 27 | NSArray *localVer = [NSArray arrayWithObjects:@"1.0.0", @"0", nil];; 28 | NSArray *packageVer; 29 | 30 | packageVer = @[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"], 31 | [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]; 32 | 33 | if(![[NSFileManager defaultManager] fileExistsAtPath:localVerFile]){ 34 | [[NSFileManager defaultManager] createFileAtPath:localVerFile contents:nil attributes:nil]; 35 | _isUpdate = YES; 36 | }else{ 37 | localVer = [[NSString stringWithContentsOfFile:localVerFile encoding:NSUTF8StringEncoding error:nil] componentsSeparatedByString:@"\n"]; 38 | 39 | NSError *error; 40 | _isUpdate = [self compareShortVersion:packageVer[0] withLocalVer:localVer[0] error:&error] != 0 || 41 | ![self compareVersion:packageVer[1] withLocalVer:localVer[1]]; 42 | if(error != nil){ 43 | showError([error.description UTF8String]); 44 | } 45 | } 46 | 47 | _version = packageVer[0]; 48 | _build = packageVer[1]; 49 | 50 | [[NSString stringWithFormat:@"%@\n%@", _version, _build] writeToFile:localVerFile atomically:YES encoding:NSUTF8StringEncoding error:nil]; 51 | } 52 | 53 | //@格式 1.0.0 54 | - (int)compareShortVersion:(NSString*)packageVer withLocalVer:(NSString*)localVer error:(NSError**)error 55 | { 56 | NSArray *packageArr = [localVer componentsSeparatedByString:@"."]; 57 | NSArray *localArr = [localVer componentsSeparatedByString:@"."]; 58 | 59 | //如果版本号不是三位数 就返回 60 | if([localArr count] != 3 || [packageArr count] != 3){ 61 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"错误版本信息,格式是三位数" forKey:NSLocalizedDescriptionKey]; 62 | *error = [NSError errorWithDomain:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"] code:ContentIllegal userInfo:userInfo]; 63 | return 0; 64 | } 65 | 66 | for(int i = 0; i < 3; i++){ 67 | int package = [packageArr[i] intValue]; 68 | int local = [packageArr[i] intValue]; 69 | 70 | if(package > local) 71 | return 1; 72 | 73 | if(package < local) 74 | return -1; 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | //格式;任意字符串 81 | - (BOOL)compareVersion:(NSString*)packageVer withLocalVer:(NSString*)localVer 82 | { 83 | return [packageVer isEqualToString:localVer]; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /IpaExporter/App/View/DetailsInfoSetting.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsInfoSetting.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/10/31. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "DragDropView.h" 12 | 13 | @class DetailsInfoData; 14 | 15 | @interface DetailsInfoSetting : NSViewController{ 16 | @private 17 | BOOL _sureBtnClicked; 18 | BOOL _isSetDataOnShow; 19 | BOOL _isEditMode; 20 | DetailsInfoData *_info; 21 | 22 | NSMutableArray *_frameworkNameArr; 23 | NSMutableArray *_frameworkIsWeakArr; 24 | NSMutableArray *_embedFrameworksArr; 25 | NSMutableArray *_libNameArr; 26 | NSMutableArray *_linkerFlagArr; 27 | NSMutableArray *_customSdkArr; 28 | 29 | NSString *_uidStr; 30 | } 31 | 32 | @property (weak) IBOutlet NSTextField *productName; 33 | @property (weak) IBOutlet NSTextField *appName; 34 | @property (weak) IBOutlet NSTextField *appID; 35 | @property (weak) IBOutlet NSTextField *debugProfileName; 36 | @property (weak) IBOutlet NSTextField *debugDevelopTeam; 37 | @property (weak) IBOutlet NSTextField *appIdRelease; 38 | @property (weak) IBOutlet NSTextField *releaseProfileName; 39 | @property (weak) IBOutlet NSTextField *releaseDevelopTeam; 40 | @property (weak) IBOutlet NSTextField *customSDKPath; 41 | @property (weak) IBOutlet NSView *detailView; 42 | @property (weak) IBOutlet NSButton *sureBtn; 43 | @property (weak) IBOutlet NSTableView *frameworkTbl; 44 | @property (weak) IBOutlet NSTableView *libsTbl; 45 | @property (weak) IBOutlet NSTableView *linkerFlagTbl; 46 | @property (weak) IBOutlet NSTableView *embedTbl; 47 | @property (weak) IBOutlet NSTableView *sdkChildTbl; 48 | 49 | - (void)setUpDataInfoOnShow:(DetailsInfoData*)info isEditMode:(BOOL)isEdit; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /IpaExporter/App/View/DetailsInfoView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsInfo.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/10/13. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | // PS:坑爹的NSTableView 要把属性contentMode改成View Based设置成Cell Based不是不能显示 9 | // @http://www.07net01.com/2015/10/937976.html 10 | // 11 | 12 | #import 13 | #import 14 | 15 | @class DetailsInfoData; 16 | 17 | @interface DetailsInfoView : NSViewController{ 18 | @private 19 | DetailsInfoData *_selectInfo; 20 | } 21 | 22 | @property (readonly) NSMutableArray* dataDict; 23 | @property (weak) IBOutlet NSTableView *infoTbls; 24 | 25 | - (IBAction)removeBtnClick:(id)sender; 26 | - (IBAction)testBtnClick:(id)sender; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /IpaExporter/App/View/GeneralView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GeneralView.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/1. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class ExportInfoManager; 13 | @class DetailsInfoData; 14 | 15 | @interface GeneralView : NSViewController{ 16 | @private 17 | NSMutableArray *_sceneArray; 18 | NSTimer *_showTimer; 19 | NSTimeInterval _packTime; 20 | BOOL _isVisable; 21 | ExportInfoManager* _manager; 22 | int _viewOpeningCount; 23 | 24 | NSInteger _selectCellRow; 25 | NSMutableSet *_platShowItems; 26 | } 27 | 28 | @property (readonly) NSMutableArray* dataDict; 29 | 30 | @property (strong) IBOutlet NSTextView* infoLabel; 31 | @property (weak) IBOutlet NSComboBox* unityPathBox; 32 | @property (weak) IBOutlet NSComboBox* exportPathBox; 33 | @property (weak) IBOutlet NSTableView *platformTbl; 34 | @property (weak) IBOutlet NSTableView *packSceneTbl; 35 | @property (weak) IBOutlet NSButton *isReleaseBox; 36 | @property (weak) IBOutlet NSButton *exportBtn; 37 | @property (weak) IBOutlet NSTextField *useTimeLabel; 38 | @property (weak) IBOutlet NSButton *isExportXcode; 39 | @property (weak) IBOutlet NSProgressIndicator *progressTip; 40 | @property (weak) IBOutlet NSButton *isExportIpa; 41 | @property (weak) IBOutlet NSButton *exportXcode; 42 | @property (weak) IBOutlet NSButton *exportIpa; 43 | @property (weak) IBOutlet NSSearchField *platformSearchLabel; 44 | 45 | - (IBAction)sureBtnClick:(id)sender; 46 | - (IBAction)unityPathSelect:(id)sender; 47 | - (IBAction)exportPathSelect:(id)sender; 48 | 49 | - (void)reloadAllInfo; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /IpaExporter/App/View/PreferenceView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreferenceView.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 6/17/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "Common.h" 12 | #import "LogicManager.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface ExtensionsMenu : NSMenuItem{ 17 | CodeTester *_tester; 18 | PreferenceData *_dataInst; 19 | } 20 | @end 21 | 22 | @interface PreferenceView : NSViewController 23 | { 24 | NSMutableDictionary *_itemCellDict; 25 | 26 | } 27 | 28 | @property (weak) IBOutlet NSTextField *savePath; 29 | @property (weak) IBOutlet NSPopUpButtonCell *codeApp; 30 | @property (weak) IBOutlet NSButton *isSimpleSearch; 31 | 32 | @end 33 | 34 | @interface UserDefaultsSetting : NSViewController 35 | @property (weak) IBOutlet NSTextField *plistPath; 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /IpaExporter/App/View/SceneSelectView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneSelectView.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 9/22/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class ExportInfoManager; 14 | @interface SceneSelectView : NSViewController 15 | { 16 | NSMutableArray *_sceneArray; 17 | NSMutableSet *_selectScene; 18 | ExportInfoManager *_exportManager; 19 | } 20 | @property (weak) IBOutlet NSTableView *unitySceneTbl; 21 | @property (weak) IBOutlet NSProgressIndicator *progress; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /IpaExporter/App/View/ViewMain.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewMain.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/27/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ViewMain : NSTabViewController 14 | { 15 | NSSet *_subView; 16 | NSMutableArray *_subViewQueue; 17 | } 18 | 19 | @property (weak) IBOutlet NSTabView *tabs; 20 | 21 | @end 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /IpaExporter/App/View/ViewMain.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewMain.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/27/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "ViewMain.h" 10 | #import "Defs.h" 11 | #import "PreferenceView.h" 12 | #import "DetailsInfoSetting.h" 13 | #import "LogicManager.h" 14 | 15 | @implementation ViewMain 16 | 17 | - (void)viewDidLoad 18 | { 19 | //子界面 20 | _subView = [NSSet setWithObjects: 21 | @"PreferenceView", 22 | @"DetailsInfoSetting", 23 | @"SceneSelectView", 24 | nil]; 25 | _subViewQueue = [NSMutableArray array]; 26 | 27 | [super viewDidLoad]; 28 | } 29 | 30 | - (void)viewDidAppear 31 | { 32 | EVENT_REGIST(EventSetViewMainTab, @selector(setTab:)); 33 | EVENT_REGIST(EventShowSubView, @selector(showSubView:)); 34 | EVENT_REGIST(EventHideSubView, @selector(hideSubView:)) 35 | 36 | [self checkIsShowSetting]; 37 | } 38 | 39 | 40 | - (void)showSubView:(NSNotification*)notification 41 | { 42 | NSString *viewName = (NSString*)notification.object; 43 | if(![_subView containsObject:viewName]) 44 | return; 45 | 46 | NSStoryboard *sb = [NSStoryboard storyboardWithName:@"Main" bundle:nil]; 47 | NSViewController *vc = [sb instantiateControllerWithIdentifier:viewName]; 48 | vc.identifier = viewName; 49 | NSViewController *mainControler = [[[NSApplication sharedApplication] mainWindow] contentViewController]; 50 | 51 | EVENT_SEND(EventViewWillAppear, vc); 52 | [mainControler presentViewControllerAsSheet:vc]; 53 | 54 | [_subViewQueue addObject:vc]; 55 | } 56 | 57 | - (void)hideSubView:(NSNotification*)notification 58 | { 59 | if(_subViewQueue.count <= 0) 60 | return; 61 | 62 | NSViewController *vc = _subViewQueue.lastObject; 63 | [vc dismissController:vc]; 64 | 65 | EVENT_SEND(EventViewDidDisappear, vc); 66 | [_subViewQueue removeObject:vc]; 67 | } 68 | 69 | - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem 70 | { 71 | [super tabView:tabView didSelectTabViewItem:tabViewItem]; 72 | 73 | EVENT_SEND(EventViewDidDisappear, nil); 74 | EVENT_SEND(EventViewWillAppear,nil); 75 | } 76 | 77 | - (void)setTab:(NSNotification*)notification 78 | { 79 | NSInteger index = (NSInteger)notification.object; 80 | self.selectedTabViewItemIndex = index; 81 | } 82 | 83 | - (void)checkIsShowSetting 84 | { 85 | VersionInfo *instance = (VersionInfo*)get_instance(@"VersionInfo"); 86 | if([instance isUpdate]) 87 | { 88 | if(![[NSFileManager defaultManager] fileExistsAtPath:PLIST_PATH]) 89 | { 90 | NSStoryboard *sb = [NSStoryboard storyboardWithName:@"Main" bundle:nil]; 91 | DetailsInfoSetting *vc = [sb instantiateControllerWithIdentifier:@"UserDefaultsSetting"]; 92 | [self presentViewControllerAsSheet:vc]; 93 | }else{ 94 | [[Alert instance] alertTip:@"确定" MessageText:@"更新" InformativeText:@"检测到版本更新,点击确认同步代码" callBackFrist:^{ 95 | inst_method_call(@"PreferenceData", restoreCustomCode); 96 | }]; 97 | } 98 | } 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon-1.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon-2.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon-3.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon-7.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon-6.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon-5.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon-4.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon-8.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon-9.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-1.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-2.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-3.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-4.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-5.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-6.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-7.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-8.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon-9.png -------------------------------------------------------------------------------- /IpaExporter/Assets.xcassets/AppIcon.appiconset/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Assets.xcassets/AppIcon.appiconset/icon.png -------------------------------------------------------------------------------- /IpaExporter/Common/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Common/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Common/Alert.h: -------------------------------------------------------------------------------- 1 | // 2 | // Alert.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/3/28. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^AlertFunc)(void); 12 | @interface Alert : NSObject 13 | 14 | + (instancetype)instance; 15 | 16 | - (void)alertTip:(NSString *)firstname MessageText:(NSString *)messagetext InformativeText:(NSString *)informativetext callBackFrist:(void(^)(void))func1; 17 | 18 | - (void)alertModalFirstBtnTitle:(NSString *)firstname SecondBtnTitle:(NSString *)secondname MessageText:(NSString *)messagetext InformativeText:(NSString *)informativetext callBackFrist:(void(^)(void))func1 callBackSecond:(void(^)(void))func2; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /IpaExporter/Common/Alert.m: -------------------------------------------------------------------------------- 1 | // 2 | // Alert.m 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/3/28. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "Alert.h" 10 | #import 11 | 12 | @implementation Alert 13 | 14 | static AlertFunc _block; 15 | static AlertFunc _block2; 16 | 17 | + (instancetype)instance 18 | { 19 | Class cls = [self class]; 20 | //动态去取属性方法 21 | id instance = objc_getAssociatedObject(cls, @"instance"); 22 | if(!instance) 23 | { 24 | instance = [[self allocWithZone:NULL] init]; 25 | objc_setAssociatedObject(cls, @"instance", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 26 | } 27 | return instance; 28 | } 29 | 30 | - (void)alertTip:(NSString *)firstname MessageText:(NSString *)messagetext InformativeText:(NSString *)informativetext callBackFrist:(AlertFunc)func1 31 | { 32 | NSAlert *alert = [[NSAlert alloc] init]; 33 | 34 | _block = func1; 35 | [alert addButtonWithTitle:firstname]; 36 | [alert setMessageText:messagetext]; 37 | [alert setInformativeText:informativetext]; 38 | [alert setAlertStyle:NSAlertStyleWarning]; 39 | 40 | [alert beginSheetModalForWindow:[NSApplication sharedApplication].keyWindow completionHandler:^(NSInteger result) { 41 | if(result == NSAlertFirstButtonReturn) 42 | _block(); 43 | }]; 44 | } 45 | 46 | - (void)alertModalFirstBtnTitle:(NSString *)firstname SecondBtnTitle:(NSString *)secondname MessageText:(NSString *)messagetext InformativeText:(NSString *)informativetext callBackFrist:(void(^)(void))func1 callBackSecond:(void(^)(void))func2 47 | { 48 | NSAlert *alert = [[NSAlert alloc] init]; 49 | 50 | _block = func1; 51 | _block2 = func2; 52 | 53 | [alert addButtonWithTitle:firstname]; 54 | [alert addButtonWithTitle:secondname]; 55 | [alert setMessageText:messagetext]; 56 | [alert setInformativeText:informativetext]; 57 | 58 | [alert setAlertStyle:NSAlertStyleWarning]; 59 | 60 | [alert beginSheetModalForWindow:[NSApplication sharedApplication].keyWindow completionHandler:^(NSInteger result){ 61 | 62 | if(result == NSAlertFirstButtonReturn) 63 | { 64 | _block(); 65 | } 66 | else if(result == NSAlertSecondButtonReturn ) 67 | { 68 | _block2(); 69 | } 70 | }]; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /IpaExporter/Common/Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Common.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/2/20. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | #ifndef Common_h 10 | #define Common_h 11 | 12 | #import "CustomLog.h" 13 | #import "EventManager.h" 14 | #import "NSString+Emoji.h" 15 | #import "MobileprovisionParser.h" 16 | #import "Alert.h" 17 | #import "LocalDataSave.h" 18 | #import "NSFileManager+Extern.h" 19 | 20 | #endif /* Common_h */ 21 | -------------------------------------------------------------------------------- /IpaExporter/Common/CustomLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomLog.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/2/17. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | /// 显示普通Log到屏幕上 10 | /// @param content 需要打印内容 11 | void showLog(const char* content, ...); 12 | 13 | 14 | /// 显示错误信息Log到屏幕(颜色为红色) 15 | /// @param content 需要打印内容 16 | void showError(const char* content, ...); 17 | 18 | 19 | /// 显示成功Log信息(颜色为绿色) 20 | /// @param content 需要打印内容 21 | void showSuccess(const char* content, ...); 22 | 23 | 24 | /// 显示警告Log信息(颜色为黄色) 25 | /// @param content 需要打印内容 26 | void showWarning(const char* content, ...); 27 | 28 | //Lua log输出到屏幕上 29 | void lua_show_log(const char* s); 30 | void lua_show_error(const char *s); 31 | -------------------------------------------------------------------------------- /IpaExporter/Common/CustomLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomLog.m 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/2/17. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EventManager.h" 11 | #import "Defs.h" 12 | 13 | void show_log_sync_safe(EventType et, NSString* showString); 14 | 15 | void showLog(const char* content, ...) 16 | { 17 | va_list ap; 18 | va_start(ap, content); 19 | NSString* contentStr = [NSString stringWithUTF8String:content]; 20 | NSString* showStr = [[NSString alloc] initWithFormat:contentStr arguments:ap]; 21 | va_end(ap); 22 | 23 | show_log_sync_safe(EventAddNewInfoContent, showStr); 24 | } 25 | 26 | void showError(const char* content, ...) 27 | { 28 | va_list ap; 29 | va_start(ap, content); 30 | NSString* contentStr = [NSString stringWithUTF8String:content]; 31 | NSString* showStr = [[NSString alloc] initWithFormat:contentStr arguments:ap]; 32 | va_end(ap); 33 | 34 | show_log_sync_safe(EventAddErrorContent, showStr); 35 | } 36 | 37 | void showWarning(const char* content, ...) 38 | { 39 | va_list ap; 40 | va_start(ap, content); 41 | NSString* contentStr = [NSString stringWithUTF8String:content]; 42 | NSString* showStr = [[NSString alloc] initWithFormat:contentStr arguments:ap]; 43 | va_end(ap); 44 | 45 | show_log_sync_safe(EventAddNewWarningContent, showStr); 46 | } 47 | 48 | void showSuccess(const char* content, ...) 49 | { 50 | va_list ap; 51 | va_start(ap, content); 52 | NSString* contentStr = [NSString stringWithUTF8String:content]; 53 | NSString* showStr = [[NSString alloc] initWithFormat:contentStr arguments:ap]; 54 | va_end(ap); 55 | 56 | show_log_sync_safe(EventAddNewSuccessContent, showStr); 57 | } 58 | 59 | void show_log_sync_safe(EventType et, NSString* showString) 60 | { 61 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 62 | [[EventManager instance] send:et withData:showString]; 63 | }else{ 64 | dispatch_sync(dispatch_get_main_queue(), ^{ 65 | [[EventManager instance] send:et withData:showString]; 66 | }); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /IpaExporter/Common/DragDropView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DragDropView.h 3 | // IpaExporter 4 | // 5 | // Created by hezunzu on 2020/2/3. 6 | // Copyright © 2020 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @protocol DragDropViewDelegate 14 | -(NSDragOperation)dragDropViewDraggingEntered:(NSArray*)fileUrlList withIdentifier:(NSString*) identifier; 15 | -(BOOL)dragDropViewFileList:(NSArray*)fileUrlList withIdentifier:(NSString*)identifier; 16 | @end 17 | 18 | @interface DragDropView : NSView 19 | @property (assign) IBOutlet id delegate; 20 | @end 21 | 22 | 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /IpaExporter/Common/DragDropView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DragDropView.m 3 | // IpaExporter 4 | // 5 | // Created by hezunzu on 2020/2/3. 6 | // Copyright © 2020 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "DragDropView.h" 10 | #import 11 | 12 | @implementation DragDropView 13 | 14 | - (void)dealloc{ 15 | } 16 | 17 | - (instancetype)initWithCoder:(NSCoder *)coder 18 | { 19 | self = [super initWithCoder:coder]; 20 | if (self) { 21 | [self registerForDraggedTypes:@[NSPasteboardTypeFileURL, NSPasteboardTypePDF, NSPasteboardTypeString]]; 22 | } 23 | return self; 24 | } 25 | 26 | - (NSDragOperation)draggingEntered:(id)sender{ 27 | if(_delegate == nil) 28 | return NSDragOperationNone; 29 | 30 | NSArray *array = [self getUrlArrayFromDragInfo:sender]; 31 | return [_delegate dragDropViewDraggingEntered:array withIdentifier:[self identifier]]; 32 | } 33 | 34 | - (BOOL)performDragOperation:(id)sender{ 35 | if(_delegate == nil) 36 | return NO; 37 | 38 | NSArray *array = [self getUrlArrayFromDragInfo:sender]; 39 | return [_delegate dragDropViewFileList:array withIdentifier:[self identifier]]; 40 | } 41 | 42 | - (NSArray*)getUrlArrayFromDragInfo:(id)sender 43 | { 44 | NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:10]; 45 | NSPasteboard *pboard = [sender draggingPasteboard]; 46 | 47 | //判断是否为单个文件 48 | if (pboard.pasteboardItems.count <= 1) { 49 | NSURL *url = [NSURL URLFromPasteboard:pboard]; 50 | if (url) { 51 | [array addObject:url]; 52 | } 53 | }else{ 54 | for(NSPasteboardItem *item in pboard.pasteboardItems){ 55 | NSString *urlStr = [item propertyListForType:NSPasteboardTypeFileURL]; 56 | [array addObject:[NSURL URLWithString:urlStr]]; 57 | } 58 | } 59 | return array; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /IpaExporter/Common/EventManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // EventManager.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/8. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EventTypeDef.h" 11 | 12 | #define EVENT_REGIST(eventType, selector) \ 13 | [[EventManager instance] regist:eventType func:selector self:self]; 14 | #define EVENT_UNREGIST(eventType) \ 15 | [[EventManager instance] unRegist:eventType self:self]; 16 | #define EVENT_SEND(eventType, data) \ 17 | [[EventManager instance] send:eventType withData:data]; 18 | 19 | @interface EventManager : NSObject 20 | 21 | + (instancetype)instance; 22 | 23 | - (void)regist:(EventType)eventType func:(SEL)func self:(id)s; 24 | - (void)unRegist:(EventType)eventType self:(id)s; 25 | - (void)send:(EventType)eventType withData:(id)obj; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /IpaExporter/Common/EventManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // EventManager.m 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/8. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "EventManager.h" 10 | #import 11 | 12 | @implementation EventManager 13 | 14 | + (instancetype)instance 15 | { 16 | Class cls = [self class]; 17 | //动态去取属性方法 18 | id instance = objc_getAssociatedObject(cls, @"instance"); 19 | if(!instance) 20 | { 21 | instance = [[self allocWithZone:NULL] init]; 22 | objc_setAssociatedObject(cls, @"instance", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | } 24 | return instance; 25 | } 26 | 27 | - (void)regist:(EventType)eventType func:(SEL)func self:(id)s 28 | { 29 | [[NSNotificationCenter defaultCenter] addObserver:s 30 | selector:func 31 | name:[NSString stringWithFormat:@"%d", eventType] 32 | object:nil]; 33 | } 34 | 35 | - (void)unRegist:(EventType)eventType self:(id)s 36 | { 37 | [[NSNotificationCenter defaultCenter] removeObserver:s 38 | name:[NSString stringWithFormat:@"%d",eventType] 39 | object:nil]; 40 | } 41 | 42 | - (void)send:(EventType)eventType withData:(id)obj 43 | { 44 | [[NSNotificationCenter defaultCenter] postNotificationName:[NSString stringWithFormat:@"%ld", (long)eventType] 45 | object:obj]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /IpaExporter/Common/EventTypeDef.h: -------------------------------------------------------------------------------- 1 | // 2 | // EventType.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2017/2/9. 6 | // Copyright © 2017年 何遵祖. All rights reserved. 7 | // 8 | 9 | #ifndef EventType_h 10 | #define EventType_h 11 | 12 | typedef int EventType; 13 | typedef NS_ENUM(EventType, EventTypeCommon) 14 | { 15 | //通用模块 16 | EventAddNewInfoContent = 10000, 17 | EventAddErrorContent, 18 | EventAddNewSuccessContent, 19 | EventAddNewWarningContent, 20 | EventCleanInfoContent, 21 | }; 22 | 23 | #endif /* EventType_h */ 24 | -------------------------------------------------------------------------------- /IpaExporter/Common/LocalDataSave.h: -------------------------------------------------------------------------------- 1 | // 2 | // LocalDataSave.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 6/29/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LocalDataSave : NSObject{ 14 | @private 15 | BOOL _keyIsSet; 16 | BOOL _useUserDefault; 17 | NSDictionary *_saveTpDict; 18 | NSString *_plistPath; 19 | NSString *_bundleIdentifier; 20 | NSMutableDictionary *_saveData; 21 | NSMutableDictionary *_savedict; 22 | } 23 | 24 | - (id)initWithPlist:(NSString*)path; 25 | 26 | /** 27 | 设置所有需要存储的key还有对应类型,如果该key已经有存储内容,同时也会解析出来 28 | 29 | @param saveTpDict 类型字典(格式:dict=@{NSString:NSArray *}) 30 | */ 31 | - (void)setAllSaveKey:(NSDictionary*)saveTpDict; 32 | 33 | /** 34 | 存储某个数据 35 | 36 | @param key 存储key,必须是在初始化中传入过的key。如果传入为空,代表存储所有 37 | @return 返回是否成功 38 | */ 39 | - (BOOL)saveDataForKey:(nullable NSString*)key; 40 | 41 | /** 42 | 存储全部 43 | */ 44 | - (BOOL)saveAll; 45 | 46 | /** 47 | 获取某个数据 48 | 49 | @param key 存储key,必须是在初始化中传入过的key 50 | @return 返回获取到的数据 51 | */ 52 | - (id)dataForKey:(nonnull NSString*)key; 53 | 54 | 55 | /** 56 | 设置某个待存储key 57 | 58 | @param key 存储key,必须是在初始化中传入过的key 59 | @param data 需要设置对象 60 | @return 返回结果 61 | */ 62 | - (BOOL)setDataForKey:(nonnull NSString*)key withData:(nullable id)data; 63 | 64 | /** 65 | 设置某个待存储key 会自动存储 66 | */ 67 | - (BOOL)setAndSaveData:(nullable id)data withKey:(NSString*)key; 68 | 69 | /** 70 | 移除某个数据 71 | 72 | @param key 存储key,必须是在初始化中传入过的key 73 | @return 返回结果 74 | */ 75 | - (BOOL)removeObjectForKey:(nonnull NSString*)key; 76 | 77 | /** 78 | 移除全部 79 | */ 80 | - (void)removeAll; 81 | 82 | /// 重新加载存储数据 83 | - (void)reload; 84 | 85 | @end 86 | 87 | NS_ASSUME_NONNULL_END 88 | -------------------------------------------------------------------------------- /IpaExporter/Common/MobileprovisionParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobileprovisionParser.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 6/3/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MobileprovisionParser : NSObject{ 14 | @private 15 | NSString *_profilePath; 16 | } 17 | 18 | - (id)initWithProfilePath:(NSString*)path; 19 | - (void)createPlistFile; 20 | - (void)parsePlistFile; 21 | 22 | @property (nonatomic, readonly) NSString* rootPath; 23 | @property (nonatomic, readonly) NSString* fileName; 24 | @property (nonatomic, readonly) NSString* bundleIdentifier; 25 | @property (nonatomic, readonly) NSString* appIDName; 26 | @property (nonatomic, readonly) NSString* teamID; 27 | @property (nonatomic, readonly) NSString* creationDate; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /IpaExporter/Common/MobileprovisionParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MobileprovisionParser.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 6/3/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "MobileprovisionParser.h" 10 | #import "Defs.h" 11 | 12 | @implementation MobileprovisionParser 13 | 14 | - (id)initWithProfilePath:(NSString*)path 15 | { 16 | if(self=[super init]) 17 | { 18 | _profilePath = path; 19 | 20 | NSString* profile = [[path componentsSeparatedByString:@"/"] lastObject]; 21 | _fileName = [[profile componentsSeparatedByString:@"."] firstObject]; 22 | 23 | NSRange range = [path rangeOfString:profile]; 24 | _rootPath = [[path substringToIndex:range.location] stringByReplacingOccurrencesOfString:@" " withString:@""]; 25 | 26 | NSString *fullPath = [NSString stringWithFormat:@"%@/%@.plist", _fileName, _rootPath]; 27 | if([[NSFileManager defaultManager] fileExistsAtPath:fullPath]) 28 | [[NSFileManager defaultManager] removeItemAtPath:fullPath error:nil]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)createPlistFile 34 | { 35 | NSTask *shellTask = [[NSTask alloc] init]; 36 | [shellTask setLaunchPath:@"/bin/sh"]; 37 | 38 | NSString *shellStr = [NSString stringWithFormat:@"security cms -D -i %@%@.mobileprovision > %@/%@.plist", _rootPath, _fileName, PACK_FOLDER_PATH, _fileName]; 39 | 40 | [shellTask setArguments:[NSArray arrayWithObjects:@"-c", shellStr, nil]]; 41 | NSPipe *pipe = [[NSPipe alloc] init]; 42 | [shellTask setStandardOutput:pipe]; 43 | [shellTask launch]; 44 | [shellTask waitUntilExit]; 45 | } 46 | 47 | - (void)parsePlistFile 48 | { 49 | NSString *filePath = [NSString stringWithFormat:@"%@/%@.%@",PACK_FOLDER_PATH, _fileName, @"plist"]; 50 | if(![[NSFileManager defaultManager] fileExistsAtPath:filePath]){ 51 | showError([[NSString stringWithFormat:@"%@文件不存在", filePath] UTF8String]); 52 | return; 53 | } 54 | 55 | NSDictionary *plist = [[NSDictionary alloc] initWithContentsOfFile:filePath]; 56 | 57 | _fileName = plist[@"UUID"]; 58 | _appIDName = plist[@"AppIDName"]; 59 | _teamID = plist[@"ApplicationIdentifierPrefix"][0]; 60 | _creationDate = plist[@"CreationDate"]; 61 | 62 | NSString *applicationIdentifier = plist[@"Entitlements"][@"application-identifier"]; 63 | NSRange range = [applicationIdentifier rangeOfString:_teamID]; 64 | _bundleIdentifier = [applicationIdentifier substringFromIndex:range.location + range.length + 1]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /IpaExporter/Common/NSFileManager+Extern.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+Copy.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 7/9/19. 6 | // Copyright © 2019 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSFileManager (Copy) 14 | 15 | /** 16 | 拷贝文件夹内容,同步 17 | @param src 需要被拷贝的文件夹 18 | @param dst 拷贝目标文件夹 19 | */ 20 | - (void)copyFolderFrom:(NSString*)src toDst:(NSString*)dst; 21 | 22 | 23 | /** 24 | 拷贝文件夹内容,同步 25 | @param cover 是否覆盖,如果目标文件夹存在(注意会直接替换) 26 | */ 27 | - (void)copyFolderFrom:(NSString*)src toDst:(NSString*)dst isCover:(BOOL)cover; 28 | 29 | /** 30 | 使用shell指令拷贝文件夹,异步,线程阻塞(需要修改) 31 | @return 返回指令执行内容和相关结果 32 | */ 33 | - (NSString*)copyUseShell:(NSString*)src toDst:(NSString*)dst; 34 | 35 | - (void)copyFile:(NSString*)src toDst:(NSString*)dst; 36 | 37 | @end 38 | 39 | @interface NSFileManager (Search) 40 | 41 | - (NSArray*)searchByExtension:(NSString*)extension withDir:(NSString*)searchDir; 42 | 43 | 44 | /// 根据后缀查找文件 45 | /// @param extension 文件类型 46 | /// @param searchDir 查找文件夹路径 47 | /// @param append 需要添加结果信息 例如搜索到路径是A 如果传入append 就变成append/A 48 | - (NSArray*)searchByExtension:(NSString*)extension withDir:(NSString*)searchDir appendPath:(NSString*)append; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /IpaExporter/Common/NSString+Emoji.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Emoji.h 3 | // 4 | // 5 | // Created by Valerio Mazzeo on 24/04/13. 6 | // Copyright (c) 2013 Valerio Mazzeo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | NSString (Emoji) extends the NSString class to provide custom functionality 13 | related to the Emoji emoticons. 14 | 15 | Through this category, it is possible to turn cheat codes from 16 | Emoji Cheat Sheet into unicode emoji characters 17 | and vice versa (useful if you need to POST a message typed by the user to a remote service). 18 | */ 19 | @interface NSString (Emoji) 20 | 21 | /** 22 | Returns a NSString in which any occurrences that match the cheat codes 23 | from Emoji Cheat Sheet are replaced by the 24 | corresponding unicode characters. 25 | 26 | Example: 27 | "This is a smiley face :smiley:" 28 | 29 | Will be replaced with: 30 | "This is a smiley face \U0001F604" 31 | */ 32 | - (NSString *)stringByReplacingEmojiCheatCodesWithUnicode; 33 | 34 | /** 35 | Returns a NSString in which any occurrences that match the unicode characters 36 | of the emoji emoticons are replaced by the corresponding cheat codes from 37 | Emoji Cheat Sheet . 38 | 39 | Example: 40 | "This is a smiley face \U0001F604" 41 | 42 | Will be replaced with: 43 | "This is a smiley face :smiley:" 44 | */ 45 | - (NSString *)stringByReplacingEmojiUnicodeWithCheatCodes; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /IpaExporter/Common/NSString+RKMatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+RKMatch.h 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 5/7/20. 6 | // Copyright © 2020 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface NSString (RKMatch) 17 | - (BOOL)isMatch:(NSString*)keyword; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /IpaExporter/Common/NSString+RKMatch.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+RKMatch.m 3 | // IpaExporter 4 | // 5 | // Created by 4399 on 5/7/20. 6 | // Copyright © 2020 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "NSString+RKMatch.h" 10 | 11 | #import 12 | 13 | 14 | @implementation NSString (RKMatch) 15 | 16 | - (BOOL)isMatch:(NSString*)keyword 17 | { 18 | NSInteger keyHash = [keyword hash]; 19 | NSInteger keyLength = [keyword length]; 20 | 21 | NSString *subString; 22 | for(int i = 0; i < self.length; i++){ 23 | if (keyLength + i >= self.length + 1) break; 24 | subString = [self substringWithRange:NSMakeRange(i, keyLength)]; 25 | if([subString hash] == keyHash){ 26 | for (int j = 0; j < keyLength; j++) { 27 | NSString *c1 = [subString substringWithRange:NSMakeRange(j, 1)]; 28 | NSString *c2 = [keyword substringWithRange:NSMakeRange(j, 1)]; 29 | 30 | if(![c1 isEqualToString:c2]) break; 31 | 32 | if (j == keyLength - 1) { 33 | return YES; 34 | } 35 | } 36 | } 37 | } 38 | return NO; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /IpaExporter/ExporterMain.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExporterMain.h 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/1. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LuaCammond.h" 11 | #import "ViewMain.h" 12 | 13 | @interface ExporterMain : NSObject 14 | 15 | @property(nonatomic, readonly) LuaCammond* l_inst; 16 | @property(nonatomic, readonly) ViewMain* v_inst; 17 | 18 | + (ExporterMain*)instance; 19 | - (void)startUp; 20 | - (void)startMain; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /IpaExporter/ExporterMain.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExporterMain.m 3 | // IpaExporter 4 | // 5 | // Created by 何遵祖 on 2016/9/1. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import "ExporterMain.h" 10 | 11 | @implementation ExporterMain 12 | 13 | +(ExporterMain*)instance 14 | { 15 | static ExporterMain* s_instance = nil; 16 | if(nil == s_instance) 17 | { 18 | @synchronized (self) 19 | { 20 | if(nil == s_instance) 21 | { 22 | s_instance = [[self alloc]init]; 23 | } 24 | } 25 | } 26 | return s_instance; 27 | } 28 | 29 | -(void)startUp 30 | { 31 | _l_inst = [[LuaCammond alloc] init]; 32 | _v_inst = [[ViewMain alloc] init]; 33 | } 34 | 35 | -(void)startMain 36 | { 37 | [_l_inst startExport]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /IpaExporter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | zh_CN 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 20210318 25 | LSApplicationCategoryType 26 | public.app-category.developer-tools 27 | LSMinimumSystemVersion 28 | $(MACOSX_DEPLOYMENT_TARGET) 29 | NSHumanReadableCopyright 30 | Copyright © 2020年 何遵祖. All rights reserved. 31 | NSMainStoryboardFile 32 | Main 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /IpaExporter/Libs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/CodeTest/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/CodeTest/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/CodeTest/CodeTest.sh: -------------------------------------------------------------------------------- 1 | #$1 unity工程路径 2 | #$2 导出路径 3 | #$3 沙盒路径 4 | #$4 是否仅打开 5 | 6 | unity_project_path=$1 7 | export_path=$2 8 | bundle_res_path=$3 9 | only_open = $4 10 | 11 | pkill Unity 12 | cd ${unity_project_path} 13 | args_config=$(cat ${bundle_res_path}'/TempCode/Builder/Users/_CustomConfig.json'| sed s/[[:space:]]//g | tr -d '\n') 14 | 15 | #生成xcode工程 16 | /Applications/Unity/Unity.app/Contents/MacOS/Unity -runEditorTests -projectPath ${unity_project_path} -testResults ${export_path}/code_test_log.xml -args_${args_config} -testPlatform editmode -logFile ${export_path}/code_test_editor_log.txt 17 | -------------------------------------------------------------------------------- /IpaExporter/Libs/CodeTest/Test/_TestBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.IO; 5 | using NUnit.Framework; 6 | 7 | //理论上不允许修改 8 | namespace IpaExporter 9 | { 10 | public class _Builder 11 | { 12 | [Test] 13 | public static void BuildApp() 14 | { 15 | //获取shell脚本参数 16 | string args = ""; 17 | string[] strs = System.Environment.GetCommandLineArgs(); 18 | foreach(var s in strs) 19 | { 20 | if(s.Contains("-args")) 21 | { 22 | //参数必须是json格式 23 | args = s.Split('_')[1]; 24 | } 25 | } 26 | 27 | //测试传近进来参数是否正确 28 | Assert.AreEqual(true, args.StartsWith("{") && args.EndsWith("}")); 29 | 30 | //必须参数 31 | PlayerSettings.iOS.sdkVersion = iOSSdkVersion.DeviceSDK; 32 | _CustomBuilder customBuilder = new _CustomBuilder(); 33 | JsonData jsonObj = JsonMapper.ToObject(args); 34 | 35 | customBuilder.BuildApp(jsonObj, LEVELS, exportPath); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /IpaExporter/Libs/CodeTest/Test/_TestConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/TempCode/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/TempCode/Builder/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/LitJson/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/TempCode/Builder/LitJson/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/LitJson/IJsonWrapper.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * IJsonWrapper.cs 4 | * Interface that represents a type capable of handling all kinds of JSON 5 | * data. This is mainly used when mapping objects through JsonMapper, and 6 | * it's implemented by JsonData. 7 | * 8 | * The authors disclaim copyright to this source code. For more details, see 9 | * the COPYING file included with this distribution. 10 | **/ 11 | #endregion 12 | 13 | 14 | using System.Collections; 15 | using System.Collections.Specialized; 16 | 17 | 18 | namespace IpaExporter 19 | { 20 | public enum JsonType 21 | { 22 | None, 23 | 24 | Object, 25 | Array, 26 | String, 27 | Int, 28 | Long, 29 | Double, 30 | Boolean 31 | } 32 | 33 | public interface IJsonWrapper : IList, IOrderedDictionary 34 | { 35 | bool IsArray { get; } 36 | bool IsBoolean { get; } 37 | bool IsDouble { get; } 38 | bool IsInt { get; } 39 | bool IsLong { get; } 40 | bool IsObject { get; } 41 | bool IsString { get; } 42 | 43 | bool GetBoolean (); 44 | double GetDouble (); 45 | int GetInt (); 46 | JsonType GetJsonType (); 47 | long GetLong (); 48 | string GetString (); 49 | 50 | void SetBoolean (bool val); 51 | void SetDouble (double val); 52 | void SetInt (int val); 53 | void SetJsonType (JsonType type); 54 | void SetLong (long val); 55 | void SetString (string val); 56 | 57 | string ToJson (); 58 | void ToJson (JsonWriter writer); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/LitJson/JsonException.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * JsonException.cs 4 | * Base class throwed by LitJSON when a parsing error occurs. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | using System; 13 | 14 | 15 | namespace IpaExporter 16 | { 17 | public class JsonException : 18 | #if NETSTANDARD1_5 19 | Exception 20 | #else 21 | ApplicationException 22 | #endif 23 | { 24 | public JsonException () : base () 25 | { 26 | } 27 | 28 | internal JsonException (ParserToken token) : 29 | base (String.Format ( 30 | "Invalid token '{0}' in input string", token)) 31 | { 32 | } 33 | 34 | internal JsonException (ParserToken token, 35 | Exception inner_exception) : 36 | base (String.Format ( 37 | "Invalid token '{0}' in input string", token), 38 | inner_exception) 39 | { 40 | } 41 | 42 | internal JsonException (int c) : 43 | base (String.Format ( 44 | "Invalid character '{0}' in input string", (char) c)) 45 | { 46 | } 47 | 48 | internal JsonException (int c, Exception inner_exception) : 49 | base (String.Format ( 50 | "Invalid character '{0}' in input string", (char) c), 51 | inner_exception) 52 | { 53 | } 54 | 55 | 56 | public JsonException (string message) : base (message) 57 | { 58 | } 59 | 60 | public JsonException (string message, Exception inner_exception) : 61 | base (message, inner_exception) 62 | { 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/LitJson/Netstandard15Polyfill.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD1_5 2 | using System; 3 | using System.Reflection; 4 | namespace IpaExporter 5 | { 6 | internal static class Netstandard15Polyfill 7 | { 8 | internal static Type GetInterface(this Type type, string name) 9 | { 10 | return type.GetTypeInfo().GetInterface(name); 11 | } 12 | 13 | internal static bool IsClass(this Type type) 14 | { 15 | return type.GetTypeInfo().IsClass; 16 | } 17 | 18 | internal static bool IsEnum(this Type type) 19 | { 20 | return type.GetTypeInfo().IsEnum; 21 | } 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/LitJson/ParserToken.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * ParserToken.cs 4 | * Internal representation of the tokens used by the lexer and the parser. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | namespace IpaExporter 13 | { 14 | internal enum ParserToken 15 | { 16 | // Lexer tokens (see section A.1.1. of the manual) 17 | None = System.Char.MaxValue + 1, 18 | Number, 19 | True, 20 | False, 21 | Null, 22 | CharSeq, 23 | // Single char 24 | Char, 25 | 26 | // Parser Rules (see section A.2.1 of the manual) 27 | Text, 28 | Object, 29 | ObjectPrime, 30 | Pair, 31 | PairRest, 32 | Array, 33 | ArrayPrime, 34 | Value, 35 | ValueRest, 36 | String, 37 | 38 | // End of input 39 | End, 40 | 41 | // The empty rule 42 | Epsilon 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/Users/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/TempCode/Builder/Users/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/Users/_CustomBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.IO; 5 | using NUnit.Framework; 6 | 7 | namespace IpaExporter 8 | { 9 | public class _CustomBuilder 10 | { 11 | //args 从配置传过来的参数 12 | public void BuildApp(JsonData args, string[] levels, string exportPath) 13 | { 14 | //自定义扩展代码都写在这里 15 | //参数获取参考 int t = (int)args["isTest"] 16 | //具体设置是在界面中的 设置参数 按钮中 在plist中配置就ok了 17 | 18 | //自己扩展代码写在这里 19 | 20 | //打包代码 如果自己逻辑里面就带了这个方法 就可以注释 21 | //levels和exportPath两个参数是必须要用打包工具传入的 22 | BuildPipeline.BuildPlayer(levels, exportPath, BuildTarget.iOS, BuildOptions.AcceptExternalModificationsToPlayer); 23 | 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/Users/_CustomConfig.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 模版-AppName 6 | 7 | args1 8 | 200 9 | args2 10 | 200 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/Users/_CustomShell.sh: -------------------------------------------------------------------------------- 1 | #$1 ruby入口文件路径 0 2 | #$2 sdk资源文件路径 1 3 | #$3 导出路径(xcode工程和ipa) 2 4 | #$4 平台名称 3 5 | #$5 配置路径 4 6 | #$6 unity工程路径 7 | #$7 xcode工程名称 目前固定xcodeProj 8 | #$8 开发者teamid(debug) 9 | #$9 开发者签名文件名字(debug) 10 | #$10 开发者teamid(release) 11 | #$11 开发者签名文件名字(release) 12 | #$12 沙盒文件路径 13 | #$13 bundleIdentifier 14 | #$14 是否release包 15 | #$15 缓存文件位置 16 | #$16 需要关联的sdk文件夹 17 | #$17 是否导出ipa 18 | #$18 应用名字 19 | 20 | #测试自定义脚本获取简单的json参数 21 | #bundle_res_path=${12} 22 | #isTest=$(cat ${bundle_res_path}'/TempCode/Builder/Users/_CustomConfig.json'| awk -F: '/isVest/{print $2}' | sed 's/,//g') 23 | 24 | #运行自定义脚本命令 25 | #project_path=$6 26 | #python $6"/test.py" $1 $2 27 | 28 | echo "CUSTOM_RUN_SUCCESS" #标示为成功 不是会被中断 29 | -------------------------------------------------------------------------------- /IpaExporter/Libs/TempCode/Builder/_Builder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.IO; 5 | 6 | //注意:${xxx} xxx代表是objc方法 7 | namespace IpaExporter 8 | { 9 | public class _Builder 10 | { 11 | static void BuildApp() 12 | { 13 | //理论上不允许修改------------ 14 | string[] LEVELS = new string[] 15 | { 16 | ${objcfunc_BuilderCSFileEdit_getPackScenePath} //form objc 17 | }; 18 | 19 | string exportPath = ${objcfunc_BuilderCSFileEdit_getExportPath}; 20 | string exportXcodePath = ${objcfunc_BuilderCSFileEdit_getXcodeExportPath}; 21 | 22 | //获取shell脚本参数 23 | string args = ""; 24 | string productName = ""; 25 | string[] strs = System.Environment.GetCommandLineArgs(); 26 | foreach(var s in strs) 27 | { 28 | if(s.Contains("-args")) 29 | { 30 | //参数必须是json格式 31 | args = s.Split('_')[1]; 32 | } 33 | 34 | if(s.Contains("-productName")) 35 | { 36 | productName = s.Split('_')[1]; 37 | } 38 | } 39 | 40 | string path = string.Format("{0}/{1}", exportPath, "xcodeproj_create_Result.txt"); 41 | if (File.Exists(path)) 42 | File.Delete(path);//删除文件 43 | 44 | //必须参数 45 | PlayerSettings.iOS.sdkVersion = iOSSdkVersion.DeviceSDK; 46 | _CustomBuilder customBuilder = new _CustomBuilder(); 47 | 48 | //获取配置信息 49 | JsonData allPlatformInfo = JsonMapper.ToObject(args); 50 | JsonData platformItem = new JsonData(); 51 | if(allPlatformInfo.Keys.Contains(productName)){ 52 | platformItem = allPlatformInfo[productName]; 53 | }else{ 54 | Debug.LogError("不存在" + productName + "配置信息"); 55 | } 56 | 57 | customBuilder.BuildApp(platformItem, LEVELS, exportXcodePath); 58 | 59 | //如果成功写入结果到文件 60 | //创建结果标记文件 61 | FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); 62 | StreamWriter writer = new StreamWriter(fs); 63 | writer.WriteLine("*****SUCCESS*****"); 64 | writer.Close(); 65 | //理论上不允许修改------------ 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/Xcodeproj/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/EditXcode.sh: -------------------------------------------------------------------------------- 1 | #$1 ruby入口文件路径 0 2 | #$2 sdk资源文件路径 1 3 | #$3 导出路径(xcode工程和ipa) 2 4 | #$4 平台名称 3 5 | #$5 配置路径 4 6 | #$6 unity工程路径 7 | #$7 xcode工程名称 目前固定xcodeProj 8 | #$8 开发者teamid(debug) 9 | #$9 开发者签名文件名字(debug) 10 | #$10 开发者teamid(release) 11 | #$11 开发者签名文件名字(release) 12 | #$12 沙盒文件路径 13 | #$13 bundleIdentifier 14 | #$14 是否release包 15 | #$15 缓存文件位置 16 | #$16 需要关联的sdk文件夹 17 | #$17 是否导出ipa 18 | #$18 应用名字 19 | 20 | echo "Main.sh脚本执行log" 21 | custom_sdk_path=$2 22 | export_path=$3 #export path 23 | product_name=$4 24 | json_path=$5 25 | unity_proj_path=$6 26 | xcode_proj_name=$7 27 | debug_team_id=$8 28 | debug_provisioning_profile=$9 29 | release_provisioning_profile=${11} 30 | release_team_id=${10} 31 | main_bundle_res_path=${12} 32 | bundleIdentifier=${13} 33 | is_release=${14} 34 | pack_folder_path=${15} 35 | sdk_folder_path=${16} 36 | is_export_ipa=${17} 37 | app_name=${18} 38 | 39 | provisioning_profile=${debug_provisioning_profile} 40 | team_id=${debug_team_id} 41 | configuration="Debug" 42 | method="development" 43 | signingCertificate='iPhone Developer' 44 | current_time=`date "+%Y%m%d%H%M%S"` 45 | 46 | xcode_proj_path=${export_path}"/"${xcode_proj_name}"-"${product_name} 47 | 48 | ruby -w $1 ${custom_sdk_path} ${export_path} ${product_name} ${json_path} ${unity_proj_path} ${xcode_proj_name} ${sdk_folder_path} ${is_release} ${app_name} 49 | 50 | #处理scheme内容 51 | project_scheme_path=${xcode_proj_path}"/Unity-iPhone-"${product_name}".xcodeproj/xcshareddata/xcschemes/Unity-iPhone.xcscheme" 52 | #修改scheme配置 53 | sed -i '' 's/container:Unity-iPhone.xcodeproj/container:Unity-iPhone-'${product_name}'.xcodeproj/g' ${project_scheme_path} 54 | 55 | echo ${project_scheme_path} 56 | 57 | echo "** EDIT XCODE PROJECT SUCCESS **" 58 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/ExportOptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | destination 6 | export 7 | method 8 | :method: 9 | provisioningProfiles 10 | 11 | :bundleIdentifier: 12 | :profileName: 13 | 14 | signingCertificate 15 | :certificate: 16 | signingStyle 17 | manual 18 | stripSwiftSymbols 19 | 20 | teamID 21 | :developTeam: 22 | uploadSymbols 23 | 24 | uploadBitcode 25 | 26 | compileBitcode 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/ExportXcode.sh: -------------------------------------------------------------------------------- 1 | #$1 unity工程路径 2 | #$2 导出路径 3 | #$3 沙盒路径 4 | 5 | #echo "打包信息" 6 | #echo "导出路径(xcode工程和ipa):"$2 7 | 8 | unity_project_path=$1 9 | export_path=$2 10 | bundle_res_path=$3 11 | product_name=$5 12 | xcode_base_projName=$6 13 | 14 | #--------------生成母包工程 15 | # 16 | #将自定义参数配置plist转换成json 17 | plutil -convert json ${bundle_res_path}'/TempCode/Builder/Users/_CustomConfig.plist' -o ${bundle_res_path}'/TempCode/Builder/Users/_CustomConfig.json' 18 | 19 | pkill Unity 20 | cd ${unity_project_path} 21 | args_config=$(cat ${bundle_res_path}'/TempCode/Builder/Users/_CustomConfig.json'| sed s/[[:space:]]//g | tr -d '\n') 22 | 23 | unity_log_file=${export_path}'/xcodeproj_create_log.log' 24 | 25 | #生成xcode工程 26 | /Applications/Unity/Unity.app/Contents/MacOS/Unity -buildTarget Ios -bacthmode -quit -projectPath ${unity_project_path} -executeMethod IpaExporter._Builder.BuildApp -logFile ${unity_log_file} -args_${args_config} -productName_${product_name} 27 | 28 | #修改工程名字 29 | xcode_base_projPath=${export_path}/${xcode_base_projName} 30 | xcode_projPath=${export_path}"/"${xcode_base_projName}"-"${product_name} 31 | mv ${xcode_base_projPath} ${xcode_projPath} 32 | 33 | echo "[配置信息]Unity日志路径:"${export_path} 34 | 35 | grep "error CS" ${unity_log_file} 36 | 37 | result_file_path=${export_path}"/xcodeproj_create_Result.txt" 38 | if [ -f ${result_file_path} ]; then 39 | grep "SUCCESS" ${result_file_path} 40 | rm ${result_file_path} 41 | fi 42 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/Main.rb: -------------------------------------------------------------------------------- 1 | PROJECT_ROOT_PATH = File.dirname(__FILE__) 2 | PROJECT_RESOURCE_PATH = ARGV.at(0) 3 | 4 | # SDK_FOLDER_NAME = "4399" #sdk对应的文件夹名字 5 | # PROJECT_RESOURCE_PATH = "#{PROJECT_ROOT_PATH}/mods/SDK/#{SDK_FOLDER_NAME}" 6 | 7 | #为了兼容开发机不能上网情况 只能本地化 不折腾了 8 | $LOAD_PATH << File.join(PROJECT_ROOT_PATH, "/lib") 9 | 10 | require "xcodeproj" 11 | require "fileutils" 12 | require_relative "XcodeProjectUpdater" 13 | 14 | $xcode_proj_root_path = ARGV.at(1) 15 | $product_name = ARGV.at(2) 16 | $config_path = ARGV.at(3) 17 | $xcode_proj_name = ARGV.at(5) 18 | $custom_sdk_path = ARGV.at(6) 19 | $is_release = ARGV.at(7) 20 | $app_name = ARGV.at(8) 21 | 22 | $project_folder_path = "#{$xcode_proj_root_path}/#{$xcode_proj_name}-#{$product_name}" 23 | $templete_project_path = "#{$project_folder_path}/Unity-iPhone.xcodeproj" 24 | $project_path = "#{$project_folder_path}/Unity-iPhone-#{$product_name}.xcodeproj" 25 | $base_proj_path = "#{$project_folder_path}/Unity-iPhone.xcodeproj" 26 | $log_file_path = "#{$xcode_proj_root_path}/xcodeproj_log_#{$product_name}.log" 27 | 28 | if !(File::exist?($log_file_path)) 29 | File.new($log_file_path, 'w') 30 | end 31 | 32 | $stdout.reopen($log_file_path, "w") 33 | $stderr.reopen($log_file_path, "w") 34 | 35 | #存在就先删除 36 | if File::exist?($project_path) 37 | FileUtils.rm_r $project_path 38 | end 39 | FileUtils.cp_r $templete_project_path, $project_path 40 | 41 | $project = Xcodeproj::Project.open($project_path) 42 | $base_project = Xcodeproj::Project.open($base_proj_path) 43 | 44 | export_main = XcodeProjectUpdater.new() 45 | export_main.start() 46 | 47 | $project.save 48 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/VERSION: -------------------------------------------------------------------------------- 1 | 0.1.3 2 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/XcodeSigningEdit.rb: -------------------------------------------------------------------------------- 1 | PROJECT_ROOT_PATH = File.dirname(__FILE__) 2 | PROJECT_RESOURCE_PATH = ARGV.at(0) 3 | 4 | #为了兼容开发机不能上网情况 只能本地化 不折腾了 5 | $LOAD_PATH << File.join(PROJECT_ROOT_PATH, "/lib") 6 | 7 | require "xcodeproj" 8 | require "fileutils" 9 | require_relative "XcodeProjectUpdater" 10 | 11 | $xcode_proj_root_path = ARGV.at(1) 12 | $product_name = ARGV.at(2) 13 | $config_path = ARGV.at(3) 14 | $xcode_proj_name = ARGV.at(5) 15 | $custom_sdk_path = ARGV.at(6) 16 | $is_release = ARGV.at(7) 17 | $app_name = ARGV.at(8) 18 | 19 | $project_folder_path = "#{$xcode_proj_root_path}/#{$xcode_proj_name}-#{$product_name}" 20 | $project_path = "#{$project_folder_path}/Unity-iPhone-#{$product_name}.xcodeproj" 21 | 22 | print(File::exist?($project_path)) 23 | if File::exist?($project_path) == false 24 | exit 25 | end 26 | 27 | # 方法定义 28 | def set_build_setting(target, key, value, build_configuration_name = "All") 29 | target.build_configurations.each do |config| 30 | if build_configuration_name == "All" || build_configuration_name == config.to_s then 31 | build_settings = config.build_settings 32 | build_settings[key] = value 33 | end 34 | end 35 | end 36 | 37 | # xcodeproj必须存在 38 | $project = Xcodeproj::Project.open($project_path) 39 | 40 | config = File.read($config_path) 41 | @setting_hash = JSON.parse(config) 42 | @target = $project.targets.first 43 | 44 | #设置证书信息 45 | bundle_identifier = @setting_hash["product_bundle_identifier"] 46 | bundle_identifier_release = @setting_hash["product_bundle_identifier_release"] 47 | develop_signing_identity = @setting_hash["develop_signing_identity"] 48 | 49 | set_build_setting(@target, "PROVISIONING_PROFILE_SPECIFIER", develop_signing_identity[0], "Debug") 50 | set_build_setting(@target, "DEVELOPMENT_TEAM", develop_signing_identity[1], "Debug") 51 | set_build_setting(@target, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer", "Debug") 52 | set_build_setting(@target, "PRODUCT_BUNDLE_IDENTIFIER", bundle_identifier, "Debug") 53 | set_build_setting(@target, "GCC_PREPROCESSOR_DEFINITIONS", "DEBUG=1", "Debug") 54 | 55 | release_signing_identity = @setting_hash["release_signing_identity"] 56 | set_build_setting(@target, "PROVISIONING_PROFILE_SPECIFIER", release_signing_identity[0], "Release") 57 | set_build_setting(@target, "DEVELOPMENT_TEAM", release_signing_identity[1], "Release") 58 | set_build_setting(@target, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Distribution", "Release") 59 | set_build_setting(@target, "PRODUCT_BUNDLE_IDENTIFIER", bundle_identifier_release, "Release") 60 | 61 | $project.save 62 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/XcodeSigningEdit.sh: -------------------------------------------------------------------------------- 1 | #$1 ruby入口文件路径 0 2 | #$2 sdk资源文件路径 1 3 | #$3 导出路径(xcode工程和ipa) 2 4 | #$4 平台名称 3 5 | #$5 配置路径 4 6 | #$6 unity工程路径 7 | #$7 xcode工程名称 目前固定xcodeProj 8 | #$8 开发者teamid(debug) 9 | #$9 开发者签名文件名字(debug) 10 | #$10 开发者teamid(release) 11 | #$11 开发者签名文件名字(release) 12 | #$12 沙盒文件路径 13 | #$13 bundleIdentifier 14 | #$14 是否release包 15 | #$15 缓存文件位置 16 | #$16 需要关联的sdk文件夹 17 | #$17 是否导出ipa 18 | #$18 应用名字 19 | 20 | echo "Main.sh脚本执行log" 21 | custom_sdk_path=$2 22 | export_path=$3 #export path 23 | product_name=$4 24 | json_path=$5 25 | unity_proj_path=$6 26 | xcode_proj_name=$7 27 | debug_team_id=$8 28 | debug_provisioning_profile=$9 29 | release_provisioning_profile=${11} 30 | release_team_id=${10} 31 | main_bundle_res_path=${12} 32 | bundleIdentifier=${13} 33 | is_release=${14} 34 | pack_folder_path=${15} 35 | sdk_folder_path=${16} 36 | is_export_ipa=${17} 37 | app_name=${18} 38 | 39 | provisioning_profile=${debug_provisioning_profile} 40 | team_id=${debug_team_id} 41 | configuration="Debug" 42 | method="development" 43 | signingCertificate='iPhone Developer' 44 | current_time=`date "+%Y%m%d%H%M%S"` 45 | 46 | xcode_proj_path=${export_path}"/"${xcode_proj_name}"-"${product_name} 47 | 48 | ruby -w $1 ${custom_sdk_path} ${export_path} ${product_name} ${json_path} ${unity_proj_path} ${xcode_proj_name} ${sdk_folder_path} ${is_release} ${app_name} 49 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/Libs/Xcodeproj/lib/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/atomos.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'atomos/version' 4 | 5 | module Atomos 6 | module_function 7 | 8 | # rubocop:disable Metrics/MethodLength 9 | def atomic_write(dest, contents = nil, tmpdir: nil, &block) 10 | unless contents.nil? ^ block.nil? 11 | raise ArgumentError, 'must provide either contents or a block' 12 | end 13 | 14 | tmpdir = Atomos.default_tmpdir_for_file(dest, tmpdir) 15 | 16 | require 'tempfile' 17 | Tempfile.open(".atomos.#{File.basename(dest)}", tmpdir) do |tmpfile| 18 | if contents 19 | tmpfile << contents 20 | else 21 | retval = yield tmpfile 22 | end 23 | 24 | tmpfile.close 25 | 26 | File.rename(tmpfile.path, dest) 27 | 28 | retval 29 | end 30 | end 31 | # rubocop:enable Metrics/MethodLength 32 | 33 | def self.default_tmpdir_for_file(dest, tmpdir) 34 | tmpdir ||= begin 35 | require 'tmpdir' 36 | Dir.tmpdir 37 | end 38 | 39 | # Ensure the destination is on the same device as tmpdir 40 | if File.stat(tmpdir).dev != File.stat(File.dirname(dest)).dev 41 | # If not, use the directory of the destination as the tmpdir. 42 | tmpdir = File.dirname(dest) 43 | end 44 | 45 | tmpdir 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/atomos/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Atomos 4 | VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)) 5 | end 6 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | # The mods of interest are {CLAide::ARGV}, {CLAide::Command}, and 4 | # {CLAide::InformativeError} 5 | # 6 | module CLAide 7 | # @return [String] 8 | # 9 | # CLAide’s version, following [semver](http://semver.org). 10 | # 11 | VERSION = '1.0.2'.freeze 12 | 13 | require 'claide/ansi' 14 | require 'claide/argument' 15 | require 'claide/argv' 16 | require 'claide/command' 17 | require 'claide/help' 18 | require 'claide/informative_error' 19 | end 20 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/ansi/cursor.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | class ANSI 5 | # Provides support for generating escape sequences relative to the position 6 | # of the cursor and to erase parts of text. 7 | # 8 | module Cursor 9 | # @return [String] The escape sequence to set the cursor at the 10 | # given line. 11 | # 12 | # @param [Fixnum] line 13 | # The line where to place the cursor. 14 | # 15 | # @param [Fixnum] column 16 | # The column where to place the cursor. 17 | # 18 | def self.set_cursor_position(line = 0, column = 0) 19 | "\e[#{line};#{column}H" 20 | end 21 | 22 | # @return [String] The escape sequence to set the cursor at the 23 | # given line. 24 | # 25 | # @param [Fixnum] lines 26 | # The amount of lines the cursor should be moved to. 27 | # Negative values indicate up direction and positive ones 28 | # down direction. 29 | # 30 | # @param [Fixnum] columns 31 | # The amount of columns the cursor should be moved to. 32 | # Negative values indicate left direction and positive ones 33 | # right direction. 34 | # 35 | def self.move_cursor(lines, columns = 0) 36 | lines_code = lines < 0 ? 'A' : 'B' 37 | columns_code = columns > 0 ? 'C' : 'D' 38 | "\e[#{lines.abs}#{lines_code};#{columns.abs}#{columns_code}" 39 | end 40 | 41 | # @return [String] The escape sequence to save the cursor position. 42 | # 43 | def self.save_cursor_position 44 | "\e[s" 45 | end 46 | 47 | # @return [String] The escape sequence to restore the cursor to the 48 | # previously saved position. This sequence also clears all the 49 | # output after the position. 50 | # 51 | def self.restore_cursor_position 52 | "\e[u" 53 | end 54 | 55 | # @return [String] The escape sequence to erase the display. 56 | # 57 | def self.erase_display 58 | "\e[2J" 59 | end 60 | 61 | # @return [String] The escape sequence to erase a line form the 62 | # cursor position to then end. 63 | # 64 | def self.erase_line 65 | "\e[K" 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/ansi/graphics.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | class ANSI 5 | # Provides support for generating escape sequences relative to the graphic 6 | # mode. 7 | # 8 | module Graphics 9 | # @return [String] The escape sequence for a text attribute. 10 | # 11 | # @param [Symbol] key 12 | # The name of the text attribute. 13 | # 14 | def self.text_attribute(key) 15 | code = ANSI.code_for_key(key, TEXT_ATTRIBUTES) 16 | graphics_mode(code) 17 | end 18 | 19 | # @return [String] The escape sequence for a foreground color. 20 | # 21 | # @param [Symbol] key 22 | # The name of the color. 23 | # 24 | def self.foreground_color(key) 25 | code = ANSI.code_for_key(key, COLORS) + 30 26 | graphics_mode(code) 27 | end 28 | 29 | # @return [String] The escape sequence for a background color. 30 | # 31 | # @param [Symbol] key 32 | # The name of the color. 33 | # 34 | def self.background_color(key) 35 | code = ANSI.code_for_key(key, COLORS) + 40 36 | graphics_mode(code) 37 | end 38 | 39 | # @return [String] The escape sequence for a foreground color using the 40 | # xterm-256 format. 41 | # 42 | # @param [Fixnum] color 43 | # The value of the color. 44 | # 45 | def self.foreground_color_256(color) 46 | code = [38, 5, color] 47 | graphics_mode(code) 48 | end 49 | 50 | # @return [String] The escape sequence for a background color using the 51 | # xterm-256 format. 52 | # 53 | # @param [Fixnum] color 54 | # The value of the color. 55 | # 56 | def self.background_color_256(color) 57 | code = [48, 5, color] 58 | graphics_mode(code) 59 | end 60 | 61 | # @return [String] The escape sequence for a single or a list of codes. 62 | # 63 | # @param [Fixnum, Array] codes 64 | # The code(s). 65 | # 66 | def self.graphics_mode(codes) 67 | codes = Array(codes) 68 | "\e[#{codes.join(';')}m" 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/ansi/string_escaper.rb: -------------------------------------------------------------------------------- 1 | module CLAide 2 | class ANSI 3 | # Provides support to wrap strings in ANSI sequences according to the 4 | # `ANSI.disabled` setting. 5 | # 6 | class StringEscaper < String 7 | # @param [String] string The string to wrap. 8 | # 9 | def initialize(string) 10 | super 11 | end 12 | 13 | # @return [StringEscaper] Wraps a string in the given ANSI sequences, 14 | # taking care of handling existing sequences for the same 15 | # family of attributes (i.e. attributes terminated by the 16 | # same sequence). 17 | # 18 | def wrap_in_ansi_sequence(open, close) 19 | if ANSI.disabled 20 | self 21 | else 22 | gsub!(close, open) 23 | insert(0, open).insert(-1, close) 24 | end 25 | end 26 | 27 | # @return [StringEscaper] 28 | # 29 | # @param [Array] keys 30 | # One or more keys corresponding to ANSI codes to apply to the 31 | # string. 32 | # 33 | def apply(*keys) 34 | keys.flatten.each do |key| 35 | send(key) 36 | end 37 | self 38 | end 39 | 40 | ANSI::COLORS.each_key do |key| 41 | # Defines a method returns a copy of the receiver wrapped in an ANSI 42 | # sequence for each foreground color (e.g. #blue). 43 | # 44 | # The methods handle nesting of ANSI sequences. 45 | # 46 | define_method key do 47 | open = Graphics.foreground_color(key) 48 | close = ANSI::DEFAULT_FOREGROUND_COLOR 49 | wrap_in_ansi_sequence(open, close) 50 | end 51 | 52 | # Defines a method returns a copy of the receiver wrapped in an ANSI 53 | # sequence for each background color (e.g. #on_blue). 54 | # 55 | # The methods handle nesting of ANSI sequences. 56 | # 57 | define_method "on_#{key}" do 58 | open = Graphics.background_color(key) 59 | close = ANSI::DEFAULT_BACKGROUND_COLOR 60 | wrap_in_ansi_sequence(open, close) 61 | end 62 | end 63 | 64 | ANSI::TEXT_ATTRIBUTES.each_key do |key| 65 | # Defines a method returns a copy of the receiver wrapped in an ANSI 66 | # sequence for each text attribute (e.g. #bold). 67 | # 68 | # The methods handle nesting of ANSI sequences. 69 | # 70 | define_method key do 71 | open = Graphics.text_attribute(key) 72 | close_code = TEXT_DISABLE_ATTRIBUTES[key] 73 | close = Graphics.graphics_mode(close_code) 74 | wrap_in_ansi_sequence(open, close) 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/argument.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | # This class is used to represent individual arguments to present to 5 | # the command help banner 6 | # 7 | class Argument 8 | # The string used for ellipsis / repeatable arguments in the banner 9 | # 10 | ELLIPSIS = '...' 11 | 12 | # @return [Array] 13 | # List of alternate names for the parameters 14 | attr_reader :names 15 | 16 | # @return [Boolean] 17 | # Indicates if the argument is required (not optional) 18 | # 19 | attr_accessor :required 20 | alias_method :required?, :required 21 | 22 | # @return [Boolean] 23 | # Indicates if the argument is repeatable (= can appear multiple 24 | # times in the command, which is indicated by '...' in the banner) 25 | # 26 | attr_accessor :repeatable 27 | alias_method :repeatable?, :repeatable 28 | 29 | # @param [String,Array] names 30 | # List of the names of each parameter alternatives. 31 | # For convenience, if there is only one alternative for that 32 | # parameter, we can use a String instead of a 1-item Array 33 | # 34 | # @param [Boolean] required 35 | # true if the parameter is required, false if it is optional 36 | # 37 | # @param [Boolean] repeatable 38 | # If true, the argument can appear multiple times in the command. 39 | # In that case, an ellipsis will be appended after the argument 40 | # in the help banner. 41 | # 42 | # @example 43 | # 44 | # # A required parameter that can be either a NAME or URL 45 | # Argument.new(%(NAME URL), true) 46 | # 47 | def initialize(names, required, repeatable = false) 48 | @names = Array(names) 49 | @required = required 50 | @repeatable = repeatable 51 | end 52 | 53 | # @return [Boolean] true on equality 54 | # 55 | # @param [Argument] other the Argument compared against 56 | # 57 | def ==(other) 58 | other.is_a?(Argument) && 59 | names == other.names && required == other.required 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/command/argument_suggester.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | class Command 5 | class ArgumentSuggester 6 | # @param [String] argument 7 | # The unrecognized argument for which to make a suggestion. 8 | # 9 | # @param [Class] command_class 10 | # The class of the command which encountered the unrecognized 11 | # arguments. 12 | # 13 | def initialize(argument, command_class) 14 | @argument, @command_class = argument, command_class 15 | @argument_type = ARGV::Parser.argument_type(@argument) 16 | end 17 | 18 | # @return [Array] The list of the valid arguments for a command 19 | # according to the type of the argument. 20 | # 21 | def possibilities 22 | case @argument_type 23 | when :option, :flag 24 | @command_class.options.map(&:first) 25 | when :arg 26 | @command_class.subcommands_for_command_lookup.map(&:command) 27 | end 28 | end 29 | 30 | # @return [String] Returns a suggested argument from `possibilities` based 31 | # on the `levenshtein_distance` score. 32 | # 33 | def suggested_argument 34 | possibilities.sort_by do |element| 35 | self.class.levenshtein_distance(@argument, element) 36 | end.first 37 | end 38 | 39 | # @return [String] Returns a message including a suggestion for the given 40 | # suggestion. 41 | # 42 | def suggestion 43 | argument_description = @argument_type == :arg ? 'command' : 'option' 44 | if suggestion = suggested_argument 45 | pretty_suggestion = self.class.prettify_suggestion(suggestion, 46 | @argument_type) 47 | "Unknown #{argument_description}: `#{@argument}`\n" \ 48 | "Did you mean: #{pretty_suggestion}?" 49 | else 50 | "Unknown #{argument_description}: `#{@argument}`" 51 | end 52 | end 53 | 54 | # Prettifies the given validation suggestion according to the type. 55 | # 56 | # @param [String] suggestion 57 | # The suggestion to prettify. 58 | # 59 | # @param [Type] argument_type 60 | # The type of the suggestion: either `:command` or `:option`. 61 | # 62 | # @return [String] A handsome suggestion. 63 | # 64 | def self.prettify_suggestion(suggestion, argument_type) 65 | case argument_type 66 | when :option, :flag 67 | suggestion = suggestion.to_s 68 | suggestion.ansi.blue 69 | when :arg 70 | suggestion.ansi.green 71 | end 72 | end 73 | 74 | # Returns the Levenshtein distance between the given strings. 75 | # From: http://rosettacode.org/wiki/Levenshtein_distance#Ruby 76 | # 77 | # @param [String] a 78 | # The first string to compare. 79 | # 80 | # @param [String] b 81 | # The second string to compare. 82 | # 83 | # @return [Fixnum] The distance between the strings. 84 | def self.levenshtein_distance(a, b) 85 | a, b = a.downcase, b.downcase 86 | costs = Array(0..b.length) 87 | (1..a.length).each do |i| 88 | costs[0], nw = i, i - 1 89 | (1..b.length).each do |j| 90 | costs[j], nw = [ 91 | costs[j] + 1, costs[j - 1] + 1, a[i - 1] == b[j - 1] ? nw : nw + 1 92 | ].min, costs[j] 93 | end 94 | end 95 | costs[b.length] 96 | end 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/help.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | require 'claide/informative_error' 5 | 6 | # The exception class that is raised to indicate a help banner should be 7 | # shown while running {Command.run}. 8 | # 9 | class Help < StandardError 10 | include InformativeError 11 | 12 | # @return [String] The banner containing the usage instructions of the 13 | # command to show in the help. 14 | # 15 | attr_reader :banner 16 | 17 | # @return [String] An optional error message that will be shown before the 18 | # help banner. 19 | # 20 | attr_reader :error_message 21 | 22 | # @param [String] banner @see banner 23 | # @param [String] error_message @see error_message 24 | # 25 | # @note If an error message is provided, the exit status, used to 26 | # terminate the program with, will be set to `1`, otherwise a {Help} 27 | # exception is treated as not being a real error and exits with `0`. 28 | # 29 | def initialize(banner, error_message = nil) 30 | @banner = banner 31 | @error_message = error_message 32 | @exit_status = @error_message.nil? ? 0 : 1 33 | end 34 | 35 | # @return [String] The optional error message, colored in red if 36 | # {Command.ansi_output} is set to `true`. 37 | # 38 | def formatted_error_message 39 | if error_message 40 | message = "[!] #{error_message}" 41 | prettify_error_message(message) 42 | end 43 | end 44 | 45 | # @return [String] 46 | # 47 | def prettify_error_message(message) 48 | message.ansi.red 49 | end 50 | 51 | # @return [String] The optional error message, combined with the help 52 | # banner of the command. 53 | # 54 | def message 55 | [formatted_error_message, banner].compact.join("\n\n") 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/claide/informative_error.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module CLAide 4 | # Including this module into an exception class will ensure that when raised, 5 | # while running {Command.run}, only the message of the exception will be 6 | # shown to the user. Unless disabled with the `--verbose` flag. 7 | # 8 | # In addition, the message will be colored red, if {Command.ansi_output} 9 | # is set to `true`. 10 | # 11 | module InformativeError 12 | # @return [Numeric] The exist status code that should be used to terminate 13 | # the program with. Defaults to `1`. 14 | # 15 | attr_writer :exit_status 16 | 17 | def exit_status 18 | @exit_status ||= 1 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2.rb: -------------------------------------------------------------------------------- 1 | require 'colored2/codes' 2 | require 'colored2/ascii_decorator' 3 | 4 | module Colored2 5 | def self.decorate(a_class) 6 | a_class.send(:include, Colored2) 7 | end 8 | 9 | def self.included(from_class) 10 | from_class.class_eval do 11 | 12 | def surround_with_color(color: nil, effect: nil, color_self: nil, string: nil, &block) 13 | color_type = if Colored2.background_next? && effect.nil? 14 | Colored2.foreground_next! 15 | :background 16 | else 17 | :foreground 18 | end 19 | 20 | opts = {} 21 | opts.merge!(color_type => color) if color 22 | opts.merge!(effect: effect) if effect 23 | 24 | if color_self then 25 | opts.merge!( beginning: :on, end: :off) 26 | colored = Colored2::AsciiDecorator.new(self).decorate(opts) 27 | if string || block 28 | arg = "#{string}#{block.call if block}" 29 | colored << Colored2::AsciiDecorator.new(arg).decorate(opts) if arg.length > 0 30 | end 31 | else 32 | opts.merge!( end: :on ) 33 | colored = Colored2::AsciiDecorator.new(self).decorate(opts) 34 | if string || block 35 | arg = "#{string}#{block.call if block}" 36 | colored << Colored2::AsciiDecorator.new(arg).decorate(opts.merge(end: :off)) if arg.length > 0 37 | end 38 | end 39 | colored 40 | end 41 | 42 | def on 43 | Colored2.background_next! 44 | self 45 | end 46 | end 47 | 48 | from_class.instance_eval do 49 | COLORS.keys.each do |color| 50 | define_method(color) do |string = nil, &block| 51 | surround_with_color(color: color, color_self: true, string: string, &block) 52 | end 53 | 54 | define_method("#{color}!".to_sym) do |string = nil, &block| 55 | surround_with_color(color: color, color_self: false, string: string, &block) 56 | end 57 | end 58 | 59 | EFFECTS.keys.each do |effect| 60 | next if effect == 'no_color' 61 | define_method(effect) do |string = nil, &block| 62 | surround_with_color(effect: effect, color_self: true, string: string, &block) 63 | end 64 | 65 | define_method("#{effect}!".to_sym) do |string = nil, &block| 66 | surround_with_color(effect: effect, color_self: false, string: string, &block) 67 | end 68 | end 69 | 70 | define_method(:to_eol) do 71 | tmp = sub(/^(\e\[[\[\e0-9;m]+m)/, "\\1\e[2K") 72 | if tmp == self 73 | return "\e[2K" << self 74 | end 75 | tmp 76 | end 77 | 78 | define_method(:to_bol) do 79 | "#{self}\033[#{length}D\033[0D" 80 | end 81 | end 82 | end 83 | end 84 | 85 | require 'colored2/strings' 86 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/ascii_decorator.rb: -------------------------------------------------------------------------------- 1 | require 'colored2/codes' 2 | require 'forwardable' 3 | 4 | module Colored2 5 | def self.enable! 6 | Colored2::AsciiDecorator.enable! 7 | end 8 | def self.disable! 9 | Colored2::AsciiDecorator.disable! 10 | end 11 | def self.background_next! 12 | Colored2::AsciiDecorator.background_next! 13 | end 14 | def self.foreground_next! 15 | Colored2::AsciiDecorator.foreground_next! 16 | end 17 | def self.background_next? 18 | Colored2::AsciiDecorator.background_next? 19 | end 20 | 21 | class AsciiDecorator 22 | @__background_next = false 23 | @__colors_disabled = false 24 | class << self 25 | attr_accessor :__background_next, :__colors_disabled 26 | def enable! 27 | self.__colors_disabled = false 28 | end 29 | def enabled? 30 | !self.__colors_disabled 31 | end 32 | def disable! 33 | self.__colors_disabled = true 34 | end 35 | def background_next! 36 | self.__background_next = true 37 | end 38 | def foreground_next! 39 | self.__background_next = false 40 | end 41 | def background_next? 42 | self.__background_next 43 | end 44 | end 45 | 46 | extend Forwardable 47 | def_delegators :@my_class, :enable!, :disable! 48 | 49 | attr_accessor :string, :my_class 50 | 51 | def initialize(a_string) 52 | self.string = a_string.instance_of?(Object) ? '' : a_string.to_s 53 | self.my_class = self.class 54 | end 55 | 56 | # options[:start] = :color 57 | # options[:end] = :color | :no_color 58 | def decorate(options = {}) 59 | return string if !self.class.enabled? || string.length == 0 60 | escape_sequence = [ 61 | Colored2::TextColor.new(options[:foreground]), 62 | Colored2::BackgroundColor.new(options[:background]), 63 | Colored2::Effect.new(options[:effect]) 64 | ].compact.join 65 | 66 | colored = '' 67 | colored << escape_sequence if options[:beginning] == :on 68 | colored << string 69 | if options[:end] 70 | colored << no_color if options[:end] == :off && !colored.end_with?(no_color) 71 | colored << escape_sequence if options[:end] == :on 72 | end 73 | colored 74 | end 75 | 76 | def un_decorate 77 | string.gsub(%r{\e\[\d+(;\d+)*m}, '') 78 | end 79 | 80 | private 81 | 82 | def no_color 83 | @no_color ||= Colored2::Effect.new(:no_color).to_s 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/codes.rb: -------------------------------------------------------------------------------- 1 | module Colored2 2 | 3 | COLORS = { 4 | black: 30, 5 | red: 31, 6 | green: 32, 7 | yellow: 33, 8 | blue: 34, 9 | magenta: 35, 10 | cyan: 36, 11 | white: 37 12 | } 13 | 14 | EFFECTS = { 15 | no_color: 0, 16 | bold: 1, 17 | dark: 2, 18 | italic: 3, 19 | underlined: 4, 20 | reversed: 7, 21 | plain: 21, # non-bold 22 | normal: 22 23 | } 24 | 25 | class Code 26 | attr_accessor :name, :escape 27 | def initialize(name) 28 | @name = name 29 | return if name.nil? 30 | @escape = codes[name.to_sym] 31 | raise ArgumentError.new("No color or effect named #{name} exists for #{self.class}.") if @escape.nil? 32 | end 33 | 34 | def value(shift = nil) 35 | escape_code = escape 36 | escape_code += shift if shift && escape_code 37 | name && escape ? "\e[#{escape_code}m" : '' 38 | end 39 | 40 | def to_s 41 | value 42 | end 43 | end 44 | 45 | class Effect < Code 46 | def codes 47 | EFFECTS 48 | end 49 | end 50 | 51 | class TextColor < Code 52 | def codes 53 | COLORS 54 | end 55 | end 56 | 57 | class BackgroundColor < TextColor 58 | def value 59 | super 10 60 | end 61 | end 62 | 63 | end 64 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/numbers.rb: -------------------------------------------------------------------------------- 1 | require 'colored2' unless defined?(Colored2) && Colored2.respond_to?(:decorate) 2 | 3 | module Colored2 4 | def self.integer_class 5 | major, minor = RUBY_VERSION.split(/\./).map(&:to_i) 6 | major >= 2 && minor >= 4 ? Integer : Kernel.const_get(:Fixnum) 7 | end 8 | end 9 | 10 | Colored2.decorate(Colored2.integer_class) 11 | Colored2.decorate(Float) 12 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/object.rb: -------------------------------------------------------------------------------- 1 | require 'colored2' unless defined?(Colored2) && Colored2.respond_to?(:decorate) 2 | Colored2.decorate(Object) 3 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/strings.rb: -------------------------------------------------------------------------------- 1 | require 'colored2' unless defined?(Colored2) && Colored2.respond_to?(:decorate) 2 | Colored2.decorate(String) 3 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/colored2/version.rb: -------------------------------------------------------------------------------- 1 | module Colored2 2 | VERSION = '3.1.2' 3 | end 4 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo.rb: -------------------------------------------------------------------------------- 1 | require 'nanaimo/version' 2 | 3 | # A native Ruby implementation of ASCII plist parsing and serialization. 4 | # 5 | module Nanaimo 6 | class Error < StandardError; end 7 | 8 | DEBUG = !ENV['NANAIMO_DEBUG'].nil? 9 | private_constant :DEBUG 10 | def self.debug 11 | return unless DEBUG 12 | warn yield 13 | end 14 | 15 | require 'nanaimo/object' 16 | require 'nanaimo/plist' 17 | require 'nanaimo/reader' 18 | require 'nanaimo/unicode' 19 | require 'nanaimo/writer' 20 | end 21 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/object.rb: -------------------------------------------------------------------------------- 1 | module Nanaimo 2 | # An object that belongs to a plist. 3 | # 4 | class Object 5 | # @return The underlying native Ruby value 6 | # 7 | attr_accessor :value 8 | 9 | # @return [String] The annotation comment 10 | # 11 | attr_accessor :annotation 12 | 13 | def initialize(value, annotation) 14 | self.value = value 15 | self.annotation = annotation 16 | 17 | raise 'Item cannot be initialize with a nil value' if value.nil? 18 | end 19 | 20 | def ==(other) 21 | return unless other 22 | if other.is_a?(self.class) 23 | other.value == value && annotation == other.annotation 24 | elsif other.is_a?(value.class) 25 | other == value 26 | end 27 | end 28 | alias eql? == 29 | 30 | def hash 31 | value.hash 32 | end 33 | 34 | def <=>(other) 35 | other_value = if other.is_a?(Object) 36 | other.value 37 | elsif other.is_a?(value.class) 38 | other 39 | end 40 | return unless other_value 41 | 42 | value <=> other_value 43 | end 44 | 45 | def to_s 46 | format('<%s %s>', self.class, value) 47 | end 48 | 49 | # @return A native Ruby object representation 50 | # 51 | def as_ruby 52 | raise 'unimplemented' 53 | end 54 | end 55 | 56 | # A string object in a Plist. 57 | # 58 | class String < Object 59 | def as_ruby 60 | value 61 | end 62 | end 63 | 64 | # A string object surrounded by quotes in a Plist. 65 | # 66 | class QuotedString < Object 67 | def as_ruby 68 | value 69 | end 70 | end 71 | 72 | # A data object in a Plist, represented by a binary-encoded string. 73 | # 74 | class Data < Object 75 | def initialize(value, annotation) 76 | value &&= value.force_encoding(Encoding::BINARY) 77 | super(value, annotation) 78 | end 79 | 80 | def as_ruby 81 | value 82 | end 83 | end 84 | 85 | # An array object in a Plist. 86 | # 87 | class Array < Object 88 | def as_ruby 89 | value.map(&:as_ruby) 90 | end 91 | end 92 | 93 | # A dictionary object in a Plist. 94 | # 95 | class Dictionary < Object 96 | def as_ruby 97 | Hash[value.map { |k, v| [k.as_ruby, v.as_ruby] }] 98 | end 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/plist.rb: -------------------------------------------------------------------------------- 1 | module Nanaimo 2 | # A Plist. 3 | # 4 | class Plist 5 | # @return [Nanaimo::Object] The root level object in the plist. 6 | # 7 | attr_accessor :root_object 8 | 9 | # @return [String] The encoding of the plist. 10 | # 11 | attr_accessor :file_type 12 | 13 | def initialize(root_object = nil, file_type = nil) 14 | @root_object = root_object 15 | @file_type = file_type 16 | end 17 | 18 | def ==(other) 19 | return unless other.is_a?(Nanaimo::Plist) 20 | file_type == other.file_type && root_object == other.root_object 21 | end 22 | 23 | def hash 24 | root_object.hash 25 | end 26 | 27 | # @return A native Ruby object representation of the plist. 28 | # 29 | def as_ruby 30 | root_object.as_ruby 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/unicode.rb: -------------------------------------------------------------------------------- 1 | # frozen-string-literal: true 2 | require 'nanaimo/unicode/next_step_mapping' 3 | require 'nanaimo/unicode/quote_maps' 4 | module Nanaimo 5 | # @!visibility private 6 | # 7 | module Unicode 8 | class UnsupportedEscapeSequenceError < Error; end 9 | class InvalidEscapeSequenceError < Error; end 10 | 11 | module_function 12 | 13 | def quotify_string(string) 14 | string.gsub(QUOTE_REGEXP, QUOTE_MAP) 15 | end 16 | 17 | ESCAPE_PREFIXES = %W( 18 | 0 1 2 3 4 5 6 7 a b f n r t v \n U \\ 19 | ).freeze 20 | 21 | OCTAL_DIGITS = (0..7).map(&:to_s).freeze 22 | 23 | # Credit to Samantha Marshall 24 | # Taken from https://github.com/samdmarshall/pbPlist/blob/346c29f91f913d35d0e24f6722ec19edb24e5707/pbPlist/StrParse.py#L197 25 | # Licensed under https://raw.githubusercontent.com/samdmarshall/pbPlist/blob/346c29f91f913d35d0e24f6722ec19edb24e5707/LICENSE 26 | # 27 | # Originally from: http://www.opensource.apple.com/source/CF/CF-744.19/CFOldStylePList.c See `getSlashedChar()` 28 | def unquotify_string(string) 29 | formatted_string = ::String.new 30 | extracted_string = string 31 | string_length = string.size 32 | index = 0 33 | while index < string_length 34 | if escape_index = extracted_string.index('\\', index) 35 | formatted_string << extracted_string[index...escape_index] unless index == escape_index 36 | index = escape_index + 1 37 | next_char = extracted_string[index] 38 | if ESCAPE_PREFIXES.include?(next_char) 39 | index += 1 40 | if unquoted = UNQUOTE_MAP[next_char] 41 | formatted_string << unquoted 42 | elsif next_char == 'U' 43 | length = 4 44 | unicode_numbers = extracted_string[index, length] 45 | unless unicode_numbers =~ /\A\h{4}\z/ 46 | raise InvalidEscapeSequenceError, "Unicode '\\U' escape sequence terminated without 4 following hex characters" 47 | end 48 | index += length 49 | formatted_string << [unicode_numbers.to_i(16)].pack('U') 50 | elsif OCTAL_DIGITS.include?(next_char) # https://twitter.com/Catfish_Man/status/658014170055507968 51 | octal_string = extracted_string[index - 1, 3] 52 | if octal_string =~ /\A[0-7]{3}\z/ 53 | index += 2 54 | code_point = octal_string.to_i(8) 55 | unless code_point <= 0x80 || converted = NEXT_STEP_MAPPING[code_point] 56 | raise InvalidEscapeSequenceError, "Invalid octal escape sequence #{octal_string}" 57 | end 58 | formatted_string << [converted].pack('U') 59 | else 60 | formatted_string << next_char 61 | end 62 | else 63 | raise UnsupportedEscapeSequenceError, "Failed to handle #{next_char} which is in the list of possible escapes" 64 | end 65 | else 66 | index += 1 67 | formatted_string << next_char 68 | end 69 | else 70 | formatted_string << extracted_string[index..-1] 71 | index = string_length 72 | end 73 | end 74 | formatted_string 75 | end 76 | 77 | XML_STRING_ESCAPES = { 78 | '&' => '&', 79 | '<' => '<', 80 | '>' => '>' 81 | }.freeze 82 | XML_STRING_ESCAPE_REGEXP = Regexp.union(XML_STRING_ESCAPES.keys) 83 | 84 | def xml_escape_string(string) 85 | string.to_s.gsub(XML_STRING_ESCAPE_REGEXP, XML_STRING_ESCAPES) 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/unicode/quote_maps.rb: -------------------------------------------------------------------------------- 1 | # frozen-string-literal: true 2 | module Nanaimo 3 | module Unicode 4 | QUOTE_MAP = { 5 | "\a" => "\\a", 6 | "\b" => "\\b", 7 | "\f" => "\\f", 8 | "\r" => "\\r", 9 | "\t" => "\\t", 10 | "\v" => "\\v", 11 | "\n" => "\\n", 12 | "\"" => "\\\"", 13 | "\\" => "\\\\", 14 | "\x00" => "\\U0000", 15 | "\x01" => "\\U0001", 16 | "\x02" => "\\U0002", 17 | "\x03" => "\\U0003", 18 | "\x04" => "\\U0004", 19 | "\x05" => "\\U0005", 20 | "\x06" => "\\U0006", 21 | "\x0E" => "\\U000e", 22 | "\x0F" => "\\U000f", 23 | "\x10" => "\\U0010", 24 | "\x11" => "\\U0011", 25 | "\x12" => "\\U0012", 26 | "\x13" => "\\U0013", 27 | "\x14" => "\\U0014", 28 | "\x15" => "\\U0015", 29 | "\x16" => "\\U0016", 30 | "\x17" => "\\U0017", 31 | "\x18" => "\\U0018", 32 | "\x19" => "\\U0019", 33 | "\x1A" => "\\U001a", 34 | "\e" => "\\U001b", 35 | "\x1C" => "\\U001c", 36 | "\x1D" => "\\U001d", 37 | "\x1E" => "\\U001e", 38 | "\x1F" => "\\U001f", 39 | }.freeze 40 | 41 | UNQUOTE_MAP = { 42 | "\n" => "\n", 43 | "a" => "\a", 44 | "b" => "\b", 45 | "f" => "\f", 46 | "r" => "\r", 47 | "t" => "\t", 48 | "v" => "\v", 49 | "n" => "\n", 50 | "'" => "'", 51 | "\"" => "\"", 52 | "\\" => "\\", 53 | }.freeze 54 | 55 | QUOTE_REGEXP = /\x07|\x08|\f|\r|\t|\v|\n|"|\\|\x00|\x01|\x02|\x03|\x04|\x05|\x06|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F/ 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/version.rb: -------------------------------------------------------------------------------- 1 | module Nanaimo 2 | VERSION = '0.2.3'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/writer/pbxproj.rb: -------------------------------------------------------------------------------- 1 | module Nanaimo 2 | class Writer 3 | # Transforms native ruby objects or Plist objects into their ASCII Plist 4 | # string representation, formatted as Xcode writes Xcode projects. 5 | # 6 | class PBXProjWriter < Writer 7 | ISA = String.new('isa', '') 8 | private_constant :ISA 9 | 10 | def initialize(*) 11 | super 12 | @objects_section = false 13 | end 14 | 15 | private 16 | 17 | def write_dictionary(object) 18 | n = newlines 19 | @newlines = false if flat_dictionary?(object) 20 | return super(sort_dictionary(object)) unless @objects_section 21 | @objects_section = false 22 | write_dictionary_start 23 | value = value_for(object) 24 | objects_by_isa = value.group_by { |_k, v| isa_for(v) } 25 | objects_by_isa.each do |isa, kvs| 26 | write_newline 27 | output << "/* Begin #{isa} section */" 28 | write_newline 29 | sort_dictionary(kvs).each do |k, v| 30 | write_dictionary_key_value_pair(k, v) 31 | end 32 | output << "/* End #{isa} section */" 33 | write_newline 34 | end 35 | write_dictionary_end 36 | ensure 37 | @newlines = n 38 | end 39 | 40 | def write_dictionary_key_value_pair(k, v) 41 | @objects_section = true if value_for(k) == 'objects' 42 | super 43 | end 44 | 45 | def sort_dictionary(dictionary) 46 | hash = value_for(dictionary) 47 | hash.to_a.sort do |(k1, v1), (k2, v2)| 48 | v2_isa = isa_for(v2) 49 | v1_isa = v2_isa && isa_for(v1) 50 | comp = v1_isa <=> v2_isa 51 | next comp if !comp.zero? && v1_isa 52 | 53 | key1 = value_for(k1) 54 | key2 = value_for(k2) 55 | next -1 if key1 == 'isa' 56 | next 1 if key2 == 'isa' 57 | key1 <=> key2 58 | end 59 | end 60 | 61 | def isa_for(dictionary) 62 | dictionary = value_for(dictionary) 63 | return unless dictionary.is_a?(Hash) 64 | isa = dictionary.values_at('isa', ISA).map(&method(:value_for)).compact.first 65 | isa && value_for(isa) 66 | end 67 | 68 | def flat_dictionary?(dictionary) 69 | case isa_for(dictionary) 70 | when 'PBXBuildFile', 'PBXFileReference' 71 | true 72 | else 73 | false 74 | end 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/nanaimo/writer/xml.rb: -------------------------------------------------------------------------------- 1 | module Nanaimo 2 | class Writer 3 | # Transforms native ruby objects or Plist objects into their XML Plist 4 | # string representation. 5 | # 6 | class XMLWriter < Writer 7 | autoload :Base64, 'base64' 8 | autoload :Date, 'date' 9 | autoload :DateTime, 'date' 10 | 11 | def write 12 | write_xml_header 13 | write_object(@plist.root_object) 14 | write_newline 15 | write_xml_footer 16 | end 17 | 18 | private 19 | 20 | def plist_format 21 | :xml 22 | end 23 | 24 | def write_object(object) 25 | case object 26 | when Float, Integer 27 | write_number(object) 28 | when Time, Date, DateTime 29 | write_date(object) 30 | when true, false 31 | write_boolean(object) 32 | else 33 | super 34 | end 35 | end 36 | 37 | def write_xml_header 38 | output << <<-EOS 39 | 40 | 41 | 42 | EOS 43 | end 44 | 45 | def write_xml_footer 46 | output << <<-EOS 47 | 48 | EOS 49 | end 50 | 51 | def write_annotation(_) 52 | end 53 | 54 | def write_number(object) 55 | type = object.integer? ? 'integer' : 'real' 56 | output << "<#{type}>#{object}" 57 | end 58 | 59 | def write_boolean(object) 60 | output << "<#{object}/>" 61 | end 62 | 63 | def write_date(object) 64 | output << '' << object.iso8601 << '' 65 | end 66 | 67 | def write_string(object) 68 | output << '' << Unicode.xml_escape_string(value_for(object)) << '' 69 | end 70 | 71 | def write_quoted_string(object) 72 | write_string(object) 73 | end 74 | 75 | def write_data(object) 76 | output << '' 77 | data = Base64.encode64(value_for(object)).delete("\n") 78 | data = data.scan(/.{1,76}/).join("\n") if pretty 79 | output << data << '' 80 | end 81 | 82 | def write_array(object) 83 | return output << '' if value_for(object).empty? 84 | super 85 | end 86 | 87 | def write_array_start 88 | output << '' 89 | write_newline if newlines 90 | push_indent! 91 | end 92 | 93 | def write_array_end 94 | pop_indent! 95 | write_indent 96 | output << '' 97 | end 98 | 99 | def write_array_element(object) 100 | write_indent 101 | write_object(object) 102 | write_newline 103 | end 104 | 105 | def write_dictionary(object) 106 | object = value_for(object) 107 | return output << '' if object.empty? 108 | keys = object.keys.sort_by(&:to_s) 109 | object = keys.each_with_object({}) do |key, hash| 110 | hash[key.to_s] = object[key] 111 | end 112 | super(object) 113 | end 114 | 115 | def write_dictionary_start 116 | output << '' 117 | write_newline if newlines 118 | push_indent! 119 | end 120 | 121 | def write_dictionary_end 122 | pop_indent! 123 | write_indent 124 | output << '' 125 | end 126 | 127 | def write_dictionary_key_value_pair(key, value) 128 | write_indent 129 | output << '' << Unicode.xml_escape_string(value_for(key)) << '' 130 | write_newline 131 | write_indent 132 | write_object(value) 133 | write_newline 134 | end 135 | end 136 | end 137 | end 138 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | require 'pathname' 3 | require 'claide' 4 | require 'colored2' 5 | 6 | class PlainInformative < StandardError 7 | include CLAide::InformativeError 8 | end 9 | 10 | class Informative < PlainInformative 11 | def message 12 | super !~ /\[!\]/ ? "[!] #{super}\n".red : super 13 | end 14 | end 15 | 16 | require 'xcodeproj/gem_version' 17 | require 'xcodeproj/user_interface' 18 | 19 | autoload :Command, 'xcodeproj/command' 20 | autoload :Config, 'xcodeproj/config' 21 | autoload :Constants, 'xcodeproj/constants' 22 | autoload :Differ, 'xcodeproj/differ' 23 | autoload :Helper, 'xcodeproj/helper' 24 | autoload :Plist, 'xcodeproj/plist' 25 | autoload :Project, 'xcodeproj/project' 26 | autoload :Workspace, 'xcodeproj/workspace' 27 | autoload :XCScheme, 'xcodeproj/scheme' 28 | autoload :XcodebuildHelper, 'xcodeproj/xcodebuild_helper' 29 | end 30 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | require 'colored2' 3 | require 'claide' 4 | 5 | class Command < CLAide::Command 6 | require 'xcodeproj/command/config_dump' 7 | require 'xcodeproj/command/target_diff' 8 | require 'xcodeproj/command/project_diff' 9 | require 'xcodeproj/command/show' 10 | require 'xcodeproj/command/sort' 11 | 12 | self.abstract_command = true 13 | self.command = 'xcodeproj' 14 | self.version = VERSION 15 | self.description = 'Xcodeproj lets you create and modify Xcode projects from Ruby.' 16 | self.plugin_prefixes = %w(claide xcodeproj) 17 | 18 | def initialize(argv) 19 | super 20 | unless self.ansi_output? 21 | Colored2.disable! 22 | String.send(:define_method, :colorize) { |string, _| string } 23 | end 24 | end 25 | 26 | private 27 | 28 | def xcodeproj_path 29 | unless @xcodeproj_path 30 | projects = Dir.glob('*.xcodeproj') 31 | if projects.size == 1 32 | xcodeproj_path = projects.first 33 | elsif projects.size > 1 34 | raise Informative, 'There are more than one Xcode project documents ' \ 35 | 'in the current working directory. Please specify ' \ 36 | 'which to use with the `--project` option.' 37 | else 38 | raise Informative, 'No Xcode project document found in the current ' \ 39 | 'working directory. Please specify which to use ' \ 40 | 'with the `--project` option.' 41 | end 42 | @xcodeproj_path = Pathname.new(xcodeproj_path).expand_path 43 | end 44 | @xcodeproj_path 45 | end 46 | 47 | def open_project!(*paths) 48 | if paths.empty? 49 | [xcodeproj] 50 | else 51 | paths.map { |path| Project.open(path) } 52 | end 53 | end 54 | 55 | def xcodeproj_path=(path) 56 | @xcodeproj_path = path && Pathname.new(path).expand_path 57 | end 58 | 59 | def xcodeproj 60 | @xcodeproj ||= Project.open(xcodeproj_path) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command/config_dump.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Command 3 | class ConfigDump < Command 4 | self.description = <<-eos 5 | Dumps the build settings of all project targets for all configurations in 6 | directories named by the target in given output directory. 7 | 8 | It extracts common build settings in a per target base.xcconfig file. 9 | 10 | If no `PROJECT` is specified then the current work directory is searched 11 | for one. 12 | 13 | If no `OUTPUT` is specified then the project directory will be used. 14 | eos 15 | 16 | self.summary = 'Dumps the build settings of all project targets for ' \ 17 | 'all configurations in directories named by the target ' \ 18 | 'in the given output directory.' 19 | 20 | self.arguments = [ 21 | CLAide::Argument.new('PROJECT', false), 22 | CLAide::Argument.new('OUTPUT', false), 23 | ] 24 | 25 | def initialize(argv) 26 | self.xcodeproj_path = argv.shift_argument 27 | @output_path = Pathname(argv.shift_argument || '.') 28 | 29 | super 30 | end 31 | 32 | def validate! 33 | super 34 | 35 | raise Informative, 'The output path must be a directory.' unless @output_path.directory? 36 | open_project! 37 | end 38 | 39 | def run 40 | dump_all_configs(xcodeproj, 'Project') 41 | 42 | xcodeproj.targets.each do |target| 43 | dump_all_configs(target, target.name) 44 | end 45 | end 46 | 47 | def dump_all_configs(configurable, name) 48 | path = Pathname(name) 49 | 50 | # Dump base configuration to file 51 | base_settings = extract_common_settings!(configurable.build_configurations) 52 | base_file_path = path + "#{name}_base.xcconfig" 53 | dump_config_to_file(base_settings, base_file_path) 54 | 55 | # Dump each configuration to file 56 | configurable.build_configurations.each do |config| 57 | settings = config.build_settings 58 | dump_config_to_file(settings, path + "#{name}_#{config.name.downcase}.xcconfig", [base_file_path]) 59 | end 60 | end 61 | 62 | def extract_common_settings!(build_configurations) 63 | # Grasp all common build settings 64 | all_build_settings = build_configurations.map(&:build_settings) 65 | common_build_settings = all_build_settings.reduce do |settings, config_build_settings| 66 | settings.select { |key, value| value == config_build_settings[key] } 67 | end 68 | 69 | # Remove all common build settings from each configuration specific build settings 70 | build_configurations.each do |config| 71 | config.build_settings.reject! { |key| !common_build_settings[key].nil? } 72 | end 73 | 74 | common_build_settings 75 | end 76 | 77 | def dump_config_to_file(settings, file_path, includes = []) 78 | dir = @output_path + file_path + '..' 79 | dir.mkpath 80 | 81 | settings = Hash[settings.map do |k, v| 82 | [k, Array(v).join(' ')] 83 | end] 84 | 85 | config = Config.new(settings) 86 | config.includes = includes 87 | config.save_as(@output_path + file_path) 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command/project_diff.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Command 3 | class ProjectDiff < Command 4 | self.summary = 'Shows the difference between two projects' 5 | 6 | self.description = summary + <<-EOS.gsub(/ {8}/, '') 7 | 8 | It shows the difference in a UUID agnostic fashion. 9 | 10 | To reduce the noise (and to simplify implementation) differences in the 11 | order of arrays are ignored. 12 | EOS 13 | 14 | def self.options 15 | [ 16 | ['--ignore=KEY', 'A key to ignore in the comparison. Can be specified multiple times.'], 17 | ].concat(super) 18 | end 19 | 20 | self.arguments = [ 21 | CLAide::Argument.new('PROJECT1', true), 22 | CLAide::Argument.new('PROJECT2', true), 23 | ] 24 | 25 | def initialize(argv) 26 | @path_project1 = argv.shift_argument 27 | @path_project2 = argv.shift_argument 28 | @keys_to_ignore = argv.all_options('ignore') 29 | super 30 | end 31 | 32 | def validate! 33 | super 34 | @project1, @project2 = open_project!(@path_project1, @path_project2) 35 | end 36 | 37 | def run 38 | hash_1 = @project1.to_tree_hash.dup 39 | hash_2 = @project2.to_tree_hash.dup 40 | @keys_to_ignore.each do |key| 41 | Differ.clean_hash!(hash_1, key) 42 | Differ.clean_hash!(hash_2, key) 43 | end 44 | 45 | diff = Differ.project_diff(hash_1, hash_2, @path_project1, @path_project2) 46 | 47 | require 'yaml' 48 | yaml = diff.to_yaml 49 | yaml.gsub!(@path_project1, @path_project1.cyan) 50 | yaml.gsub!(@path_project2, @path_project2.magenta) 51 | yaml.gsub!(':diff:', 'diff:'.yellow) 52 | puts yaml 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command/show.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Command 3 | class Show < Command 4 | self.summary = 'Shows an overview of a project in a YAML representation.' 5 | 6 | def self.options 7 | [ 8 | ['--format=[hash|tree_hash|raw]', 'YAML output format'], 9 | ].concat(super) 10 | end 11 | 12 | self.arguments = [ 13 | CLAide::Argument.new('PROJECT', false), 14 | ] 15 | 16 | def initialize(argv) 17 | self.xcodeproj_path = argv.shift_argument 18 | @output_format = argv.option('format') 19 | @output_format &&= @output_format.to_sym 20 | super 21 | end 22 | 23 | def validate 24 | super 25 | unless [nil, :hash, :tree_hash, :raw].include?(@output_format) 26 | help! "Unknown format `#{@output_format}`" 27 | end 28 | open_project! 29 | end 30 | 31 | def run 32 | require 'yaml' 33 | 34 | if @output_format 35 | case @output_format 36 | when :hash 37 | puts xcodeproj.to_hash.to_yaml 38 | when :tree_hash 39 | puts xcodeproj.to_tree_hash.to_yaml 40 | when :raw 41 | puts xcodeproj.to_yaml 42 | end 43 | return 44 | end 45 | 46 | pretty_print = xcodeproj.pretty_print 47 | sections = [] 48 | pretty_print.each do |key, value| 49 | section = key.green 50 | yaml = value.to_yaml 51 | yaml.gsub!(/^---$/, '') 52 | yaml.gsub!(/^-/, "\n-") 53 | yaml.prepend(section) 54 | sections << yaml 55 | end 56 | puts sections * "\n\n" 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command/sort.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Command 3 | class Sort < Command 4 | self.description = <<-eos 5 | Sorts the given project. 6 | 7 | If no `PROJECT' is specified then the current work directory is searched for one. 8 | eos 9 | 10 | self.summary = 'Sorts the given project.' 11 | 12 | self.arguments = [ 13 | CLAide::Argument.new('PROJECT', false), 14 | ] 15 | 16 | def initialize(argv) 17 | self.xcodeproj_path = argv.shift_argument 18 | super 19 | end 20 | 21 | def validate! 22 | super 23 | open_project! 24 | end 25 | 26 | def run 27 | xcodeproj.sort 28 | xcodeproj.save 29 | puts "The `#{File.basename(xcodeproj_path)}` project was sorted" 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/command/target_diff.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Command 3 | class TargetDiff < Command 4 | self.summary = 'Shows the difference between two targets' 5 | 6 | def self.options 7 | [ 8 | ['--project PATH', 'The Xcode project document to use.'], 9 | ].concat(super) 10 | end 11 | 12 | self.arguments = [ 13 | CLAide::Argument.new('TARGET1', true), 14 | CLAide::Argument.new('TARGET2', true), 15 | ] 16 | 17 | def initialize(argv) 18 | @target1 = argv.shift_argument 19 | @target2 = argv.shift_argument 20 | self.xcodeproj_path = argv.option('--project') 21 | super 22 | end 23 | 24 | def validate! 25 | super 26 | open_project! 27 | end 28 | 29 | def run 30 | require 'yaml' 31 | differ = Helper::TargetDiff.new(xcodeproj, @target1, @target2) 32 | files = differ.new_source_build_files.map do |build_file| 33 | { 34 | 'Name' => build_file.file_ref.name, 35 | 'Path' => build_file.file_ref.path, 36 | 'Build settings' => build_file.settings, 37 | } 38 | end 39 | puts files.to_yaml 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/config/other_linker_flags_parser.rb: -------------------------------------------------------------------------------- 1 | require 'shellwords' 2 | 3 | module Xcodeproj 4 | class Config 5 | # Parses other linker flags values. 6 | # 7 | module OtherLinkerFlagsParser 8 | # @return [Hash{Symbol, Array[String]}] Splits the given 9 | # other linker flags value by type. 10 | # 11 | # @param [String, Array] flags 12 | # The other linker flags value. 13 | # 14 | def self.parse(flags) 15 | result = { 16 | :frameworks => [], 17 | :weak_frameworks => [], 18 | :libraries => [], 19 | :simple => [], 20 | :force_load => [], 21 | } 22 | 23 | key = nil 24 | if flags.is_a? String 25 | flags = split(flags) 26 | end 27 | flags.each do |token| 28 | case token 29 | when '-framework' 30 | key = :frameworks 31 | when '-weak_framework' 32 | key = :weak_frameworks 33 | when '-l' 34 | key = :libraries 35 | when '-force_load' 36 | key = :force_load 37 | else 38 | if key 39 | result[key] << token 40 | key = nil 41 | else 42 | result[:simple] << token 43 | end 44 | end 45 | end 46 | result 47 | end 48 | 49 | # @return [Array] Split the given other linker 50 | # flags value, taking into account quoting and 51 | # the fact that the `-l` flag might omit the 52 | # space. 53 | # 54 | # @param [String] flags 55 | # The other linker flags value. 56 | # 57 | def self.split(flags) 58 | flags.strip.shellsplit.flat_map do |string| 59 | if string =~ /\A-l.+/ 60 | ['-l', string[2..-1]] 61 | else 62 | string 63 | end 64 | end 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/gem_version.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | # The version of the xcodeproj gem. 3 | # 4 | VERSION = '1.14.0'.freeze unless defined? Xcodeproj::VERSION 5 | end 6 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/helper.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | module Helper 3 | class TargetDiff 4 | attr_reader :project, :target1, :target2 5 | 6 | def initialize(project, target1_name, target2_name) 7 | @project = project 8 | unless @target1 = @project.targets.find { |target| target.name == target1_name } 9 | raise ArgumentError, "Target 1 by name `#{target1_name}' not found in the project." 10 | end 11 | unless @target2 = @project.targets.find { |target| target.name == target2_name } 12 | raise ArgumentError, "Target 1 by name `#{target2_name}' not found in the project." 13 | end 14 | end 15 | 16 | # @return [Array] A list of source files (that will be 17 | # compiled) which are in ‘target 2’ but not in ‘target 1’. The 18 | # list is sorted by file path. 19 | # 20 | def new_source_build_files 21 | new = @target2.source_build_phase.files.reject do |target2_build_file| 22 | @target1.source_build_phase.files.any? do |target1_build_file| 23 | target1_build_file.file_ref.path == target2_build_file.file_ref.path 24 | end 25 | end 26 | new.sort_by { |build_file| build_file.file_ref.path } 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/plist.rb: -------------------------------------------------------------------------------- 1 | autoload :Nanaimo, 'nanaimo' 2 | autoload :CFPropertyList, 'cfpropertylist' 3 | 4 | module Xcodeproj 5 | # Provides support for loading and serializing property list files. 6 | # 7 | module Plist 8 | # @return [Hash] Returns the native objects loaded from a property list 9 | # file. 10 | # 11 | # @param [#to_s] path 12 | # The path of the file. 13 | # 14 | def self.read_from_path(path) 15 | path = path.to_s 16 | unless File.exist?(path) 17 | raise Informative, "The plist file at path `#{path}` doesn't exist." 18 | end 19 | contents = File.read(path) 20 | if file_in_conflict?(contents) 21 | raise Informative, "The file `#{path}` is in a merge conflict." 22 | end 23 | case Nanaimo::Reader.plist_type(contents) 24 | when :xml, :binary 25 | CFPropertyList.native_types(CFPropertyList::List.new(:data => contents).value) 26 | else 27 | Nanaimo::Reader.new(contents).parse!.as_ruby 28 | end 29 | end 30 | 31 | # Serializes a hash as an XML property list file. 32 | # 33 | # @param [#to_hash] hash 34 | # The hash to store. 35 | # 36 | # @param [#to_s] path 37 | # The path of the file. 38 | # 39 | def self.write_to_path(hash, path) 40 | if hash.respond_to?(:to_hash) 41 | hash = hash.to_hash 42 | else 43 | raise TypeError, "The given `#{hash.inspect}` must respond " \ 44 | "to #to_hash'." 45 | end 46 | 47 | unless path.is_a?(String) || path.is_a?(Pathname) 48 | raise TypeError, "The given `#{path}` must be a string or 'pathname'." 49 | end 50 | path = path.to_s 51 | raise IOError, 'Empty path.' if path.empty? 52 | 53 | File.open(path, 'w') do |f| 54 | plist = Nanaimo::Plist.new(hash, :xml) 55 | Nanaimo::Writer::XMLWriter.new(plist, :pretty => true, :output => f, :strict => false).write 56 | end 57 | end 58 | 59 | # The known modules that can serialize plists. 60 | # 61 | KNOWN_IMPLEMENTATIONS = [] 62 | 63 | class << self 64 | # @deprecated This method will be removed in 2.0 65 | # 66 | # @return [Nil] 67 | # 68 | attr_accessor :implementation 69 | end 70 | 71 | # @deprecated This method will be removed in 2.0 72 | # 73 | # @return [Nil] 74 | # 75 | def self.autoload_implementation 76 | end 77 | 78 | # @return [Bool] Checks whether there are merge conflicts in the file. 79 | # 80 | # @param [#to_s] contents 81 | # The contents of the file. 82 | # 83 | def self.file_in_conflict?(contents) 84 | conflict_regex = / 85 | ^<{7}(?!<) # Exactly 7 left arrows at the beginning of the line 86 | [\w\W]* # Anything 87 | ^={7}(?!=) # Exactly 7 equality symbols at the beginning of the line 88 | [\w\W]* # Anything 89 | ^>{7}(?!>) # Exactly 7 right arrows at the beginning of the line 90 | /xm 91 | contents.match(conflict_regex) 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/case_converter.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # Converts between camel case names used in the xcodeproj plist files 5 | # and the ruby symbols used to represent them. 6 | # 7 | module CaseConverter 8 | # @return [String] The plist equivalent of the given Ruby name. 9 | # 10 | # @param [Symbol, String] name 11 | # The name to convert 12 | # 13 | # @param [Symbol, Nil] type 14 | # The type of conversion. Pass `nil` for normal camel case and 15 | # `:lower` for camel case starting with a lower case letter. 16 | # 17 | # @example 18 | # CaseConverter.convert_to_plist(:project_ref) #=> ProjectRef 19 | # 20 | def self.convert_to_plist(name, type = nil) 21 | case name 22 | when :remote_global_id_string 23 | 'remoteGlobalIDString' 24 | else 25 | if type == :lower 26 | cache = plist_cache[:lower] ||= {} 27 | cache[name] ||= camelize(name, :uppercase_first_letter => false) 28 | else 29 | cache = plist_cache[:normal] ||= {} 30 | cache[name] ||= camelize(name) 31 | end 32 | end 33 | end 34 | 35 | # The following two methods are taken from activesupport, 36 | # https://github.com/rails/rails/blob/v5.0.2/activesupport/lib/active_support/inflector/methods.rb 37 | # all credit for them goes to the original authors. 38 | # 39 | # The code is used under the MIT license. 40 | 41 | def self.camelize(term, uppercase_first_letter: true) 42 | string = term.to_s 43 | string = if uppercase_first_letter 44 | string.sub(/^[a-z\d]*/, &:capitalize) 45 | else 46 | string.sub(/^(?:(?=a)b(?=\b|[A-Z_])|\w)/, &:downcase) 47 | end 48 | string.gsub!(%r{(?:_|(/))([a-z\d]*)}i) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" } 49 | string.gsub!('/'.freeze, '::'.freeze) 50 | string 51 | end 52 | private_class_method :camelize 53 | 54 | def self.underscore(camel_cased_word) 55 | return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/ 56 | word = camel_cased_word.to_s.gsub('::'.freeze, '/'.freeze) 57 | word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/) { "#{Regexp.last_match(1) && '_'.freeze}#{Regexp.last_match(2).downcase}" } 58 | word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze) 59 | word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze) 60 | word.tr!('-'.freeze, '_'.freeze) 61 | word.downcase! 62 | word 63 | end 64 | private_class_method :underscore 65 | 66 | # @return [Symbol] The Ruby equivalent of the given plist name. 67 | # 68 | # @param [String] name 69 | # The name to convert 70 | # 71 | # @example 72 | # CaseConverter.convert_to_ruby('ProjectRef') #=> :project_ref 73 | # 74 | def self.convert_to_ruby(name) 75 | underscore(name.to_s).to_sym 76 | end 77 | 78 | # @return [Hash] A cache for the conversion to the Plist format. 79 | # 80 | # @note A cache is used because this operation is performed for each 81 | # attribute of the project when it is saved and caching it has 82 | # an important performance benefit. 83 | # 84 | def self.plist_cache 85 | @plist_cache ||= {} 86 | end 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/build_file.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # Contains the information about the build settings of a file used by an 5 | # {AbstractBuildPhase}. 6 | # 7 | class PBXBuildFile < AbstractObject 8 | # @!group Attributes 9 | 10 | # @return [Hash] the list of build settings for this file. 11 | # 12 | # @note The contents of this array depend on the phase of the build 13 | # file. 14 | # 15 | # For PBXHeadersBuildPhase is `{ "ATTRIBUTES" => [:value] }` 16 | # where `:value` can be `Public`, `Private`, or nil 17 | # (Protected). 18 | # 19 | attribute :settings, Hash 20 | 21 | # @return [PBXFileReference] the file to build. 22 | # 23 | # @todo I think that is possible to add any kind of group (for 24 | # example folders linked to a path). 25 | # 26 | has_one :file_ref, [ 27 | PBXFileReference, 28 | PBXGroup, 29 | PBXVariantGroup, 30 | XCVersionGroup, 31 | PBXReferenceProxy, 32 | ] 33 | 34 | # @return [XCSwiftPackageProductDependency] the Swift Package file to build. 35 | # 36 | has_one :product_ref, XCSwiftPackageProductDependency 37 | 38 | # @return [String] the platform filter for this build file. 39 | # 40 | attribute :platform_filter, String 41 | 42 | #---------------------------------------------------------------------# 43 | 44 | public 45 | 46 | # @!group AbstractObject Hooks 47 | 48 | # @return [String] A name suitable for displaying the object to the 49 | # user. 50 | # 51 | def display_name 52 | if file_ref 53 | file_ref.display_name 54 | else 55 | super 56 | end 57 | end 58 | 59 | # @return [Hash{String => Hash}, String] A hash suitable to display the 60 | # object to the user. 61 | # 62 | def pretty_print 63 | if settings.nil? || settings.empty? 64 | display_name 65 | else 66 | { display_name => settings } 67 | end 68 | end 69 | 70 | def ascii_plist_annotation 71 | " #{display_name} in #{GroupableHelper.parent(self).display_name} " 72 | end 73 | 74 | #---------------------------------------------------------------------# 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/build_rule.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # This class represents a custom build rule of a Target. 5 | # 6 | class PBXBuildRule < AbstractObject 7 | # @!group Attributes 8 | 9 | # @return [String] the name of the rule. 10 | # 11 | attribute :name, String 12 | 13 | # @return [String] a string representing what compiler to use. 14 | # 15 | # @example 16 | # `com.apple.compilers.proxy.script`. 17 | # 18 | attribute :compiler_spec, String 19 | 20 | # @return [String] the type of the files that should be processed by 21 | # this rule. 22 | # 23 | # @example 24 | # `pattern.proxy`. 25 | # 26 | attribute :file_type, String 27 | 28 | # @return [String] the pattern of the files that should be processed by 29 | # this rule. This attribute is an alternative to to 30 | # `file_type`. 31 | # 32 | # @example 33 | # `*.css`. 34 | # 35 | attribute :file_patterns, String 36 | 37 | # @return [String] whether the rule is editable. 38 | # 39 | # @example 40 | # `1`. 41 | # 42 | attribute :is_editable, String, '1' 43 | 44 | # @return [ObjectList] the file references for the 45 | # input files files. 46 | # 47 | attribute :input_files, Array 48 | 49 | # @return [ObjectList] the file references for the 50 | # output files. 51 | # 52 | attribute :output_files, Array 53 | 54 | # @return [ObjectList] the compiler flags used when creating the 55 | # respective output files. 56 | # 57 | attribute :output_files_compiler_flags, Array 58 | 59 | # @return [String] whether the rule should be run once per architecture. 60 | # 61 | # @example 62 | # `0`. 63 | # 64 | attribute :run_once_per_architecture, String 65 | 66 | # @return [String] the content of the script to use for the build rule. 67 | # 68 | # @note This attribute is present if the #{#compiler_spec} is 69 | # `com.apple.compilers.proxy.script` 70 | # 71 | attribute :script, String 72 | 73 | # @!group Helpers 74 | 75 | # Adds an output file with the specified compiler flags. 76 | # 77 | # @param [PBXFileReference] file the file to add. 78 | # 79 | # @param [String] compiler_flags the compiler flags for the file. 80 | # 81 | # @return [Void] 82 | # 83 | def add_output_file(file, compiler_flags = '') 84 | (self.output_files ||= []) << file 85 | (self.output_files_compiler_flags ||= []) << compiler_flags 86 | end 87 | 88 | # @return [Array<[PBXFileReference, String]>] 89 | # An array containing tuples of output files and their compiler 90 | # flags. 91 | # 92 | def output_files_and_flags 93 | (output_files || []).zip(output_files_compiler_flags || []) 94 | end 95 | 96 | def ascii_plist_annotation 97 | " #{isa} " 98 | end 99 | end 100 | end 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/helpers/build_settings_array_settings_by_object_version.rb: -------------------------------------------------------------------------------- 1 | require 'set' 2 | 3 | module Xcodeproj 4 | class Project 5 | module Object 6 | class XCBuildConfiguration 7 | # yes, they are case-sensitive. 8 | # no, Xcode doesn't do this for other PathList settings nor other 9 | # settings ending in SEARCH_PATHS. 10 | module BuildSettingsArraySettingsByObjectVersion 11 | ARRAY_SETTINGS = %w( 12 | ALTERNATE_PERMISSIONS_FILES 13 | ARCHS 14 | BUILD_VARIANTS 15 | EXCLUDED_SOURCE_FILE_NAMES 16 | FRAMEWORK_SEARCH_PATHS 17 | GCC_PREPROCESSOR_DEFINITIONS 18 | GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS 19 | HEADER_SEARCH_PATHS 20 | INFOPLIST_PREPROCESSOR_DEFINITIONS 21 | LIBRARY_SEARCH_PATHS 22 | OTHER_CFLAGS 23 | OTHER_CPLUSPLUSFLAGS 24 | OTHER_LDFLAGS 25 | REZ_SEARCH_PATHS 26 | SECTORDER_FLAGS 27 | WARNING_CFLAGS 28 | WARNING_LDFLAGS 29 | ).to_set.freeze 30 | private_constant :ARRAY_SETTINGS 31 | 32 | ARRAY_SETTINGS_OBJECT_VERSION_50 = %w( 33 | ALTERNATE_PERMISSIONS_FILES 34 | ARCHS 35 | BUILD_VARIANTS 36 | EXCLUDED_SOURCE_FILE_NAMES 37 | FRAMEWORK_SEARCH_PATHS 38 | GCC_PREPROCESSOR_DEFINITIONS 39 | GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS 40 | HEADER_SEARCH_PATHS 41 | INCLUDED_SOURCE_FILE_NAMES 42 | INFOPLIST_PREPROCESSOR_DEFINITIONS 43 | LD_RUNPATH_SEARCH_PATHS 44 | LIBRARY_SEARCH_PATHS 45 | LOCALIZED_STRING_MACRO_NAMES 46 | OTHER_CFLAGS 47 | OTHER_CPLUSPLUSFLAGS 48 | OTHER_LDFLAGS 49 | REZ_SEARCH_PATHS 50 | SECTORDER_FLAGS 51 | SYSTEM_FRAMEWORK_SEARCH_PATHS 52 | SYSTEM_HEADER_SEARCH_PATHS 53 | USER_HEADER_SEARCH_PATHS 54 | WARNING_CFLAGS 55 | WARNING_LDFLAGS 56 | ).to_set.freeze 57 | private_constant :ARRAY_SETTINGS_OBJECT_VERSION_50 58 | 59 | def self.[](object_version) 60 | object_version = object_version.to_i 61 | 62 | if object_version >= 50 63 | ARRAY_SETTINGS_OBJECT_VERSION_50 64 | else 65 | ARRAY_SETTINGS 66 | end 67 | end 68 | end 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/reference_proxy.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # Apparently a proxy for a reference object which might belong another 5 | # project contained in the same workspace of the project document. 6 | # 7 | # This class is used for referencing the products of another project. 8 | # 9 | class PBXReferenceProxy < AbstractObject 10 | # @!group Attributes 11 | 12 | # @return [String] the name of the reference. 13 | # 14 | attribute :name, String 15 | 16 | # @return [String] the path of the referenced filed. 17 | # 18 | attribute :path, String 19 | 20 | # @return [String] the file type of the referenced filed. 21 | # 22 | attribute :file_type, String 23 | 24 | # @return [PBXContainerItemProxy] the proxy to the project that 25 | # contains the object. 26 | # 27 | has_one :remote_ref, PBXContainerItemProxy 28 | 29 | # @return [String] the source tree for the path of the reference. 30 | # 31 | # @example 32 | # "BUILT_PRODUCTS_DIR" 33 | # 34 | attribute :source_tree, String 35 | 36 | #---------------------------------------------------------------------# 37 | 38 | public 39 | 40 | # @!group Helpers 41 | 42 | # Checks whether the reference is a proxy. 43 | # 44 | # @return [Bool] always true for this ISA. 45 | # 46 | def proxy? 47 | true 48 | end 49 | 50 | #---------------------------------------------------------------------# 51 | 52 | def ascii_plist_annotation 53 | " #{name || path && File.basename(path)} " 54 | end 55 | 56 | # @return [String] A name suitable for displaying the object to the 57 | # user. 58 | # 59 | def display_name 60 | return name if name 61 | return path if path 62 | super 63 | end 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/swift_package_product_dependency.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # This class represents a Swift package product dependency. 5 | # 6 | class XCSwiftPackageProductDependency < AbstractObject 7 | # @!group Attributes 8 | 9 | # @return [XCRemoteSwiftPackageReference] the Swift package reference. 10 | # 11 | has_one :package, XCRemoteSwiftPackageReference 12 | 13 | # @return [String] the product name of this Swift package. 14 | # 15 | attribute :product_name, String 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/swift_package_remote_reference.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # This class represents a Swift package reference. 5 | # 6 | class XCRemoteSwiftPackageReference < AbstractObject 7 | # @!group Attributes 8 | 9 | # @return [String] the repository url this Swift package was installed from. 10 | # 11 | attribute :repositoryURL, String 12 | 13 | # @return [Hash] the version requirements for this Swift package. 14 | # 15 | attribute :requirement, Hash 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/project/object/target_dependency.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Project 3 | module Object 4 | # Represents a dependency of a target on another one. 5 | # 6 | class PBXTargetDependency < AbstractObject 7 | # @!group Attributes 8 | 9 | # @return [PBXNativeTarget] the target that needs to be built to 10 | # satisfy the dependency. 11 | # 12 | has_one :target, AbstractTarget 13 | 14 | # @return [PBXContainerItemProxy] a proxy for the target that needs to 15 | # be built. 16 | # 17 | # @note Apparently to support targets in other projects of the same 18 | # workspace. 19 | # 20 | has_one :target_proxy, PBXContainerItemProxy 21 | 22 | # @return [String] the name of the target. 23 | # 24 | # @note This seems only to be used when the target dependency is a 25 | # target from a nested Xcode project. 26 | # 27 | attribute :name, String 28 | 29 | # @return [String] the platform filter for this target dependency. 30 | # 31 | attribute :platform_filter, String 32 | 33 | # @return [String] the product reference for this target dependency. 34 | # 35 | attribute :product_ref, String 36 | 37 | public 38 | 39 | # @!group AbstractObject Hooks 40 | #--------------------------------------# 41 | 42 | # @return [String] The name of the dependency. 43 | # 44 | def display_name 45 | return name if name 46 | return target.name if target 47 | return target_proxy.remote_info if target_proxy 48 | end 49 | 50 | def ascii_plist_annotation 51 | " #{isa} " 52 | end 53 | 54 | # @return [String] uuid of the target, if the dependency 55 | # is a native target, otherwise the uuid of the 56 | # target in the sub-project if the dependency is 57 | # a target proxy 58 | # 59 | def native_target_uuid 60 | return target.uuid if target 61 | return target_proxy.remote_global_id_string if target_proxy 62 | raise "Expected target or target_proxy, from which to fetch a uuid for target '#{display_name}'." \ 63 | "Find and clear the PBXTargetDependency entry with uuid '#{@uuid}' in your .xcodeproj." 64 | end 65 | 66 | # @note This override is necessary because Xcode allows for circular 67 | # target dependencies. 68 | # 69 | # @return [Hash String>] Returns a cascade representation of 70 | # the object without UUIDs. 71 | # 72 | def to_tree_hash 73 | hash = {} 74 | hash['displayName'] = display_name 75 | hash['isa'] = isa 76 | hash 77 | end 78 | 79 | # @note This is a no-op, because the targets could theoretically depend 80 | # on each other, leading to a stack level too deep error. 81 | # 82 | # @see AbstractObject#sort_recursively 83 | # 84 | def sort_recursively(_options = nil) 85 | end 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/abstract_scheme_action.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/scheme/xml_element_wrapper' 2 | require 'xcodeproj/scheme/environment_variables' 3 | require 'xcodeproj/scheme/command_line_arguments' 4 | 5 | module Xcodeproj 6 | class XCScheme 7 | # This abstract class aims to be the base class for every XxxAction class 8 | # that have a #build_configuration attribute 9 | # 10 | class AbstractSchemeAction < XMLElementWrapper 11 | # @return [String] 12 | # The build configuration associated with this action 13 | # (usually either 'Debug' or 'Release') 14 | # 15 | def build_configuration 16 | @xml_element.attributes['buildConfiguration'] 17 | end 18 | 19 | # @param [String] config_name 20 | # The build configuration to associate with this action 21 | # (usually either 'Debug' or 'Release') 22 | # 23 | def build_configuration=(config_name) 24 | @xml_element.attributes['buildConfiguration'] = config_name 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/analyze_action.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/scheme/abstract_scheme_action' 2 | 3 | module Xcodeproj 4 | class XCScheme 5 | # This class wraps the AnalyzeAction node of a .xcscheme XML file 6 | # 7 | class AnalyzeAction < AbstractSchemeAction 8 | # @param [REXML::Element] node 9 | # The 'AnalyzeAction' XML node that this object will wrap. 10 | # If nil, will create a default XML node to use. 11 | # 12 | def initialize(node = nil) 13 | create_xml_element_with_fallback(node, 'AnalyzeAction') do 14 | self.build_configuration = 'Debug' 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/archive_action.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/scheme/abstract_scheme_action' 2 | 3 | module Xcodeproj 4 | class XCScheme 5 | # This class wraps the ArchiveAction node of a .xcscheme XML file 6 | # 7 | class ArchiveAction < AbstractSchemeAction 8 | # @param [REXML::Element] node 9 | # The 'ArchiveAction' XML node that this object will wrap. 10 | # If nil, will create a default XML node to use. 11 | # 12 | def initialize(node = nil) 13 | create_xml_element_with_fallback(node, 'ArchiveAction') do 14 | self.build_configuration = 'Release' 15 | self.reveal_archive_in_organizer = true 16 | end 17 | end 18 | 19 | # @return [Bool] 20 | # Whether the Archive will be revealed in Xcode's Organizer 21 | # after it's done building. 22 | # 23 | def reveal_archive_in_organizer? 24 | string_to_bool(@xml_element.attributes['revealArchiveInOrganizer']) 25 | end 26 | 27 | # @param [Bool] flag 28 | # Set whether the Archive will be revealed in Xcode's Organizer 29 | # after it's done building. 30 | # 31 | def reveal_archive_in_organizer=(flag) 32 | @xml_element.attributes['revealArchiveInOrganizer'] = bool_to_string(flag) 33 | end 34 | 35 | # @return [String] 36 | # The custom name to give to the archive. 37 | # If nil, the generated archive will have the same name as the one 38 | # set in the associated target's Build Settings for the built product. 39 | # 40 | def custom_archive_name 41 | @xml_element.attributes['customArchiveName'] 42 | end 43 | 44 | # @param [String] name 45 | # Set the custom name to use for the built archive 46 | # If nil, the customization of the archive name will be removed and 47 | # the generated archive will have the same name as the one set in the 48 | # associated target's Build Settings for the build product. 49 | # 50 | def custom_archive_name=(name) 51 | if name 52 | @xml_element.attributes['customArchiveName'] = name 53 | else 54 | @xml_element.delete_attribute('customArchiveName') 55 | end 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/buildable_product_runnable.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class XCScheme 3 | # This class wraps the BuildableProductRunnable node of a .xcscheme XML file 4 | # 5 | # A BuildableProductRunnable is a product that is both buildable 6 | # (it contains a BuildableReference) and runnable (it can be launched and debugged) 7 | # 8 | class BuildableProductRunnable < XMLElementWrapper 9 | # @param [Xcodeproj::Project::Object::AbstractTarget, REXML::Element] target_or_node 10 | # Either the Xcode target to reference, 11 | # or an existing XML 'BuildableProductRunnable' node element to reference 12 | # or nil to create an new, empty BuildableProductRunnable 13 | # 14 | # @param [#to_s] runnable_debugging_mode 15 | # The debugging mode (usually '0') 16 | # 17 | def initialize(target_or_node = nil, runnable_debugging_mode = nil) 18 | create_xml_element_with_fallback(target_or_node, 'BuildableProductRunnable') do 19 | self.buildable_reference = BuildableReference.new(target_or_node) if target_or_node 20 | @xml_element.attributes['runnableDebuggingMode'] = runnable_debugging_mode.to_s if runnable_debugging_mode 21 | end 22 | end 23 | 24 | # @return [String] 25 | # The Runnable debugging mode (usually either empty or equal to '0') 26 | # 27 | def runnable_debugging_mode 28 | @xml_element.attributes['runnableDebuggingMode'] 29 | end 30 | 31 | # @param [String] value 32 | # Set the runnable debugging mode of this buildable product runnable 33 | # 34 | def runnable_debugging_mode=(value) 35 | @xml_element.attributes['runnableDebuggingMode'] = value.to_s 36 | end 37 | 38 | # @return [BuildableReference] 39 | # The Buildable Reference this Buildable Product Runnable is gonna build and run 40 | # 41 | def buildable_reference 42 | @buildable_reference ||= BuildableReference.new @xml_element.elements['BuildableReference'] 43 | end 44 | 45 | # @param [BuildableReference] ref 46 | # Set the Buildable Reference this Buildable Product Runnable is gonna build and run 47 | # 48 | def buildable_reference=(ref) 49 | @xml_element.delete_element('BuildableReference') 50 | @xml_element.add_element(ref.xml_element) 51 | @buildable_reference = ref 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/macro_expansion.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class XCScheme 3 | # This class wraps the MacroExpansion node of a .xcscheme XML file 4 | # 5 | class MacroExpansion < XMLElementWrapper 6 | # @param [Xcodeproj::Project::Object::AbstractTarget, REXML::Element] target_or_node 7 | # Either the Xcode target to reference, 8 | # or an existing XML 'MacroExpansion' node element 9 | # or nil to create an empty MacroExpansion object 10 | # 11 | def initialize(target_or_node = nil) 12 | create_xml_element_with_fallback(target_or_node, 'MacroExpansion') do 13 | self.buildable_reference = BuildableReference.new(target_or_node) if target_or_node 14 | end 15 | end 16 | 17 | # @return [BuildableReference] 18 | # The BuildableReference this MacroExpansion refers to 19 | # 20 | def buildable_reference 21 | @buildable_reference ||= BuildableReference.new @xml_element.elements['BuildableReference'] 22 | end 23 | 24 | # @param [BuildableReference] ref 25 | # Set the BuildableReference this MacroExpansion refers to 26 | # 27 | def buildable_reference=(ref) 28 | @xml_element.delete_element('BuildableReference') 29 | @xml_element.add_element(ref.xml_element) 30 | @buildable_reference = ref 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/profile_action.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/scheme/abstract_scheme_action' 2 | 3 | module Xcodeproj 4 | class XCScheme 5 | # This class wraps the ProfileAction node of a .xcscheme XML file 6 | # 7 | class ProfileAction < AbstractSchemeAction 8 | # @param [REXML::Element] node 9 | # The 'ProfileAction' XML node that this object will wrap. 10 | # If nil, will create a default XML node to use. 11 | # 12 | def initialize(node = nil) 13 | create_xml_element_with_fallback(node, 'ProfileAction') do 14 | # Add some attributes (that are not handled by this wrapper class yet but expected in the XML) 15 | @xml_element.attributes['savedToolIdentifier'] = '' 16 | @xml_element.attributes['useCustomWorkingDirectory'] = bool_to_string(false) 17 | @xml_element.attributes['debugDocumentVersioning'] = bool_to_string(true) 18 | 19 | # Setup default values for other (handled) attributes 20 | self.build_configuration = 'Release' 21 | self.should_use_launch_scheme_args_env = true 22 | end 23 | end 24 | 25 | # @return [Bool] 26 | # Whether this Profile Action should use the same arguments and environment variables 27 | # as the Launch Action. 28 | # 29 | def should_use_launch_scheme_args_env? 30 | string_to_bool(@xml_element.attributes['shouldUseLaunchSchemeArgsEnv']) 31 | end 32 | 33 | # @param [Bool] flag 34 | # Set Whether this Profile Action should use the same arguments and environment variables 35 | # as the Launch Action. 36 | # 37 | def should_use_launch_scheme_args_env=(flag) 38 | @xml_element.attributes['shouldUseLaunchSchemeArgsEnv'] = bool_to_string(flag) 39 | end 40 | 41 | # @return [BuildableProductRunnable] 42 | # The BuildableProductRunnable to launch when launching the Profile action 43 | # 44 | def buildable_product_runnable 45 | BuildableProductRunnable.new @xml_element.elements['BuildableProductRunnable'] 46 | end 47 | 48 | # @param [BuildableProductRunnable] runnable 49 | # Set the BuildableProductRunnable referencing the target to launch when profiling 50 | # 51 | def buildable_product_runnable=(runnable) 52 | @xml_element.delete_element('BuildableProductRunnable') 53 | @xml_element.add_element(runnable.xml_element) if runnable 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/remote_runnable.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class XCScheme 3 | # This class wraps the RemoteRunnable node of a .xcscheme XML file 4 | # 5 | # A RemoteRunnable is a product that is both buildable 6 | # (it contains a BuildableReference) and 7 | # runnable remotely (it can be launched and debugged on a remote device, i.e. an Apple Watch) 8 | # 9 | class RemoteRunnable < XMLElementWrapper 10 | # @param [Xcodeproj::Project::Object::AbstractTarget, REXML::Element] target_or_node 11 | # Either the Xcode target to reference, 12 | # or an existing XML 'RemoteRunnable' node element to reference 13 | # or nil to create an new, empty RemoteRunnable 14 | # 15 | # @param [#to_s] runnable_debugging_mode 16 | # The debugging mode (usually '2') 17 | # 18 | # @param [#to_s] bundle_identifier 19 | # The bundle identifier (usually 'com.apple.Carousel') 20 | # 21 | # @param [#to_s] remote_path 22 | # The remote path (not required, unknown usage) 23 | # 24 | def initialize(target_or_node = nil, runnable_debugging_mode = nil, bundle_identifier = nil, remote_path = nil) 25 | create_xml_element_with_fallback(target_or_node, 'RemoteRunnable') do 26 | self.buildable_reference = BuildableReference.new(target_or_node) if target_or_node 27 | @xml_element.attributes['runnableDebuggingMode'] = runnable_debugging_mode.to_s if runnable_debugging_mode 28 | @xml_element.attributes['BundleIdentifier'] = bundle_identifier.to_s if bundle_identifier 29 | @xml_element.attributes['RemotePath'] = remote_path.to_s if remote_path 30 | end 31 | end 32 | 33 | # @return [String] 34 | # The runnable debugging mode (usually '2') 35 | # 36 | def runnable_debugging_mode 37 | @xml_element.attributes['runnableDebuggingMode'] 38 | end 39 | 40 | # @param [String] value 41 | # Set the runnable debugging mode 42 | # 43 | def runnable_debugging_mode=(value) 44 | @xml_element.attributes['runnableDebuggingMode'] = value.to_s 45 | end 46 | 47 | # @return [String] 48 | # The runnable bundle identifier (usually 'com.apple.Carousel') 49 | # 50 | def bundle_identifier 51 | @xml_element.attributes['BundleIdentifier'] 52 | end 53 | 54 | # @param [String] value 55 | # Set the runnable bundle identifier 56 | # 57 | def bundle_identifier=(value) 58 | @xml_element.attributes['BundleIdentifier'] = value.to_s 59 | end 60 | 61 | # @return [String] 62 | # The runnable remote path (not required, unknown usage) 63 | # 64 | def remote_path 65 | @xml_element.attributes['RemotePath'] 66 | end 67 | 68 | # @param [String] value 69 | # Set the runnable remote path 70 | # 71 | def remote_path=(value) 72 | @xml_element.attributes['RemotePath'] = value.to_s 73 | end 74 | 75 | # @return [BuildableReference] 76 | # The buildable reference this remote runnable is gonna build and run 77 | # 78 | def buildable_reference 79 | @buildable_reference ||= BuildableReference.new @xml_element.elements['BuildableReference'] 80 | end 81 | 82 | # @param [BuildableReference] ref 83 | # Set the buildable reference this remote runnable is gonna build and run 84 | # 85 | def buildable_reference=(ref) 86 | @xml_element.delete_element('BuildableReference') 87 | @xml_element.add_element(ref.xml_element) 88 | @buildable_reference = ref 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/scheme/xml_element_wrapper.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class XCScheme 3 | # Abstract base class used for other XCScheme classes wrapping an XML element 4 | # 5 | class XMLElementWrapper 6 | # @return [REXML::Element] 7 | # The XML node wrapped and manipulated by this XMLElementWrapper object 8 | # 9 | attr_reader :xml_element 10 | 11 | # @return [String] 12 | # The XML representation of the node this XMLElementWrapper wraps, 13 | # formatted in the same way that Xcode would. 14 | def to_s 15 | formatter = XMLFormatter.new(2) 16 | formatter.compact = false 17 | out = '' 18 | formatter.write(@xml_element, out) 19 | out.gsub!("", '') 20 | out << "\n" 21 | out 22 | end 23 | 24 | private 25 | 26 | # This is a method intended to be used to facilitate the implementation of the initializers. 27 | # 28 | # - Create the @xml_element attribute based on the node passed as parameter, only if 29 | # that parameter is of type REXML::Element and its name matches the tag_name given. 30 | # - Otherwise, create a brand new REXML::Element with the proper tag name and 31 | # execute the block given as a fallback to let the caller the chance to configure it 32 | # 33 | # @param [REXML::Element, *] node 34 | # The node this XMLElementWrapper is expected to wrap 35 | # or any other object (typically an AbstractTarget instance, or nil) the initializer might expect 36 | # 37 | # @param [String] tag_name 38 | # The expected name for the node, which will also be the name used to create the new node 39 | # if that `node` parameter is not a REXML::Element itself. 40 | # 41 | # @yield a parameter-less block if the `node` parameter is not actually a REXML::Element 42 | # 43 | # @raise Informative 44 | # If the `node` parameter is a REXML::Element instance but the node's name 45 | # doesn't match the one provided by the `tag_name` parameter. 46 | # 47 | def create_xml_element_with_fallback(node, tag_name) 48 | if node && node.is_a?(REXML::Element) 49 | raise Informative, 'Wrong XML tag name' unless node.name == tag_name 50 | @xml_element = node 51 | else 52 | @xml_element = REXML::Element.new(tag_name) 53 | yield if block_given? 54 | end 55 | end 56 | 57 | # @param [Bool] 58 | # The boolean we want to represent as a string 59 | # 60 | # @return [String] 61 | # The string representaiton of that boolean used in the XML ('YES' or 'NO') 62 | # 63 | def bool_to_string(flag) 64 | flag ? 'YES' : 'NO' 65 | end 66 | 67 | # @param [String] 68 | # The string representaiton of a boolean used in the XML ('YES' or 'NO') 69 | # 70 | # @return [Bool] 71 | # The boolean interpretation of that string 72 | # 73 | # @raise Informative 74 | # If the string is not representing a boolean (i.e. is neither 'YES' nor 'NO') 75 | # 76 | def string_to_bool(str) 77 | raise Informative, 'Invalid tag value. Expected YES or NO.' unless %w(YES NO).include?(str) 78 | str == 'YES' 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/user_interface.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | # Manages the UI output so clients can customize it. 3 | # 4 | module UserInterface 5 | # Prints a message to standard output. 6 | # 7 | # @return [void] 8 | # 9 | def self.puts(message) 10 | STDOUT.puts message 11 | end 12 | 13 | # Prints a message to standard error. 14 | # 15 | # @return [void] 16 | # 17 | def self.warn(message) 18 | STDERR.puts message 19 | end 20 | end 21 | UI = UserInterface 22 | end 23 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/workspace/file_reference.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/workspace/reference' 2 | 3 | module Xcodeproj 4 | class Workspace 5 | # Describes a file reference of a Workspace. 6 | # 7 | class FileReference < Reference 8 | # @return [String] the path to the project 9 | # 10 | attr_reader :path 11 | 12 | # @param [#to_s] path @see path 13 | # @param [#to_s] type @see type 14 | # 15 | def initialize(path, type = 'group') 16 | @path = path.to_s 17 | @type = type.to_s 18 | end 19 | 20 | # @return [Bool] Wether a file reference is equal to another. 21 | # 22 | def ==(other) 23 | path == other.path && type == other.type 24 | end 25 | alias_method :eql?, :== 26 | 27 | # @return [Fixnum] A hash identical for equals objects. 28 | # 29 | def hash 30 | [path, type].hash 31 | end 32 | 33 | # Returns a file reference given XML representation. 34 | # 35 | # @param [REXML::Element] xml_node 36 | # the XML representation. 37 | # 38 | # @return [FileReference] The new file reference instance. 39 | # 40 | def self.from_node(xml_node) 41 | type, path = xml_node.attribute('location').value.split(':', 2) 42 | if type == 'group' 43 | path = prepend_parent_path(xml_node, path) 44 | end 45 | new(path, type) 46 | end 47 | 48 | # @return [REXML::Element] the XML representation of the file reference. 49 | # 50 | def to_node 51 | REXML::Element.new('FileRef').tap do |element| 52 | element.add_attribute('location', "#{type}:#{path}") 53 | end 54 | end 55 | 56 | # Returns the absolute path of a file reference given the path of the 57 | # directory containing workspace. 58 | # 59 | # @param [#to_s] workspace_dir_path 60 | # The Path of the directory containing the workspace. 61 | # 62 | # @return [String] The absolute path to the project. 63 | # 64 | def absolute_path(workspace_dir_path) 65 | workspace_dir_path = workspace_dir_path.to_s 66 | case type 67 | when 'group', 'container', 'self' 68 | File.expand_path(File.join(workspace_dir_path, path)) 69 | when 'absolute' 70 | File.expand_path(path) 71 | when 'developer' 72 | raise "Developer workspace file reference type is not yet supported (#{path})" 73 | else 74 | raise "Unsupported workspace file reference type `#{type}`" 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/workspace/group_reference.rb: -------------------------------------------------------------------------------- 1 | require 'xcodeproj/workspace/reference' 2 | 3 | module Xcodeproj 4 | class Workspace 5 | # Describes a group reference of a Workspace. 6 | # 7 | class GroupReference < Reference 8 | # @return [String] the name of the group 9 | # 10 | attr_reader :name 11 | 12 | # @return [String] the location of the group on disk 13 | # 14 | attr_reader :location 15 | 16 | # @param [#to_s] name @see name 17 | # @param [#to_s] type @see type 18 | # @param [#to_s] location @see location 19 | # 20 | def initialize(name, type = 'container', location = '') 21 | @name = name.to_s 22 | @type = type.to_s 23 | @location = location.to_s 24 | end 25 | 26 | # @return [Bool] Whether a group reference is equal to another. 27 | # 28 | def ==(other) 29 | name == other.name && type == other.type && location == other.location 30 | end 31 | alias_method :eql?, :== 32 | 33 | # @return [Fixnum] A hash identical for equals objects. 34 | # 35 | def hash 36 | [name, type, location].hash 37 | end 38 | 39 | # Returns a group reference given XML representation. 40 | # 41 | # @param [REXML::Element] xml_node 42 | # the XML representation. 43 | # 44 | # @return [GroupReference] The new group reference instance. 45 | # 46 | def self.from_node(xml_node) 47 | location_array = xml_node.attribute('location').value.split(':', 2) 48 | type = location_array.first 49 | location = location_array[1] || '' 50 | if type == 'group' 51 | location = prepend_parent_path(xml_node, location) 52 | end 53 | name = xml_node.attribute('name').value 54 | new(name, type, location) 55 | end 56 | 57 | # @return [REXML::Element] the XML representation of the group reference. 58 | # 59 | def to_node 60 | REXML::Element.new('Group').tap do |element| 61 | element.add_attribute('location', "#{type}:#{location}") 62 | element.add_attribute('name', "#{name}") 63 | end 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/workspace/reference.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | class Workspace 3 | # Describes a file/group reference of a Workspace. 4 | # 5 | class Reference 6 | # @return [String] the type of reference to the project 7 | # 8 | # This can be of the following values: 9 | # - absolute 10 | # - group 11 | # - container 12 | # - developer (unsupported) 13 | # 14 | attr_reader :type 15 | 16 | # Returns the relative path to the parent group reference (if one exists) 17 | # prepended to the passed in path. 18 | # 19 | # @param [REXML::Element] xml_node 20 | # the XML representation. 21 | # 22 | # @param [String] path 23 | # the path that will be prepended to. 24 | # 25 | # @return [String] the extended path including the parent node's path. 26 | # 27 | def self.prepend_parent_path(xml_node, path) 28 | if !xml_node.parent.nil? && (xml_node.parent.name == 'Group') 29 | group = GroupReference.from_node(xml_node.parent) 30 | if !group.location.nil? && !group.location.empty? 31 | path = '' if path.nil? 32 | path = File.join(group.location, path) 33 | end 34 | end 35 | 36 | path 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/lib/xcodeproj/xcodebuild_helper.rb: -------------------------------------------------------------------------------- 1 | module Xcodeproj 2 | # Helper class which returns information from xcodebuild. 3 | # 4 | class XcodebuildHelper 5 | def initialize 6 | @needs_to_parse_sdks = true 7 | end 8 | 9 | # @return [String] The version of the last iOS sdk. 10 | # 11 | def last_ios_sdk 12 | parse_sdks_if_needed 13 | versions_by_sdk[:ios].sort.last 14 | end 15 | 16 | # @return [String] The version of the last OS X sdk. 17 | # 18 | def last_osx_sdk 19 | parse_sdks_if_needed 20 | versions_by_sdk[:osx].sort.last 21 | end 22 | 23 | # @return [String] The version of the last tvOS sdk. 24 | # 25 | def last_tvos_sdk 26 | parse_sdks_if_needed 27 | versions_by_sdk[:tvos].sort.last 28 | end 29 | 30 | # @return [String] The version of the last watchOS sdk. 31 | # 32 | def last_watchos_sdk 33 | parse_sdks_if_needed 34 | versions_by_sdk[:watchos].sort.last 35 | end 36 | 37 | private 38 | 39 | # !@group Private Helpers 40 | 41 | #-------------------------------------------------------------------------# 42 | 43 | # @return [Hash] The versions of the sdks grouped by name (`:ios`, or `:osx`). 44 | # 45 | attr_accessor :versions_by_sdk 46 | 47 | # @return [void] Parses the SDKs returned by xcodebuild and stores the 48 | # information in the `needs_to_parse_sdks` hash. 49 | # 50 | def parse_sdks_if_needed 51 | if @needs_to_parse_sdks 52 | @versions_by_sdk = {} 53 | @versions_by_sdk[:osx] = [] 54 | @versions_by_sdk[:ios] = [] 55 | @versions_by_sdk[:tvos] = [] 56 | @versions_by_sdk[:watchos] = [] 57 | if xcodebuild_available? 58 | sdks = parse_sdks_information(xcodebuild_sdks) 59 | sdks.each do |(name, version)| 60 | case 61 | when name == 'macosx' then @versions_by_sdk[:osx] << version 62 | when name == 'iphoneos' then @versions_by_sdk[:ios] << version 63 | when name == 'appletvos' then @versions_by_sdk[:tvos] << version 64 | when name == 'watchos' then @versions_by_sdk[:watchos] << version 65 | end 66 | end 67 | end 68 | end 69 | end 70 | 71 | # @return [Bool] Whether xcodebuild is available. 72 | # 73 | def xcodebuild_available? 74 | if @xcodebuild_available.nil? 75 | `which xcodebuild 2>/dev/null` 76 | @xcodebuild_available = $?.exitstatus.zero? 77 | end 78 | @xcodebuild_available 79 | end 80 | 81 | # @return [Array>] An array of tuples where the first element 82 | # is the name of the SDK and the second is the version. 83 | # 84 | def parse_sdks_information(output) 85 | output.scan(/-sdk (macosx|iphoneos|watchos|appletvos)(.+\w)/) 86 | end 87 | 88 | # @return [String] The sdk information reported by xcodebuild. 89 | # 90 | def xcodebuild_sdks 91 | `xcodebuild -showsdks 2>/dev/null` 92 | end 93 | 94 | #-------------------------------------------------------------------------# 95 | 96 | # @!group Singleton 97 | 98 | # @return [XcodebuildHelper] the current xcodebuild instance creating one 99 | # if needed, which caches the information from the xcodebuild 100 | # command line tool. 101 | # 102 | def self.instance 103 | @instance ||= new 104 | end 105 | 106 | #-------------------------------------------------------------------------# 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /IpaExporter/Libs/Xcodeproj/packer.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | }, 7 | { 8 | "path": "/Users/a4399/Documents/Projects/XcodeExportTest/XcodeProj/Unity-iPhone.xcodeproj/project.xcworkspace" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /IpaExporter/LuaLib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/LuaLib/.DS_Store -------------------------------------------------------------------------------- /IpaExporter/LuaLib/include/lua.hpp: -------------------------------------------------------------------------------- 1 | // lua.hpp 2 | // Lua header files for C++ 3 | // <> not supplied automatically because Lua also compiles as C++ 4 | 5 | extern "C" { 6 | #include "lua.h" 7 | #include "lualib.h" 8 | #include "lauxlib.h" 9 | } 10 | -------------------------------------------------------------------------------- /IpaExporter/LuaLib/include/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | 15 | LUAMOD_API int (luaopen_base) (lua_State *L); 16 | 17 | #define LUA_COLIBNAME "coroutine" 18 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); 19 | 20 | #define LUA_TABLIBNAME "table" 21 | LUAMOD_API int (luaopen_table) (lua_State *L); 22 | 23 | #define LUA_IOLIBNAME "io" 24 | LUAMOD_API int (luaopen_io) (lua_State *L); 25 | 26 | #define LUA_OSLIBNAME "os" 27 | LUAMOD_API int (luaopen_os) (lua_State *L); 28 | 29 | #define LUA_STRLIBNAME "string" 30 | LUAMOD_API int (luaopen_string) (lua_State *L); 31 | 32 | #define LUA_UTF8LIBNAME "utf8" 33 | LUAMOD_API int (luaopen_utf8) (lua_State *L); 34 | 35 | #define LUA_BITLIBNAME "bit32" 36 | LUAMOD_API int (luaopen_bit32) (lua_State *L); 37 | 38 | #define LUA_MATHLIBNAME "math" 39 | LUAMOD_API int (luaopen_math) (lua_State *L); 40 | 41 | #define LUA_DBLIBNAME "debug" 42 | LUAMOD_API int (luaopen_debug) (lua_State *L); 43 | 44 | #define LUA_LOADLIBNAME "package" 45 | LUAMOD_API int (luaopen_package) (lua_State *L); 46 | 47 | 48 | /* open all previous libraries */ 49 | LUALIB_API void (luaL_openlibs) (lua_State *L); 50 | 51 | 52 | 53 | #if !defined(lua_assert) 54 | #define lua_assert(x) ((void)0) 55 | #endif 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /IpaExporter/LuaLib/liblua.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/LuaLib/liblua.a -------------------------------------------------------------------------------- /IpaExporter/zh-Hans.lproj/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GITHZZ/UnityiOSExporter/31c80c7eb1024c47de629d177582e3345aa99e00/IpaExporter/zh-Hans.lproj/.DS_Store -------------------------------------------------------------------------------- /IpaExporterTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /IpaExporterTests/IpaExporterTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // IpaExporterTests.m 3 | // IpaExporterTests 4 | // 5 | // Created by 何遵祖 on 2016/8/31. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IpaExporterTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation IpaExporterTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /IpaExporterUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | zh_CN 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /IpaExporterUITests/IpaExporterUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // IpaExporterUITests.m 3 | // IpaExporterUITests 4 | // 5 | // Created by 何遵祖 on 2016/8/31. 6 | // Copyright © 2016年 何遵祖. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IpaExporterUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation IpaExporterUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## iOS打包工具(IpaExporter) 2 | ### 一.功能简述 3 | #### 主体界面如下,按编号进行逐一解释: 4 | ![示例图1](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc1.png) 5 | ##### 1、Unity工程路径和导出路径 6 | * 工程路径必须选择,否则会无法选择场景等文件,打包会受到影响 7 | * 导出路径,此路径是导出xcode工程和日志文件,注意该路径也是必须选择,否则会导出xcode工程出错。 8 | 9 | ##### 2、需要打包平台,该平台列表是根据另一个界面配置显示,如下图: 10 | ![示例图1](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc2.png) 11 | 同样依据编号解释每块功能: 12 | * **1.platformName - 平台名字 该名字用户自定义,用户区分平台。** 13 | * **2.AppName - 应用名字 该名字由用户定义,用于定义包名。** 14 | * **3.Bundle Identifier - 唯一标识符,苹果证书里面的bundleid,该名字直接读取证书获取,在具体配置界面可以填写,后面具体解析。** 15 | * **4.添加新平台信息,会跳到配置界面。** 16 | * **5.删除平台信息,依据用户选择当前行删除。** 17 | * **6.依据用户选择当前行选择进行信息编辑。** 18 | 19 | 平台具体信息编辑界面如下: 20 | 21 | ![857e346ff936adba912b740bd32a11ad.png](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc3.png) 22 | ![27a276bd1f39c67f5061d902876ca971.png](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc4.png) 23 | ![1353e16520e015483e7b58c25e0e8b8f.png](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc5.png) 24 | ![71484fb0fef124f023e183f6fa00c7f9.png](https://github.com/GITHZZ/UnityiOSExporter/blob/master/Doc/doc6.png) 25 | 自上而下的进行参数解析: 26 | * platformName - 平台名字 该名字用户自定义,用户区分平台 27 | * AppName - 应用名字 该名字由用户定义,用于定义包名。 28 | * 证书信息选择 - 选择provisionProfile文件,工具会把相关信息解析出来。(后续会具体解析这块) 29 | * Copy Directory Root Path - 拷贝的sdk代码资源等跟目录。(后续会具体解析这块) 30 | * Copy Folder - 相对上个参数而言,选择具体需要关联的sdk目录。 31 | * Frameworks - 系统库 32 | * Embed Frameworks - 动态库 33 | * Libs - 静态库 34 | * Linker Flag - 链接库额外参数 35 | 36 | ##### 3、需要打包场景,点击选择会自动筛选可以打包场景,以.unity后缀判断。点击之后会打开一个界面,选择需要打包的场景即可。 37 | ##### 4、打包具体功能,提供可以分开打xcode和ipa,也可以直接一键打出ipa(每个项目情况不一样,所以这么干了)。 38 | --------------------------------------------------------------------------------