Source code
Revision control
Copy as Markdown
Other Tools
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# Ensure Android SDK and build-tools versions depending on mobile target.
@depends(host, toolchains_base_dir, "--help")
@imports(_from="os.path", _import="isdir")
def default_android_sdk_root(host, toolchains_base_dir, _):
sdk_basename = {
"Darwin": "android-sdk-macosx",
"Linux": "android-sdk-linux",
"WINNT": "android-sdk-windows",
}.get(host.kernel, "android-sdk")
for sdk_basename in (sdk_basename, "android-sdk"):
path = os.path.join(toolchains_base_dir, sdk_basename)
if isdir(path):
return path
option(
"--with-android-sdk",
nargs=1,
default=default_android_sdk_root,
help="Location where the Android SDK can be found (like ~/.mozbuild/android-sdk-linux){|}",
)
@dependable
@imports(_from="platform", _import="machine")
@imports(_from="mozboot.android", _import="get_os_name_for_android")
@imports(_from="mozboot.android", _import="get_os_tag_for_android")
def android_os_info():
os_name = get_os_name_for_android()
os_tag = get_os_tag_for_android(os_name)
os_arch = machine()
if os_arch.lower() == "amd64":
# On Windows, x86_64 is reported as AMD64, but we use x86_64
# everywhere else, so let's normalize it.
os_arch = "x86_64"
if os_name == "windows" and os_arch.startswith("arm"):
die(
"Building for Android is not supported on ARM64 Windows because "
"Google does not distribute an emulator binary for ARM64 Windows. "
)
return namespace(os_name=os_name, os_tag=os_tag, os_arch=os_arch)
@depends(android_os_info)
@imports(_from="mozboot.android", _import="AVD_MANIFEST_X86_64")
@imports(_from="mozboot.android", _import="AVD_MANIFEST_ARM64")
@imports(_from="mozboot.android", _import="get_avd_manifest")
def avd_manifest(android_os_info):
if any(k in android_os_info.os_arch for k in ("x86", "x86_64")):
avd_manifest_path_for_arch = AVD_MANIFEST_X86_64
else:
avd_manifest_path_for_arch = AVD_MANIFEST_ARM64
return get_avd_manifest(avd_manifest_path_for_arch)
@imports(_from="os.path", _import="exists")
@imports(_from="mozboot.android", _import="get_android_packages")
@imports(_from="mozboot.android", _import="ensure_android_packages")
@imports(_from="mozboot.android", _import="AndroidPackageList")
def _ensure_android_package(
package_relative_path,
sdk_root,
os_name,
os_arch,
want_bootstrap,
package_prefix,
package_list_enum,
avd_manifest=None,
):
full_path = os.path.join(sdk_root, package_relative_path)
if exists(full_path):
return [full_path]
if not want_bootstrap("android-sdk"):
die(
f"You must install the Android {package_relative_path}. "
f"Try |mach bootstrap|. (Looked for {full_path})"
)
packages = get_android_packages(package_list_enum)
to_install = {pkg for pkg in packages if pkg.startswith(package_prefix)}
ensure_android_packages(
os_name,
os_arch,
packages=to_install,
no_interactive=True,
avd_manifest=avd_manifest,
)
return [full_path]
@depends("--with-android-sdk", android_os_info, want_bootstrap)
@imports(_from="os.path", _import="isdir")
@imports(_from="mozboot.android", _import="ensure_android_sdk")
@imports(_from="mozboot.android", _import="get_sdk_path")
def android_sdk_root(value, android_os_info, want_bootstrap):
if value:
sdk_path = value[0]
if not isdir(sdk_path):
die(
"The path you specified with --with-android-sdk (%s) is not "
"a directory" % sdk_path
)
return sdk_path
if not want_bootstrap("android-sdk"):
die(
"You must specify --with-android-sdk=/path/to/sdk when targeting Android, "
"or try |mach bootstrap|."
)
ensure_android_sdk(android_os_info.os_name, android_os_info.os_tag)
return str(get_sdk_path(android_os_info.os_name))
@dependable
def android_sdk_version():
# We support Android SDK version 21 and up by default.
# See the --enable-android-min-sdk option below.
#
# Warning: Before increasing the with-android-min-sdk value, please note several places in
# and out of tree have to be changed. Otherwise, places like Treeherder or archive.mozilla.org
# will advertise a bad API level. This may confuse people. As an example, please look at
# If you think you can't handle the whole set of changes, please reach out to the Release
# Engineering team.
return namespace(
build_tools_version="36.0.0",
compile_sdk_version="36",
target_sdk_version="35",
min_sdk_version="21",
)
option(
"--with-android-min-sdk",
default=android_sdk_version.min_sdk_version,
help="Impose a minimum Firefox for Android SDK version",
)
@depends("--with-android-min-sdk", android_sdk_version.target_sdk_version)
@imports(_from="__builtin__", _import="ValueError")
def valid_android_min_sdk(min_sdk_version, target_sdk_version):
if not min_sdk_version:
die("--without-android-min-sdk is not a valid option")
try:
if int(min_sdk_version[0]) > int(target_sdk_version):
die(
"--with-android-min-sdk is expected to be less than {}".format(
target_sdk_version
)
)
except ValueError:
die("--with-android-min-sdk takes a numerical value")
return min_sdk_version[0]
set_config("MOZ_ANDROID_MIN_SDK_VERSION", valid_android_min_sdk)
@depends(android_sdk_root, android_sdk_version, android_os_info, want_bootstrap)
@checking("for Android build-tools")
@imports(_from="mozboot.android", _import="AndroidPackageList")
def android_build_tools(sdk_root, sdk_version, android_os_info, want_bootstrap):
prefix = "build-tools"
return _ensure_android_package(
package_relative_path=os.path.join(prefix, sdk_version.build_tools_version),
sdk_root=sdk_root,
os_name=android_os_info.os_name,
os_arch=android_os_info.os_arch,
want_bootstrap=want_bootstrap,
package_prefix=prefix,
package_list_enum=AndroidPackageList.ALL,
)
@depends(android_sdk_root, android_os_info, want_bootstrap)
@checking("for Android platform-tools")
@imports(_from="mozboot.android", _import="AndroidPackageList")
def android_platform_tools(sdk_root, android_os_info, want_bootstrap):
prefix = "platform-tools"
return _ensure_android_package(
package_relative_path=prefix,
sdk_root=sdk_root,
os_name=android_os_info.os_name,
os_arch=android_os_info.os_arch,
want_bootstrap=want_bootstrap,
package_prefix=prefix,
package_list_enum=AndroidPackageList.ALL,
)
@depends(android_sdk_root, android_sdk_version, android_os_info, want_bootstrap)
@checking("for Android platforms")
@imports(_from="mozboot.android", _import="AndroidPackageList")
def android_platforms(sdk_root, sdk_version, android_os_info, want_bootstrap):
prefix = "platforms"
platforms_path = os.path.join(prefix, "android-" + sdk_version.compile_sdk_version)
return _ensure_android_package(
package_relative_path=platforms_path,
sdk_root=sdk_root,
os_name=android_os_info.os_name,
os_arch=android_os_info.os_arch,
want_bootstrap=want_bootstrap,
package_prefix=prefix,
package_list_enum=AndroidPackageList.ALL,
)
# Emulator
@depends(android_sdk_root, android_os_info, want_bootstrap, avd_manifest)
@checking("for Android emulator")
@imports(_from="os.path", _import="exists")
@imports(_from="mozboot.android", _import="AndroidPackageList")
def android_emulator(sdk_root, android_os_info, want_bootstrap, avd_manifest):
prefix = "emulator"
return _ensure_android_package(
package_relative_path=prefix,
sdk_root=sdk_root,
os_name=android_os_info.os_name,
os_arch=android_os_info.os_arch,
want_bootstrap=want_bootstrap,
package_prefix=prefix,
package_list_enum=AndroidPackageList.EMULATOR,
avd_manifest=avd_manifest,
)
@depends(toolchains_base_dir, want_bootstrap)
@checking("for Bundletool")
@imports(_from="os.path", _import="exists")
@imports(_from="mozboot.android", _import="ensure_bundletool")
def android_bundletool(toolchains_base_dir, want_bootstrap):
bundletool_path = os.path.join(toolchains_base_dir, "bundletool.jar")
if exists(bundletool_path):
return [bundletool_path]
if not want_bootstrap("android-sdk"):
die(
"You must install Bundletool. Try |mach bootstrap|. (Looked for %s)"
% bundletool_path
)
ensure_bundletool()
return [bundletool_path]
@depends(
toolchains_base_dir,
android_os_info,
want_bootstrap,
avd_manifest,
when=~moz_automation,
)
@checking("for AVD")
@imports(_from="os.path", _import="exists")
@imports(_from="mozboot.android", _import="ensure_android_avd")
def android_avd(toolchains_base_dir, android_os_info, want_bootstrap, avd_manifest):
avd_path = os.path.join(toolchains_base_dir, "android-device", "avd")
if exists(avd_path):
return [avd_path]
if not want_bootstrap("android-sdk"):
die("You must install AVD. Try |mach bootstrap|. (Looked for %s)" % avd_path)
ensure_android_avd(
android_os_info.os_name,
android_os_info.os_arch,
no_interactive=True,
avd_manifest=avd_manifest,
)
return [avd_path]
@template
def check_file(filename, search_dirs):
@depends(search_dirs)
@checking("for %s" % filename)
@imports(_from="os.path", _import="exists")
@imports(_from="os.path", _import="join")
def require_file(dirs):
for d in dirs:
path = join(d, filename)
if exists(path):
return path
die("The file %s was not found. Try |mach bootstrap|" % filename)
return require_file
@template
def check_android_tools(tool, tool_dir):
check = check_prog(
tool.upper(), (tool, tool + ".exe"), paths=tool_dir, allow_missing=True
)
@depends(check)
def require_tool(result):
if result is None:
die("The program %s was not found. Try |mach bootstrap|" % tool)
return result
return require_tool
set_config("ANDROID_SDK_ROOT", android_sdk_root)
check_android_tools("zipalign", android_build_tools)
check_android_tools("adb", android_platform_tools)
check_android_tools("emulator", android_emulator)
check_file("android.jar", android_platforms)
set_config("ANDROID_BUILD_TOOLS_VERSION", android_sdk_version.build_tools_version)
set_config("ANDROID_TARGET_SDK", android_sdk_version.target_sdk_version)
set_config("ANDROID_COMPILE_SDK", android_sdk_version.compile_sdk_version)