if os.path.exists(path):
shutil.rmtree(path)
+
def AllArchitectures():
return ("x86", "arm")
+
def RunCommand(command, verbose=False, shell=False):
"""Runs the command list, print the output, and propagate its result."""
proc = subprocess.Popen(command, stdout=subprocess.PIPE,
def Which(name):
- """Search PATH for executable files with the given name."""
- result = []
- exts = [_f for _f in os.environ.get('PATHEXT', '').split(os.pathsep) if _f]
- path = os.environ.get('PATH', None)
- if path is None:
- return []
- for p in os.environ.get('PATH', '').split(os.pathsep):
- p = os.path.join(p, name)
- if os.access(p, os.X_OK):
- result.append(p)
- for e in exts:
- pext = p + e
- if os.access(pext, os.X_OK):
- result.append(pext)
- return result
+ """Searches PATH for executable files with the given name, also taking
+ PATHEXT into account. Returns the first existing match, or None if no matches
+ are found."""
+ for path in os.environ.get('PATH', '').split(os.pathsep):
+ for filename in AddExeExtensions(name):
+ full_path = os.path.join(path, filename)
+ if os.path.isfile(full_path) and os.access(full_path, os.X_OK):
+ return full_path
+ return None
def Find(name, path):
if parser.GetAppRoot():
options.app_root = parser.GetAppRoot()
options.icon_dict = parser.GetIcons()
+ if parser.GetOrientation():
+ options.orientation = parser.GetOrientation()
if parser.GetFullScreenFlag().lower() == 'true':
options.fullscreen = True
elif parser.GetFullScreenFlag().lower() == 'false':
def Execution(options, name):
- android_path_array = Which('android')
- if not android_path_array:
- print('Please install Android SDK first.')
+ android_path = Which('android')
+ if android_path is None:
+ print('The "android" binary could not be found. Check your Android SDK '
+ 'installation and your PATH environment variable.')
sys.exit(1)
- sdk_root_path = os.path.dirname(os.path.dirname(android_path_array[0]))
+ sdk_root_path = os.path.dirname(os.path.dirname(android_path))
try:
sdk_jar_path = Find('android.jar',
'scripts/ant/apk-package.xml']
RunCommand(cmd, options.verbose)
+ # Find the path of zipalign.
+ # XWALK-2033: zipalign can be in different locations depending on Android
+ # SDK version that used ((eg. /tools, /build-tools/android-4.4W etc),).
+ # So looking up the location of zipalign here instead of hard coding.
+ # Refer to: https://codereview.chromium.org/238253015
+ zipalign_path = ''
+ for zipalign_str in AddExeExtensions('zipalign'):
+ try:
+ zipalign_path = Find(zipalign_str, sdk_root_path)
+ if options.verbose:
+ print('Use %s in %s.' % (zipalign_str, sdk_root_path))
+ break
+ except Exception:
+ pass
+ if not zipalign_path:
+ print('zipalign could not be found in your Android SDK.'
+ ' Make sure it is installed.')
+ sys.exit(10)
apk_path = '--unsigned-apk-path=' + os.path.join('out', 'app-unsigned.apk')
final_apk_path = '--final-apk-path=' + \
os.path.join('out', name + '.apk')
cmd = ['python', 'scripts/gyp/finalize_apk.py',
- '--android-sdk-root=%s' % sdk_root_path,
+ '--zipalign-path=%s' % zipalign_path,
apk_path,
final_apk_path,
'--keystore-path=%s' % key_store,
if len(packaged_archs) == 0:
print('No packages created, aborting')
sys.exit(13)
- else:
- print('Unknown mode for packaging the application. Abort!')
- sys.exit(11)
PrintPackageInfo(options, packaged_archs)
'The value \'embedded\' means that the runtime is embedded into the '
'application itself and distributed along with it.'
'Set the default mode as \'embedded\'. For example: --mode=embedded')
- parser.add_option('--mode', default='embedded', help=info)
+ parser.add_option('--mode', choices=('embedded', 'shared'),
+ default='embedded', help=info)
info = ('The target architecture of the embedded runtime. Supported values '
'are \'x86\' and \'arm\'. Note, if undefined, APKs for all possible '
'architestures will be generated.')
options.name = ReplaceSpaceWithUnderscore(options.name)
else:
parser.error('The APK name is required! Please use "--name" option.')
- if not ((options.app_url and
- not options.app_root and
- not options.app_local_path) or
- (not options.app_url and
- options.app_root and
- options.app_local_path)):
- parser.error('The entry is required. If the entry is a remote url, '
- 'please use "--app-url" option; If the entry is local, '
- 'please use "--app-root" and '
- '"--app-local-path" options together!')
+
+ # The checks here are really convoluted, but at the moment make_apk
+ # misbehaves any of the following conditions is true.
+ if options.app_url:
+ # 1) --app-url must be passed without either --app-local-path or
+ # --app-root.
+ if options.app_root or options.app_local_path:
+ parser.error('You must pass either "--app-url" or "--app-local-path" '
+ 'with "--app-root", but not all.')
+ else:
+ # 2) --app-url is not passed but only one of --app-local-path and
+ # --app-root is set.
+ if bool(options.app_root) != bool(options.app_local_path):
+ parser.error('You must specify both "--app-local-path" and '
+ '"--app-root".')
+ # 3) None of --app-url, --app-local-path and --app-root are passed.
+ elif not options.app_root and not options.app_local_path:
+ parser.error('You must pass either "--app-url" or "--app-local-path" '
+ 'with "--app-root".')
+
if options.permissions:
permission_list = options.permissions.split(':')
else: