3 # Copyright (c) 2013, 2014 Intel Corporation. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 # pylint: disable=F0401
8 import compress_js_and_css
17 sys.path.append('scripts/gyp')
18 from customize import ReplaceInvalidChars
19 from dex import AddExeExtensions
20 from handle_permissions import permission_mapping_table
21 from manifest_json_parser import HandlePermissionList
22 from manifest_json_parser import ManifestJsonParser
25 if os.path.exists(path):
29 def RunCommand(command, shell=False):
30 """Runs the command list, print the output, and propagate its result."""
31 proc = subprocess.Popen(command, stdout=subprocess.PIPE,
32 stderr=subprocess.STDOUT, shell=shell)
34 output = proc.communicate()[0]
35 result = proc.returncode
36 print(output.decode("utf-8"))
38 print ('Command "%s" exited with non-zero exit code %d'
39 % (' '.join(command), result))
44 """Search PATH for executable files with the given name."""
46 exts = [_f for _f in os.environ.get('PATHEXT', '').split(os.pathsep) if _f]
47 path = os.environ.get('PATH', None)
50 for p in os.environ.get('PATH', '').split(os.pathsep):
51 p = os.path.join(p, name)
52 if os.access(p, os.X_OK):
56 if os.access(pext, os.X_OK):
62 """Find executable file with the given name
63 and maximum API level under specific path."""
65 for root, _, files in os.walk(path):
67 key = os.path.join(root, name)
68 sdk_version = os.path.basename(os.path.dirname(key))
69 str_num = re.search(r'\d+', sdk_version)
71 result[key] = int(str_num.group())
76 return max(iter(result.items()), key=operator.itemgetter(1))[0]
80 """Get the version of this python tool."""
81 version_str = 'Crosswalk app packaging tool version is '
82 file_handle = open(path, 'r')
83 src_content = file_handle.read()
84 version_nums = re.findall(r'\d+', src_content)
85 version_str += ('.').join(version_nums)
90 def ParseManifest(options):
91 parser = ManifestJsonParser(os.path.expanduser(options.manifest))
92 if not options.package:
93 options.package = 'org.xwalk.' + parser.GetAppName().lower()
95 options.name = parser.GetAppName()
96 if not options.app_version:
97 options.app_version = parser.GetVersion()
98 if not options.app_versionCode and not options.app_versionCodeBase:
99 options.app_versionCode = 1
100 if parser.GetDescription():
101 options.description = parser.GetDescription()
102 if parser.GetPermissions():
103 options.permissions = parser.GetPermissions()
104 if parser.GetAppUrl():
105 options.app_url = parser.GetAppUrl()
106 elif parser.GetAppLocalPath():
107 options.app_local_path = parser.GetAppLocalPath()
109 print('Error: there is no app launch path defined in manifest.json.')
111 if parser.GetAppRoot():
112 options.app_root = parser.GetAppRoot()
113 temp_dict = parser.GetIcons()
115 icon_dict = dict((int(k), v) for k, v in temp_dict.items())
117 print('The key of icon in the manifest file should be a number.')
118 # TODO(junmin): add multiple icons support.
120 icon_file = max(iter(icon_dict.items()), key=operator.itemgetter(0))[1]
121 options.icon = os.path.join(options.app_root, icon_file)
122 if parser.GetFullScreenFlag().lower() == 'true':
123 options.fullscreen = True
124 elif parser.GetFullScreenFlag().lower() == 'false':
125 options.fullscreen = False
126 if parser.GetLaunchScreenImg():
127 options.launch_screen_img = os.path.join(options.app_root,
128 parser.GetLaunchScreenImg())
131 def ParseXPK(options, out_dir):
132 cmd = ['python', 'parse_xpk.py',
133 '--file=%s' % os.path.expanduser(options.xpk),
134 '--out=%s' % out_dir]
137 print ('Use the manifest from XPK by default '
138 'when "--xpk" option is specified, and '
139 'the "--manifest" option would be ignored.')
142 if os.path.isfile(os.path.join(out_dir, 'manifest.json')):
143 options.manifest = os.path.join(out_dir, 'manifest.json')
145 print('XPK doesn\'t contain manifest file.')
149 def FindExtensionJars(root_path):
150 ''' Find all .jar files for external extensions. '''
152 if not os.path.exists(root_path):
153 return extension_jars
155 for afile in os.listdir(root_path):
156 if os.path.isdir(os.path.join(root_path, afile)):
157 base_name = os.path.basename(afile)
158 extension_jar = os.path.join(root_path, afile, base_name + '.jar')
159 if os.path.isfile(extension_jar):
160 extension_jars.append(extension_jar)
161 return extension_jars
163 # Follows the recommendation from
164 # http://software.intel.com/en-us/blogs/2012/11/12/how-to-publish-
165 # your-apps-on-google-play-for-x86-based-android-devices-using
166 def MakeVersionCode(options):
167 ''' Construct a version code'''
168 if options.app_versionCode:
169 return '--app-versionCode=%s' % options.app_versionCode
171 # First digit is ABI, ARM=2, x86=6
173 if options.arch == 'arm':
175 if options.arch == 'x86':
178 if options.app_versionCodeBase:
179 b = str(options.app_versionCodeBase)
181 print('Version code base must be 7 digits or less: '
182 'versionCodeBase=%s' % (b))
184 # zero pad to 7 digits, middle digits can be used for other
185 # features, according to recommendation in URL
186 return '--app-versionCode=%s%s' % (abi, b.zfill(7))
188 def Customize(options):
189 package = '--package=org.xwalk.app.template'
191 package = '--package=%s' % options.package
192 name = '--name=AppTemplate'
194 name = '--name=%s' % options.name
195 app_version = '--app-version=1.0.0'
196 if options.app_version:
197 app_version = '--app-version=%s' % options.app_version
198 app_versionCode = MakeVersionCode(options)
200 if options.description:
201 description = '--description=%s' % options.description
203 if options.permissions:
204 permissions = '--permissions=%s' % options.permissions
207 icon = '--icon=%s' % os.path.expanduser(options.icon)
210 app_url = '--app-url=%s' % options.app_url
213 app_root = '--app-root=%s' % os.path.expanduser(options.app_root)
215 if options.app_local_path:
216 app_local_path = '--app-local-path=%s' % options.app_local_path
217 remote_debugging = ''
218 if options.enable_remote_debugging:
219 remote_debugging = '--enable-remote-debugging'
221 if options.fullscreen:
222 fullscreen_flag = '-f'
224 if options.extensions:
225 extensions_list = '--extensions=%s' % options.extensions
226 orientation = '--orientation=unspecified'
227 if options.orientation:
228 orientation = '--orientation=%s' % options.orientation
230 if options.launch_screen_img:
231 default_image = '--launch-screen-img=' + options.launch_screen_img
232 cmd = ['python', 'customize.py', package,
233 name, app_version, app_versionCode, description, icon, permissions,
234 app_url, remote_debugging, app_root, app_local_path, fullscreen_flag,
235 extensions_list, orientation, default_image]
239 def Execution(options, sanitized_name):
240 android_path_array = Which('android')
241 if not android_path_array:
242 print('Please install Android SDK first.')
245 sdk_root_path = os.path.dirname(os.path.dirname(android_path_array[0]))
248 sdk_jar_path = Find('android.jar', os.path.join(sdk_root_path, 'platforms'))
250 print('Your Android SDK may be ruined, please reinstall it.')
253 level_string = os.path.basename(os.path.dirname(sdk_jar_path))
254 api_level = int(re.search(r'\d+', level_string).group())
256 print('Please install Android API level (>=14) first.')
259 if options.keystore_path:
260 key_store = os.path.expanduser(options.keystore_path)
261 if options.keystore_alias:
262 key_alias = options.keystore_alias
264 print('Please provide an alias name of the developer key.')
266 if options.keystore_passcode:
267 key_code = options.keystore_passcode
269 print('Please provide the passcode of the developer key.')
272 print ('Use xwalk\'s keystore by default for debugging. '
273 'Please switch to your keystore when distributing it to app market.')
274 key_store = 'scripts/ant/xwalk-debug.keystore'
275 key_alias = 'xwalkdebugkey'
276 key_code = 'xwalkdebug'
278 if not os.path.exists('out'):
281 # Make sure to use ant-tasks.jar correctly.
282 # Default Android SDK names it as ant-tasks.jar
283 # Chrome third party Android SDk names it as anttasks.jar
284 ant_tasks_jar_path = os.path.join(sdk_root_path,
285 'tools', 'lib', 'ant-tasks.jar')
286 if not os.path.exists(ant_tasks_jar_path):
287 ant_tasks_jar_path = os.path.join(sdk_root_path,
288 'tools', 'lib' ,'anttasks.jar')
291 for aapt_str in AddExeExtensions('aapt'):
293 aapt_path = Find(aapt_str, sdk_root_path)
294 print('Use %s in %s.' % (aapt_str, sdk_root_path))
297 print('There doesn\'t exist %s in %s.' % (aapt_str, sdk_root_path))
299 print('Your Android SDK may be ruined, please reinstall it.')
302 # Check whether ant is installed.
304 cmd = ['ant', '-version']
305 RunCommand(cmd, True)
306 except EnvironmentError:
307 print('Please install ant first.')
310 res_dirs = '-DADDITIONAL_RES_DIRS=\'\''
311 res_packages = '-DADDITIONAL_RES_PACKAGES=\'\''
312 res_r_text_files = '-DADDITIONAL_R_TEXT_FILES=\'\''
313 if options.mode == 'embedded':
314 # Prepare the .pak file for embedded mode.
315 pak_src_path = os.path.join('native_libs_res', 'xwalk.pak')
316 pak_des_path = os.path.join(sanitized_name, 'assets', 'xwalk.pak')
317 shutil.copy(pak_src_path, pak_des_path)
319 js_src_dir = os.path.join('native_libs_res', 'jsapi')
320 js_des_dir = os.path.join(sanitized_name, 'assets', 'jsapi')
321 if os.path.exists(js_des_dir):
322 shutil.rmtree(js_des_dir)
323 shutil.copytree(js_src_dir, js_des_dir)
325 res_ui_java = os.path.join('gen', 'ui_java')
326 res_content_java = os.path.join('gen', 'content_java')
327 res_xwalk_java = os.path.join('gen', 'xwalk_core_java')
328 res_dirs = ('-DADDITIONAL_RES_DIRS='
329 + os.path.join(res_ui_java, 'res_crunched') + ' '
330 + os.path.join(res_ui_java, 'res_v14_compatibility') + ' '
331 + os.path.join(res_ui_java, 'res_grit') + ' '
332 + os.path.join('libs_res', 'ui') + ' '
333 + os.path.join(res_content_java, 'res_crunched') + ' '
334 + os.path.join(res_content_java, 'res_v14_compatibility') + ' '
335 + os.path.join('libs_res', 'content') + ' '
336 + os.path.join(res_content_java, 'res_grit') + ' '
337 + os.path.join(res_xwalk_java, 'res_crunched') + ' '
338 + os.path.join(res_xwalk_java, 'res_v14_compatibility') + ' '
339 + os.path.join('libs_res', 'runtime') + ' '
340 + os.path.join(res_xwalk_java, 'res_grit'))
341 res_packages = ('-DADDITIONAL_RES_PACKAGES=org.chromium.ui '
342 'org.xwalk.core org.chromium.content')
343 res_r_text_files = ('-DADDITIONAL_R_TEXT_FILES='
344 + os.path.join(res_ui_java, 'java_R', 'R.txt') + ' '
345 + os.path.join(res_xwalk_java, 'java_R', 'R.txt') + ' '
346 + os.path.join(res_content_java, 'java_R', 'R.txt'))
348 resource_dir = '-DRESOURCE_DIR=' + os.path.join(sanitized_name, 'res')
349 manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
350 cmd = ['python', os.path.join('scripts', 'gyp', 'ant.py'),
351 '-DAAPT_PATH=%s' % aapt_path,
355 '-DANDROID_MANIFEST=%s' % manifest_path,
356 '-DANDROID_SDK_JAR=%s' % sdk_jar_path,
357 '-DANDROID_SDK_ROOT=%s' % sdk_root_path,
358 '-DANDROID_SDK_VERSION=%d' % api_level,
359 '-DANT_TASKS_JAR=%s' % ant_tasks_jar_path,
360 '-DLIBRARY_MANIFEST_PATHS= ',
363 '-DSTAMP=codegen.stamp',
366 os.path.join('scripts', 'ant', 'apk-codegen.xml')]
369 # Check whether java is installed.
371 cmd = ['java', '-version']
372 RunCommand(cmd, True)
373 except EnvironmentError:
374 print('Please install Oracle JDK first.')
377 # Compile App source code with app runtime code.
378 classpath = '--classpath='
379 classpath += os.path.join(os.getcwd(), 'libs',
380 'xwalk_app_runtime_java.jar')
381 classpath += ' ' + sdk_jar_path
382 src_dirs = '--src-dirs=' + os.path.join(os.getcwd(), sanitized_name, 'src') +\
383 ' ' + os.path.join(os.getcwd(), 'out', 'gen')
384 cmd = ['python', os.path.join('scripts', 'gyp', 'javac.py'),
385 '--output-dir=%s' % os.path.join('out', 'classes'),
390 '--stamp=compile.stam']
394 asset_dir = '-DASSET_DIR=%s' % os.path.join(sanitized_name, 'assets')
395 xml_path = os.path.join('scripts', 'ant', 'apk-package-resources.xml')
396 cmd = ['python', os.path.join('scripts', 'gyp', 'ant.py'),
397 '-DAAPT_PATH=%s' % aapt_path,
401 '-DANDROID_SDK_JAR=%s' % sdk_jar_path,
402 '-DANDROID_SDK_ROOT=%s' % sdk_root_path,
403 '-DANT_TASKS_JAR=%s' % ant_tasks_jar_path,
404 '-DAPK_NAME=%s' % sanitized_name,
405 '-DAPP_MANIFEST_VERSION_CODE=0',
406 '-DAPP_MANIFEST_VERSION_NAME=Developer Build',
408 '-DCONFIGURATION_NAME=Release',
411 '-DSTAMP=package_resources.stamp',
417 dex_path = '--dex-path=' + os.path.join(os.getcwd(), 'out', 'classes.dex')
418 app_runtime_jar = os.path.join(os.getcwd(),
419 'libs', 'xwalk_app_runtime_java.jar')
421 # Check whether external extensions are included.
422 extensions_string = 'xwalk-extensions'
423 extensions_dir = os.path.join(os.getcwd(), sanitized_name, extensions_string)
424 external_extension_jars = FindExtensionJars(extensions_dir)
426 if options.mode == 'embedded':
427 input_jars.append(os.path.join(os.getcwd(), 'libs',
428 'xwalk_runtime_embedded.dex.jar'))
429 dex_command_list = ['python', os.path.join('scripts', 'gyp', 'dex.py'),
431 '--android-sdk-root=%s' % sdk_root_path,
433 os.path.join(os.getcwd(), 'out', 'classes')]
434 dex_command_list.extend(external_extension_jars)
435 dex_command_list.extend(input_jars)
436 RunCommand(dex_command_list)
438 src_dir = '-DSOURCE_DIR=' + os.path.join(sanitized_name, 'src')
439 apk_path = '-DUNSIGNED_APK_PATH=' + os.path.join('out', 'app-unsigned.apk')
440 native_lib_path = '-DNATIVE_LIBS_DIR='
441 if options.mode == 'embedded':
442 if options.arch == 'x86':
443 x86_native_lib_path = os.path.join('native_libs', 'x86', 'libs',
444 'x86', 'libxwalkcore.so')
445 if os.path.isfile(x86_native_lib_path):
446 native_lib_path += os.path.join('native_libs', 'x86', 'libs')
448 print('Missing x86 native library for Crosswalk embedded APK. Abort!')
450 elif options.arch == 'arm':
451 arm_native_lib_path = os.path.join('native_libs', 'armeabi-v7a', 'libs',
452 'armeabi-v7a', 'libxwalkcore.so')
453 if os.path.isfile(arm_native_lib_path):
454 native_lib_path += os.path.join('native_libs', 'armeabi-v7a', 'libs')
456 print('Missing ARM native library for Crosswalk embedded APK. Abort!')
458 # A space is needed for Windows.
459 native_lib_path += ' '
460 cmd = ['python', 'scripts/gyp/ant.py',
461 '-DANDROID_SDK_ROOT=%s' % sdk_root_path,
462 '-DANT_TASKS_JAR=%s' % ant_tasks_jar_path,
463 '-DAPK_NAME=%s' % sanitized_name,
464 '-DCONFIGURATION_NAME=Release',
471 'scripts/ant/apk-package.xml']
474 apk_path = '--unsigned-apk-path=' + os.path.join('out', 'app-unsigned.apk')
475 final_apk_path = '--final-apk-path=' + \
476 os.path.join('out', sanitized_name + '.apk')
477 cmd = ['python', 'scripts/gyp/finalize_apk.py',
478 '--android-sdk-root=%s' % sdk_root_path,
481 '--keystore-path=%s' % key_store,
482 '--keystore-alias=%s' % key_alias,
483 '--keystore-passcode=%s' % key_code]
486 src_file = os.path.join('out', sanitized_name + '.apk')
487 package_name = options.name
488 if options.app_version:
489 package_name += ('_' + options.app_version)
490 if options.mode == 'shared':
491 dst_file = '%s.apk' % package_name
492 elif options.mode == 'embedded':
493 dst_file = '%s_%s.apk' % (package_name, options.arch)
494 shutil.copyfile(src_file, dst_file)
496 if options.mode == 'embedded':
497 os.remove(pak_des_path)
500 def PrintPackageInfo(app_name, app_version, arch = ''):
501 package_name_version = app_name
502 if app_version != '':
503 package_name_version += ('_' + app_version)
505 print ('A non-platform specific APK for the web application "%s" was '
506 'generated successfully at %s.apk. It requires a shared Crosswalk '
507 'Runtime to be present.'
508 % (app_name, package_name_version))
510 print ('An APK for the web application "%s" including the Crosswalk '
511 'Runtime built for %s was generated successfully, which can be '
512 'found at %s_%s.apk.'
513 % (app_name, arch, package_name_version, arch))
516 def MakeApk(options, sanitized_name):
519 if options.app_version:
520 app_version = options.app_version
521 if options.mode == 'shared':
522 Execution(options, sanitized_name)
523 PrintPackageInfo(sanitized_name, app_version)
524 elif options.mode == 'embedded':
526 Execution(options, sanitized_name)
527 PrintPackageInfo(sanitized_name, app_version, options.arch)
529 # If the arch option is unspecified, all of available platform APKs
531 valid_archs = ['x86', 'armeabi-v7a']
533 for arch in valid_archs:
534 if os.path.isfile(os.path.join('native_libs', arch, 'libs',
535 arch, 'libxwalkcore.so')):
536 if arch.find('x86') != -1:
538 elif arch.find('arm') != -1:
540 Execution(options, sanitized_name)
541 packaged_archs.append(options.arch)
542 for arch in packaged_archs:
543 PrintPackageInfo(sanitized_name, app_version, arch)
545 print('Unknown mode for packaging the application. Abort!')
548 def parse_optional_arg(default_value):
549 def func(option, value, values, parser):
552 if parser.rargs and not parser.rargs[0].startswith('-'):
553 val = parser.rargs[0]
557 setattr(parser.values, option.dest, val)
561 parser = optparse.OptionParser()
562 parser.add_option('-v', '--version', action='store_true',
563 dest='version', default=False,
564 help='The version of this python tool.')
565 info = ('The packaging mode of the web application. The value \'shared\' '
566 'means that the runtime is shared across multiple application '
567 'instances and that the runtime needs to be distributed separately. '
568 'The value \'embedded\' means that the runtime is embedded into the '
569 'application itself and distributed along with it.'
570 'Set the default mode as \'embedded\'. For example: --mode=embedded')
571 parser.add_option('--mode', default='embedded', help=info)
572 info = ('The target architecture of the embedded runtime. Supported values '
573 'are \'x86\' and \'arm\'. Note, if undefined, APKs for all possible '
574 'architestures will be generated.')
575 parser.add_option('--arch', help=info)
576 group = optparse.OptionGroup(parser, 'Application Source Options',
577 'This packaging tool supports 3 kinds of web application source: '
578 '1) XPK package; 2) manifest.json; 3) various command line options, '
579 'for example, \'--app-url\' for website, \'--app-root\' and '
580 '\'--app-local-path\' for local web application.')
581 info = ('The path of the XPK package. For example, --xpk=/path/to/xpk/file')
582 group.add_option('--xpk', help=info)
583 info = ('The manifest file with the detail description of the application. '
584 'For example, --manifest=/path/to/your/manifest/file')
585 group.add_option('--manifest', help=info)
586 info = ('The url of application. '
587 'This flag allows to package website as apk. For example, '
588 '--app-url=http://www.intel.com')
589 group.add_option('--app-url', help=info)
590 info = ('The root path of the web app. '
591 'This flag allows to package local web app as apk. For example, '
592 '--app-root=/root/path/of/the/web/app')
593 group.add_option('--app-root', help=info)
594 info = ('The relative path of entry file based on the value from '
595 '\'app_root\'. This flag should work with \'--app-root\' together. '
596 'For example, --app-local-path=/relative/path/of/entry/file')
597 group.add_option('--app-local-path', help=info)
598 parser.add_option_group(group)
599 group = optparse.OptionGroup(parser, 'Mandatory arguments',
600 'They are used for describing the APK information through '
601 'command line options.')
602 info = ('The apk name. For example, --name="Your Application Name"')
603 group.add_option('--name', help=info)
604 info = ('The package name. For example, '
605 '--package=com.example.YourPackage')
606 group.add_option('--package', help=info)
607 parser.add_option_group(group)
608 group = optparse.OptionGroup(parser, 'Optional arguments',
609 'They are used for various settings for applications through '
610 'command line options.')
611 info = ('The version name of the application. '
612 'For example, --app-version=1.0.0')
613 group.add_option('--app-version', help=info)
614 info = ('The version code of the application. '
615 'For example, --app-versionCode=24')
616 group.add_option('--app-versionCode', type='int', help=info)
617 info = ('The version code base of the application. Version code will '
618 'be made by adding a prefix based on architecture to the version '
619 'code base. For example, --app-versionCodeBase=24')
620 group.add_option('--app-versionCodeBase', type='int', help=info)
621 info = ('The description of the application. For example, '
622 '--description=YourApplicationDescription')
623 group.add_option('--description', help=info)
624 group.add_option('--enable-remote-debugging', action='store_true',
625 dest='enable_remote_debugging', default=False,
626 help = 'Enable remote debugging.')
627 info = ('The list of external extension paths splitted by OS separators. '
628 'The separators are \':\' , \';\' and \':\' on Linux, Windows and '
629 'Mac OS respectively. For example, '
630 '--extensions=/path/to/extension1:/path/to/extension2.')
631 group.add_option('--extensions', help=info)
632 group.add_option('-f', '--fullscreen', action='store_true',
633 dest='fullscreen', default=False,
634 help='Make application fullscreen.')
635 info = ('The path of application icon. '
636 'Such as: --icon=/path/to/your/customized/icon')
637 group.add_option('--icon', help=info)
638 info = ('The orientation of the web app\'s display on the device. '
639 'For example, --orientation=landscape. The default value is '
640 '\'unspecified\'. The permitted values are from Android: '
641 'http://developer.android.com/guide/topics/manifest/'
642 'activity-element.html#screen')
643 group.add_option('--orientation', help=info)
644 info = ('The list of permissions to be used by web application. For example, '
645 '--permissions=geolocation:webgl')
646 group.add_option('--permissions', help=info)
647 parser.add_option_group(group)
648 group = optparse.OptionGroup(parser, 'Keystore Options',
649 'The keystore is a signature from web developer, it\'s used when '
650 'developer wants to distribute the applications.')
651 info = ('The path to the developer keystore. For example, '
652 '--keystore-path=/path/to/your/developer/keystore')
653 group.add_option('--keystore-path', help=info)
654 info = ('The alias name of keystore. For example, --keystore-alias=name')
655 group.add_option('--keystore-alias', help=info)
656 info = ('The passcode of keystore. For example, --keystore-passcode=code')
657 group.add_option('--keystore-passcode', help=info)
658 info = ('Minify and obfuscate javascript and css.'
659 '--compressor: compress javascript and css.'
660 '--compressor=js: compress javascript.'
661 '--compressor=css: compress css.')
662 group.add_option('--compressor', dest='compressor', action='callback',
663 callback=parse_optional_arg('all'), help=info)
664 parser.add_option_group(group)
665 options, _ = parser.parse_args()
670 # This option will not export to users.
671 # Initialize here and will be read from manifest.json.
672 options.launch_screen_img = ''
675 if os.path.isfile('VERSION'):
676 print(GetVersion('VERSION'))
679 parser.error('Can\'t get version due to the VERSION file missing!')
683 xpk_name = os.path.splitext(os.path.basename(options.xpk))[0]
684 xpk_temp_dir = xpk_name + '_xpk'
685 ParseXPK(options, xpk_temp_dir)
687 if options.app_root and not options.manifest:
688 manifest_path = os.path.join(options.app_root, 'manifest.json')
689 if os.path.exists(manifest_path):
690 print('Using manifest.json distributed with the application.')
691 options.manifest = manifest_path
693 if not options.manifest:
694 if not options.package:
695 parser.error('The package name is required! '
696 'Please use "--package" option.')
698 parser.error('The APK name is required! Please use "--name" option.')
699 if not ((options.app_url and not options.app_root
700 and not options.app_local_path) or ((not options.app_url)
701 and options.app_root and options.app_local_path)):
702 parser.error('The entry is required. If the entry is a remote url, '
703 'please use "--app-url" option; If the entry is local, '
704 'please use "--app-root" and '
705 '"--app-local-path" options together!')
706 if options.permissions:
707 permission_list = options.permissions.split(':')
709 print ('Warning: all supported permissions on Android port are added. '
710 'Refer to https://github.com/crosswalk-project/'
711 'crosswalk-website/wiki/Crosswalk-manifest')
712 permission_list = permission_mapping_table.keys()
713 options.permissions = HandlePermissionList(permission_list)
717 ParseManifest(options)
718 except SystemExit as ec:
721 options.name = ReplaceInvalidChars(options.name, 'apkname')
722 options.package = ReplaceInvalidChars(options.package)
723 sanitized_name = ReplaceInvalidChars(options.name, 'apkname')
726 compress = compress_js_and_css.CompressJsAndCss(options.app_root)
727 if options.compressor == 'all':
728 compress.CompressJavaScript()
729 compress.CompressCss()
730 elif options.compressor == 'js':
731 compress.CompressJavaScript()
732 elif options.compressor == 'css':
733 compress.CompressCss()
734 MakeApk(options, sanitized_name)
735 except SystemExit as ec:
736 CleanDir(sanitized_name)
738 if os.path.exists(xpk_temp_dir):
739 CleanDir(xpk_temp_dir)
744 if __name__ == '__main__':
745 sys.exit(main(sys.argv))