android-sdk.configure (11940B)
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- 2 # vim: set filetype=python: 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 # Ensure Android SDK and build-tools versions depending on mobile target. 8 9 10 @depends(host, toolchains_base_dir, "--help") 11 @imports(_from="os.path", _import="isdir") 12 def default_android_sdk_root(host, toolchains_base_dir, _): 13 sdk_basename = { 14 "Darwin": "android-sdk-macosx", 15 "Linux": "android-sdk-linux", 16 "WINNT": "android-sdk-windows", 17 }.get(host.kernel, "android-sdk") 18 for sdk_basename in (sdk_basename, "android-sdk"): 19 path = os.path.join(toolchains_base_dir, sdk_basename) 20 if isdir(path): 21 return path 22 23 24 option( 25 "--with-android-sdk", 26 nargs=1, 27 default=default_android_sdk_root, 28 help="Location where the Android SDK can be found (like ~/.mozbuild/android-sdk-linux){|}", 29 ) 30 31 32 @dependable 33 @imports(_from="platform", _import="machine") 34 @imports(_from="mozboot.android", _import="get_os_name_for_android") 35 @imports(_from="mozboot.android", _import="get_os_tag_for_android") 36 def android_os_info(): 37 os_name = get_os_name_for_android() 38 os_tag = get_os_tag_for_android(os_name) 39 os_arch = machine() 40 if os_arch.lower() == "amd64": 41 # On Windows, x86_64 is reported as AMD64, but we use x86_64 42 # everywhere else, so let's normalize it. 43 os_arch = "x86_64" 44 45 if os_name == "windows" and os_arch.startswith("arm"): 46 die( 47 "Building for Android is not supported on ARM64 Windows because " 48 "Google does not distribute an emulator binary for ARM64 Windows. " 49 "See also https://issuetracker.google.com/issues/264614669." 50 ) 51 52 return namespace(os_name=os_name, os_tag=os_tag, os_arch=os_arch) 53 54 55 @depends(android_os_info) 56 @imports(_from="mozboot.android", _import="AVD_MANIFEST_X86_64") 57 @imports(_from="mozboot.android", _import="AVD_MANIFEST_ARM64") 58 @imports(_from="mozboot.android", _import="get_avd_manifest") 59 def avd_manifest(android_os_info): 60 if any(k in android_os_info.os_arch for k in ("x86", "x86_64")): 61 avd_manifest_path_for_arch = AVD_MANIFEST_X86_64 62 else: 63 avd_manifest_path_for_arch = AVD_MANIFEST_ARM64 64 65 return get_avd_manifest(avd_manifest_path_for_arch) 66 67 68 @imports(_from="os.path", _import="exists") 69 @imports(_from="mozboot.android", _import="get_android_packages") 70 @imports(_from="mozboot.android", _import="ensure_android_packages") 71 @imports(_from="mozboot.android", _import="AndroidPackageList") 72 def _ensure_android_package( 73 package_relative_path, 74 sdk_root, 75 os_name, 76 os_arch, 77 want_bootstrap, 78 package_prefix, 79 package_list_enum, 80 avd_manifest=None, 81 ): 82 full_path = os.path.join(sdk_root, package_relative_path) 83 84 if exists(full_path): 85 return [full_path] 86 if not want_bootstrap("android-sdk"): 87 die( 88 f"You must install the Android {package_relative_path}. " 89 f"Try |mach bootstrap|. (Looked for {full_path})" 90 ) 91 packages = get_android_packages(package_list_enum) 92 to_install = {pkg for pkg in packages if pkg.startswith(package_prefix)} 93 ensure_android_packages( 94 os_name, 95 os_arch, 96 packages=to_install, 97 no_interactive=True, 98 avd_manifest=avd_manifest, 99 ) 100 return [full_path] 101 102 103 @depends("--with-android-sdk", android_os_info, want_bootstrap) 104 @imports(_from="os.path", _import="isdir") 105 @imports(_from="mozboot.android", _import="ensure_android_sdk") 106 @imports(_from="mozboot.android", _import="get_sdk_path") 107 def android_sdk_root(value, android_os_info, want_bootstrap): 108 if value: 109 sdk_path = value[0] 110 if not isdir(sdk_path): 111 die( 112 "The path you specified with --with-android-sdk (%s) is not " 113 "a directory" % sdk_path 114 ) 115 return sdk_path 116 117 if not want_bootstrap("android-sdk"): 118 die( 119 "You must specify --with-android-sdk=/path/to/sdk when targeting Android, " 120 "or try |mach bootstrap|." 121 ) 122 123 ensure_android_sdk(android_os_info.os_name, android_os_info.os_tag) 124 125 return str(get_sdk_path(android_os_info.os_name)) 126 127 128 @dependable 129 def android_sdk_version(): 130 major, minor, patch = "36", "1", "0" 131 return namespace( 132 build_tools_version=f"{major}.{minor}.{patch}", 133 compile_sdk_major_version=major, 134 compile_sdk_minor_version=minor, 135 target_sdk_version="36", 136 min_sdk_version="26", 137 ) 138 139 140 option( 141 "--with-android-min-sdk", 142 default=android_sdk_version.min_sdk_version, 143 help="Impose a minimum Firefox for Android SDK version", 144 ) 145 146 147 @depends("--with-android-min-sdk", android_sdk_version.target_sdk_version) 148 @imports(_from="__builtin__", _import="ValueError") 149 def valid_android_min_sdk(min_sdk_version, target_sdk_version): 150 if not min_sdk_version: 151 die("--without-android-min-sdk is not a valid option") 152 try: 153 if int(min_sdk_version[0]) > int(target_sdk_version): 154 die( 155 "--with-android-min-sdk is expected to be less than {}".format( 156 target_sdk_version 157 ) 158 ) 159 except ValueError: 160 die("--with-android-min-sdk takes a numerical value") 161 return min_sdk_version[0] 162 163 164 set_config("MOZ_ANDROID_MIN_SDK_VERSION", valid_android_min_sdk) 165 166 167 @depends(android_sdk_root, android_sdk_version, android_os_info, want_bootstrap) 168 @checking("for Android build-tools") 169 @imports(_from="mozboot.android", _import="AndroidPackageList") 170 def android_build_tools(sdk_root, sdk_version, android_os_info, want_bootstrap): 171 prefix = "build-tools" 172 return _ensure_android_package( 173 package_relative_path=os.path.join(prefix, sdk_version.build_tools_version), 174 sdk_root=sdk_root, 175 os_name=android_os_info.os_name, 176 os_arch=android_os_info.os_arch, 177 want_bootstrap=want_bootstrap, 178 package_prefix=prefix, 179 package_list_enum=AndroidPackageList.ALL, 180 ) 181 182 183 @depends(android_sdk_root, android_os_info, want_bootstrap) 184 @checking("for Android platform-tools") 185 @imports(_from="mozboot.android", _import="AndroidPackageList") 186 def android_platform_tools(sdk_root, android_os_info, want_bootstrap): 187 prefix = "platform-tools" 188 return _ensure_android_package( 189 package_relative_path=prefix, 190 sdk_root=sdk_root, 191 os_name=android_os_info.os_name, 192 os_arch=android_os_info.os_arch, 193 want_bootstrap=want_bootstrap, 194 package_prefix=prefix, 195 package_list_enum=AndroidPackageList.ALL, 196 ) 197 198 199 @depends(android_sdk_root, android_sdk_version, android_os_info, want_bootstrap) 200 @checking("for Android platforms") 201 @imports(_from="mozboot.android", _import="AndroidPackageList") 202 def android_platforms(sdk_root, sdk_version, android_os_info, want_bootstrap): 203 prefix = "platforms" 204 205 version = sdk_version.compile_sdk_major_version 206 if int(sdk_version.compile_sdk_minor_version) != 0: 207 version = f"{version}.{sdk_version.compile_sdk_minor_version}" 208 209 platforms_path = os.path.join(prefix, f"android-{version}") 210 211 return _ensure_android_package( 212 package_relative_path=platforms_path, 213 sdk_root=sdk_root, 214 os_name=android_os_info.os_name, 215 os_arch=android_os_info.os_arch, 216 want_bootstrap=want_bootstrap, 217 package_prefix=prefix, 218 package_list_enum=AndroidPackageList.ALL, 219 ) 220 221 222 # Emulator 223 @depends(android_sdk_root, android_os_info, want_bootstrap, avd_manifest) 224 @checking("for Android emulator") 225 @imports(_from="os.path", _import="exists") 226 @imports(_from="mozboot.android", _import="AndroidPackageList") 227 def android_emulator(sdk_root, android_os_info, want_bootstrap, avd_manifest): 228 prefix = "emulator" 229 return _ensure_android_package( 230 package_relative_path=prefix, 231 sdk_root=sdk_root, 232 os_name=android_os_info.os_name, 233 os_arch=android_os_info.os_arch, 234 want_bootstrap=want_bootstrap, 235 package_prefix=prefix, 236 package_list_enum=AndroidPackageList.EMULATOR, 237 avd_manifest=avd_manifest, 238 ) 239 240 241 @depends(toolchains_base_dir, "--help") 242 @imports(_from="os.path", _import="isdir") 243 def bundletool_default_path(toolchains_base_dir, _): 244 return os.path.join(toolchains_base_dir, "bundletool.jar") 245 246 247 option( 248 env="ANDROID_BUNDLETOOL_PATH", 249 nargs=1, 250 help="Optional path to a bundletool.jar (like ~/.mozbuild/bundletool.jar). If unset, the default location is used", 251 ) 252 253 254 @depends("ANDROID_BUNDLETOOL_PATH", bundletool_default_path, want_bootstrap) 255 @checking("for Bundletool") 256 @imports(_from="os.path", _import="exists") 257 @imports(_from="mozboot.android", _import="ensure_bundletool") 258 def android_bundletool(bundletool_path, bundletool_default_path, want_bootstrap): 259 if bundletool_path: 260 return [bundletool_path[0]] 261 262 if exists(bundletool_default_path): 263 return [bundletool_default_path] 264 265 if not want_bootstrap("android-sdk"): 266 die( 267 "You must install Bundletool. Try |mach bootstrap|. (Looked for %s)" 268 % bundletool_default_path 269 ) 270 271 ensure_bundletool() 272 273 return [bundletool_default_path] 274 275 276 @depends(toolchains_base_dir, "--help") 277 @imports(_from="os.path", _import="isdir") 278 def avd_default_path(toolchains_base_dir, _): 279 return os.path.join(toolchains_base_dir, "android-device", "avd") 280 281 282 option( 283 env="ANDROID_AVD_PATH", 284 nargs=1, 285 help="Optional path to an AVD executable (like ~/.mozbuild/android-device/avd). If unset, the default location is used", 286 ) 287 288 289 @depends(want_bootstrap, moz_automation) 290 def want_android_avd_bootstrap(want_bootstrap, moz_automation): 291 return not moz_automation and want_bootstrap("android-sdk") 292 293 294 @depends( 295 "ANDROID_AVD_PATH", 296 avd_default_path, 297 android_os_info, 298 avd_manifest, 299 when=want_android_avd_bootstrap, 300 ) 301 @checking("for AVD") 302 @imports(_from="os.path", _import="exists") 303 @imports(_from="mozboot.android", _import="ensure_android_avd") 304 def android_avd(avd_path, avd_default_path, android_os_info, avd_manifest): 305 if avd_path: 306 return [avd_path[0]] 307 308 if exists(avd_default_path): 309 return [avd_default_path] 310 311 ensure_android_avd( 312 android_os_info.os_name, 313 android_os_info.os_arch, 314 no_interactive=True, 315 avd_manifest=avd_manifest, 316 ) 317 return [avd_path] 318 319 320 @template 321 def check_file(filename, search_dirs): 322 @depends(search_dirs) 323 @checking("for %s" % filename) 324 @imports(_from="os.path", _import="exists") 325 @imports(_from="os.path", _import="join") 326 def require_file(dirs): 327 for d in dirs: 328 path = join(d, filename) 329 if exists(path): 330 return path 331 die("The file %s was not found. Try |mach bootstrap|" % filename) 332 333 return require_file 334 335 336 @template 337 def check_android_tools(tool, tool_dir): 338 check = check_prog( 339 tool.upper(), (tool, tool + ".exe"), paths=tool_dir, allow_missing=True 340 ) 341 342 @depends(check) 343 def require_tool(result): 344 if result is None: 345 die("The program %s was not found. Try |mach bootstrap|" % tool) 346 return result 347 348 return require_tool 349 350 351 set_config("ANDROID_SDK_ROOT", android_sdk_root) 352 353 check_android_tools("zipalign", android_build_tools) 354 check_android_tools("adb", android_platform_tools) 355 check_android_tools("emulator", android_emulator) 356 check_file("android.jar", android_platforms) 357 358 set_config("ANDROID_BUILD_TOOLS_VERSION", android_sdk_version.build_tools_version) 359 set_config("ANDROID_TARGET_SDK", android_sdk_version.target_sdk_version) 360 set_config("ANDROID_COMPILE_SDK_MAJOR", android_sdk_version.compile_sdk_major_version) 361 set_config("ANDROID_COMPILE_SDK_MINOR", android_sdk_version.compile_sdk_minor_version)