def build_modules_info(self, resources_dir, app_bin_dir): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir)) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: module_bindings.append(method[len(module)+1:]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] break if module_apiName == None: continue # module wasn't found if '.' not in module: ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': module_bindings, 'external_child_modules': ext_modules }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp, 'android') for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id'] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_id = module_bindings['proxies'][module_class]['proxyAttrs']['id'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'class_name': module_class, 'manifest': module.manifest })
def compileProject(self, xcode=False, devicefamily='ios', iphone_version='iphoneos', silent=False, sdk=None): tiapp_xml = os.path.join(self.project_dir, 'tiapp.xml') ti = TiAppXML(tiapp_xml) if sdk is None: sdk_version = os.path.basename( os.path.abspath(os.path.join(template_dir, '../'))) else: sdk_version = sdk if xcode: app_name = os.environ['FULL_PRODUCT_NAME'] app_dir = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['CONTENTS_FOLDER_PATH']) else: target = 'Debug' if self.deploytype == 'production': target = 'Release' app_name = self.project_name + '.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath( os.path.join(self.iphone_dir, 'build', app_folder_name, app_name)) if not silent: print "[INFO] Titanium SDK version: %s" % sdk_version print "[INFO] iPhone Device family: %s" % devicefamily print "[INFO] iPhone SDK version: %s" % iphone_version if self.deploytype != 'export-build': main_template_file = os.path.join(template_dir, 'main.m') main_template = codecs.open(main_template_file, encoding='utf-8').read() main_template = main_template.replace('__PROJECT_NAME__', self.project_name) main_template = main_template.replace('__PROJECT_ID__', self.appid) main_template = main_template.replace('__DEPLOYTYPE__', self.deploytype) main_template = main_template.replace('__APP_ID__', self.appid) main_template = main_template.replace('__APP_ANALYTICS__', ti.properties['analytics']) main_template = main_template.replace('__APP_PUBLISHER__', ti.properties['publisher']) main_template = main_template.replace('__APP_URL__', ti.properties['url']) main_template = main_template.replace('__APP_NAME__', ti.properties['name']) main_template = main_template.replace('__APP_VERSION__', ti.properties['version']) main_template = main_template.replace('__APP_DESCRIPTION__', ti.properties['description']) main_template = main_template.replace('__APP_COPYRIGHT__', ti.properties['copyright']) main_template = main_template.replace('__APP_GUID__', ti.properties['guid']) main_template = main_template.replace('__APP_RESOURCE_DIR__', '') main_template_out = os.path.join(self.iphone_dir, 'main.m') main_file = codecs.open(main_template_out, 'w+', encoding='utf-8') main_file_contents = main_file.read() if main_file_contents != main_template: main_file.write(main_template) main_file.close() resources_dir = os.path.join(self.project_dir, 'Resources') iphone_resources_dir = os.path.join(resources_dir, 'iphone') iphone_platform_dir = os.path.join(self.project_dir, 'platform', 'iphone') # copy in any resources in our module like icons # NOTE: This means that any JS-only modules in the local project # are hashed up and dumped into the export. has_modules = False missing_modules, modules, module_js = ([], [], []) module_js_dir = os.path.join(self.project_dir, 'modules') if os.path.exists(module_js_dir): for file in os.listdir(module_js_dir): if file.endswith('.js'): module_js.append({ 'from': os.path.join(module_js_dir, file), 'to': os.path.join(app_dir, file), 'path': 'modules/' + file }) if self.deploytype != 'export-build': # Have to load the module detection here, in order to # prevent distributing even MORE stuff in export/transport sys.path.append(os.path.join(template_dir, '../module')) from module import ModuleDetector detector = ModuleDetector(self.project_dir) missing_modules, modules = detector.find_app_modules(ti, 'iphone') # we have to copy these even in simulator given the path difference if os.path.exists(app_dir): self.copy_resources([iphone_resources_dir], app_dir, False) if os.path.exists(app_dir): self.copy_resources([iphone_platform_dir], app_dir, False) # generate the includes for all compiled modules xcconfig_c = "// this is a generated file - DO NOT EDIT\n\n" if len(modules) > 0: mods = open( os.path.join(self.classes_dir, 'ApplicationMods.m'), 'w+') variables = {} mods.write(MODULE_IMPL_HEADER) for module in modules: if module.js: # CommonJS module module_js.append({ 'from': module.js, 'path': 'modules/' + os.path.basename(module.js) }) module_id = module.manifest.moduleid.lower() module_name = module.manifest.name.lower() module_version = module.manifest.version module_guid = '' module_licensekey = '' if module.manifest.has_property('guid'): module_guid = module.manifest.guid if module.manifest.has_property('licensekey'): module_licensekey = module.manifest.licensekey self.modules_metadata.append({ 'guid': module_guid, 'name': module_name, 'id': module_id, 'dir': module.path, 'version': module_version, 'licensekey': module_licensekey }) xcfile = module.get_resource('module.xcconfig') if os.path.exists(xcfile): xcconfig_contents = parse_xcconfig( xcfile, module_id, variables) xcconfig_c += xcconfig_contents xcfile = os.path.join(self.project_dir, 'modules', 'iphone', "%s.xcconfig" % module_name) if os.path.exists(xcfile): xcconfig_contents = parse_xcconfig( xcfile, module_id, variables) xcconfig_c += xcconfig_contents mods.write( " [modules addObject:[NSDictionary dictionaryWithObjectsAndKeys:@\"%s\",@\"name\",@\"%s\",@\"moduleid\",@\"%s\",@\"version\",@\"%s\",@\"guid\",@\"%s\",@\"licensekey\",nil]];\n" % (module_name, module_id, module_version, module_guid, module_licensekey)) # Load export symbols from modules... metadata_path = os.path.join(module.path, 'metadata.json') if os.path.exists(metadata_path): self.load_metadata(metadata_path) mods.write(" return modules;\n") mods.write("}\n") mods.write(FOOTER) mods.close() for (name, values) in variables.iteritems(): xcconfig_c += name + '=$(inherited) ' for value in values: xcconfig_c += '$(%s) ' % value xcconfig_c += '\n' has_modules = True xcconfig = os.path.join(self.iphone_dir, "module.xcconfig") make_xcc = True if os.path.exists(xcconfig): existing_xcc = open(xcconfig).read() # only copy if different so we don't trigger re-compile in xcode make_xcc = existing_xcc != xcconfig_c if make_xcc: xcconfig = open(xcconfig, 'w') xcconfig.write(xcconfig_c) xcconfig.close() #endif deploytype != 'export-build' else: # ... And for exported projects, load export symbols from # the 'metadata' dir. metadata_dir = os.path.join(self.iphone_dir, 'metadata') if os.path.isdir(metadata_dir): for file in os.listdir(metadata_dir): self.load_metadata(os.path.join(metadata_dir, file)) if self.deploytype == 'simulator' or self.deploytype == 'export': shutil.copy(os.path.join(template_dir, 'Classes', 'defines.h'), os.path.join(self.classes_dir, 'defines.h')) if self.deploytype != 'development' or has_modules: if os.path.exists(app_dir) and self.deploytype != 'development': self.copy_resources([resources_dir], app_dir, self.deploytype != 'test', module_js) if self.deploytype == 'production': debugger_plist = os.path.join(app_dir, 'debugger.plist') if os.path.exists(debugger_plist): os.remove(debugger_plist) if self.deploytype != 'development' and self.deploytype != 'export': defines_file = os.path.join(self.classes_dir, 'defines.h') defines_header = open(defines_file, 'w+') defines_content = "// Warning: this is generated file. Do not modify!\n\n" defines_content += "#define TI_VERSION %s\n" % sdk_version for sym in self.defines: defines_content += "#define %s\n" % sym if defines_content != defines_header.read(): defines_header.write(defines_content) defines_header.close() # deploy any module image files for module in self.modules: img_dir = os.path.join(template_dir, 'modules', module.lower(), 'images') print "[DEBUG] module image = %s" % img_dir if not os.path.exists(img_dir): continue dest_img_dir = os.path.join(app_dir, 'modules', module.lower(), 'images') if not os.path.exists(dest_img_dir): os.makedirs(dest_img_dir) self.copy_resources([img_dir], dest_img_dir, False) if self.deploytype != 'development' and os.path.exists(app_dir): # optimize PNGs - since we don't include them in the Resources of the xcodeproj # the ones we copy in won't get optimized so we need to run it manually # we can skip this on the simulator but should do it on device dev_path = "/Developer" # we need to ask xcode where the root path is path = run.run(["/usr/bin/xcode-select", "-print-path"], True, False) if path: dev_path = path.strip() run.run([ "%s/Platforms/iPhoneOS.platform/Developer/usr/bin/iphoneos-optimize" % dev_path, app_dir ], False) # remove empty directories os.chdir(app_dir) os.system("find . -type d -empty -delete") else: print "[INFO] Skipping JS compile, running from simulator" if self.deploytype == 'development': softlink_for_simulator(self.project_dir, app_dir)
def build_modules_info(self, resources_dir, app_bin_dir, include_all_ti_modules=False): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, None, os.path.dirname(app_bin_dir), include_all_modules=include_all_ti_modules) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module + '.') and '.' not in method: module_bindings.append(method[len(module) + 1:]) module_onAppCreate = None module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] if 'onAppCreate' in modules[m]: module_onAppCreate = modules[m]['onAppCreate'] break if module_apiName == None: continue # module wasn't found ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': module_bindings, 'external_child_modules': ext_modules, 'on_app_create': module_onAppCreate }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules( self.tiapp, 'android', self.deploy_type) for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id'] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_apiName = module_bindings['modules'][module_class][ 'apiName'] module_proxy = module_bindings['proxies'][module_class] module_id = module_proxy['proxyAttrs']['id'] module_proxy_class_name = module_proxy['proxyClassName'] module_onAppCreate = None if 'onAppCreate' in module_proxy: module_onAppCreate = module_proxy['onAppCreate'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: # make sure that the module was not built before 1.8.0.1 try: module_api_version = int(module.manifest.apiversion) if module_api_version < 2: print "[ERROR] The 'apiversion' for '%s' in the module manifest is less than version 2. The module was likely built against a Titanium SDK pre 1.8.0.1. Please use a version of the module that has 'apiversion' 2 or greater" % module_id touch_tiapp_xml( os.path.join(self.project_dir, 'tiapp.xml')) sys.exit(1) except (TypeError, ValueError): print "[ERROR] The 'apiversion' for '%s' in the module manifest is not a valid value. Please use a version of the module that has an 'apiversion' value of 2 or greater set in it's manifest file" % module_id touch_tiapp_xml( os.path.join(self.project_dir, 'tiapp.xml')) sys.exit(1) is_native_js_module = (hasattr(module.manifest, 'commonjs') and module.manifest.commonjs) print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'module_id': module_id, 'module_apiName': module_apiName, 'proxy_name': module_proxy_class_name, 'class_name': module_class, 'manifest': module.manifest, 'on_app_create': module_onAppCreate, 'is_native_js_module': is_native_js_module }) if is_native_js_module: # Need to look at the app modules used in this external js module metadata_file = os.path.join(module.path, "metadata.json") metadata = None try: f = open(metadata_file, "r") metadata = f.read() finally: f.close() if metadata: metadata = simplejson.loads(metadata) if metadata.has_key("exports"): exported_module_ids = metadata["exports"] already_included_module_ids = [ m["api_name"].lower() for m in self.app_modules ] need_to_add = [ m for m in exported_module_ids if m not in already_included_module_ids ] if need_to_add: for to_add in need_to_add: module_onAppCreate = None module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower( ) == to_add: module_class = m module_apiName = modules[m][ 'fullAPIName'] if 'onAppCreate' in modules[m]: module_onAppCreate = modules[ m]['onAppCreate'] break if module_apiName == None: continue # module wasn't found ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[ module_class]: if child_module[ 'fullAPIName'].lower( ) in compiler.modules: ext_modules.append( child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': [], 'external_child_modules': ext_modules, 'on_app_create': module_onAppCreate })
def main(args): if len(args) < 2: print "Usage: %s <project_directory> [sdk_verison]" % os.path.basename( args[0]) sys.exit(1) # What needs to be done in order to perform a "true" export? # --- # Wipe the build dir # Migrate resources # Migrate tiapp.xml (required for scripts) # Generate project from template # Populate Info.plist # Compile/migrate i18n # Migrate scripts for compiling JSS files (and i18n) # Modify xcodeproj build steps to call the JSS compiler # Then... Share and Enjoy. project_dir = os.path.abspath(args[1]) build_dir = os.path.join(project_dir, 'build', 'iphone') titanium_local = os.path.join(build_dir, 'titanium') if len(args) == 3: version = args[2] sdk_dir = find_sdk(version) else: sdk_dir = os.path.abspath(os.path.dirname(template_dir)) version = os.path.basename(sdk_dir) tiappxml = os.path.join(project_dir, 'tiapp.xml') tiapp = TiAppXML(tiappxml) app_id = tiapp.properties['id'] app_name = tiapp.properties['name'] if app_id is None or app_name is None: info("Your tiapp.xml is malformed - please specify an app name and id") sys.exit(1) # Clean build dir (if it exists), error otherwise (no iphone support) info("Cleaning build...") if os.path.exists(build_dir): for f in os.listdir(build_dir): path = os.path.join(build_dir, f) if os.path.isfile(path): os.remove(path) else: shutil.rmtree(path) else: info("Your project is not configured to be built for iphone.") exit(1) # Migrate Resources info("Migrating resources...") project_resources = os.path.join(project_dir, 'Resources') resources_dir = os.path.join(build_dir, 'Resources') shutil.copytree(project_resources, resources_dir) # Migrate platform/iphone contents into Resources. info("Migrating platform/iphone to Resources...") project_platform = os.path.join(project_dir, 'platform', 'iphone') if os.path.isdir(project_platform): contents = os.listdir(project_platform) for file in contents: path = os.path.join(project_platform, file) if os.path.isdir(path): shutil.copytree(path, os.path.join(resources_dir, file)) else: shutil.copy(path, os.path.join(resources_dir, file)) # Migrate tiapp.xml info("Migrating tiapp.xml...") shutil.copy(tiappxml, build_dir) # Generate project stuff from the template info("Generating project from Titanium template...") project = Projector(app_name, version, template_dir, project_dir, app_id) project.create(template_dir, build_dir) # Because the debugger.plist is built as part of the required # resources, we need to autogen an empty one debug_plist = os.path.join(resources_dir, 'debugger.plist') force_xcode = write_debugger_plist(None, None, template_dir, debug_plist) # Populate Info.plist applogo = None info("Populating Info.plist...") plist_out = os.path.join(build_dir, 'Info.plist') create_info_plist(tiapp, template_dir, project_dir, plist_out) applogo = tiapp.generate_infoplist(plist_out, app_id, 'iphone', project_dir, None) # Run the compiler to autogenerate .m files info("Copying classes, creating generated .m files...") compiler = Compiler(project_dir, app_id, app_name, 'export') compiler.compileProject(silent=True) #... But we still have to nuke the stuff that gets built that we don't want # to bundle. ios_build = os.path.join(build_dir, 'build') if os.path.isdir(ios_build): shutil.rmtree(os.path.join(build_dir, 'build')) # Install applogo/splash/etc. info("Copying icons and splash...") install_logo(tiapp, applogo, project_dir, template_dir, resources_dir) install_defaults(project_dir, template_dir, resources_dir) # Get Modules detector = ModuleDetector(project_dir) missing_modules, modules = detector.find_app_modules(tiapp, 'iphone') if len(missing_modules) != 0: for module in missing_modules: info("MISSING MODULE: %s ... Project will not build correctly" % module['id']) info("Terminating export: Please fix your modules.") sys.exit(1) module_search_path, module_asset_dirs = locate_modules( modules, project_dir, resources_dir, info) lib_dir = os.path.join(build_dir, 'lib') if not os.path.exists(lib_dir): os.makedirs(lib_dir) if len(module_search_path) > 0: info("Copying modules...") for module in module_search_path: module_name, module_path = module info("\t%s..." % module_name) shutil.copy(os.path.join(module_path, module_name), lib_dir) module[1] = os.path.join(lib_dir, module_name) info("Copying module metadata...") metadata_dir = os.path.join(build_dir, 'metadata') for module in modules: module_metadata = os.path.join(module.path, 'metadata.json') if os.path.exists(module_metadata): if not os.path.exists(metadata_dir): os.makedirs(metadata_dir) target = os.path.join(metadata_dir, "%s.json" % module.manifest.moduleid) shutil.copyfile(module_metadata, target) # Note: The module link information has to be added to # the xcodeproj after it's created. # We also have to mod the module_search_path to reference # the local 'lib' directory instead of the original # module install location info("Linking modules...") local_modules = [] for module in module_search_path: name = module[0] newpath = os.path.join('lib', name) local_modules.append([name, newpath]) link_modules(local_modules, app_name, build_dir, relative=True) # Copy libraries info("Copying libraries...") iphone_dir = os.path.join(sdk_dir, 'iphone') for lib in glob.iglob(os.path.join(iphone_dir, 'lib*')): info("\t%s..." % lib) shutil.copy(lib, lib_dir) # Process i18n files info("Processing i18n...") locale_compiler = LocaleCompiler(app_name, project_dir, 'ios', 'development', resources_dir) locale_compiler.compile() # Migrate compile scripts info("Copying custom Titanium compiler scripts...") shutil.copytree(os.path.join(sdk_dir, 'common'), titanium_local) shutil.copy(os.path.join(sdk_dir, 'tiapp.py'), titanium_local) iphone_script_dir = os.path.join(titanium_local, 'iphone') os.mkdir(iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'compiler.py'), iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'tools.py'), iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'run.py'), iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'csspacker.py'), iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'jspacker.py'), iphone_script_dir) shutil.copy(os.path.join(sdk_dir, 'iphone', 'titanium_prep'), iphone_script_dir) # Add compilation to the build script in project info("Modifying pre-compile stage...") xcodeproj = os.path.join(build_dir, '%s.xcodeproj' % app_name, 'project.pbxproj') contents = codecs.open(xcodeproj, 'r', encoding='utf-8').read() css_compiler = os.path.join('titanium', 'css', 'csscompiler.py') ti_compiler = os.path.join('titanium', 'iphone', 'compiler.py') script = """%s . ios Resources %s . export-build $TARGETED_DEVICE_FAMILY $SDKROOT %s""" % ( css_compiler, ti_compiler, version) contents = fix_xcode_script(contents, "Pre-Compile", script) # write our new project f = codecs.open(xcodeproj, 'w', encoding='utf-8') f.write(contents) f.close() info("Finished! Share and Enjoy.")
def __init__(self, project_dir, appid, name, deploytype, xcode, devicefamily, iphone_version, silent=False): self.project_dir = project_dir self.project_name = name self.appid = appid self.iphone_dir = os.path.join(project_dir, 'build', 'iphone') self.classes_dir = os.path.join(self.iphone_dir, 'Classes') self.modules = [] self.modules_metadata = [] # for now, these are required self.defines = [ 'USE_TI_ANALYTICS', 'USE_TI_NETWORK', 'USE_TI_PLATFORM', 'USE_TI_UI' ] tiapp_xml = os.path.join(project_dir, 'tiapp.xml') ti = TiAppXML(tiapp_xml) sdk_version = os.path.basename( os.path.abspath(os.path.join(template_dir, '../'))) detector = ModuleDetector(project_dir) missing_modules, modules = detector.find_app_modules(ti, 'iphone') if xcode: app_name = os.environ['FULL_PRODUCT_NAME'] app_dir = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['CONTENTS_FOLDER_PATH']) else: target = 'Debug' if deploytype == 'install': target = 'Release' app_name = name + '.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath( os.path.join(self.iphone_dir, 'build', app_folder_name, app_name)) main_template_file = os.path.join(template_dir, 'main.m') main_template = codecs.open(main_template_file, encoding='utf-8').read() main_template = main_template.replace('__PROJECT_NAME__', name) main_template = main_template.replace('__PROJECT_ID__', appid) main_template = main_template.replace('__DEPLOYTYPE__', deploytype) main_template = main_template.replace('__APP_ID__', appid) main_template = main_template.replace('__APP_ANALYTICS__', ti.properties['analytics']) main_template = main_template.replace('__APP_PUBLISHER__', ti.properties['publisher']) main_template = main_template.replace('__APP_URL__', ti.properties['url']) main_template = main_template.replace('__APP_NAME__', ti.properties['name']) main_template = main_template.replace('__APP_VERSION__', ti.properties['version']) main_template = main_template.replace('__APP_DESCRIPTION__', ti.properties['description']) main_template = main_template.replace('__APP_COPYRIGHT__', ti.properties['copyright']) main_template = main_template.replace('__APP_GUID__', ti.properties['guid']) if deploytype == 'development': main_template = main_template.replace( '__APP_RESOURCE_DIR__', os.path.abspath(os.path.join(project_dir, 'Resources'))) else: main_template = main_template.replace('__APP_RESOURCE_DIR__', '') if not silent: print "[INFO] Titanium SDK version: %s" % sdk_version print "[INFO] iPhone Device family: %s" % devicefamily print "[INFO] iPhone SDK version: %s" % iphone_version main_template_out = os.path.join(self.iphone_dir, 'main.m') main_file = codecs.open(main_template_out, 'w+', encoding='utf-8') main_file_contents = main_file.read() if main_file_contents != main_template: main_file.write(main_template) main_file.close() if deploytype == 'production': version = ti.properties['version'] # we want to make sure in debug mode the version always changes version = "%s.%d" % (version, time.time()) ti.properties['version'] = version resources_dir = os.path.join(project_dir, 'Resources') iphone_resources_dir = os.path.join(resources_dir, 'iphone') # copy in any resources in our module like icons project_module_dir = os.path.join(project_dir, 'modules', 'iphone') if os.path.exists(project_module_dir): self.copy_resources([project_module_dir], app_dir, False) # we have to copy these even in simulator given the path difference if os.path.exists(app_dir): self.copy_resources([iphone_resources_dir], app_dir, False) # generate the includes for all compiled modules xcconfig_c = "// this is a generated file - DO NOT EDIT\n\n" has_modules = False if len(modules) > 0: mods = open(os.path.join(self.classes_dir, 'ApplicationMods.m'), 'w+') mods.write(MODULE_IMPL_HEADER) for module in modules: module_id = module.manifest.moduleid.lower() module_name = module.manifest.name.lower() module_version = module.manifest.version module_guid = '' module_licensekey = '' if module.manifest.has_property('guid'): module_guid = module.manifest.guid if module.manifest.has_property('licensekey'): module_licensekey = module.manifest.licensekey self.modules_metadata.append({ 'guid': module_guid, 'name': module_name, 'id': module_id, 'dir': module.path, 'version': module_version, 'licensekey': module_licensekey }) xcfile = module.get_resource('module.xcconfig') if os.path.exists(xcfile): xcconfig_c += "#include \"%s\"\n" % xcfile xcfile = os.path.join(self.project_dir, 'modules', 'iphone', "%s.xcconfig" % module_name) if os.path.exists(xcfile): xcconfig_c += "#include \"%s\"\n" % xcfile mods.write( " [modules addObject:[NSDictionary dictionaryWithObjectsAndKeys:@\"%s\",@\"name\",@\"%s\",@\"moduleid\",@\"%s\",@\"version\",@\"%s\",@\"guid\",@\"%s\",@\"licensekey\",nil]];\n" % (module_name, module_id, module_version, module_guid, module_licensekey)) mods.write(" return modules;\n") mods.write("}\n") mods.write(FOOTER) mods.close() has_modules = True xcconfig = os.path.join(self.iphone_dir, "module.xcconfig") make_xcc = True if os.path.exists(xcconfig): existing_xcc = open(xcconfig).read() # only copy if different so we don't trigger re-compile in xcode make_xcc = existing_xcc != xcconfig_c if make_xcc: xcconfig = open(xcconfig, 'w') xcconfig.write(xcconfig_c) xcconfig.close() if deploytype == 'simulator': shutil.copy(os.path.join(template_dir, 'Classes', 'defines.h'), os.path.join(self.classes_dir, 'defines.h')) if deploytype != 'development' or has_modules: if os.path.exists(app_dir): self.copy_resources([resources_dir], app_dir) if deploytype != 'development': defines_file = os.path.join(self.classes_dir, 'defines.h') defines_header = open(defines_file, 'w+') defines_content = "// Warning: this is generated file. Do not modify!\n\n" defines_content += "#define TI_VERSION %s\n" % sdk_version for sym in self.defines: defines_content += "#define %s 1\n" % sym if defines_content != defines_header.read(): defines_header.write(defines_content) defines_header.close() # deploy any module image files for module in self.modules: img_dir = os.path.join(template_dir, 'modules', module.lower(), 'images') print "[DEBUG] module image = %s" % img_dir if not os.path.exists(img_dir): continue dest_img_dir = os.path.join(app_dir, 'modules', module.lower(), 'images') if not os.path.exists(dest_img_dir): os.makedirs(dest_img_dir) self.copy_resources([img_dir], dest_img_dir, False) if deploytype != 'development' and os.path.exists(app_dir): # optimize PNGs - since we don't include them in the Resources of the xcodeproj # the ones we copy in won't get optimized so we need to run it manually # we can skip this on the simulator but should do it on device dev_path = "/Developer" # we need to ask xcode where the root path is path = run.run(["/usr/bin/xcode-select", "-print-path"], True, False) if path: dev_path = path.strip() run.run([ "%s/Platforms/iPhoneOS.platform/Developer/usr/bin/iphoneos-optimize" % dev_path, app_dir ], False) # remove empty directories os.chdir(app_dir) os.system("find . -type d -empty -delete") else: print "[INFO] Skipping JS compile, running from simulator"