1# -*- bazel-starlark -*- 2# Copyright 2023 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5"""Siso configuration for Android builds.""" 6 7load("@builtin//encoding.star", "json") 8load("@builtin//lib/gn.star", "gn") 9load("@builtin//struct.star", "module") 10load("./config.star", "config") 11load("./gn_logs.star", "gn_logs") 12 13# TODO: crbug.com/323091468 - Propagate target android ABI and 14# android SDK version from GN, and remove the hardcoded filegroups. 15__archs = [ 16 "aarch64-linux-android", 17 "arm-linux-androideabi", 18 "i686-linux-android", 19 "riscv64-linux-android", 20 "x86_64-linux-android", 21] 22 23def __enabled(ctx): 24 if "args.gn" in ctx.metadata: 25 gn_args = gn.args(ctx) 26 if gn_args.get("target_os") == '"android"': 27 return True 28 return False 29 30def __filegroups(ctx): 31 fg = {} 32 for arch in __archs: 33 api_level = gn_logs.read(ctx).get("android64_ndk_api_level") 34 if api_level: 35 group = "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/%s/%s:link" % (arch, api_level) 36 fg[group] = { 37 "type": "glob", 38 "includes": ["*"], 39 } 40 return fg 41 42def __step_config(ctx, step_config): 43 remote_run = True # Turn this to False when you do file access trace. 44 45 # Run static analysis steps locally when build server is enabled. 46 # https://chromium.googlesource.com/chromium/src/+/main/docs/android_build_instructions.md#asynchronous-static-analysis 47 remote_run_static_analysis = True 48 if "args.gn" in ctx.metadata: 49 gn_args = gn.args(ctx) 50 if gn_args.get("android_static_analysis") == '"build_server"': 51 remote_run_static_analysis = False 52 53 step_config["rules"].extend([ 54 # See also https://chromium.googlesource.com/chromium/src/build/+/HEAD/android/docs/java_toolchain.md 55 { 56 "name": "android/write_build_config", 57 "command_prefix": "python3 ../../build/android/gyp/write_build_config.py", 58 "handler": "android_write_build_config", 59 "remote": remote_run, 60 "canonicalize_dir": True, 61 "timeout": "2m", 62 }, 63 { 64 "name": "android/ijar", 65 "command_prefix": "python3 ../../build/android/gyp/ijar.py", 66 "remote": remote_run, 67 "canonicalize_dir": True, 68 "timeout": "2m", 69 }, 70 { 71 "name": "android/turbine", 72 "command_prefix": "python3 ../../build/android/gyp/turbine.py", 73 "handler": "android_turbine", 74 # TODO: crbug.com/396220357 - fix gn to remove unnecessary deps 75 "exclude_input_patterns": [ 76 "*.a", 77 "*.cc", 78 "*.cpp", 79 "*.h", 80 "*.html", 81 "*.inc", 82 "*.info", 83 "*.js", 84 "*.map", 85 "*.o", 86 "*.pak", 87 "*.proto", 88 "*.sql", 89 "*.stamp", 90 "*.svg", 91 "*.xml", 92 ], 93 "remote": remote_run, 94 "platform_ref": "large", 95 "canonicalize_dir": True, 96 "timeout": "2m", 97 }, 98 { 99 "name": "android/compile_resources", 100 "command_prefix": "python3 ../../build/android/gyp/compile_resources.py", 101 "handler": "android_compile_resources", 102 "exclude_input_patterns": [ 103 "*.a", 104 "*.cc", 105 "*.h", 106 "*.inc", 107 "*.info", 108 "*.o", 109 "*.pak", 110 "*.sql", 111 ], 112 "remote": remote_run, 113 "canonicalize_dir": True, 114 "timeout": "5m", 115 }, 116 { 117 "name": "android/compile_java", 118 "command_prefix": "python3 ../../build/android/gyp/compile_java.py", 119 "handler": "android_compile_java", 120 "exclude_input_patterns": [ 121 "*.a", 122 "*.cc", 123 "*.h", 124 "*.inc", 125 "*.info", 126 "*.o", 127 "*.pak", 128 "*.sql", 129 ], 130 # Don't include files under --generated-dir. 131 # This is probably optimization for local incrmental builds. 132 # However, this is harmful for remote build cache hits. 133 "ignore_extra_input_pattern": ".*srcjars.*\\.java", 134 "ignore_extra_output_pattern": ".*srcjars.*\\.java", 135 "remote": remote_run, 136 "platform_ref": "large", 137 "canonicalize_dir": True, 138 "timeout": "2m", 139 }, 140 { 141 "name": "android/errorprone", 142 "command_prefix": "python3 ../../build/android/gyp/errorprone.py", 143 "handler": "android_compile_java", 144 "exclude_input_patterns": [ 145 "*.a", 146 "*.cc", 147 "*.h", 148 "*.inc", 149 "*.info", 150 "*.o", 151 "*.pak", 152 "*.sql", 153 ], 154 "remote": remote_run_static_analysis, 155 "platform_ref": "large", 156 "canonicalize_dir": True, 157 "timeout": "2m", 158 }, 159 { 160 "name": "android/compile_kt", 161 "command_prefix": "python3 ../../build/android/gyp/compile_kt.py", 162 "handler": "android_compile_java", 163 "exclude_input_patterns": [ 164 "*.a", 165 "*.cc", 166 "*.h", 167 "*.inc", 168 "*.info", 169 "*.o", 170 "*.pak", 171 "*.sql", 172 ], 173 # Don't include files under --generated-dir. 174 # This is probably optimization for local incrmental builds. 175 # However, this is harmful for remote build cache hits. 176 "ignore_extra_input_pattern": ".*srcjars.*\\.java", 177 "ignore_extra_output_pattern": ".*srcjars.*\\.java", 178 "remote": remote_run, 179 "platform_ref": "large", 180 "canonicalize_dir": True, 181 "timeout": "2m", 182 }, 183 { 184 "name": "android/dex", 185 "command_prefix": "python3 ../../build/android/gyp/dex.py", 186 "handler": "android_dex", 187 # TODO(crbug.com/40270798): include only required jar, dex files in GN config. 188 "indirect_inputs": { 189 "includes": ["*.dex", "*.ijar.jar", "*.turbine.jar"], 190 }, 191 "exclude_input_patterns": [ 192 "*.a", 193 "*.cc", 194 "*.h", 195 "*.inc", 196 "*.info", 197 "*.o", 198 "*.pak", 199 "*.sql", 200 ], 201 # *.dex files are intermediate files used in incremental builds. 202 # Fo remote actions, let's ignore them, assuming remote cache hits compensate. 203 "ignore_extra_input_pattern": ".*\\.dex", 204 "ignore_extra_output_pattern": ".*\\.dex", 205 "remote": remote_run, 206 "platform_ref": "large", 207 "canonicalize_dir": True, 208 "timeout": "2m", 209 }, 210 { 211 "name": "android/filter_zip", 212 "command_prefix": "python3 ../../build/android/gyp/filter_zip.py", 213 "remote": remote_run, 214 "canonicalize_dir": True, 215 "timeout": "2m", 216 }, 217 { 218 "name": "android/generate_resource_allowlist", 219 "command_prefix": "python3 ../../tools/resources/generate_resource_allowlist.py", 220 "indirect_inputs": { 221 "includes": ["*.o", "*.a"], 222 }, 223 # When remote linking without bytes enabled, .o, .a files don't 224 # exist on the local file system. 225 # This step also should run remortely to avoid downloading them. 226 "remote": config.get(ctx, "remote-link"), 227 "platform_ref": "large", 228 "canonicalize_dir": True, 229 "timeout": "2m", 230 }, 231 { 232 "name": "android/proguard", 233 "command_prefix": "python3 ../../build/android/gyp/proguard.py", 234 "handler": "android_proguard", 235 "exclude_input_patterns": [ 236 "*.a", 237 "*.cc", 238 "*.h", 239 "*.inc", 240 "*.info", 241 "*.o", 242 "*.pak", 243 "*.sql", 244 ], 245 "canonicalize_dir": True, 246 # Speculatively disabling for https://crbug.com/398058215 247 "remote": False, 248 "platform_ref": "large", 249 "timeout": "10m", 250 }, 251 ]) 252 return step_config 253 254def __filearg(ctx, arg): 255 fn = "" 256 if arg.startswith("@FileArg("): 257 f = arg.removeprefix("@FileArg(").removesuffix(")").split(":") 258 fn = f[0].removesuffix("[]") # [] suffix controls expand list? 259 v = json.decode(str(ctx.fs.read(ctx.fs.canonpath(fn)))) 260 for k in f[1:]: 261 v = v[k] 262 arg = v 263 if type(arg) == "string": 264 if arg.startswith("["): 265 return fn, json.decode(arg) 266 return fn, [arg] 267 return fn, arg 268 269def __android_compile_resources_handler(ctx, cmd): 270 # Script: 271 # https://crsrc.org/c/build/android/gyp/compile_resources.py 272 # GN Config: 273 # https://crsrc.org/c/build/config/android/internal_rules.gni;l=2163;drc=1b15af251f8a255e44f2e3e3e7990e67e87dcc3b 274 # https://crsrc.org/c/build/config/android/system_image.gni;l=58;drc=39debde76e509774287a655285d8556a9b8dc634 275 # Sample args: 276 # --aapt2-path ../../third_party/android_build_tools/aapt2/cipd/aapt2 277 # --android-manifest gen/chrome/android/trichrome_library_system_stub_apk__manifest.xml 278 # --arsc-package-name=org.chromium.trichromelibrary 279 # --arsc-path obj/chrome/android/trichrome_library_system_stub_apk.ap_ 280 # --debuggable 281 # --dependencies-res-zip-overlays=@FileArg\(gen/chrome/android/webapk/shell_apk/maps_go_webapk.build_config.json:deps_info:dependency_zip_overlays\) 282 # --dependencies-res-zips=@FileArg\(gen/chrome/android/webapk/shell_apk/maps_go_webapk.build_config.json:deps_info:dependency_zips\) 283 # --depfile gen/chrome/android/webapk/shell_apk/maps_go_webapk__compile_resources.d 284 # --emit-ids-out=gen/chrome/android/webapk/shell_apk/maps_go_webapk__compile_resources.resource_ids 285 # --extra-res-packages=@FileArg\(gen/chrome/android/webapk/shell_apk/maps_go_webapk.build_config.json:deps_info:extra_package_names\) 286 # --include-resources(=)../../third_party/android_sdk/public/platforms/android-34/android.jar 287 # --info-path obj/chrome/android/webapk/shell_apk/maps_go_webapk.ap_.info 288 # --min-sdk-version=24 289 # --proguard-file obj/chrome/android/webapk/shell_apk/maps_go_webapk/maps_go_webapk.resources.proguard.txt 290 # --r-text-out gen/chrome/android/webapk/shell_apk/maps_go_webapk__compile_resources_R.txt 291 # --rename-manifest-package=org.chromium.trichromelibrary 292 # --srcjar-out gen/chrome/android/webapk/shell_apk/maps_go_webapk__compile_resources.srcjar 293 # --target-sdk-version=33 294 # --version-code 1 295 # --version-name Developer\ Build 296 # --webp-cache-dir=obj/android-webp-cache 297 inputs = [] 298 for i, arg in enumerate(cmd.args): 299 for k in ["--dependencies-res-zips=", "--dependencies-res-zip-overlays=", "--extra-res-packages="]: 300 if arg.startswith(k): 301 arg = arg.removeprefix(k) 302 _, v = __filearg(ctx, arg) 303 for f in v: 304 f = ctx.fs.canonpath(f) 305 inputs.append(f) 306 if k == "--dependencies-res-zips=" and ctx.fs.exists(f + ".info"): 307 inputs.append(f + ".info") 308 309 ctx.actions.fix( 310 inputs = cmd.inputs + inputs, 311 ) 312 313def __android_compile_java_handler(ctx, cmd): 314 # Script: 315 # https://crsrc.org/c/build/android/gyp/compile_java.py 316 # GN Config: 317 # https://crsrc.org/c/build/config/android/internal_rules.gni;l=2995;drc=775b3a9ebccd468c79592dad43ef46632d3a411f 318 # Sample args: 319 # --depfile=gen/chrome/android/chrome_test_java__compile_java.d 320 # --generated-dir=gen/chrome/android/chrome_test_java/generated_java 321 # --jar-path=obj/chrome/android/chrome_test_java.javac.jar 322 # --java-srcjars=\[\"gen/chrome/browser/tos_dialog_behavior_generated_enum.srcjar\",\ \"gen/chrome/android/chrome_test_java__assetres.srcjar\",\ \"gen/chrome/android/chrome_test_java.generated.srcjar\"\] 323 # --target-name //chrome/android:chrome_test_java__compile_java 324 # --classpath=@FileArg\(gen/chrome/android/chrome_test_java.build_config.json:android:sdk_interface_jars\) 325 # --header-jar obj/chrome/android/chrome_test_java.turbine.jar 326 # --classpath=\[\"obj/chrome/android/chrome_test_java.turbine.jar\"\] 327 # --classpath=@FileArg\(gen/chrome/android/chrome_test_java.build_config.json:deps_info:javac_full_interface_classpath\) 328 # --kotlin-jar-path=obj/chrome/browser/tabmodel/internal/java.kotlinc.jar 329 # --chromium-code=1 330 # --warnings-as-errors 331 # --jar-info-exclude-globs=\[\"\*/R.class\",\ \"\*/R\\\$\*.class\",\ \"\*/Manifest.class\",\ \"\*/Manifest\\\$\*.class\",\ \"\*/\*GEN_JNI.class\"\] 332 # --enable-errorprone 333 # @gen/chrome/android/chrome_test_java.sources 334 335 out = cmd.outputs[0] 336 outputs = [ 337 out + ".md5.stamp", 338 ] 339 340 inputs = [] 341 for i, arg in enumerate(cmd.args): 342 for k in ["--classpath=", "--bootclasspath=", "--processorpath="]: 343 if arg.startswith(k): 344 arg = arg.removeprefix(k) 345 fn, v = __filearg(ctx, arg) 346 if fn: 347 inputs.append(ctx.fs.canonpath(fn)) 348 for f in v: 349 f, _, _ = f.partition(":") 350 inputs.append(ctx.fs.canonpath(f)) 351 352 ctx.actions.fix( 353 inputs = cmd.inputs + inputs, 354 outputs = cmd.outputs + outputs, 355 ) 356 357def __android_dex_handler(ctx, cmd): 358 out = cmd.outputs[0] 359 inputs = [] 360 361 # Add __dex.desugardeps to the outputs. 362 outputs = [ 363 out + ".md5.stamp", 364 ] 365 for i, arg in enumerate(cmd.args): 366 if arg == "--desugar-dependencies": 367 outputs.append(ctx.fs.canonpath(cmd.args[i + 1])) 368 for k in ["--class-inputs=", "--bootclasspath=", "--classpath=", "--class-inputs-filearg=", "--dex-inputs-filearg="]: 369 if arg.startswith(k): 370 arg = arg.removeprefix(k) 371 _, v = __filearg(ctx, arg) 372 for f in v: 373 f, _, _ = f.partition(":") 374 f = ctx.fs.canonpath(f) 375 inputs.append(f) 376 377 # TODO: dex.py takes --incremental-dir to reuse the .dex produced in a previous build. 378 # Should remote dex action also take this? 379 ctx.actions.fix( 380 inputs = cmd.inputs + inputs, 381 outputs = cmd.outputs + outputs, 382 ) 383 384def __android_proguard_handler(ctx, cmd): 385 inputs = [] 386 outputs = [] 387 for i, arg in enumerate(cmd.args): 388 for k in ["--proguard-configs=", "--input-paths=", "--feature-jars="]: 389 if arg.startswith(k): 390 arg = arg.removeprefix(k) 391 fn, v = __filearg(ctx, arg) 392 if fn: 393 inputs.append(ctx.fs.canonpath(fn)) 394 for f in v: 395 f, _, _ = f.partition(":") 396 inputs.append(ctx.fs.canonpath(f)) 397 break 398 if arg in ["--sdk-jars", "--sdk-extension-jars"]: 399 fn, v = __filearg(ctx, cmd.args[i + 1]) 400 if fn: 401 inputs.append(ctx.fs.canonpath(fn)) 402 for f in v: 403 f, _, _ = f.partition(":") 404 inputs.append(ctx.fs.canonpath(f)) 405 continue 406 if arg.startswith("--dex-dest="): 407 arg = arg.removeprefix("--dex-dest=") 408 fn, v = __filearg(ctx, arg) 409 if fn: 410 inputs.append(ctx.fs.canonpath(fn)) 411 for f in v: 412 f, _, _ = f.partition(":") 413 outputs.append(ctx.fs.canonpath(f)) 414 continue 415 416 ctx.actions.fix( 417 inputs = cmd.inputs + inputs, 418 outputs = cmd.outputs + outputs, 419 ) 420 421def __android_turbine_handler(ctx, cmd): 422 inputs = [] 423 for i, arg in enumerate(cmd.args): 424 for k in ["--classpath=", "--processorpath="]: 425 if arg.startswith(k): 426 arg = arg.removeprefix(k) 427 _, v = __filearg(ctx, arg) 428 for f in v: 429 f, _, _ = f.partition(":") 430 inputs.append(ctx.fs.canonpath(f)) 431 432 ctx.actions.fix( 433 inputs = cmd.inputs + inputs, 434 ) 435 436def __deps_configs(ctx, f, seen, inputs): 437 if f in seen: 438 return 439 seen[f] = True 440 inputs.append(f) 441 v = json.decode(str(ctx.fs.read(f))) 442 for f in v["deps_info"]["deps_configs"]: 443 f = ctx.fs.canonpath(f) 444 __deps_configs(ctx, f, seen, inputs) 445 if "public_deps_configs" in v["deps_info"]: 446 for f in v["deps_info"]["public_deps_configs"]: 447 f = ctx.fs.canonpath(f) 448 __deps_configs(ctx, f, seen, inputs) 449 450def __android_write_build_config_handler(ctx, cmd): 451 # Script: 452 # https://crsrc.org/c/build/android/gyp/write_build_config.py 453 # GN Config: 454 # https://crsrc.org/c/build/config/android/internal_rules.gni;l=122;drc=99e4f79301e108ea3d27ec84320f430490382587 455 # Sample args: 456 # --type=java_library 457 # --depfile gen/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm_java__build_config_crbug_908819.d 458 # --deps-configs=\[\"gen/third_party/kotlin_stdlib/kotlin_stdlib_java.build_config.json\"\] 459 # --public-deps-configs=\[\] 460 # --build-config gen/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm_java.build_config.json 461 # --gn-target //third_party/android_deps:org_jetbrains_kotlinx_kotlinx_metadata_jvm_java 462 # --non-chromium-code 463 # --host-jar-path lib.java/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm.jar 464 # --unprocessed-jar-path ../../third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm/kotlinx-metadata-jvm-0.1.0.jar 465 # --interface-jar-path obj/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm.ijar.jar 466 # --is-prebuilt 467 # --bundled-srcjars=\[\] 468 inputs = [] 469 seen = {} 470 for i, arg in enumerate(cmd.args): 471 if arg in ["--shared-libraries-runtime-deps", "--secondary-abi-shared-libraries-runtime-deps"]: 472 inputs.append(ctx.fs.canonpath(cmd.args[i + 1])) 473 continue 474 if arg == "--tested-apk-config": 475 f = ctx.fs.canonpath(cmd.args[i + 1]) 476 __deps_configs(ctx, f, seen, inputs) 477 continue 478 for k in ["--deps-configs=", "--public-deps-configs=", "--annotation-processor-configs="]: 479 if arg.startswith(k): 480 arg = arg.removeprefix(k) 481 v = json.decode(arg) 482 for f in v: 483 f = ctx.fs.canonpath(f) 484 __deps_configs(ctx, f, seen, inputs) 485 486 ctx.actions.fix(inputs = cmd.inputs + inputs) 487 488__handlers = { 489 "android_compile_java": __android_compile_java_handler, 490 "android_compile_resources": __android_compile_resources_handler, 491 "android_dex": __android_dex_handler, 492 "android_proguard": __android_proguard_handler, 493 "android_turbine": __android_turbine_handler, 494 "android_write_build_config": __android_write_build_config_handler, 495} 496 497android = module( 498 "android", 499 enabled = __enabled, 500 archs = __archs, 501 step_config = __step_config, 502 filegroups = __filegroups, 503 handlers = __handlers, 504) 505