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
17 # get xwalk absolute path so we can run this script from any location
18 xwalk_dir = os.path.dirname(os.path.abspath(__file__))
19 sys.path.append(xwalk_dir)
21 from app_info import AppInfo
22 from customize import VerifyPackageName, CustomizeAll, \
23 ParseParameterForCompressor
24 from extension_manager import GetExtensionList, GetExtensionStatus
25 from handle_permissions import permission_mapping_table
26 from util import AllArchitectures, CleanDir, GetVersion, RunCommand, \
27 CreateAndCopyDir, GetBuildDir
28 from manifest_json_parser import HandlePermissionList
29 from manifest_json_parser import ManifestJsonParser
32 NATIVE_LIBRARY = 'libxwalkcore.so'
35 def ConvertArchNameToArchFolder(arch):
41 return arch_dict.get(arch, None)
44 def AddExeExtensions(name):
45 exts_str = os.environ.get('PATHEXT', '').lower()
46 exts = [_f for _f in exts_str.split(os.pathsep) if _f]
49 result.append(name + e)
55 """Searches PATH for executable files with the given name, also taking
56 PATHEXT into account. Returns the first existing match, or None if no matches
58 for path in os.environ.get('PATH', '').split(os.pathsep):
59 for filename in AddExeExtensions(name):
60 full_path = os.path.join(path, filename)
61 if os.path.isfile(full_path) and os.access(full_path, os.X_OK):
66 def GetAndroidApiLevel(android_path):
67 """Get Highest Android target level installed.
68 return -1 if no targets have been found.
70 target_output = RunCommand([android_path, 'list', 'target', '-c'])
71 target_regex = re.compile(r'android-(\d+)')
72 targets = [int(i) for i in target_regex.findall(target_output)]
77 def ContainsNativeLibrary(path):
78 return os.path.isfile(os.path.join(path, NATIVE_LIBRARY))
81 def ParseManifest(options):
82 parser = ManifestJsonParser(os.path.expanduser(options.manifest))
84 options.name = parser.GetAppName()
85 if not options.app_version:
86 options.app_version = parser.GetVersion()
87 if not options.app_versionCode and not options.app_versionCodeBase:
88 options.app_versionCode = 1
89 if parser.GetDescription():
90 options.description = parser.GetDescription()
91 if parser.GetPermissions():
92 options.permissions = parser.GetPermissions()
93 if parser.GetAppUrl():
94 options.app_url = parser.GetAppUrl()
95 elif parser.GetAppLocalPath():
96 options.app_local_path = parser.GetAppLocalPath()
98 print('Error: there is no app launch path defined in manifest.json.')
100 options.icon_dict = {}
101 if parser.GetAppRoot():
102 options.app_root = parser.GetAppRoot()
103 options.icon_dict = parser.GetIcons()
104 if parser.GetOrientation():
105 options.orientation = parser.GetOrientation()
106 if parser.GetFullScreenFlag().lower() == 'true':
107 options.fullscreen = True
108 elif parser.GetFullScreenFlag().lower() == 'false':
109 options.fullscreen = False
113 def ParseXPK(options, out_dir):
114 cmd = ['python', os.path.join(xwalk_dir, 'parse_xpk.py'),
115 '--file=%s' % os.path.expanduser(options.xpk),
116 '--out=%s' % out_dir]
119 print ('Use the manifest from XPK by default '
120 'when "--xpk" option is specified, and '
121 'the "--manifest" option would be ignored.')
124 if os.path.isfile(os.path.join(out_dir, 'manifest.json')):
125 options.manifest = os.path.join(out_dir, 'manifest.json')
127 print('XPK doesn\'t contain manifest file.')
131 def FindExtensionJars(root_path):
132 ''' Find all .jar files for external extensions. '''
134 if not os.path.exists(root_path):
135 return extension_jars
137 for afile in os.listdir(root_path):
138 if os.path.isdir(os.path.join(root_path, afile)):
139 base_name = os.path.basename(afile)
140 extension_jar = os.path.join(root_path, afile, base_name + '.jar')
141 if os.path.isfile(extension_jar):
142 extension_jars.append(extension_jar)
143 return extension_jars
146 # Follows the recommendation from
147 # http://software.intel.com/en-us/blogs/2012/11/12/how-to-publish-
148 # your-apps-on-google-play-for-x86-based-android-devices-using
149 def MakeVersionCode(options):
150 ''' Construct a version code'''
151 if options.app_versionCode:
152 return options.app_versionCode
154 # First digit is ABI, ARM=2, x86=6
156 if options.arch == 'arm':
158 if options.arch == 'x86':
160 if options.arch == 'x86_64':
163 if options.app_versionCodeBase:
164 b = str(options.app_versionCodeBase)
166 print('Version code base must be 7 digits or less: '
167 'versionCodeBase=%s' % (b))
169 # zero pad to 7 digits, middle digits can be used for other
170 # features, according to recommendation in URL
171 return '%s%s' % (abi, b.zfill(7))
174 def GetExtensionBinaryPathList():
175 local_extension_list = []
176 extensions_path = os.path.join(os.getcwd(), "extensions")
177 exist_extension_list = GetExtensionList(extensions_path)
178 for item in exist_extension_list:
179 build_json_path = os.path.join(extensions_path, item, "build.json")
180 with open(build_json_path) as fd:
182 if not GetExtensionStatus(item, extensions_path):
185 if data.get("binary_path", False):
186 extension_binary_path = os.path.join(extensions_path,
190 print("The extension \"%s\" doesn't exists." % item)
192 if os.path.isdir(extension_binary_path):
193 local_extension_list.append(extension_binary_path)
195 print("The extension \"%s\" doesn't exists." % item)
198 return local_extension_list
201 def Customize(options, app_info, manifest):
202 app_info.package = options.package
203 app_info.app_name = options.name
204 # 'org.xwalk.my_first_app' => 'MyFirstApp'
205 android_name = options.package.split('.')[-1].split('_')
206 app_info.android_name = ''.join([i.capitalize() for i in android_name if i])
207 if options.app_version:
208 app_info.app_version = options.app_version
209 app_info.app_versionCode = MakeVersionCode(options)
211 app_info.app_root = os.path.expanduser(options.app_root)
212 if options.enable_remote_debugging:
213 app_info.remote_debugging = '--enable-remote-debugging'
214 if options.use_animatable_view:
215 app_info.use_animatable_view = '--use-animatable-view'
216 if options.fullscreen:
217 app_info.fullscreen_flag = '-f'
218 if options.orientation:
219 app_info.orientation = options.orientation
221 app_info.icon = '%s' % os.path.expanduser(options.icon)
223 #Add local extensions to extension list.
224 extension_binary_path_list = GetExtensionBinaryPathList()
225 if len(extension_binary_path_list) > 0:
226 if options.extensions is None:
227 options.extensions = ""
229 options.extensions += os.pathsep
231 for item in extension_binary_path_list:
232 options.extensions += item
233 options.extensions += os.pathsep
234 #trim final path separator
235 options.extensions = options.extensions[0:-1]
237 CustomizeAll(app_info, options.description, options.icon_dict,
238 options.permissions, options.app_url, options.app_local_path,
239 options.keep_screen_on, options.extensions, manifest,
240 options.xwalk_command_line, options.compressor)
243 def Execution(options, name):
244 arch_string = (' ('+options.arch+')' if options.arch else '')
245 print('\nStarting application build' + arch_string)
246 app_dir = GetBuildDir(name)
247 android_path = Which('android')
248 api_level = GetAndroidApiLevel(android_path)
249 target_string = 'android-%d' % api_level
251 print (' * Checking keystore for signing')
252 if options.keystore_path:
253 key_store = os.path.expanduser(options.keystore_path)
254 if options.keystore_alias:
255 key_alias = options.keystore_alias
257 print('Please provide an alias name of the developer key.')
259 if options.keystore_passcode:
260 key_code = options.keystore_passcode
263 if options.keystore_alias_passcode:
264 key_alias_code = options.keystore_alias_passcode
266 key_alias_code = None
268 print(' No keystore provided for signing. Using xwalk\'s keystore '
269 'for debugging.\n Please use a valid keystore when '
270 'distributing to the app market.')
271 key_store = os.path.join(xwalk_dir, 'xwalk-debug.keystore')
272 key_alias = 'xwalkdebugkey'
273 key_code = 'xwalkdebug'
274 key_alias_code = 'xwalkdebug'
276 # Update android project for app and xwalk_core_library.
277 update_project_cmd = [android_path, 'update', 'project',
279 '--target', target_string,
281 if options.mode == 'embedded':
282 print(' * Updating project with xwalk_core_library')
283 RunCommand([android_path, 'update', 'lib-project',
284 '--path', os.path.join(app_dir, 'xwalk_core_library'),
285 '--target', target_string])
286 update_project_cmd.extend(['-l', 'xwalk_core_library'])
288 print(' * Updating project')
289 RunCommand(update_project_cmd)
291 # Check whether external extensions are included.
292 print(' * Checking for external extensions')
293 extensions_string = 'xwalk-extensions'
294 extensions_dir = os.path.join(app_dir, extensions_string)
295 external_extension_jars = FindExtensionJars(extensions_dir)
296 for external_extension_jar in external_extension_jars:
297 shutil.copyfile(external_extension_jar,
298 os.path.join(app_dir, 'libs',
299 os.path.basename(external_extension_jar)))
301 if options.mode == 'embedded':
302 print (' * Copying native libraries for %s' % options.arch)
303 # Remove existing native libraries in xwalk_core_library, they are probably
304 # for the last execution to make apk for another CPU arch.
305 # And then copy the native libraries for the specified arch into
306 # xwalk_core_library.
307 arch = ConvertArchNameToArchFolder(options.arch)
309 print ('Invalid CPU arch: %s.' % arch)
311 library_lib_path = os.path.join(app_dir, 'xwalk_core_library', 'libs')
312 for dir_name in os.listdir(library_lib_path):
313 lib_dir = os.path.join(library_lib_path, dir_name)
314 if ContainsNativeLibrary(lib_dir):
315 shutil.rmtree(lib_dir)
316 native_lib_path = os.path.join(app_dir, 'native_libs', arch)
317 if ContainsNativeLibrary(native_lib_path):
318 shutil.copytree(native_lib_path, os.path.join(library_lib_path, arch))
320 print('No %s native library has been found for creating a Crosswalk '
321 'embedded APK.' % arch)
324 if options.project_only:
325 print (' (Skipping apk package creation)')
329 if options.mode == 'embedded':
330 print(' * Building Android apk package with Crosswalk embedded' +
333 print(' * Building Android apk package')
334 ant_path = Which('ant')
335 ant_cmd = [ant_path, 'release', '-f', os.path.join(app_dir, 'build.xml')]
336 ant_cmd.extend(['-Dkey.store=%s' % os.path.abspath(key_store)])
337 ant_cmd.extend(['-Dkey.alias=%s' % key_alias])
339 ant_cmd.extend(['-Dkey.store.password=%s' % key_code])
341 ant_cmd.extend(['-Dkey.alias.password=%s' % key_alias_code])
343 cmd_display = ' '.join([str(item) for item in ant_cmd])
345 print('Executing:\n %s\n' % cmd_display)
347 ant_cmd.extend(['-quiet'])
348 ant_result = subprocess.call(ant_cmd)
350 print('Command "%s" exited with non-zero exit code %d'
351 % (cmd_display, ant_result))
354 src_file = os.path.join(app_dir, 'bin', '%s-release.apk' % name)
356 if options.app_version:
357 package_name += ('_' + options.app_version)
358 if options.mode == 'shared':
359 dst_file = os.path.join(options.target_dir, '%s.apk' % package_name)
360 elif options.mode == 'embedded':
361 dst_file = os.path.join(options.target_dir,
362 '%s_%s.apk' % (package_name, options.arch))
363 shutil.copyfile(src_file, dst_file)
364 print(' (Location: %s)' % dst_file)
366 def PrintPackageInfo(options, name, packaged_archs):
367 package_name_version = os.path.join(options.target_dir, name)
368 if options.app_version:
369 package_name_version += '_' + options.app_version
371 if len(packaged_archs) == 0:
372 print ('\nA non-platform specific APK for the web application "%s" was '
373 'generated successfully at:\n %s.apk.\nIt requires a shared '
374 'Crosswalk Runtime to be present.'
375 % (name, package_name_version))
378 all_archs = set(AllArchitectures())
380 if len(packaged_archs) != len(all_archs):
381 missed_archs = all_archs - set(packaged_archs)
382 print ('\nNote: This APK will only work on %s-based Android devices.'
383 ' Consider building\nfor %s as well.' %
384 (', '.join(packaged_archs), ', '.join(missed_archs)))
386 print ("\nApplication apk's were created for %d architectures (%s)." %
387 (len(all_archs), (','.join(all_archs))))
388 print ('If you submit this application to an application '
389 'store, please submit both\npackages. Instructions '
390 'for submitting multiple APKs to Google Play Store are\navailable '
392 print (' https://software.intel.com/en-us/html5/articles/submitting'
393 '-multiple-crosswalk-apk-to-google-play-store')
396 def CheckSystemRequirements():
397 ''' Check for android, ant, template dir '''
398 sys.stdout.write('Checking system requirements...')
400 # check android install
401 android_path = Which('android')
402 if android_path is None:
403 print('failed\nThe "android" binary could not be found. Check your Android '
404 'SDK installation and your PATH environment variable.')
406 if GetAndroidApiLevel(android_path) < 14:
407 print('failed\nPlease install Android API level (>=14) first.')
411 ant_path = Which('ant')
413 print('failed\nAnt could not be found. Please make sure it is installed.')
419 def MakeApk(options, app_info, manifest):
420 CheckSystemRequirements()
421 Customize(options, app_info, manifest)
422 name = app_info.android_name
423 app_dir = GetBuildDir(name)
425 if options.mode == 'shared':
426 # For shared mode, it's not necessary to use the whole xwalk core library,
427 # use xwalk_core_library_java_app_part.jar from it is enough.
428 java_app_part_jar = os.path.join(xwalk_dir, 'xwalk_core_library', 'libs',
429 'xwalk_core_library_java_app_part.jar')
430 shutil.copy(java_app_part_jar, os.path.join(app_dir, 'libs'))
431 Execution(options, name)
432 elif options.mode == 'embedded':
433 # Copy xwalk_core_library into app folder and move the native libraries
435 # When making apk for specified CPU arch, will only include the
436 # corresponding native library by copying it back into xwalk_core_library.
437 target_library_path = os.path.join(app_dir, 'xwalk_core_library')
438 shutil.copytree(os.path.join(xwalk_dir, 'xwalk_core_library'),
440 library_lib_path = os.path.join(target_library_path, 'libs')
441 native_lib_path = os.path.join(app_dir, 'native_libs')
442 os.makedirs(native_lib_path)
444 for dir_name in os.listdir(library_lib_path):
445 lib_dir = os.path.join(library_lib_path, dir_name)
446 if ContainsNativeLibrary(lib_dir):
447 shutil.move(lib_dir, os.path.join(native_lib_path, dir_name))
448 available_archs.append(dir_name)
450 Execution(options, name)
451 packaged_archs.append(options.arch)
453 # If the arch option is unspecified, all of available platform APKs
455 valid_archs = ['x86', 'x86_64', 'armeabi-v7a']
456 for arch in valid_archs:
457 if arch in available_archs:
458 if arch.find('arm') != -1:
462 print "options.arch:", options.arch
463 Execution(options, name)
464 packaged_archs.append(options.arch)
466 print('Warning: failed to create package for arch "%s" '
467 'due to missing native library' % arch)
468 if len(packaged_archs) == 0:
469 print('No packages created, aborting')
472 # if project_dir, save build directory
473 if options.project_dir:
474 print ('\nCreating project directory')
475 save_dir = os.path.join(options.project_dir, name)
476 if CreateAndCopyDir(app_dir, save_dir, True):
477 print (' A project directory was created successfully in:\n %s' %
478 os.path.abspath(save_dir))
479 print (' To manually generate an APK, run the following in that '
481 print (' ant release -f build.xml')
482 print (' For more information, see:\n'
483 ' http://developer.android.com/tools/building/'
484 'building-cmdline.html')
486 print ('Error: Unable to create a project directory during the build. '
487 'Please check the directory passed in --project-dir, '
488 'available disk space, and write permission.')
490 if not options.project_only:
491 PrintPackageInfo(options, name, packaged_archs)
494 parser = optparse.OptionParser()
495 parser.add_option('-v', '--version', action='store_true',
496 dest='version', default=False,
497 help='The version of this python tool.')
498 parser.add_option('--verbose', action="store_true",
499 dest='verbose', default=False,
500 help='Print debug messages.')
501 info = ('The packaging mode of the web application. The value \'shared\' '
502 'means that the runtime is shared across multiple application '
503 'instances and that the runtime needs to be distributed separately. '
504 'The value \'embedded\' means that the runtime is embedded into the '
505 'application itself and distributed along with it.'
506 'Set the default mode as \'embedded\'. For example: --mode=embedded')
507 parser.add_option('--mode', choices=('embedded', 'shared'),
508 default='embedded', help=info)
509 info = ('The target architecture of the embedded runtime. Supported values '
510 'are \'x86\' \'x86_64\' and \'arm\'. Note, if undefined, APKs for '
511 'all possible architestures will be generated.')
512 parser.add_option('--arch', choices=AllArchitectures(), help=info)
513 group = optparse.OptionGroup(parser, 'Application Source Options',
514 'This packaging tool supports 3 kinds of web application source: '
515 '1) XPK package; 2) manifest.json; 3) various command line options, '
516 'for example, \'--app-url\' for website, \'--app-root\' and '
517 '\'--app-local-path\' for local web application.')
518 info = ('The path of the XPK package. For example, --xpk=/path/to/xpk/file')
519 group.add_option('--xpk', help=info)
520 info = ('The manifest file with the detail description of the application. '
521 'For example, --manifest=/path/to/your/manifest/file')
522 group.add_option('--manifest', help=info)
523 info = ('The url of application. '
524 'This flag allows to package website as apk. For example, '
525 '--app-url=http://www.intel.com')
526 group.add_option('--app-url', help=info)
527 info = ('The root path of the web app. '
528 'This flag allows to package local web app as apk. For example, '
529 '--app-root=/root/path/of/the/web/app')
530 group.add_option('--app-root', help=info)
531 info = ('The relative path of entry file based on the value from '
532 '\'app_root\'. This flag should work with \'--app-root\' together. '
533 'For example, --app-local-path=/relative/path/of/entry/file')
534 group.add_option('--app-local-path', help=info)
535 parser.add_option_group(group)
536 # Mandatory options group
537 group = optparse.OptionGroup(parser, 'Mandatory arguments',
538 'They are used for describing the APK information through '
539 'command line options.')
540 info = ('The apk name. For example, --name="Your Application Name"')
541 group.add_option('--name', help=info)
542 info = ('The package name. For example, '
543 '--package=com.example.YourPackage')
544 group.add_option('--package', help=info)
545 parser.add_option_group(group)
546 # Optional options group (alphabetical)
547 group = optparse.OptionGroup(parser, 'Optional arguments',
548 'They are used for various settings for applications through '
549 'command line options.')
550 info = ('The version name of the application. '
551 'For example, --app-version=1.0.0')
552 group.add_option('--app-version', help=info)
553 info = ('The version code of the application. '
554 'For example, --app-versionCode=24')
555 group.add_option('--app-versionCode', type='int', help=info)
556 info = ('The version code base of the application. Version code will '
557 'be made by adding a prefix based on architecture to the version '
558 'code base. For example, --app-versionCodeBase=24')
559 group.add_option('--app-versionCodeBase', type='int', help=info)
560 info = ('The description of the application. For example, '
561 '--description=YourApplicationDescription')
562 group.add_option('--description', help=info)
563 group.add_option('--enable-remote-debugging', action='store_true',
564 dest='enable_remote_debugging', default=False,
565 help='Enable remote debugging.')
566 group.add_option('--use-animatable-view', action='store_true',
567 dest='use_animatable_view', default=False,
568 help='Enable using animatable view (TextureView).')
569 info = ('The list of external extension paths splitted by OS separators. '
570 'The separators are \':\' , \';\' and \':\' on Linux, Windows and '
571 'Mac OS respectively. For example, '
572 '--extensions=/path/to/extension1:/path/to/extension2.')
573 group.add_option('--extensions', help=info)
574 group.add_option('-f', '--fullscreen', action='store_true',
575 dest='fullscreen', default=False,
576 help='Make application fullscreen.')
577 group.add_option('--keep-screen-on', action='store_true', default=False,
578 help='Support keeping screen on')
579 info = ('The path of application icon. '
580 'Such as: --icon=/path/to/your/customized/icon')
581 group.add_option('--icon', help=info)
582 info = ('The orientation of the web app\'s display on the device. '
583 'For example, --orientation=landscape. The default value is '
584 '\'unspecified\'. The permitted values are from Android: '
585 'http://developer.android.com/guide/topics/manifest/'
586 'activity-element.html#screen')
587 group.add_option('--orientation', help=info)
588 info = ('The list of permissions to be used by web application. For example, '
589 '--permissions=geolocation:webgl')
590 group.add_option('--permissions', help=info)
591 info = ('Create an Android project directory with Crosswalk at this location.'
592 ' (See project-only option below)')
593 group.add_option('--project-dir', help=info)
594 info = ('Must be used with project-dir option. Create an Android project '
595 'directory with Crosswalk but do not build the APK package')
596 group.add_option('--project-only', action='store_true', default=False,
597 dest='project_only', help=info)
598 info = ('Packaging tool will move the output APKs to the target directory')
599 group.add_option('--target-dir', default=os.getcwd(), help=info)
600 info = ('Use command lines.'
601 'Crosswalk is powered by Chromium and supports Chromium command line.'
603 '--xwalk-command-line=\'--chromium-command-1 --xwalk-command-2\'')
604 group.add_option('--xwalk-command-line', default='', help=info)
605 parser.add_option_group(group)
606 # Keystore options group
607 group = optparse.OptionGroup(parser, 'Keystore Options',
608 'The keystore is a signature from web developer, it\'s used when '
609 'developer wants to distribute the applications.')
610 info = ('The path to the developer keystore. For example, '
611 '--keystore-path=/path/to/your/developer/keystore')
612 group.add_option('--keystore-path', help=info)
613 info = ('The alias name of keystore. For example, --keystore-alias=name')
614 group.add_option('--keystore-alias', help=info)
615 info = ('The passcode of keystore. For example, --keystore-passcode=code')
616 group.add_option('--keystore-passcode', help=info)
617 info = ('Passcode for alias\'s private key in the keystore, '
618 'For example, --keystore-alias-passcode=alias-code')
619 group.add_option('--keystore-alias-passcode', help=info)
620 info = ('Minify and obfuscate javascript and css.'
621 '--compressor: compress javascript and css.'
622 '--compressor=js: compress javascript.'
623 '--compressor=css: compress css.')
624 group.add_option('--compressor', dest='compressor', action='callback',
625 callback=ParseParameterForCompressor, type='string',
627 parser.add_option_group(group)
628 options, _ = parser.parse_args()
634 if os.path.isfile('VERSION'):
635 print(GetVersion('VERSION'))
638 parser.error('VERSION was not found, so Crosswalk\'s version could not '
643 xpk_name = os.path.splitext(os.path.basename(options.xpk))[0]
644 xpk_temp_dir = tempfile.mkdtemp(prefix="%s-" % xpk_name + '_xpk')
645 CleanDir(xpk_temp_dir)
646 ParseXPK(options, xpk_temp_dir)
649 options.manifest = os.path.abspath(options.manifest)
650 if not os.path.isfile(options.manifest):
651 print('Error: The manifest file does not exist.')
654 if options.app_root and not options.manifest:
655 manifest_path = os.path.join(options.app_root, 'manifest.json')
656 if os.path.exists(manifest_path):
657 print('Using manifest.json distributed with the application.')
658 options.manifest = manifest_path
662 if not options.manifest:
663 # The checks here are really convoluted, but at the moment make_apk
664 # misbehaves any of the following conditions is true.
666 # 1) --app-url must be passed without either --app-local-path or
668 if options.app_root or options.app_local_path:
669 parser.error('You must pass either "--app-url" or "--app-local-path" '
670 'with "--app-root", but not all.')
672 # 2) --app-url is not passed but only one of --app-local-path and
674 if bool(options.app_root) != bool(options.app_local_path):
675 parser.error('You must specify both "--app-local-path" and '
677 # 3) None of --app-url, --app-local-path and --app-root are passed.
678 elif not options.app_root and not options.app_local_path:
679 parser.error('You must pass either "--app-url" or "--app-local-path" '
680 'with "--app-root".')
682 if options.permissions:
683 permission_list = options.permissions.split(':')
685 print('Warning: all supported permissions on Android port are added. '
686 'Refer to https://github.com/crosswalk-project/'
687 'crosswalk-website/wiki/Crosswalk-manifest')
688 permission_list = permission_mapping_table.keys()
689 options.permissions = HandlePermissionList(permission_list)
690 options.icon_dict = {}
693 manifest = ParseManifest(options)
694 except SystemExit as ec:
698 parser.error('An APK name is required. Please use the "--name" option.')
700 if not options.package:
701 parser.error('A package name is required. Please use the "--package" '
703 VerifyPackageName(options.package)
705 if (options.app_root and options.app_local_path and
706 not os.path.isfile(os.path.join(options.app_root,
707 options.app_local_path))):
708 print('Please make sure that the local path file of launching app '
712 if options.target_dir:
713 target_dir = os.path.abspath(os.path.expanduser(options.target_dir))
714 options.target_dir = target_dir
715 if not os.path.isdir(target_dir):
716 os.makedirs(target_dir)
718 if options.project_only and not options.project_dir:
719 print('\nmake_apk.py error: Option --project-only must be used '
720 'with --project-dir')
724 MakeApk(options, app_info, manifest)
725 except SystemExit as ec:
728 CleanDir(GetBuildDir(app_info.android_name))
729 CleanDir(xpk_temp_dir)
733 if __name__ == '__main__':
735 sys.exit(main(sys.argv))
736 except KeyboardInterrupt: