aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
committermosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
commitc7bade461dc55726f62997d13a48582f7c4b4655 (patch)
treeea0588da76060a2038f54f67efd046ca77634b10
parent0f5414d19317805e8bbbe7c4db5f0fd78769bad5 (diff)
parent89d78cff8b00d3b20a90074635c3fe5a2ee49474 (diff)
Merge branch 'lineage-23.1' of https://github.com/LineageOS/android_build_soong into HEADw16.1
* 'lineage-23.1' of https://github.com/LineageOS/android_build_soong: (528 commits) Revert "install_symlink: Make symlink target configurable" Reapply "Clear as much of cc.Module as possible after GenerateBuildActions" Revert "rust: config: Fix missing CPU variant LD flags in Rust" Rename build-flag in outdir Revert^4 "cipd: Default CIPD proxy server to on, add opt-out" Convert check-vintf-all to phony with actions Create a partial implementation of check-vintf-all for soong-only Configure RBE rust pool based on build variant Revert^3 "Add sdk version check to arr" Add jdk.internal.invoke to the allowlist Make droid always depend on symbols zip Import Device and Odm skus Don't install gob_gen in Soong Remove bazel reference from run_integration_tests.sh Fix bootstrap_test.sh Don't panic in aconfig libraries when AllowMissingDependencies is set Avoid returning nil paths from PathForModuleSrc Revert "Flag controled clang version" Rework module target dependencies on required deps Revert^2 "Add sdk version check to arr" ... Change-Id: I6e9a63fa14fda917a42e426e5dcebbad7f67e1de
-rw-r--r--Android.bp23
-rw-r--r--OWNERS3
-rw-r--r--PREUPLOAD.cfg10
-rw-r--r--README.md8
-rw-r--r--aconfig/Android.bp1
-rw-r--r--aconfig/aconfig_declarations.go34
-rw-r--r--aconfig/aconfig_declarations_test.go14
-rw-r--r--aconfig/aconfig_value_set.go16
-rw-r--r--aconfig/aconfig_value_set_test.go4
-rw-r--r--aconfig/all_aconfig_declarations.go138
-rw-r--r--aconfig/all_aconfig_declarations_extension.go6
-rw-r--r--aconfig/all_aconfig_declarations_extension_test.go2
-rw-r--r--aconfig/build_flags/Android.bp6
-rw-r--r--aconfig/build_flags/build_flags.go12
-rw-r--r--aconfig/build_flags/build_flags_singleton.go58
-rw-r--r--aconfig/build_flags/init.go14
-rw-r--r--aconfig/build_flags/release_configs.go53
-rw-r--r--aconfig/codegen/aconfig_declarations_group.go2
-rw-r--r--aconfig/codegen/cc_aconfig_library.go14
-rw-r--r--aconfig/codegen/cc_aconfig_library_test.go6
-rw-r--r--aconfig/codegen/init.go5
-rw-r--r--aconfig/codegen/java_aconfig_library.go27
-rw-r--r--aconfig/codegen/java_aconfig_library_test.go4
-rw-r--r--aconfig/codegen/rust_aconfig_library.go2
-rw-r--r--aconfig/exported_java_aconfig_library.go17
-rw-r--r--aconfig/init.go60
-rw-r--r--aidl_library/aidl_library.go2
-rw-r--r--android/Android.bp22
-rw-r--r--android/aconfig_providers.go20
-rw-r--r--android/aconfig_providers_gob_enc.go270
-rw-r--r--android/androidmk.go92
-rw-r--r--android/androidmk_gob_enc.go324
-rw-r--r--android/apex.go62
-rw-r--r--android/apex_contributions.go32
-rw-r--r--android/api_levels.go57
-rw-r--r--android/api_levels_gob_enc.go58
-rw-r--r--android/arch.go68
-rw-r--r--android/arch_gob_enc.go278
-rw-r--r--android/arch_list.go30
-rw-r--r--android/arch_module_context.go18
-rw-r--r--android/base_module_context.go212
-rw-r--r--android/build_prop.go7
-rw-r--r--android/cipd/Android.bp19
-rw-r--r--android/cipd/cipd.go147
-rw-r--r--android/cipd/cipd_test.go101
-rw-r--r--android/compliance_metadata.go106
-rw-r--r--android/compliance_metadata_gob_enc.go183
-rw-r--r--android/config.go260
-rw-r--r--android/config_test.go67
-rw-r--r--android/container.go11
-rw-r--r--android/container_gob_enc.go38
-rw-r--r--android/container_violations.go345
-rw-r--r--android/deapexer.go14
-rw-r--r--android/defaults_test.go4
-rw-r--r--android/defs.go24
-rw-r--r--android/early_module_context.go13
-rw-r--r--android/filegroup.go20
-rw-r--r--android/fixture.go17
-rw-r--r--android/fixture_test.go7
-rw-r--r--android/hooks.go28
-rw-r--r--android/license_metadata.go3
-rw-r--r--android/license_metadata_gob_enc.go49
-rw-r--r--android/license_sdk_member.go14
-rw-r--r--android/licenses.go53
-rw-r--r--android/licenses_gob_enc.go118
-rw-r--r--android/logtags.go3
-rw-r--r--android/logtags_gob_enc.go56
-rw-r--r--android/makevars.go21
-rw-r--r--android/module.go606
-rw-r--r--android/module_context.go101
-rw-r--r--android/module_gob_enc.go1497
-rw-r--r--android/module_info_json.go33
-rw-r--r--android/module_info_json_gob_enc.go865
-rw-r--r--android/module_proxy.go230
-rw-r--r--android/module_test.go17
-rw-r--r--android/mutator.go7
-rw-r--r--android/mutator_test.go2
-rw-r--r--android/namespace.go11
-rw-r--r--android/namespace_test.go9
-rw-r--r--android/neverallow.go3
-rw-r--r--android/override_module.go211
-rw-r--r--android/package_ctx.go17
-rw-r--r--android/packaging.go129
-rw-r--r--android/packaging_gob_enc.go226
-rw-r--r--android/path_properties.go103
-rw-r--r--android/path_properties_test.go4
-rw-r--r--android/paths.go179
-rw-r--r--android/paths_gob_enc.go502
-rw-r--r--android/paths_test.go2
-rw-r--r--android/phony.go18
-rw-r--r--android/phony_gob_enc.go81
-rw-r--r--android/plugin.go51
-rw-r--r--android/prebuilt.go106
-rw-r--r--android/prebuilt_test.go4
-rw-r--r--android/product_config.go16
-rw-r--r--android/provider.go21
-rw-r--r--android/provider_keys.go8
-rw-r--r--android/raw_files.go2
-rw-r--r--android/rule_builder.go101
-rw-r--r--android/rule_builder_gob_enc.go50
-rw-r--r--android/sbom.go2
-rw-r--r--android/sdk.go21
-rw-r--r--android/sdk_gob_enc.go200
-rw-r--r--android/sdk_version.go2
-rw-r--r--android/selects_test.go21
-rw-r--r--android/singleton.go126
-rw-r--r--android/soong_config_modules.go2
-rw-r--r--android/symbols.go107
-rw-r--r--android/symbols_gob_enc.go112
-rw-r--r--android/system_dev_certificate.go45
-rw-r--r--android/team.go3
-rw-r--r--android/team_gob_enc.go47
-rw-r--r--android/team_proto/OWNERS1
-rw-r--r--android/test_config.go14
-rw-r--r--android/test_suites.go464
-rw-r--r--android/test_suites_gob_enc.go415
-rw-r--r--android/test_suites_test.go23
-rw-r--r--android/testing.go210
-rw-r--r--android/transition.go17
-rw-r--r--android/util.go20
-rw-r--r--android/variable.go65
-rw-r--r--android/vendor_api_levels.go4
-rw-r--r--android/visibility.go19
-rw-r--r--android_sdk/sdk_repo_host.go4
-rw-r--r--apex/androidmk.go75
-rw-r--r--apex/apex.go234
-rw-r--r--apex/apex_sdk_member.go4
-rw-r--r--apex/apex_singleton.go4
-rw-r--r--apex/apex_test.go101
-rw-r--r--apex/builder.go65
-rw-r--r--apex/classpath_element_test.go54
-rw-r--r--apex/dexpreopt_bootjars_test.go2
-rw-r--r--apex/key.go8
-rw-r--r--apex/prebuilt.go116
-rwxr-xr-xbin/printflags25
-rw-r--r--bpf/bpf.go4
-rw-r--r--bpf/libbpf/libbpf_prog.go26
-rw-r--r--bpf/libbpf/libbpf_prog_test.go25
-rwxr-xr-xbuild_kzip.bash4
-rw-r--r--cc/Android.bp8
-rw-r--r--cc/afdo_test.go48
-rw-r--r--cc/androidmk.go19
-rw-r--r--cc/binary.go4
-rw-r--r--cc/binary_sdk_member.go69
-rw-r--r--cc/binary_sdk_member_gob_enc.go37
-rw-r--r--cc/builder.go35
-rw-r--r--cc/builder_gob_enc.go192
-rw-r--r--cc/cc.go502
-rw-r--r--cc/cc_gob_enc.go2290
-rw-r--r--cc/cc_test.go16
-rw-r--r--cc/cc_test_only_property_test.go8
-rw-r--r--cc/ccdeps.go41
-rw-r--r--cc/cmake_snapshot.go4
-rw-r--r--cc/cmakelists.go49
-rw-r--r--cc/compdb.go36
-rw-r--r--cc/config/arm64_device.go67
-rw-r--r--cc/config/arm64_linux_host.go11
-rw-r--r--cc/config/arm_device.go35
-rw-r--r--cc/config/arm_linux_host.go32
-rw-r--r--cc/config/darwin_host.go5
-rw-r--r--cc/config/global.go26
-rw-r--r--cc/config/riscv64_device.go17
-rw-r--r--cc/config/toolchain.go1
-rw-r--r--cc/config/x86_64_device.go11
-rw-r--r--cc/config/x86_device.go5
-rw-r--r--cc/config/x86_linux_bionic_host.go12
-rw-r--r--cc/config/x86_linux_host.go41
-rw-r--r--cc/config/x86_windows_host.go25
-rw-r--r--cc/coverage.go41
-rw-r--r--cc/fuzz.go217
-rw-r--r--cc/installer.go2
-rw-r--r--cc/library.go26
-rw-r--r--cc/library_headers_test.go4
-rw-r--r--cc/library_sdk_member.go68
-rw-r--r--cc/linkable.go9
-rw-r--r--cc/linkable_gob_enc.go190
-rw-r--r--cc/linker.go60
-rw-r--r--cc/llvm_coverage_tools_zip.go55
-rw-r--r--cc/lto_test.go26
-rw-r--r--cc/makevars.go16
-rw-r--r--cc/misc_disted_files.go5
-rw-r--r--cc/ndk_library.go8
-rw-r--r--cc/ndk_test.go4
-rw-r--r--cc/ndk_translation_package.go270
-rw-r--r--cc/object.go4
-rw-r--r--cc/orderfile_test.go20
-rw-r--r--cc/prebuilt_test.go65
-rw-r--r--cc/sanitize.go35
-rw-r--r--cc/sanitize_gob_enc.go631
-rw-r--r--cc/sdk.go16
-rw-r--r--cc/test.go95
-rw-r--r--cc/testing.go2
-rw-r--r--ci_tests/Android.bp1
-rw-r--r--ci_tests/ci_test_package_zip.go106
-rw-r--r--cmd/dir_to_depfile/Android.bp (renamed from android/init.go)23
-rw-r--r--cmd/dir_to_depfile/dir_to_depfile.go80
-rw-r--r--cmd/find_input_delta/find_input_delta/main.go22
-rw-r--r--cmd/find_input_delta/find_input_delta_lib/internal_state.go46
-rw-r--r--cmd/find_input_delta/find_input_delta_lib/internal_state_test.go6
-rw-r--r--cmd/incremental_dex_input/Android.bp26
-rw-r--r--cmd/incremental_dex_input/README.md43
-rw-r--r--cmd/incremental_dex_input/incremental_dex_input_lib/Android.bp29
-rw-r--r--cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input.go194
-rw-r--r--cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input_test.go493
-rw-r--r--cmd/incremental_dex_input/main.go55
-rw-r--r--cmd/incremental_javac_input/Android.bp27
-rw-r--r--cmd/incremental_javac_input/README.md45
-rw-r--r--cmd/incremental_javac_input/incremental_javac_input_lib/Android.bp30
-rw-r--r--cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input.go290
-rw-r--r--cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input_test.go699
-rw-r--r--cmd/incremental_javac_input/main.go68
-rw-r--r--cmd/kotlinc_incremental/Android.bp26
-rw-r--r--cmd/kotlinc_incremental/kotlin-jar-snapshotter.mf1
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Argument.kt254
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Options.kt (renamed from cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt)14
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Argument.kt296
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/BuildFileParser.kt104
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/ClientOptions.kt195
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Logger.kt51
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt233
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Argument.kt44
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Main.kt58
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/SnapshotterOptions.kt28
-rw-r--r--cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Util.kt24
-rw-r--r--cmd/kotlinc_incremental/tests/resources/test_build.xml10
-rw-r--r--cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/cli/ArgumentTest.kt97
-rw-r--r--cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/ArgumentTest.kt425
-rw-r--r--cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/BuildFileParserTest.kt66
-rw-r--r--cmd/release_config/build_flag/Android.bp2
-rw-r--r--cmd/release_config/build_flag/main.go30
-rw-r--r--cmd/release_config/build_flag_declarations/main.go5
-rw-r--r--cmd/release_config/release_config/main.go13
-rw-r--r--cmd/release_config/release_config_lib/Android.bp7
-rw-r--r--cmd/release_config/release_config_lib/flag_artifact.go12
-rw-r--r--cmd/release_config/release_config_lib/flag_declaration.go33
-rw-r--r--cmd/release_config/release_config_lib/flag_declaration_test.go90
-rw-r--r--cmd/release_config/release_config_lib/flag_value.go22
-rw-r--r--cmd/release_config/release_config_lib/flag_value_test.go34
-rw-r--r--cmd/release_config/release_config_lib/release_config.go18
-rw-r--r--cmd/release_config/release_config_lib/release_configs.go163
-rw-r--r--cmd/release_config/release_config_proto/Android.bp18
-rw-r--r--cmd/release_config/release_config_proto/build_flags_common.pb.go51
-rw-r--r--cmd/release_config/release_config_proto/build_flags_common.proto8
-rw-r--r--cmd/release_config/release_config_proto/build_flags_declarations.pb.go78
-rw-r--r--cmd/release_config/release_config_proto/build_flags_out.pb.go171
-rw-r--r--cmd/release_config/release_config_proto/build_flags_src.pb.go234
-rw-r--r--cmd/release_config/release_config_proto/release_configs_contributions.pb.go76
-rw-r--r--cmd/sbox/sbox.go139
-rw-r--r--cmd/sbox/sbox_proto/sbox.pb.go225
-rw-r--r--cmd/sbox/sbox_proto/sbox.proto13
-rw-r--r--cmd/soong_build/main.go38
-rw-r--r--cmd/soong_ui/main.go9
-rw-r--r--compliance/notice.go16
-rw-r--r--dexpreopt/class_loader_context.go5
-rw-r--r--dexpreopt/config.go50
-rw-r--r--dexpreopt/dexpreopt.go2
-rw-r--r--dexpreopt/dexpreopt_test.go2
-rw-r--r--dexpreopt/testing.go9
-rw-r--r--docs/best_practices.md3
-rw-r--r--docs/perf.md4
-rw-r--r--etc/install_symlink.go4
-rw-r--r--etc/prebuilt_etc.go64
-rw-r--r--filesystem/Android.bp2
-rw-r--r--filesystem/aconfig_files.go20
-rw-r--r--filesystem/android_device.go566
-rw-r--r--filesystem/android_device_product_out.go21
-rw-r--r--filesystem/bootimg.go14
-rw-r--r--filesystem/filesystem.go373
-rw-r--r--filesystem/filesystem_test.go62
-rw-r--r--filesystem/fsverity_metadata.go8
-rw-r--r--filesystem/recovery_background_pictures.go142
-rw-r--r--filesystem/super_image.go4
-rw-r--r--filesystem/system_image.go9
-rw-r--r--filesystem/system_other.go35
-rw-r--r--filesystem/vbmeta.go77
-rw-r--r--fsgen/boot_imgs.go2
-rw-r--r--fsgen/filesystem_creator.go211
-rw-r--r--fsgen/filesystem_creator_test.go134
-rw-r--r--fsgen/fsgen_mutators.go375
-rw-r--r--fsgen/prebuilt_etc_modules_gen.go51
-rw-r--r--fsgen/util.go55
-rw-r--r--fsgen/vbmeta_partitions.go6
-rw-r--r--fuzz/Android.bp1
-rw-r--r--fuzz/fuzz_common.go13
-rw-r--r--fuzz/fuzz_common_gob_enc.go241
-rw-r--r--genrule/genrule.go120
-rw-r--r--genrule/genrule_test.go42
-rw-r--r--go.work2
-rw-r--r--golang/Android.bp1
-rw-r--r--golang/golang.go20
-rw-r--r--golang/plugin_test.go54
-rw-r--r--java/Android.bp5
-rw-r--r--java/aapt2.go23
-rw-r--r--java/aar.go67
-rw-r--r--java/aar_test.go28
-rw-r--r--java/android_manifest.go2
-rw-r--r--java/androidmk.go14
-rw-r--r--java/apkcerts.go126
-rw-r--r--java/app.go194
-rw-r--r--java/app_import.go65
-rw-r--r--java/app_set.go14
-rw-r--r--java/app_test.go192
-rw-r--r--java/base.go297
-rw-r--r--java/base_gob_enc.go89
-rw-r--r--java/boot_jars.go15
-rw-r--r--java/bootclasspath.go37
-rw-r--r--java/bootclasspath_fragment.go85
-rw-r--r--java/builder.go294
-rw-r--r--java/classpath_element.go26
-rw-r--r--java/classpath_fragment.go28
-rw-r--r--java/config/config.go3
-rw-r--r--java/config/kotlin.go2
-rw-r--r--java/device_host_converter.go21
-rw-r--r--java/dex.go358
-rw-r--r--java/dexpreopt.go2
-rw-r--r--java/dexpreopt_bootjars.go80
-rw-r--r--java/dexpreopt_check.go11
-rw-r--r--java/dexpreopt_test.go41
-rw-r--r--java/droiddoc.go13
-rw-r--r--java/droidstubs.go40
-rw-r--r--java/fuzz.go87
-rw-r--r--java/genrule_combiner.go14
-rw-r--r--java/hiddenapi.go15
-rw-r--r--java/hiddenapi_modular.go118
-rw-r--r--java/hiddenapi_monolithic.go7
-rw-r--r--java/jacoco.go64
-rw-r--r--java/java.go344
-rw-r--r--java/java_gob_enc.go54
-rw-r--r--java/java_test.go70
-rw-r--r--java/jdeps.go2
-rw-r--r--java/kotlin.go260
-rw-r--r--java/kotlin_test.go126
-rw-r--r--java/lint.go37
-rw-r--r--java/lint_gob_enc.go110
-rw-r--r--java/platform_bootclasspath.go22
-rw-r--r--java/platform_compat_config.go40
-rw-r--r--java/prebuilt_apis_test.go4
-rw-r--r--java/ravenwood.go109
-rw-r--r--java/ravenwood_test.go28
-rw-r--r--java/robolectric.go3
-rw-r--r--java/rro.go29
-rw-r--r--java/rro_test.go2
-rw-r--r--java/sdk.go2
-rw-r--r--java/sdk_library.go261
-rw-r--r--java/sdk_library_internal.go40
-rw-r--r--java/sdk_library_test.go4
-rw-r--r--java/system_modules.go34
-rw-r--r--java/system_modules_gob_enc.go137
-rw-r--r--java/systemserver_classpath_fragment.go33
-rw-r--r--java/testing.go14
-rw-r--r--kernel/prebuilt_kernel_modules.go62
-rw-r--r--licenses/Android.bp11
-rw-r--r--licenses/opensourcerequest1
-rw-r--r--phony/phony.go2
-rw-r--r--provenance/provenance_singleton.go30
-rw-r--r--python/binary.go13
-rw-r--r--python/python.go5
-rw-r--r--python/python_test.go97
-rw-r--r--python/scripts/main.py90
-rw-r--r--python/test.go32
-rw-r--r--rust/Android.bp3
-rw-r--r--rust/androidmk.go9
-rw-r--r--rust/benchmark.go13
-rw-r--r--rust/binary.go50
-rw-r--r--rust/bindgen.go6
-rw-r--r--rust/builder.go245
-rw-r--r--rust/builder_test.go6
-rw-r--r--rust/compiler.go139
-rw-r--r--rust/compiler_test.go16
-rw-r--r--rust/config/Android.bp2
-rw-r--r--rust/config/arm64_device.go96
-rw-r--r--rust/config/arm_device.go8
-rw-r--r--rust/config/arm_linux_host.go4
-rw-r--r--rust/config/darwin_host.go4
-rw-r--r--rust/config/global.go33
-rw-r--r--rust/config/riscv64_device.go8
-rw-r--r--rust/config/toolchain.go10
-rw-r--r--rust/config/x86_64_device.go8
-rw-r--r--rust/config/x86_device.go8
-rw-r--r--rust/config/x86_linux_bionic_host.go2
-rw-r--r--rust/config/x86_linux_host.go28
-rw-r--r--rust/config/x86_windows_host.go193
-rw-r--r--rust/fuzz.go24
-rw-r--r--rust/fuzz_test.go40
-rw-r--r--rust/library.go48
-rw-r--r--rust/library_test.go44
-rw-r--r--rust/object.go125
-rw-r--r--rust/object_test.go35
-rw-r--r--rust/prebuilt.go16
-rw-r--r--rust/proc_macro.go6
-rw-r--r--rust/project_json.go91
-rw-r--r--rust/protobuf.go3
-rw-r--r--rust/rust.go214
-rw-r--r--rust/test.go61
-rw-r--r--rust/testing.go3
-rw-r--r--rust/toolchain_library.go27
-rw-r--r--rust/toolchain_object.go96
-rw-r--r--scripts/check_boot_jars/package_allowed_list.txt1
-rw-r--r--scripts/disk_usage.py86
-rw-r--r--scripts/gen_build_prop.py3
-rwxr-xr-xscripts/manifest_check.py17
-rwxr-xr-xscripts/manifest_check_test.py22
-rwxr-xr-xscripts/rustc_linker.py29
-rwxr-xr-xscripts/soong_only_diff_test.py237
-rw-r--r--sdk/bootclasspath_fragment_sdk_test.go3
-rw-r--r--sdk/member_trait_test.go6
-rw-r--r--sdk/sdk.go3
-rw-r--r--sdk/update.go109
-rw-r--r--sh/sh_binary.go15
-rw-r--r--sysprop/sysprop_library.go44
-rw-r--r--systemfeatures/system_features.go57
-rw-r--r--systemfeatures/system_features_test.go80
-rwxr-xr-xtests/bootstrap_test.sh65
-rwxr-xr-xtests/run_integration_tests.sh1
-rwxr-xr-xtests/sbom_test.sh10
-rw-r--r--tradefed_modules/test_module_config.go33
-rw-r--r--tradefed_modules/test_module_config_test.go9
-rw-r--r--ui/build/Android.bp2
-rw-r--r--ui/build/androidmk_denylist.go1
-rw-r--r--ui/build/build.go19
-rw-r--r--ui/build/cipd.go169
-rw-r--r--ui/build/cipd_proxy_policy.txtpb6
-rw-r--r--ui/build/config.go165
-rw-r--r--ui/build/config_test.go30
-rw-r--r--ui/build/context.go2
-rw-r--r--ui/build/dumpvars.go28
-rw-r--r--ui/build/finder.go34
-rw-r--r--ui/build/goma.go80
-rw-r--r--ui/build/kati.go5
-rw-r--r--ui/build/ninja.go3
-rw-r--r--ui/build/rbe.go25
-rw-r--r--ui/build/sandbox_linux.go61
-rw-r--r--ui/build/soong.go153
-rw-r--r--ui/build/test_build.go2
-rw-r--r--ui/metrics/event.go6
-rw-r--r--ui/metrics/metrics.go55
-rw-r--r--ui/metrics/metrics_proto/metrics.pb.go1095
-rw-r--r--ui/metrics/metrics_proto/metrics.proto57
-rw-r--r--ui/status/critical_path.go2
-rw-r--r--ui/status/kati.go2
-rw-r--r--ui/status/ninja.go24
-rw-r--r--unbundled/Android.bp28
-rw-r--r--unbundled/unbundled.go218
-rw-r--r--unbundled/unbundled_test.go72
-rw-r--r--xml/xml.go6
445 files changed, 28276 insertions, 6961 deletions
diff --git a/Android.bp b/Android.bp
index 713459112..0d7e5720c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -161,6 +161,22 @@ cc_defaults {
defaults_visibility: ["//visibility:public"],
}
+rust_defaults {
+ name: "rust_baremetal_defaults",
+ arch: {
+ arm64: {
+ flags: [
+ // There is no Rust flag that says "use baseline instruction set",
+ // so we disable SVE specifically. This can be extended with more
+ // problematic target features from rust/config/arm64_device.go
+ // as needed.
+ "-C target-feature=-sve2",
+ ],
+ },
+ },
+ defaults_visibility: ["//visibility:public"],
+}
+
product_config {
name: "product_config",
visibility: [
@@ -283,3 +299,10 @@ all_apex_certs {
"//cts/hostsidetests/appsecurity",
],
}
+
+system_dev_certificate {
+ name: "system_dev_certificate",
+ visibility: [
+ "//bootable/recovery:__subpackages__",
+ ],
+}
diff --git a/OWNERS b/OWNERS
index 01025fb65..490c15726 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,11 +7,10 @@ ccross@android.com
colefaust@google.com
dwillemsen@google.com
jihoonkang@google.com
-joeo@google.com
lamontjones@google.com
mrziwang@google.com
spandandas@google.com
weiwli@google.com
yudiliu@google.com
-per-file build/soong/ui/build/androidmk_denylist.go = joeo@google.com, weiwli@google.com \ No newline at end of file
+per-file build/soong/ui/build/androidmk_denylist.go =weiwli@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index e8cad7d7b..b89e5f8c8 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,7 +1,15 @@
[Builtin Hooks]
gofmt = true
bpfmt = true
+ktfmt = true
[Hook Scripts]
do_not_use_DO_NOT_MERGE = ${REPO_ROOT}/build/soong/scripts/check_do_not_merge.sh ${PREUPLOAD_COMMIT}
-aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
+
+ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --no-verify-format -f ${PREUPLOAD_FILES}
+
+[Builtin Hooks Options]
+ktfmt = --kotlinlang-style --include-dirs=cmd/kotlinc_incremental
+
+[Tool Paths]
+ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh \ No newline at end of file
diff --git a/README.md b/README.md
index 6d1a2c5d3..45c6d5757 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,7 @@
# Soong
-Soong is one of the build systems used in Android. There are altogether three:
-* The legacy Make-based build system that is controlled by files called
- `Android.mk`.
-* Soong, which is controlled by files called `Android.bp`.
-* The upcoming Bazel-based build system that is controlled by files called
- `BUILD.bazel`.
+Soong is one of the build systems used in Android, which is controlled by files called `Android.bp`.
+There is also the legacy Make-based build system that is controlled by files called `Android.mk`.
`Android.bp` file are JSON-like declarative descriptions of "modules" to build;
a "module" is the basic unit of building that Soong understands, similarly to
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index a15fe866b..47a999987 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -35,6 +35,7 @@ all_aconfig_declarations {
name: "all_aconfig_declarations",
visibility: [
"//vendor:__subpackages__", // for vendor extensions
+ "//frameworks/base/ravenwood",
],
api_signature_files: [
":frameworks-base-api-current.txt",
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index b06839831..22dba9b1a 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -15,12 +15,13 @@
package aconfig
import (
- "android/soong/android"
"path/filepath"
"slices"
"strconv"
"strings"
+ "android/soong/android"
+
"github.com/google/blueprint"
)
@@ -144,8 +145,10 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
values := make(map[string][]string)
valuesFiles := make(map[string][]android.Path, 0)
- providerData := android.AconfigReleaseDeclarationsProviderData{}
- ctx.VisitDirectDeps(func(dep android.Module) {
+ providerData := android.AconfigReleaseDeclarationsProviderData{
+ Data: map[string]android.AconfigDeclarationsProviderData{},
+ }
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
depTag := ctx.OtherModuleDependencyTag(dep)
for _, config := range configs {
@@ -170,7 +173,7 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
// Intermediate format
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
- intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.pb"))
+ intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "aconfig-cache.pb"))
var defaultPermission string
defaultPermission = ctx.Config().ReleaseAconfigFlagDefaultPermission()
if config != "" {
@@ -178,6 +181,8 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
defaultPermission = confPerm
}
}
+
+ forceReadOnly := ctx.Config().GetBuildFlagBool("RELEASE_CONFIG_FORCE_READ_ONLY")
var allowReadWrite bool
if requireAllReadOnly, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY"); ok {
// The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag
@@ -188,13 +193,16 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
inputFiles := make([]android.Path, len(declarationFiles))
copy(inputFiles, declarationFiles)
inputFiles = append(inputFiles, valuesFiles[config]...)
+ mainlineBetaNamespaceConfig := ctx.Config().ReleaseMainlineBetaNamespaceConfig()
args := map[string]string{
- "release_version": ctx.Config().ReleaseVersion(),
- "package": module.properties.Package,
- "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
- "values": joinAndPrefix(" --values ", values[config]),
- "default-permission": optionalVariable(" --default-permission ", defaultPermission),
- "allow-read-write": optionalVariable(" --allow-read-write ", strconv.FormatBool(allowReadWrite)),
+ "release_version": ctx.Config().ReleaseVersion(),
+ "package": module.properties.Package,
+ "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
+ "values": joinAndPrefix(" --values ", values[config]),
+ "default-permission": optionalVariable(" --default-permission ", defaultPermission),
+ "allow-read-write": optionalVariable(" --allow-read-write ", strconv.FormatBool(allowReadWrite)),
+ "mainline-beta-namespace-config": optionalVariable(" --mainline-beta-namespace-config ", mainlineBetaNamespaceConfig),
+ "force-read-only": optionalVariable(" --force-read-only ", strconv.FormatBool(forceReadOnly)),
}
if len(module.properties.Container) > 0 {
args["container"] = "--container " + module.properties.Container
@@ -207,7 +215,7 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
Args: args,
})
- intermediateDumpFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.txt"))
+ intermediateDumpFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "aconfig-flags.txt"))
ctx.Build(pctx, android.BuildParams{
Rule: aconfigTextRule,
Output: intermediateDumpFilePath,
@@ -215,7 +223,7 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
Description: "aconfig_text",
})
- providerData[config] = android.AconfigDeclarationsProviderData{
+ providerData.Data[config] = android.AconfigDeclarationsProviderData{
Package: module.properties.Package,
Container: module.properties.Container,
Exportable: module.properties.Exportable,
@@ -223,7 +231,7 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
IntermediateDumpOutputPath: intermediateDumpFilePath,
}
}
- android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""])
+ android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData.Data[""])
android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData)
}
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index c39008b74..4eb325ccf 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -44,10 +44,10 @@ func TestAconfigDeclarations(t *testing.T) {
android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
android.AssertStringEquals(t, "container", depData.Container, "com.android.foo")
android.AssertBoolEquals(t, "exportable", depData.Exportable, true)
- if !strings.HasSuffix(depData.IntermediateCacheOutputPath.String(), "/intermediate.pb") {
+ if !strings.HasSuffix(depData.IntermediateCacheOutputPath.String(), "/aconfig-cache.pb") {
t.Errorf("Missing intermediates proto path in provider: %s", depData.IntermediateCacheOutputPath.String())
}
- if !strings.HasSuffix(depData.IntermediateDumpOutputPath.String(), "/intermediate.txt") {
+ if !strings.HasSuffix(depData.IntermediateDumpOutputPath.String(), "/aconfig-flags.txt") {
t.Errorf("Missing intermediates text path in provider: %s", depData.IntermediateDumpOutputPath.String())
}
}
@@ -212,17 +212,17 @@ func TestGenerateAndroidBuildActions(t *testing.T) {
}
slices.Sort(expectedKeys)
actualKeys := []string{}
- for rc := range depData {
+ for rc := range depData.Data {
actualKeys = append(actualKeys, rc)
}
slices.Sort(actualKeys)
android.AssertStringEquals(t, "provider keys", strings.Join(expectedKeys, " "), strings.Join(actualKeys, " "))
for _, rc := range actualKeys {
- if !strings.HasSuffix(depData[rc].IntermediateCacheOutputPath.String(), assembleFileName(rc, "/intermediate.pb")) {
- t.Errorf("Incorrect intermediates proto path in provider for release config %s: %s", rc, depData[rc].IntermediateCacheOutputPath.String())
+ if !strings.HasSuffix(depData.Data[rc].IntermediateCacheOutputPath.String(), assembleFileName(rc, "/aconfig-cache.pb")) {
+ t.Errorf("Incorrect intermediates proto path in provider for release config %s: %s", rc, depData.Data[rc].IntermediateCacheOutputPath.String())
}
- if !strings.HasSuffix(depData[rc].IntermediateDumpOutputPath.String(), assembleFileName(rc, "/intermediate.txt")) {
- t.Errorf("Incorrect intermediates text path in provider for release config %s: %s", rc, depData[rc].IntermediateDumpOutputPath.String())
+ if !strings.HasSuffix(depData.Data[rc].IntermediateDumpOutputPath.String(), assembleFileName(rc, "/aconfig-flags.txt")) {
+ t.Errorf("Incorrect intermediates text path in provider for release config %s: %s", rc, depData.Data[rc].IntermediateDumpOutputPath.String())
}
}
}
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
index d72ec48ff..d142bdfd4 100644
--- a/aconfig/aconfig_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -15,10 +15,11 @@
package aconfig
import (
- "android/soong/android"
"fmt"
"strings"
+ "android/soong/android"
+
"github.com/google/blueprint"
)
@@ -91,14 +92,7 @@ func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
- deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
- for _, dep := range deps {
- _, ok := dep.(*ValuesModule)
- if !ok {
- ctx.PropertyErrorf("values", "values must be a aconfig_values module")
- return
- }
- }
+ ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
}
func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -106,11 +100,13 @@ func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleCont
// valueSetProviderKey provider that aconfig modules can read and use
// to append values to their aconfig actions.
packages := make(map[string]android.Paths)
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(valueSetTag, func(dep android.ModuleProxy) {
if depData, ok := android.OtherModuleProvider(ctx, dep, valuesProviderKey); ok {
srcs := make([]android.Path, len(depData.Values))
copy(srcs, depData.Values)
packages[depData.Package] = srcs
+ } else {
+ ctx.PropertyErrorf("values", "values dependency %q must be a aconfig_values module", ctx.OtherModuleName(dep))
}
})
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
index 1f042442c..cc1579cee 100644
--- a/aconfig/aconfig_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -18,8 +18,6 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
func TestAconfigValueSet(t *testing.T) {
@@ -90,7 +88,7 @@ func TestAconfigValueSetBpGlob(t *testing.T) {
t.Helper()
module := result.ModuleForTests(t, name, variant).Module()
depFound := false
- result.VisitDirectDeps(module, func(m blueprint.Module) {
+ result.VisitDirectDeps(module, func(m android.Module) {
if m.Name() == dep {
depFound = true
}
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index 5a5262485..84b0337d0 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -24,6 +24,10 @@ import (
"github.com/google/blueprint/proptools"
)
+const allAconfigDeclarationsStorage = "all_aconfig_declarations_storage"
+
+const AllAconfigModule = "all_aconfig_declarations"
+
// A singleton module that collects all of the aconfig flags declared in the
// tree into a single combined file for export to the external flag setting
// server (inside Google it's Gantry).
@@ -38,15 +42,40 @@ func AllAconfigDeclarationsFactory() android.SingletonModule {
return module
}
-type allAconfigDeclarationsInfo struct {
- parsedFlagsFile android.Path
+// AllAconfigDeclarationsInfo contains flag storage files containing all flags from all the modules
+// across the whole Android source tree. None of these files may be installed on the device.
+// They should only be used or consumed as artifacts from the build servers,
+// or used by host side tools/tests.
+type AllAconfigDeclarationsInfo struct {
+ // ParsedFlagsFile contains all flags in a binary proto format.
+ ParsedFlagsFile android.Path
+
+ // TextProtoFlagsFile contains all flags in a text proto format.
+ TextProtoFlagsFile android.Path
+
+ // StorageFlagVal is a "flag_val" storage file for all flags.
+ StorageFlagVal android.Path
+
+ // StorageFlagMap is a "flag_map" storage file for all flags.
+ StorageFlagMap android.Path
+
+ // StorageFlagInfo is a "flag_info" storage file for all flags.
+ StorageFlagInfo android.Path
+
+ // StoragePackageMap is a "package_map" storage file for all flags.
+ StoragePackageMap android.Path
}
-var allAconfigDeclarationsInfoProvider = blueprint.NewProvider[allAconfigDeclarationsInfo]()
+var AllAconfigDeclarationsInfoProvider = blueprint.NewProvider[AllAconfigDeclarationsInfo]()
type allAconfigReleaseDeclarationsSingleton struct {
intermediateBinaryProtoPath android.OutputPath
intermediateTextProtoPath android.OutputPath
+
+ intermediateStorageFlagVal android.OutputPath
+ intermediateStorageFlagMap android.OutputPath
+ intermediateStorageFlagInfo android.OutputPath
+ intermediateStoragePackageMap android.OutputPath
}
type ApiSurfaceContributorProperties struct {
@@ -83,16 +112,25 @@ func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath a
}
finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file)
- ctx.Build(pctx, android.BuildParams{
- Rule: RecordFinalizedFlagsRule,
- Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile),
- Output: outputPath,
- Args: map[string]string{
- "api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "),
- "finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(),
- "parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(),
- },
- })
+ intermediateMetalavaFlagsConfig := android.PathForModuleOut(ctx, "metalava-flags.config")
+ intermediateFlagReport := android.PathForModuleOut(ctx, "metalava-flag-report.csv")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().
+ BuiltTool("aconfig-to-metalava-flags").
+ Input(parsedFlagsFile).
+ FlagWithOutput("> ", intermediateMetalavaFlagsConfig)
+ builder.Command().
+ BuiltTool("metalava").
+ Flag("flag-report").
+ FlagWithInput("--config-file ", intermediateMetalavaFlagsConfig).
+ FlagWithOutput("--output-file ", intermediateFlagReport).
+ Inputs(apiSignatureFiles)
+ builder.Command().
+ BuiltTool("record-finalized-flags").
+ FlagWithInput("--finalized-flags ", finalizedFlagsFile).
+ FlagWithInput("--flag-report ", intermediateFlagReport).
+ FlagWithOutput("> ", outputPath)
+ builder.Build("finalized-flags", "Record all aconfig flags used with finalized @FlaggedApi APIs")
}
func GenerateExportedFlagCheck(ctx android.ModuleContext, outputPath android.WritablePath,
@@ -135,8 +173,14 @@ func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx and
ctx.Phony("all_aconfig_declarations", depsFiles...)
- android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{
- parsedFlagsFile: parsedFlagsFile,
+ android.SetProvider(ctx, AllAconfigDeclarationsInfoProvider, AllAconfigDeclarationsInfo{
+ ParsedFlagsFile: parsedFlagsFile,
+ TextProtoFlagsFile: android.PathForIntermediates(ctx, "all_aconfig_declarations.textproto"),
+
+ StoragePackageMap: android.PathForIntermediates(ctx, "all_aconfig_declarations.package.map"),
+ StorageFlagMap: android.PathForIntermediates(ctx, "all_aconfig_declarations.flag.map"),
+ StorageFlagInfo: android.PathForIntermediates(ctx, "all_aconfig_declarations.flag.info"),
+ StorageFlagVal: android.PathForIntermediates(ctx, "all_aconfig_declarations.val"),
})
}
@@ -150,8 +194,8 @@ func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx a
if !ok {
return
}
- cacheFiles = append(cacheFiles, decl[rcName].IntermediateCacheOutputPath)
- packages[decl[rcName].Package]++
+ cacheFiles = append(cacheFiles, decl.Data[rcName].IntermediateCacheOutputPath)
+ packages[decl.Data[rcName].Package]++
})
var numOffendingPkg = 0
@@ -171,6 +215,11 @@ func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx a
paths := allAconfigReleaseDeclarationsSingleton{
intermediateBinaryProtoPath: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.pb")),
intermediateTextProtoPath: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.textproto")),
+
+ intermediateStoragePackageMap: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.package.map")),
+ intermediateStorageFlagMap: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.flag.map")),
+ intermediateStorageFlagInfo: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.flag.info")),
+ intermediateStorageFlagVal: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.val")),
}
this.releaseMap[rcName] = paths
ctx.Build(pctx, android.BuildParams{
@@ -195,6 +244,61 @@ func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx a
},
})
ctx.Phony("all_aconfig_declarations_textproto", this.releaseMap[rcName].intermediateTextProtoPath)
+
+ storageFilesVersion := ctx.Config().ReleaseAconfigStorageVersion()
+ const container = "all_aconfig_declarations"
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRuleStoragePackageMap,
+ Inputs: cacheFiles,
+ Output: this.releaseMap[rcName].intermediateStoragePackageMap,
+ Description: "all_aconfig_declarations_storage_package_map",
+ Args: map[string]string{
+ "container": container,
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
+ "version": storageFilesVersion,
+ },
+ })
+ ctx.Phony(allAconfigDeclarationsStorage, this.releaseMap[rcName].intermediateStoragePackageMap)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRuleStorageFlagMap,
+ Inputs: cacheFiles,
+ Output: this.releaseMap[rcName].intermediateStorageFlagMap,
+ Description: "all_aconfig_declarations_storage_flag_map",
+ Args: map[string]string{
+ "container": container,
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
+ "version": storageFilesVersion,
+ },
+ })
+ ctx.Phony(allAconfigDeclarationsStorage, this.releaseMap[rcName].intermediateStorageFlagMap)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRuleStorageFlagInfo,
+ Inputs: cacheFiles,
+ Output: this.releaseMap[rcName].intermediateStorageFlagInfo,
+ Description: "all_aconfig_declarations_storage_flag_info",
+ Args: map[string]string{
+ "container": container,
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
+ "version": storageFilesVersion,
+ },
+ })
+ ctx.Phony(allAconfigDeclarationsStorage, this.releaseMap[rcName].intermediateStorageFlagInfo)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRuleStorageFlagVal,
+ Inputs: cacheFiles,
+ Output: this.releaseMap[rcName].intermediateStorageFlagVal,
+ Description: "all_aconfig_declarations_storage_flag_val",
+ Args: map[string]string{
+ "container": container,
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
+ "version": storageFilesVersion,
+ },
+ })
+ ctx.Phony(allAconfigDeclarationsStorage, this.releaseMap[rcName].intermediateStorageFlagVal)
}
for _, rcName := range this.sortedConfigNames() {
diff --git a/aconfig/all_aconfig_declarations_extension.go b/aconfig/all_aconfig_declarations_extension.go
index d5a458811..83540526c 100644
--- a/aconfig/all_aconfig_declarations_extension.go
+++ b/aconfig/all_aconfig_declarations_extension.go
@@ -62,10 +62,10 @@ func (ext *allAconfigDeclarationsExtension) GenerateAndroidBuildActions(ctx andr
var parsedFlagsFile android.Path
ctx.VisitDirectDepsProxyWithTag(allAconfigDeclarationsDependencyTag, func(proxy android.ModuleProxy) {
- if info, ok := android.OtherModuleProvider(ctx, proxy, allAconfigDeclarationsInfoProvider); ok {
- parsedFlagsFile = info.parsedFlagsFile
+ if info, ok := android.OtherModuleProvider(ctx, proxy, AllAconfigDeclarationsInfoProvider); ok {
+ parsedFlagsFile = info.ParsedFlagsFile
} else {
- ctx.PropertyErrorf("base", "base must provide allAconfigDeclarationsInfo")
+ ctx.PropertyErrorf("base", "base must provide AllAconfigDeclarationsInfo")
}
})
diff --git a/aconfig/all_aconfig_declarations_extension_test.go b/aconfig/all_aconfig_declarations_extension_test.go
index 5bd99d0c9..6a82af161 100644
--- a/aconfig/all_aconfig_declarations_extension_test.go
+++ b/aconfig/all_aconfig_declarations_extension_test.go
@@ -46,5 +46,5 @@ func TestAllAconfigDeclarationsExtension(t *testing.T) {
`)
finalizedFlags := result.ModuleForTests(t, "custom_aconfig_declarations", "").Output("finalized-flags.txt")
- android.AssertStringContainsEquals(t, "must depend on all_aconfig_declarations", strings.Join(finalizedFlags.Inputs.Strings(), " "), "all_aconfig_declarations.pb", true)
+ android.AssertStringContainsEquals(t, "must (implicitly) depend on all_aconfig_declarations", strings.Join(finalizedFlags.Implicits.Strings(), " "), "all_aconfig_declarations.pb", true)
}
diff --git a/aconfig/build_flags/Android.bp b/aconfig/build_flags/Android.bp
index 139aeac3b..7c124e611 100644
--- a/aconfig/build_flags/Android.bp
+++ b/aconfig/build_flags/Android.bp
@@ -23,3 +23,9 @@ bootstrap_go_package {
],
pluginFor: ["soong_build"],
}
+
+all_release_configs {
+ name: "all_release_configs",
+ // Visibility must be limited to host tests!
+ visibility: ["//build/make/tools/finalization/finalization-test"],
+}
diff --git a/aconfig/build_flags/build_flags.go b/aconfig/build_flags/build_flags.go
index 94e1eb193..a9415f8b3 100644
--- a/aconfig/build_flags/build_flags.go
+++ b/aconfig/build_flags/build_flags.go
@@ -44,14 +44,22 @@ func buildFlagsFactory() android.Module {
return module
}
+func (m *buildFlags) UseGenericConfig() bool {
+ return false
+}
+
func (m *buildFlags) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Read the build_flags_<partition>.json file generated by soong
// 'release-config' command.
- srcPath := android.PathForOutput(ctx, "release-config", fmt.Sprintf("build_flags_%s.json", m.PartitionTag(ctx.DeviceConfig())))
+ product := "None"
+ if ctx.Config().HasDeviceProduct() {
+ product = ctx.Config().DeviceProduct()
+ }
+ srcPath := android.PathForOutput(ctx, "release-config", fmt.Sprintf("build_flags_%s-%s.json", product, m.PartitionTag(ctx.DeviceConfig())))
outputPath := android.PathForModuleOut(ctx, outJsonFileName)
// The 'release-config' command is called for every build, and generates the
- // build_flags_<partition>.json file.
+ // build_flags_<target_product>-<partition>.json file.
// Update the output file only if the source file is changed.
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go
index 3a06e72d6..68d8cda88 100644
--- a/aconfig/build_flags/build_flags_singleton.go
+++ b/aconfig/build_flags/build_flags_singleton.go
@@ -38,6 +38,10 @@ type allBuildFlagDeclarationsSingleton struct {
configsTextProtoPath android.OutputPath
}
+var buildFlagArtifactsDistGoals = []string{
+ "docs", "droid", "sdk", "release_config_metadata", "gms",
+}
+
func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Find all of the build_flag_declarations modules
var flagsFiles android.Paths
@@ -55,8 +59,10 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.
}
})
+ basePath := android.PathForIntermediates(ctx, "release_configs")
+
// Generate build action for build_flag (binary proto output)
- this.flagsBinaryProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.pb")
+ this.flagsBinaryProtoPath = basePath.Join(ctx, "all_build_flag_declarations.pb")
ctx.Build(pctx, android.BuildParams{
Rule: allDeclarationsRule,
Inputs: flagsFiles,
@@ -69,7 +75,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.
ctx.Phony("all_build_flag_declarations", this.flagsBinaryProtoPath)
// Generate build action for build_flag (text proto output)
- this.flagsTextProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.textproto")
+ this.flagsTextProtoPath = basePath.Join(ctx, "all_build_flag_declarations.textproto")
ctx.Build(pctx, android.BuildParams{
Rule: allDeclarationsRuleTextProto,
Input: this.flagsBinaryProtoPath,
@@ -79,7 +85,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.
ctx.Phony("all_build_flag_declarations_textproto", this.flagsTextProtoPath)
// Generate build action for release_configs (binary proto output)
- this.configsBinaryProtoPath = android.PathForIntermediates(ctx, "all_release_config_contributions.pb")
+ this.configsBinaryProtoPath = basePath.Join(ctx, "all_release_config_contributions.pb")
ctx.Build(pctx, android.BuildParams{
Rule: allReleaseConfigContributionsRule,
Inputs: contributionDirs,
@@ -92,7 +98,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.
})
ctx.Phony("all_release_config_contributions", this.configsBinaryProtoPath)
- this.configsTextProtoPath = android.PathForIntermediates(ctx, "all_release_config_contributions.textproto")
+ this.configsTextProtoPath = basePath.Join(ctx, "all_release_config_contributions.textproto")
ctx.Build(pctx, android.BuildParams{
Rule: allReleaseConfigContributionsRule,
Inputs: contributionDirs,
@@ -105,29 +111,57 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.
})
ctx.Phony("all_release_config_contributions_textproto", this.configsTextProtoPath)
+ // Validator to ensure that there are no duplicate flag declarations.
+ // The Validator timestamp file.
+ mapsListPath := basePath.Join(ctx, "release_config_map.list")
+ duplicatesPath := basePath.Join(ctx, "duplicate_allowlist.list")
+ validatorPath := basePath.Join(ctx, "release_config_map.timestamp")
+
+ // The file containing the list of all `release_config_map.textproto` files in the source tree.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: android.PathForArbitraryOutput(ctx, ".module_paths", "release_config_map.list"),
+ Output: mapsListPath,
+ Validation: validatorPath,
+ })
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: android.PathForArbitraryOutput(ctx, ".module_paths", "duplicate_allowlist.list"),
+ Output: duplicatesPath,
+ Validation: validatorPath,
+ })
+ ctx.Build(pctx, android.BuildParams{
+ Rule: flagDeclarationsValidationRule,
+ Input: mapsListPath,
+ Implicits: append(android.Paths{duplicatesPath}, flagsFiles...),
+ Output: validatorPath,
+ })
+ // Make sure that this is at least built on CI machines.
+ ctx.Phony("droid", mapsListPath)
+
// Add a simple target for ci/build_metadata to use.
ctx.Phony("release_config_metadata",
this.flagsBinaryProtoPath,
this.flagsTextProtoPath,
this.configsBinaryProtoPath,
this.configsTextProtoPath,
+ mapsListPath,
)
ctx.DistForGoal("droid", this.flagsBinaryProtoPath)
- for _, goal := range []string{"docs", "droid", "sdk", "release_config_metadata"} {
- ctx.DistForGoalWithFilename(goal, this.flagsBinaryProtoPath, "build_flags/all_flags.pb")
- ctx.DistForGoalWithFilename(goal, this.flagsTextProtoPath, "build_flags/all_flags.textproto")
- ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
- ctx.DistForGoalWithFilename(goal, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
- }
+
+ ctx.DistForGoalsWithFilename(buildFlagArtifactsDistGoals, this.flagsBinaryProtoPath, "build_flags/all_flags.pb")
+ ctx.DistForGoalsWithFilename(buildFlagArtifactsDistGoals, this.flagsTextProtoPath, "build_flags/all_flags.textproto")
+ ctx.DistForGoalsWithFilename(buildFlagArtifactsDistGoals, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
+ ctx.DistForGoalsWithFilename(buildFlagArtifactsDistGoals, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
if ctx.Config().HasDeviceProduct() {
flagsDir := android.PathForOutput(ctx, "release-config")
baseAllRelease := fmt.Sprintf("all_release_configs-%s", ctx.Config().DeviceProduct())
distAllReleaseConfigsArtifact := func(ext string) {
- ctx.DistForGoalWithFilename(
- "droid",
+ ctx.DistForGoalsWithFilename(
+ buildFlagArtifactsDistGoals,
flagsDir.Join(ctx, fmt.Sprintf("%s.%s", baseAllRelease, ext)),
fmt.Sprintf("build_flags/all_release_configs.%s", ext),
)
diff --git a/aconfig/build_flags/init.go b/aconfig/build_flags/init.go
index a7575e86a..0b499600a 100644
--- a/aconfig/build_flags/init.go
+++ b/aconfig/build_flags/init.go
@@ -72,19 +72,24 @@ var (
CommandDeps: []string{
"${releaseConfigContributions}",
},
+ Restat: true,
}, "dirs", "format")
- allReleaseConfigContributionsRuleText = pctx.AndroidStaticRule("all-release-config-contributions-dumptext",
+
+ flagDeclarationsValidationRule = pctx.AndroidStaticRule("flagDeclarationsValidation",
blueprint.RuleParams{
- Command: `${releaseConfigContributions} ${dirs} --format ${format} --output ${out}`,
+ // Get no flags, so that we have no output.
+ Command: `${buildFlag} --maps-file ${in} --quiet --declarations-only get && date > ${out}`,
CommandDeps: []string{
- "${releaseConfigContributions}",
+ "${buildFlag}",
},
- }, "dirs", "format")
+ Restat: true,
+ })
)
func init() {
RegisterBuildComponents(android.InitRegistrationContext)
pctx.Import("android/soong/android")
+ pctx.HostBinToolVariable("buildFlag", "build-flag-internal")
pctx.HostBinToolVariable("buildFlagDeclarations", "build-flag-declarations")
pctx.HostBinToolVariable("releaseConfigContributions", "release-config-contributions")
}
@@ -92,5 +97,6 @@ func init() {
func RegisterBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("build_flag_declarations", DeclarationsFactory)
ctx.RegisterModuleType("release_config_contributions", ReleaseConfigContributionsFactory)
+ ctx.RegisterModuleType("all_release_configs", AllReleaseConfigsFactory)
ctx.RegisterParallelSingletonType("all_build_flag_declarations", AllBuildFlagDeclarationsFactory)
}
diff --git a/aconfig/build_flags/release_configs.go b/aconfig/build_flags/release_configs.go
index 3fa8a7c02..b5012152b 100644
--- a/aconfig/build_flags/release_configs.go
+++ b/aconfig/build_flags/release_configs.go
@@ -15,6 +15,7 @@
package build_flags
import (
+ "fmt"
"path/filepath"
"android/soong/android"
@@ -28,6 +29,12 @@ type ReleaseConfigContributionsProviderData struct {
var ReleaseConfigContributionsProviderKey = blueprint.NewProvider[ReleaseConfigContributionsProviderData]()
+type AllReleaseConfigsProviderData struct {
+ AllReleaseConfigsPath android.Path
+}
+
+var AllReleaseConfigsProviderKey = blueprint.NewProvider[AllReleaseConfigsProviderData]()
+
// Soong uses `release_config_contributions` modules to produce the
// `build_flags/all_release_config_contributions.*` artifacts, listing *all* of
// the directories in the source tree that contribute to each release config,
@@ -76,3 +83,49 @@ func (module *ReleaseConfigContributionsModule) GenerateAndroidBuildActions(ctx
})
}
+
+// Soong provides release config informamtion via an `all_release_configs` module.
+//
+// This module can be used by test modules that need to inspect release configs.
+type AllReleaseConfigsModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ // There are no extra properties for "all_release_configs".
+ properties struct{}
+}
+
+func AllReleaseConfigsFactory() android.Module {
+ module := &AllReleaseConfigsModule{}
+
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+func (module *AllReleaseConfigsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if !ctx.Config().HasDeviceProduct() {
+ return
+ }
+ // The 'release-config' command is called for every build, and generates the
+ // all_release_configs-${TARGET_PRODUCT}.pb file.
+ srcPath := android.PathForOutput(ctx, "release-config", fmt.Sprintf("all_release_configs-%s.pb", ctx.Config().DeviceProduct()))
+ outputPath := android.PathForModuleOut(ctx, "all_release_configs.pb")
+
+ ctx.Phony("droid", outputPath)
+ ctx.Phony("all_release_configs", outputPath)
+
+ // Update the output file only if the source file is changed.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: srcPath,
+ Output: outputPath,
+ })
+ ctx.SetOutputFiles(android.Paths{outputPath}, "")
+
+ android.SetProvider(ctx, AllReleaseConfigsProviderKey, AllReleaseConfigsProviderData{
+ AllReleaseConfigsPath: outputPath,
+ })
+}
diff --git a/aconfig/codegen/aconfig_declarations_group.go b/aconfig/codegen/aconfig_declarations_group.go
index 6811d06b9..042762d42 100644
--- a/aconfig/codegen/aconfig_declarations_group.go
+++ b/aconfig/codegen/aconfig_declarations_group.go
@@ -76,7 +76,7 @@ func (adg *AconfigDeclarationsGroup) GenerateAndroidBuildActions(ctx android.Mod
var aconfigDeclarationNames []string
var intermediateCacheOutputPaths android.Paths
var javaSrcjars android.Paths
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(dep)
if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index ce3745665..528c100f3 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -99,7 +99,12 @@ func (this *CcAconfigLibraryCallbacks) GeneratorSources(ctx cc.ModuleContext) cc
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
declarationsModules := ctx.GetDirectDepsProxyWithTag(ccDeclarationsTag)
if len(declarationsModules) != 1 {
- panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{"exactly_one_aconfig_declarations_required"})
+ return result
+ } else {
+ panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ }
}
declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
@@ -129,7 +134,12 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
declarationsModules := ctx.GetDirectDepsProxyWithTag(ccDeclarationsTag)
if len(declarationsModules) != 1 {
- panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{"exactly_one_aconfig_declarations_required"})
+ return
+ } else {
+ panic("Exactly one aconfig_declarations property required")
+ }
}
declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index 5cb3f8b33..3ea77394a 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -20,8 +20,6 @@ import (
"android/soong/android"
"android/soong/cc"
-
- "github.com/google/blueprint"
)
var ccCodegenModeTestData = []struct {
@@ -214,7 +212,7 @@ func TestAndroidMkCcLibrary(t *testing.T) {
entry := android.AndroidMkInfoForTest(t, result.TestContext, module).PrimaryInfo
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
- android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/aconfig-cache.pb")
}
func TestForceReadOnly(t *testing.T) {
@@ -256,7 +254,7 @@ func TestForceReadOnly(t *testing.T) {
module := result.ModuleForTests(t, "my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module()
dependOnReadLib := false
- result.VisitDirectDeps(module, func(dep blueprint.Module) {
+ result.VisitDirectDeps(module, func(dep android.Module) {
if dep.Name() == libAconfigStorageReadApiCcDep {
dependOnReadLib = true
}
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index 325e367ba..059b7a332 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -33,9 +33,6 @@ var (
` --mode ${mode}` +
` --cache ${in}` +
` --out ${out}.tmp` +
- ` --allow-instrumentation ${debug}` +
- ` --new-exported ${new_exported}` +
- ` --check-api-level ${check_api_level}` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
` && rm -rf ${out}.tmp`,
// LINT.ThenChange(/aconfig/init.go)
@@ -44,7 +41,7 @@ var (
"$soong_zip",
},
Restat: true,
- }, "mode", "debug", "new_exported", "check_api_level")
+ }, "mode")
// For cc_aconfig_library: Generate C++ library
cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 7b9da8eb4..371bdf4f2 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -20,7 +20,6 @@ import (
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
- "strconv"
)
type declarationsTagType struct {
@@ -78,14 +77,19 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *ja
func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) (android.Path, android.Path) {
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
- declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
+ declarationsModules := ctx.GetDirectDepsProxyWithTag(declarationsTag)
+ srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
if len(declarationsModules) != 1 {
- panic("Exactly one aconfig_declarations property required")
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{"exactly_one_aconfig_declarations_required"})
+ return srcJarPath, android.PathForModuleOut(ctx, "missing_declarations")
+ } else {
+ panic("Exactly one aconfig_declarations property required")
+ }
}
declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
// Generate the action to build the srcjar
- srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
mode := proptools.StringDefault(callbacks.properties.Mode, "production")
if !isModeSupported(mode) {
@@ -98,28 +102,17 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild
ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
}
- var newExported bool
- if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
- // The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag
- // (allow-read-write) for historical reasons.
- // Bool build flags are always "" for false, and generally "true" for true.
- newExported = useNewExported == "true"
- }
-
ctx.Build(pctx, android.BuildParams{
Rule: javaRule,
Input: declarations.IntermediateCacheOutputPath,
Output: srcJarPath,
Description: "aconfig.srcjar",
Args: map[string]string{
- "mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
- "new_exported": strconv.FormatBool(newExported),
- "check_api_level": strconv.FormatBool(ctx.Config().ReleaseAconfigCheckApiLevel()),
+ "mode": mode,
},
})
- if declarations.Exportable {
+ if ctx.Config().ReleaseJarjarFlagsInFramework() || declarations.Exportable {
// Mark our generated code as possibly needing jarjar repackaging
// The repackaging only happens when the corresponding aconfig_declaration
// has property exportable true
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index b9455f77d..a34f48c3c 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -62,7 +62,7 @@ func runJavaAndroidMkTest(t *testing.T, bp string) {
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
- android.EnsureListContainsSuffix(t, makeVar, "android_common/system/aconfig_merged.pb")
+ android.EnsureListContainsSuffix(t, makeVar, "android_common/merged_aconfig_files/system/aconfig_merged.pb")
}
func TestAndroidMkJavaLibrary(t *testing.T) {
@@ -285,5 +285,5 @@ func TestMkEntriesMatchedContainer(t *testing.T) {
module := result.ModuleForTests(t, "my_module", "android_common").Module()
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
- android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/aconfig-cache.pb")
}
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index 53818c250..fba7a42f1 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -60,7 +60,7 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path
generatedDir := android.PathForModuleGen(ctx)
generatedSource := android.PathForModuleGen(ctx, "src", "lib.rs")
- declarationsModules := ctx.GetDirectDepsWithTag(rustDeclarationsTag)
+ declarationsModules := ctx.GetDirectDepsProxyWithTag(rustDeclarationsTag)
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go
index ffb2a0cbe..37c1364a7 100644
--- a/aconfig/exported_java_aconfig_library.go
+++ b/aconfig/exported_java_aconfig_library.go
@@ -15,8 +15,6 @@
package aconfig
import (
- "strconv"
-
"android/soong/android"
)
@@ -39,16 +37,6 @@ func (this *exportedJavaDeclarationsLibrarySingleton) GenerateBuildActions(ctx a
cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
})
- var newExported bool
- if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
- newExported = useNewExported == "true"
- }
-
- var newStorage bool
- if useNewStorage, ok := ctx.Config().GetBuildFlag("RELEASE_READ_FROM_NEW_STORAGE"); ok {
- newStorage = useNewStorage == "true"
- }
-
// Generate build action for aconfig
this.intermediatePath = android.PathForIntermediates(ctx, "exported_java_aconfig_library.jar")
ctx.Build(pctx, android.BuildParams{
@@ -57,10 +45,7 @@ func (this *exportedJavaDeclarationsLibrarySingleton) GenerateBuildActions(ctx a
Output: this.intermediatePath,
Description: "exported_java_aconfig_library",
Args: map[string]string{
- "cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
- "use_new_storage": strconv.FormatBool(newStorage),
- "use_new_exported": strconv.FormatBool(newExported),
- "check_api_level": strconv.FormatBool(ctx.Config().ReleaseAconfigCheckApiLevel()),
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
},
})
ctx.Phony("exported_java_aconfig_library", this.intermediatePath)
diff --git a/aconfig/init.go b/aconfig/init.go
index d8d547022..a7d032675 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -33,6 +33,8 @@ var (
` ${values}` +
` ${default-permission}` +
` ${allow-read-write}` +
+ ` ${mainline-beta-namespace-config}` +
+ ` ${force-read-only}` +
` --cache ${out}.tmp` +
` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
// ` --build-id ${release_version}` +
@@ -40,7 +42,7 @@ var (
"${aconfig}",
},
Restat: true,
- }, "release_version", "package", "container", "declarations", "values", "default-permission", "allow-read-write")
+ }, "release_version", "package", "container", "declarations", "values", "default-permission", "allow-read-write", "mainline-beta-namespace-config", "force-read-only")
// For create-device-config-sysprops: Generate aconfig flag value map text file
aconfigTextRule = pctx.AndroidStaticRule("aconfig_text",
@@ -70,16 +72,41 @@ var (
"${aconfig}",
},
}, "cache_files")
- RecordFinalizedFlagsRule = pctx.AndroidStaticRule("RecordFinalizedFlagsRule",
+
+ allDeclarationsRuleStoragePackageMap = pctx.AndroidStaticRule("all_aconfig_declarations_storage_package_map",
blueprint.RuleParams{
- Command: `${record-finalized-flags} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`,
+ Command: `${aconfig} create-storage --container ${container} --file package_map --out ${out} ${cache_files} --version ${version}`,
CommandDeps: []string{
- "${record-finalized-flags}",
+ "${aconfig}",
},
- }, "api_signature_files", "finalized_flags_file", "parsed_flags_file")
+ }, "container", "cache_files", "version")
+ allDeclarationsRuleStorageFlagMap = pctx.AndroidStaticRule("all_aconfig_declarations_storage_flag_map",
+ blueprint.RuleParams{
+ Command: `${aconfig} create-storage --container ${container} --file flag_map --out ${out} ${cache_files} --version ${version}`,
+ CommandDeps: []string{
+ "${aconfig}",
+ },
+ }, "container", "cache_files", "version")
+ allDeclarationsRuleStorageFlagInfo = pctx.AndroidStaticRule("all_aconfig_declarations_storage_flag_info",
+ blueprint.RuleParams{
+ Command: `${aconfig} create-storage --container ${container} --file flag_info --out ${out} ${cache_files} --version ${version}`,
+ CommandDeps: []string{
+ "${aconfig}",
+ },
+ }, "container", "cache_files", "version")
+ allDeclarationsRuleStorageFlagVal = pctx.AndroidStaticRule("all_aconfig_declarations_storage_flag_val",
+ blueprint.RuleParams{
+ Command: `${aconfig} create-storage --container ${container} --file flag_val --out ${out} ${cache_files} --version ${version}`,
+ CommandDeps: []string{
+ "${aconfig}",
+ },
+ }, "container", "cache_files", "version")
ExportedFlagCheckRule = pctx.AndroidStaticRule("ExportedFlagCheckRule",
blueprint.RuleParams{
- Command: `${exported-flag-check} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`,
+ Command: `${exported-flag-check} validate-exported-flags ` +
+ ` ${parsed_flags_file} ` +
+ ` ${finalized_flags_file} ` +
+ ` ${api_signature_files} > ${out}`,
CommandDeps: []string{
"${exported-flag-check}",
},
@@ -102,35 +129,34 @@ var (
// exported flags (only). Finally collect all generated code
// into the ${out} JAR file.
blueprint.RuleParams{
- // LINT.IfChange
- Command: `rm -rf ${out}.tmp` +
+ Command: `rm -rf ${out}.tmp && rm -rf ${out}.pb.tmp ` +
`&& for cache in ${cache_files}; do ` +
- ` if [ -n "$$(${aconfig} dump-cache --dedup --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
+ ` ${exported-flag-check} filter-api-flags --cache $$cache --out ${out}.pb.tmp/$$cache &&` +
+ ` if [ -n "$$(${aconfig} dump-cache --dedup --cache ${out}.pb.tmp/$$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
+ // LINT.IfChange
` ${aconfig} create-java-lib` +
- ` --cache $$cache` +
+ ` --cache ${out}.pb.tmp/$$cache` +
` --mode=exported` +
- ` --allow-instrumentation ${use_new_storage}` +
- ` --new-exported ${use_new_exported}` +
` --single-exported-file true` +
- ` --check-api-level ${check_api_level}` +
` --out ${out}.tmp; ` +
+ // LINT.ThenChange(/aconfig/codegen/init.go)
` fi ` +
`done` +
`&& $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
- `&& rm -rf ${out}.tmp`,
- // LINT.ThenChange(/aconfig/codegen/init.go)
+ `&& rm -rf ${out}.tmp && rm -rf ${out}.pb.tmp `,
+
CommandDeps: []string{
"$aconfig",
"$soong_zip",
+ "$exported-flag-check",
},
- }, "cache_files", "use_new_storage", "use_new_exported", "check_api_level")
+ }, "cache_files")
)
func init() {
RegisterBuildComponents(android.InitRegistrationContext)
pctx.HostBinToolVariable("aconfig", "aconfig")
pctx.HostBinToolVariable("soong_zip", "soong_zip")
- pctx.HostBinToolVariable("record-finalized-flags", "record-finalized-flags")
pctx.HostBinToolVariable("exported-flag-check", "exported-flag-check")
}
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
index 1e0ab3056..690b458f6 100644
--- a/aidl_library/aidl_library.go
+++ b/aidl_library/aidl_library.go
@@ -99,7 +99,7 @@ func (lib *AidlLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
)
includeDirsDepSetBuilder.Direct(includeDir)
- for _, dep := range ctx.GetDirectDepsWithTag(aidlLibraryTag) {
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(aidlLibraryTag) {
if info, ok := android.OtherModuleProvider(ctx, dep, AidlLibraryProvider); ok {
includeDirsDepSetBuilder.Transitive(info.IncludeDirs)
hdrsDepSetBuilder.Transitive(info.Hdrs)
diff --git a/android/Android.bp b/android/Android.bp
index 97d634fb5..6f00fedf3 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -32,22 +32,28 @@ bootstrap_go_package {
],
srcs: [
"aconfig_providers.go",
+ "aconfig_providers_gob_enc.go",
"all_teams.go",
"android_info.go",
"androidmk.go",
+ "androidmk_gob_enc.go",
"apex.go",
"apex_contributions.go",
"api_domain.go",
"api_levels.go",
+ "api_levels_gob_enc.go",
"arch.go",
+ "arch_gob_enc.go",
"arch_list.go",
"arch_module_context.go",
"base_module_context.go",
"build_prop.go",
"compliance_metadata.go",
+ "compliance_metadata_gob_enc.go",
"config.go",
"container_violations.go",
"container.go",
+ "container_gob_enc.go",
"test_config.go",
"configurable_properties.go",
"configured_jars.go",
@@ -64,18 +70,22 @@ bootstrap_go_package {
"gen_notice.go",
"hooks.go",
"image.go",
- "init.go",
"license.go",
"license_kind.go",
"license_metadata.go",
+ "license_metadata_gob_enc.go",
"license_sdk_member.go",
"licenses.go",
+ "licenses_gob_enc.go",
"logtags.go",
+ "logtags_gob_enc.go",
"makevars.go",
"metrics.go",
"module.go",
"module_context.go",
+ "module_gob_enc.go",
"module_info_json.go",
+ "module_info_json_gob_enc.go",
"module_proxy.go",
"mutator.go",
"namespace.go",
@@ -89,9 +99,12 @@ bootstrap_go_package {
"package.go",
"package_ctx.go",
"packaging.go",
+ "packaging_gob_enc.go",
"path_properties.go",
"paths.go",
+ "paths_gob_enc.go",
"phony.go",
+ "phony_gob_enc.go",
"plugin.go",
"prebuilt.go",
"prebuilt_build_tool.go",
@@ -105,18 +118,25 @@ bootstrap_go_package {
"register.go",
"removed_package.go",
"rule_builder.go",
+ "rule_builder_gob_enc.go",
"sandbox.go",
"sbom.go",
"sdk.go",
+ "sdk_gob_enc.go",
"sdk_version.go",
"shared_properties.go",
"singleton.go",
"singleton_module.go",
"soong_config_modules.go",
+ "symbols.go",
+ "symbols_gob_enc.go",
+ "system_dev_certificate.go",
"team.go",
+ "team_gob_enc.go",
"test_asserts.go",
"test_mapping_zip.go",
"test_suites.go",
+ "test_suites_gob_enc.go",
"testing.go",
"transition.go",
"util.go",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index bb73f0bdd..8bac91266 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -23,6 +23,8 @@ import (
"github.com/google/blueprint"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
mergeAconfigFilesRule = pctx.AndroidStaticRule("mergeAconfigFilesRule",
blueprint.RuleParams{
@@ -33,6 +35,7 @@ var (
)
// Provider published by aconfig_value_set
+// @auto-generate: gob
type AconfigDeclarationsProviderData struct {
Package string
Container string
@@ -43,10 +46,14 @@ type AconfigDeclarationsProviderData struct {
var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
-type AconfigReleaseDeclarationsProviderData map[string]AconfigDeclarationsProviderData
+// @auto-generate: gob
+type AconfigReleaseDeclarationsProviderData struct {
+ Data map[string]AconfigDeclarationsProviderData
+}
var AconfigReleaseDeclarationsProviderKey = blueprint.NewProvider[AconfigReleaseDeclarationsProviderData]()
+// @auto-generate: gob
type ModeInfo struct {
Container string
Mode string
@@ -67,7 +74,7 @@ type CodegenInfo struct {
var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
-func propagateModeInfos(ctx ModuleContext, module Module, to, from map[string]ModeInfo) {
+func propagateModeInfos(ctx ModuleContext, module ModuleProxy, to, from map[string]ModeInfo) {
if len(from) > 0 {
depTag := ctx.OtherModuleDependencyTag(module)
if tag, ok := depTag.(PropagateAconfigValidationDependencyTag); ok && tag.PropagateAconfigValidation() {
@@ -76,6 +83,7 @@ func propagateModeInfos(ctx ModuleContext, module Module, to, from map[string]Mo
}
}
+// @auto-generate: gob
type aconfigPropagatingDeclarationsInfo struct {
AconfigFiles map[string]Paths
ModeInfos map[string]ModeInfo
@@ -83,7 +91,7 @@ type aconfigPropagatingDeclarationsInfo struct {
var AconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
-func VerifyAconfigBuildMode(ctx ModuleContext, container string, module blueprint.Module, asError bool) {
+func VerifyAconfigBuildMode(ctx ModuleContext, container string, module ModuleOrProxy, asError bool) {
if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok {
for k, v := range dep.ModeInfos {
msg := fmt.Sprintf("%s/%s depends on %s/%s/%s across containers\n",
@@ -191,7 +199,7 @@ func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func aconfigUpdateAndroidMkInfos(ctx fillInEntriesContext, mod Module, infos *AndroidMkProviderInfo) {
+func aconfigUpdateAndroidMkInfos(ctx fillInEntriesContext, mod ModuleOrProxy, infos *AndroidMkProviderInfo) {
info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
if !ok || len(info.AconfigFiles) == 0 {
return
@@ -213,7 +221,7 @@ func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, genera
return Paths{inputs[0]}
}
- output := PathForModuleOut(ctx, container, "aconfig_merged.pb")
+ output := PathForModuleOut(ctx, "merged_aconfig_files", container, "aconfig_merged.pb")
if generateRule {
ctx.Build(pctx, BuildParams{
@@ -246,7 +254,7 @@ func getContainer(m Module) string {
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func getContainerUsingProviders(ctx OtherModuleProviderContext, m Module) string {
+func getContainerUsingProviders(ctx OtherModuleProviderContext, m ModuleOrProxy) string {
container := "system"
commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider)
if commonInfo.Vendor || commonInfo.Proprietary || commonInfo.SocSpecific {
diff --git a/android/aconfig_providers_gob_enc.go b/android/aconfig_providers_gob_enc.go
new file mode 100644
index 000000000..85a11d799
--- /dev/null
+++ b/android/aconfig_providers_gob_enc.go
@@ -0,0 +1,270 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ AconfigDeclarationsProviderDataGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(AconfigDeclarationsProviderData) })
+ AconfigReleaseDeclarationsProviderDataGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(AconfigReleaseDeclarationsProviderData) })
+ ModeInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModeInfo) })
+ aconfigPropagatingDeclarationsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(aconfigPropagatingDeclarationsInfo) })
+}
+
+func (r AconfigDeclarationsProviderData) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Package); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Container); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Exportable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.IntermediateCacheOutputPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.IntermediateDumpOutputPath); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *AconfigDeclarationsProviderData) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Package)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Container)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Exportable)
+ if err != nil {
+ return err
+ }
+
+ if val5, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val5 == nil {
+ r.IntermediateCacheOutputPath = nil
+ } else {
+ r.IntermediateCacheOutputPath = val5.(WritablePath)
+ }
+
+ if val7, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val7 == nil {
+ r.IntermediateDumpOutputPath = nil
+ } else {
+ r.IntermediateDumpOutputPath = val7.(WritablePath)
+ }
+
+ return err
+}
+
+var AconfigDeclarationsProviderDataGobRegId int16
+
+func (r AconfigDeclarationsProviderData) GetTypeId() int16 {
+ return AconfigDeclarationsProviderDataGobRegId
+}
+
+func (r AconfigReleaseDeclarationsProviderData) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Data))); err != nil {
+ return err
+ }
+ for k, v := range r.Data {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = v.Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *AconfigReleaseDeclarationsProviderData) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val1 int32
+ err = gobtools.DecodeSimple[int32](buf, &val1)
+ if err != nil {
+ return err
+ }
+ if val1 > 0 {
+ r.Data = make(map[string]AconfigDeclarationsProviderData, val1)
+ for val2 := 0; val2 < int(val1); val2++ {
+ var k string
+ var v AconfigDeclarationsProviderData
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ if err = v.Decode(buf); err != nil {
+ return err
+ }
+ r.Data[k] = v
+ }
+ }
+
+ return err
+}
+
+var AconfigReleaseDeclarationsProviderDataGobRegId int16
+
+func (r AconfigReleaseDeclarationsProviderData) GetTypeId() int16 {
+ return AconfigReleaseDeclarationsProviderDataGobRegId
+}
+
+func (r ModeInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Container); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Mode); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModeInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Container)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Mode)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModeInfoGobRegId int16
+
+func (r ModeInfo) GetTypeId() int16 {
+ return ModeInfoGobRegId
+}
+
+func (r aconfigPropagatingDeclarationsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.AconfigFiles))); err != nil {
+ return err
+ }
+ for k, v := range r.AconfigFiles {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, int32(len(v))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(v); val1++ {
+ if err = gobtools.EncodeInterface(buf, v[val1]); err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ModeInfos))); err != nil {
+ return err
+ }
+ for k, v := range r.ModeInfos {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = v.Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *aconfigPropagatingDeclarationsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val1 int32
+ err = gobtools.DecodeSimple[int32](buf, &val1)
+ if err != nil {
+ return err
+ }
+ if val1 > 0 {
+ r.AconfigFiles = make(map[string]Paths, val1)
+ for val2 := 0; val2 < int(val1); val2++ {
+ var k string
+ var v Paths
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ v = make([]Path, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ if val9, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val9 == nil {
+ v[val7] = nil
+ } else {
+ v[val7] = val9.(Path)
+ }
+ }
+ }
+ r.AconfigFiles[k] = v
+ }
+ }
+
+ var val10 int32
+ err = gobtools.DecodeSimple[int32](buf, &val10)
+ if err != nil {
+ return err
+ }
+ if val10 > 0 {
+ r.ModeInfos = make(map[string]ModeInfo, val10)
+ for val11 := 0; val11 < int(val10); val11++ {
+ var k string
+ var v ModeInfo
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ if err = v.Decode(buf); err != nil {
+ return err
+ }
+ r.ModeInfos[k] = v
+ }
+ }
+
+ return err
+}
+
+var aconfigPropagatingDeclarationsInfoGobRegId int16
+
+func (r aconfigPropagatingDeclarationsInfo) GetTypeId() int16 {
+ return aconfigPropagatingDeclarationsInfoGobRegId
+}
diff --git a/android/androidmk.go b/android/androidmk.go
index e32835946..4c4631298 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -38,6 +38,8 @@ import (
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterAndroidMkBuildComponents(InitRegistrationContext)
}
@@ -358,13 +360,14 @@ func (d *distCopies) Strings() (ret []string) {
// This gets the dist contributuions from the given module that were specified in the Android.bp
// file using the dist: property. It does not include contribututions that the module's
// implementation may have defined with ctx.DistForGoals(), for that, see DistProvider.
-func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod Module) *distContributions {
- amod := mod.base()
- name := amod.BaseModuleName()
+func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod ModuleOrProxy) *distContributions {
+ name := mod.Name()
info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
availableTaggedDists := info.DistFiles
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider)
+
if len(availableTaggedDists) == 0 {
// Nothing dist-able for this module.
return nil
@@ -378,7 +381,7 @@ func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod Module) *
}
// Iterate over this module's dist structs, merged from the dist and dists properties.
- for _, dist := range amod.Dists() {
+ for _, dist := range commonInfo.Dists {
// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
goals := strings.Join(dist.Targets, " ")
@@ -501,12 +504,12 @@ func (a *AndroidMkEntries) GetDistForGoals(mod Module) []string {
// fillInEntries goes through the common variable processing and calls the extra data funcs to
// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
type fillInEntriesContext interface {
- ModuleDir(module blueprint.Module) string
- ModuleSubDir(module blueprint.Module) string
+ ModuleDir(module ModuleOrProxy) string
+ ModuleSubDir(module ModuleOrProxy) string
Config() Config
- otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
- ModuleType(module blueprint.Module) string
- OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ otherModuleProvider(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool)
+ ModuleType(module ModuleOrProxy) string
+ OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt string, args ...interface{})
HasMutatorFinished(mutatorName string) bool
}
@@ -570,10 +573,12 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) {
a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
}
+ moduleBuildTargetsInfo := OtherModuleProviderOrDefault(ctx, mod, ModuleBuildTargetsProvider)
+
if info.UncheckedModule {
a.SetBool("LOCAL_DONT_CHECK_MODULE", true)
- } else if info.CheckbuildTarget != nil {
- a.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget)
+ } else if moduleBuildTargetsInfo.CheckbuildTarget != nil {
+ a.SetPath("LOCAL_CHECKED_MODULE", moduleBuildTargetsInfo.CheckbuildTarget)
} else {
a.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile)
}
@@ -582,9 +587,8 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) {
a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
}
- if am, ok := mod.(ApexModule); ok {
- a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
- }
+ platformAvailabilityInfo := OtherModuleProviderOrDefault(ctx, mod, PlatformAvailabilityInfoProvider)
+ a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", platformAvailabilityInfo.NotAvailableToPlatform)
archStr := base.Arch().ArchType.String()
host := false
@@ -716,10 +720,10 @@ func AndroidMkSingleton() Singleton {
type androidMkSingleton struct{}
-func allModulesSorted(ctx SingletonContext) []Module {
- var allModules []Module
+func allModulesSorted(ctx SingletonContext) []ModuleOrProxy {
+ var allModules []ModuleOrProxy
- ctx.VisitAllModules(func(module Module) {
+ ctx.VisitAllModulesOrProxies(func(module ModuleOrProxy) {
allModules = append(allModules, module)
})
@@ -776,7 +780,7 @@ func (so *soongOnlyAndroidMkSingleton) GenerateBuildActions(ctx SingletonContext
// the androidmk singleton that just focuses on getting the dist contributions
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []Module) {
+func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []ModuleOrProxy) {
allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods)
singletonDists := getSingletonDists(ctx.Config())
@@ -804,7 +808,7 @@ func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContex
ctx.Phony("droidcore-unbundled", moduleInfoJSONPath)
allDistContributions = append(allDistContributions, distContributions{
copiesForGoals: []*copiesForGoals{{
- goals: "general-tests droidcore-unbundled",
+ goals: "general-tests droidcore-unbundled haiku module-info",
copies: []distCopy{{
from: moduleInfoJSONPath,
dest: "module-info.json",
@@ -886,7 +890,7 @@ func distsToDistContributions(dists []dist) *distContributions {
// getSoongOnlyDataFromMods gathers data from the given modules needed in soong-only builds.
// Currently, this is the dist contributions, and the module-info.json contents.
-func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distContributions, []*ModuleInfoJSON) {
+func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []ModuleOrProxy) ([]distContributions, []*ModuleInfoJSON) {
var allDistContributions []distContributions
var moduleInfoJSONs []*ModuleInfoJSON
for _, mod := range mods {
@@ -908,7 +912,7 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo
continue
}
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON.Data...)
}
if contribution := getDistContributions(ctx, mod); contribution != nil {
allDistContributions = append(allDistContributions, *contribution)
@@ -921,28 +925,28 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo
data.Include = "$(BUILD_PREBUILT)"
}
- data.fillInData(ctx, mod)
+ data.fillInData(ctx, mod.(Module))
if data.Entries.disabled() {
continue
}
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON.Data...)
}
- if contribution := getDistContributions(ctx, mod); contribution != nil {
+ if contribution := getDistContributions(ctx, mod.(Module)); contribution != nil {
allDistContributions = append(allDistContributions, *contribution)
}
}
if x, ok := mod.(AndroidMkEntriesProvider); ok {
entriesList := x.AndroidMkEntries()
for _, entries := range entriesList {
- entries.fillInEntries(ctx, mod)
+ entries.fillInEntries(ctx, mod.(Module))
if entries.disabled() {
continue
}
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON.Data...)
}
- if contribution := getDistContributions(ctx, mod); contribution != nil {
+ if contribution := getDistContributions(ctx, mod.(Module)); contribution != nil {
allDistContributions = append(allDistContributions, *contribution)
}
}
@@ -952,7 +956,7 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo
return allDistContributions, moduleInfoJSONs
}
-func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []Module) error {
+func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []ModuleOrProxy) error {
buf := &bytes.Buffer{}
var moduleInfoJSONs []*ModuleInfoJSON
@@ -967,7 +971,7 @@ func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPa
return err
}
- if ctx.PrimaryModule(mod) == mod {
+ if ctx.IsPrimaryModule(mod) {
typeStats[ctx.ModuleType(mod)] += 1
}
}
@@ -1012,7 +1016,7 @@ func writeModuleInfoJSON(ctx SingletonContext, moduleInfoJSONs []*ModuleInfoJSON
return nil
}
-func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod Module) error {
+func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod ModuleOrProxy) error {
defer func() {
if r := recover(); r != nil {
panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
@@ -1028,9 +1032,9 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs
} else {
switch x := mod.(type) {
case AndroidMkDataProvider:
- err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
+ err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod.(Module), x)
case AndroidMkEntriesProvider:
- err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
+ err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod.(Module), x)
default:
// Not exported to make so no make variables to set.
}
@@ -1135,7 +1139,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *
if !data.Entries.disabled() {
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON...)
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON.Data...)
}
}
@@ -1178,7 +1182,7 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleIn
if providesModuleInfoJSON && !entries.disabled() {
// append only the name matching moduleInfoJSON entry
- for _, m := range moduleInfoJSON {
+ for _, m := range moduleInfoJSON.Data {
if m.RegisterNameOverride == entries.OverrideName && m.SubName == entries.SubName {
*moduleInfoJSONs = append(*moduleInfoJSONs, m)
}
@@ -1270,11 +1274,13 @@ func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) {
fmt.Fprintln(w)
}
+// @auto-generate: gob
type AndroidMkProviderInfo struct {
PrimaryInfo AndroidMkInfo
ExtraInfo []AndroidMkInfo
}
+// @auto-generate: gob
type AndroidMkInfo struct {
// Android.mk class string, e.g. EXECUTABLES, JAVA_LIBRARIES, ETC
Class string
@@ -1327,7 +1333,7 @@ var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]()
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
- mod Module, providerInfo *AndroidMkProviderInfo) error {
+ mod ModuleOrProxy, providerInfo *AndroidMkProviderInfo) error {
commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider)
if commonInfo.SkipAndroidMkProcessing {
return nil
@@ -1350,7 +1356,7 @@ func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, modu
if !info.PrimaryInfo.disabled() {
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON...)
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON.Data...)
}
}
@@ -1474,7 +1480,7 @@ func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) {
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) {
+func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod ModuleOrProxy, commonInfo *CommonModuleInfo) {
helperInfo := AndroidMkInfo{
EntryMap: make(map[string][]string),
}
@@ -1529,10 +1535,12 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, comm
helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", commonInfo.NoFullInstall)
}
+ moduleBuildTargetsInfo := OtherModuleProviderOrDefault(ctx, mod, ModuleBuildTargetsProvider)
+
if info.UncheckedModule {
helperInfo.SetBool("LOCAL_DONT_CHECK_MODULE", true)
- } else if info.CheckbuildTarget != nil {
- helperInfo.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget)
+ } else if moduleBuildTargetsInfo.CheckbuildTarget != nil {
+ helperInfo.SetPath("LOCAL_CHECKED_MODULE", moduleBuildTargetsInfo.CheckbuildTarget)
} else {
helperInfo.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile)
}
@@ -1541,8 +1549,8 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, comm
helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
}
- if commonInfo.IsApexModule {
- helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", commonInfo.NotAvailableForPlatform)
+ if platformAvailabilityInfo, ok := OtherModuleProvider(ctx, mod, PlatformAvailabilityInfoProvider); ok {
+ helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", platformAvailabilityInfo.NotAvailableToPlatform)
}
archStr := commonInfo.Target.Arch.ArchType.String()
@@ -1655,7 +1663,7 @@ func (a *AndroidMkInfo) write(w io.Writer) {
// calls from the module's dist and dists properties.
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) []string {
+func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod ModuleOrProxy, commonInfo *CommonModuleInfo) []string {
distContributions := getDistContributions(ctx, mod)
if distContributions == nil {
return nil
diff --git a/android/androidmk_gob_enc.go b/android/androidmk_gob_enc.go
new file mode 100644
index 000000000..c24fac368
--- /dev/null
+++ b/android/androidmk_gob_enc.go
@@ -0,0 +1,324 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ AndroidMkProviderInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(AndroidMkProviderInfo) })
+ AndroidMkInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(AndroidMkInfo) })
+}
+
+func (r AndroidMkProviderInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.PrimaryInfo.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExtraInfo))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.ExtraInfo); val1++ {
+ if err = r.ExtraInfo[val1].Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *AndroidMkProviderInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.PrimaryInfo.Decode(buf); err != nil {
+ return err
+ }
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.ExtraInfo = make([]AndroidMkInfo, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if err = r.ExtraInfo[val4].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var AndroidMkProviderInfoGobRegId int16
+
+func (r AndroidMkProviderInfo) GetTypeId() int16 {
+ return AndroidMkProviderInfoGobRegId
+}
+
+func (r AndroidMkInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Class); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.SubName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.OverrideName); err != nil {
+ return err
+ }
+
+ if err = r.OutputFile.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Disabled); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Include); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Required))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Required); val1++ {
+ if err = gobtools.EncodeString(buf, r.Required[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Host_required))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Host_required); val2++ {
+ if err = gobtools.EncodeString(buf, r.Host_required[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Target_required))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Target_required); val3++ {
+ if err = gobtools.EncodeString(buf, r.Target_required[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.HeaderStrings))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.HeaderStrings); val4++ {
+ if err = gobtools.EncodeString(buf, r.HeaderStrings[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.FooterStrings))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.FooterStrings); val5++ {
+ if err = gobtools.EncodeString(buf, r.FooterStrings[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.EntryMap))); err != nil {
+ return err
+ }
+ for k, v := range r.EntryMap {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, int32(len(v))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(v); val6++ {
+ if err = gobtools.EncodeString(buf, v[val6]); err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.EntryOrder))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.EntryOrder); val7++ {
+ if err = gobtools.EncodeString(buf, r.EntryOrder[val7]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *AndroidMkInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Class)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.SubName)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.OverrideName)
+ if err != nil {
+ return err
+ }
+
+ if err = r.OutputFile.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Disabled)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Include)
+ if err != nil {
+ return err
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.Required = make([]string, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ err = gobtools.DecodeString(buf, &r.Required[val9])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val12 int32
+ err = gobtools.DecodeSimple[int32](buf, &val12)
+ if err != nil {
+ return err
+ }
+ if val12 > 0 {
+ r.Host_required = make([]string, val12)
+ for val13 := 0; val13 < int(val12); val13++ {
+ err = gobtools.DecodeString(buf, &r.Host_required[val13])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ r.Target_required = make([]string, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ err = gobtools.DecodeString(buf, &r.Target_required[val17])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val20 int32
+ err = gobtools.DecodeSimple[int32](buf, &val20)
+ if err != nil {
+ return err
+ }
+ if val20 > 0 {
+ r.HeaderStrings = make([]string, val20)
+ for val21 := 0; val21 < int(val20); val21++ {
+ err = gobtools.DecodeString(buf, &r.HeaderStrings[val21])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val24 int32
+ err = gobtools.DecodeSimple[int32](buf, &val24)
+ if err != nil {
+ return err
+ }
+ if val24 > 0 {
+ r.FooterStrings = make([]string, val24)
+ for val25 := 0; val25 < int(val24); val25++ {
+ err = gobtools.DecodeString(buf, &r.FooterStrings[val25])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val27 int32
+ err = gobtools.DecodeSimple[int32](buf, &val27)
+ if err != nil {
+ return err
+ }
+ if val27 > 0 {
+ r.EntryMap = make(map[string][]string, val27)
+ for val28 := 0; val28 < int(val27); val28++ {
+ var k string
+ var v []string
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ var val31 int32
+ err = gobtools.DecodeSimple[int32](buf, &val31)
+ if err != nil {
+ return err
+ }
+ if val31 > 0 {
+ v = make([]string, val31)
+ for val32 := 0; val32 < int(val31); val32++ {
+ err = gobtools.DecodeString(buf, &v[val32])
+ if err != nil {
+ return err
+ }
+ }
+ }
+ r.EntryMap[k] = v
+ }
+ }
+
+ var val35 int32
+ err = gobtools.DecodeSimple[int32](buf, &val35)
+ if err != nil {
+ return err
+ }
+ if val35 > 0 {
+ r.EntryOrder = make([]string, val35)
+ for val36 := 0; val36 < int(val35); val36++ {
+ err = gobtools.DecodeString(buf, &r.EntryOrder[val36])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var AndroidMkInfoGobRegId int16
+
+func (r AndroidMkInfo) GetTypeId() int16 {
+ return AndroidMkInfoGobRegId
+}
diff --git a/android/apex.go b/android/apex.go
index 57baff5cf..ebd1ed445 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -26,7 +26,7 @@ import (
var (
// This is the sdk version when APEX was first introduced
- SdkVersion_Android10 = uncheckedFinalApiLevel(29)
+ SdkVersion_Android10 = UncheckedFinalApiLevel(29)
)
// ApexInfo describes the metadata about one or more apexBundles that an apex variant of a module is
@@ -111,14 +111,6 @@ type ApexAvailableInfo struct {
var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex_mutate")
var ApexAvailableInfoProvider = blueprint.NewMutatorProvider[ApexAvailableInfo]("apex_mutate")
-func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
- (*d)["Apex"] = map[string]interface{}{
- "ApexVariationName": i.ApexVariationName,
- "MinSdkVersion": i.MinSdkVersion,
- "ForPrebuiltApex": i.ForPrebuiltApex,
- }
-}
-
// mergedName gives the name of the alias variation that will be used when multiple apex variations
// of a module can be deduped into one variation. For example, if libfoo is included in both apex.a
// and apex.b, and if the two APEXes have the same min_sdk_version (say 29), then libfoo doesn't
@@ -155,6 +147,12 @@ type ApexBundleInfo struct {
var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_mutate")
+var PlatformAvailabilityInfoProvider = blueprint.NewMutatorProvider[PlatformAvailabilityInfo]("mark_platform_availability")
+
+type PlatformAvailabilityInfo struct {
+ NotAvailableToPlatform bool
+}
+
// DepInSameApexChecker defines an interface that should be used to determine whether a given dependency
// should be considered as part of the same APEX as the current module or not.
type DepInSameApexChecker interface {
@@ -188,7 +186,7 @@ type DepInSameApexInfo struct {
var DepInSameApexInfoProvider = blueprint.NewMutatorProvider[DepInSameApexInfo]("apex_unique")
-func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool {
+func IsDepInSameApex(ctx BaseModuleContext, module, dep ModuleOrProxy) bool {
depTag := ctx.OtherModuleDependencyTag(dep)
if _, ok := depTag.(ExcludeFromApexContentsTag); ok {
// The tag defines a dependency that never requires the child module to be part of the same
@@ -273,15 +271,6 @@ type ApexModule interface {
// Returns false by default.
AlwaysRequiresPlatformApexVariant() bool
- // Returns true if this module is not available to platform (i.e. apex_available property
- // doesn't have "//apex_available:platform"), or shouldn't be available to platform, which
- // is the case when this module depends on other module that isn't available to platform.
- NotAvailableForPlatform() bool
-
- // Marks that this module is not available to platform. Set by the
- // check-platform-availability mutator in the apex package.
- SetNotAvailableForPlatform()
-
// Returns the min sdk version that the module supports, .
MinSdkVersionSupported(ctx BaseModuleContext) ApiLevel
@@ -305,9 +294,6 @@ type ApexProperties struct {
// Default is ["//apex_available:platform"].
Apex_available []string
- // See ApexModule.NotAvailableForPlatform()
- NotAvailableForPlatform bool `blueprint:"mutated"`
-
// See ApexModule.UniqueApexVariants()
UniqueApexVariationsForDeps bool `blueprint:"mutated"`
}
@@ -389,7 +375,9 @@ func (m *ApexModuleBase) ApexTransitionMutatorMutate(ctx BottomUpMutatorContext,
ApexAvailableFor: module.ApexAvailableFor(),
})
}
- if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
+
+ platformAvailabilityInfo, _ := ModuleProvider(ctx, PlatformAvailabilityInfoProvider)
+ if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && platformAvailabilityInfo.NotAvailableToPlatform {
// Do not install the module for platform, but still allow it to output
// uninstallable AndroidMk entries in certain cases when they have side
// effects. TODO(jiyong): move this routine to somewhere else
@@ -524,10 +512,6 @@ func CheckAvailableForApex(what string, apex_available []string) bool {
if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
return true
}
- // TODO b/383863941: Remove once legacy name is no longer used
- if (apex_name == "com.android.btservices" && what == "com.android.bt") || (apex_name == "com.android.bt" && what == "com.android.btservices") {
- return true
- }
}
return false
}
@@ -542,16 +526,6 @@ func (m *ApexModuleBase) AlwaysRequiresPlatformApexVariant() bool {
return false
}
-// Implements ApexModule
-func (m *ApexModuleBase) NotAvailableForPlatform() bool {
- return m.ApexProperties.NotAvailableForPlatform
-}
-
-// Implements ApexModule
-func (m *ApexModuleBase) SetNotAvailableForPlatform() {
- m.ApexProperties.NotAvailableForPlatform = true
-}
-
// This function makes sure that the apex_available property is valid
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available {
@@ -653,6 +627,14 @@ type ApexBundleDepsData struct {
var ApexBundleDepsDataProvider = blueprint.NewProvider[ApexBundleDepsData]()
+// ApexBundleTypeInfo is used to identify the module is a apexBundle module.
+type ApexBundleTypeInfo struct {
+ Pem Path
+ Key Path
+}
+
+var ApexBundleTypeInfoProvider = blueprint.NewProvider[ApexBundleTypeInfo]()
+
func (d *ApexBundleDepsInfo) FlatListPath() Path {
return d.flatListPath
}
@@ -764,7 +746,7 @@ type MinSdkVersionFromValueContext interface {
// error if not. No default implementation is provided for this method. A module type
// implementing this interface should provide an implementation. A module supports an sdk
// version when the module's min_sdk_version is equal to or less than the given sdk version.
-func ShouldSupportSdkVersion(ctx BaseModuleContext, module Module, sdkVersion ApiLevel) error {
+func ShouldSupportSdkVersion(ctx BaseModuleContext, module ModuleOrProxy, sdkVersion ApiLevel) error {
info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoProvider)
if !ok || info.MinSdkVersionSupported.IsNone() {
return fmt.Errorf("min_sdk_version is not specified")
@@ -806,10 +788,10 @@ type ApexExportsInfo struct {
LibraryNameToDexJarPathOnHost map[string]Path
}
-var PrebuiltInfoProvider = blueprint.NewProvider[PrebuiltInfo]()
+var PrebuiltJsonInfoProvider = blueprint.NewProvider[PrebuiltJsonInfo]()
// contents of prebuilt_info.json
-type PrebuiltInfo struct {
+type PrebuiltJsonInfo struct {
// Name of the apex, without the prebuilt_ prefix
Name string
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index fe7a8352e..72de5b81a 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -29,6 +29,14 @@ func RegisterApexContributionsBuildComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("all_apex_contributions", allApexContributionsFactory)
}
+type apexContributionsInfo struct {
+ Name string
+ Contents []string
+ ApiDomain string
+}
+
+var apexContributionsInfoProvider = blueprint.NewMutatorProvider[apexContributionsInfo]("prebuilt_select")
+
type apexContributions struct {
ModuleBase
DefaultableModuleBase
@@ -44,12 +52,12 @@ type contributionProps struct {
Contents []string
}
-func (m *apexContributions) ApiDomain() string {
- return proptools.String(m.properties.Api_domain)
-}
-
-func (m *apexContributions) Contents() []string {
- return m.properties.Contents
+func (m *apexContributions) setApexContributionsInfoProvider(ctx BottomUpMutatorContext) {
+ SetProvider(ctx, apexContributionsInfoProvider, apexContributionsInfo{
+ Name: m.Name(),
+ Contents: m.properties.Contents,
+ ApiDomain: proptools.String(m.properties.Api_domain),
+ })
}
// apex_contributions contains a list of module names (source or
@@ -106,18 +114,18 @@ var (
// Set PrebuiltSelectionInfoProvider in post deps phase
func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BottomUpMutatorContext) {
- addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
- for _, content := range m.Contents() {
+ addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m apexContributionsInfo) {
+ for _, content := range m.Contents {
// Verify that the module listed in contents exists in the tree
// Remove the prebuilt_ prefix to account for partner worksapces where the source module does not
// exist, and PrebuiltRenameMutator renames `prebuilt_foo` to `foo`
if !ctx.OtherModuleExists(content) && !ctx.OtherModuleExists(RemoveOptionalPrebuiltPrefix(content)) && !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
+ ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name)
}
pi := &PrebuiltSelectionInfo{
selectedModuleName: content,
- metadataModuleName: m.Name(),
- apiDomain: m.ApiDomain(),
+ metadataModuleName: m.Name,
+ apiDomain: m.ApiDomain,
}
p.Add(ctx, pi)
}
@@ -134,7 +142,7 @@ func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BottomUpMuta
if child == nil {
continue
}
- if m, ok := child.(*apexContributions); ok {
+ if m, ok := OtherModuleProvider(ctx, child, apexContributionsInfoProvider); ok {
addContentsToProvider(&p, m)
} else {
ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
diff --git a/android/api_levels.go b/android/api_levels.go
index c83fae878..8f0fe458e 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -19,10 +19,10 @@ import (
"fmt"
"strconv"
"strings"
-
- "github.com/google/blueprint/gobtools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterParallelSingletonType("api_levels", ApiLevelsSingleton)
}
@@ -37,6 +37,7 @@ const previewAPILevelBase = 9000
// Java has these, and they're managed with the SdkKind enum of the SdkSpec. A
// future cleanup should be to migrate SdkSpec to using ApiLevel instead of its
// SdkVersion int, and to move SdkSpec into this package.
+// @auto-generate: gob
type ApiLevel struct {
// The string representation of the API level.
value string
@@ -54,34 +55,6 @@ type ApiLevel struct {
isPreview bool
}
-type apiLevelGob struct {
- Value string
- Number int
- IsPreview bool
-}
-
-func (a *ApiLevel) ToGob() *apiLevelGob {
- return &apiLevelGob{
- Value: a.value,
- Number: a.number,
- IsPreview: a.isPreview,
- }
-}
-
-func (a *ApiLevel) FromGob(data *apiLevelGob) {
- a.value = data.Value
- a.number = data.Number
- a.isPreview = data.IsPreview
-}
-
-func (a ApiLevel) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[apiLevelGob](&a)
-}
-
-func (a *ApiLevel) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[apiLevelGob](data, a)
-}
-
func (this ApiLevel) FinalInt() int {
if this.IsInvalid() {
panic(fmt.Errorf("%v is not a recognized api_level\n", this))
@@ -259,7 +232,7 @@ func (this ApiLevel) LessThanOrEqualTo(other ApiLevel) bool {
return this.CompareTo(other) <= 0
}
-func uncheckedFinalApiLevel(num int) ApiLevel {
+func UncheckedFinalApiLevel(num int) ApiLevel {
return ApiLevel{
value: strconv.Itoa(num),
number: num,
@@ -299,32 +272,32 @@ func NewInvalidApiLevel(raw string) ApiLevel {
}
// The first version that introduced 64-bit ABIs.
-var FirstLp64Version = uncheckedFinalApiLevel(21)
+var FirstLp64Version = UncheckedFinalApiLevel(21)
// Android has had various kinds of packed relocations over the years
// (http://b/187907243).
//
// API level 30 is where the now-standard SHT_RELR is available.
-var FirstShtRelrVersion = uncheckedFinalApiLevel(30)
+var FirstShtRelrVersion = UncheckedFinalApiLevel(30)
// API level 28 introduced SHT_RELR when it was still Android-only, and used an
// Android-specific relocation.
-var FirstAndroidRelrVersion = uncheckedFinalApiLevel(28)
+var FirstAndroidRelrVersion = UncheckedFinalApiLevel(28)
// API level 23 was when we first had the Chrome relocation packer, which is
// obsolete and has been removed, but lld can now generate compatible packed
// relocations itself.
-var FirstPackedRelocationsVersion = uncheckedFinalApiLevel(23)
+var FirstPackedRelocationsVersion = UncheckedFinalApiLevel(23)
// LastWithoutModuleLibCoreSystemModules is the last API level where prebuilts/sdk does not contain
// a core-for-system-modules.jar for the module-lib API scope.
-var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel(31)
+var LastWithoutModuleLibCoreSystemModules = UncheckedFinalApiLevel(31)
-var ApiLevelR = uncheckedFinalApiLevel(30)
+var ApiLevelR = UncheckedFinalApiLevel(30)
-var ApiLevelUpsideDownCake = uncheckedFinalApiLevel(34)
+var ApiLevelUpsideDownCake = UncheckedFinalApiLevel(34)
-var ApiLevelVanillaIceCream = uncheckedFinalApiLevel(35)
+var ApiLevelVanillaIceCream = UncheckedFinalApiLevel(35)
// ReplaceFinalizedCodenames returns the API level number associated with that API level
// if the `raw` input is the codename of an API level has been finalized.
@@ -399,10 +372,10 @@ func ApiLevelFromUserWithConfig(config Config, raw string) (ApiLevel, error) {
if err != nil {
return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw)
}
- return uncheckedFinalApiLevel(asInt), nil
+ return UncheckedFinalApiLevel(asInt), nil
}
- return uncheckedFinalApiLevel(canonical), nil
+ return UncheckedFinalApiLevel(canonical), nil
}
@@ -439,7 +412,7 @@ func ApiLevelForTest(raw string) ApiLevel {
panic(fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw))
}
- apiLevel := uncheckedFinalApiLevel(asInt)
+ apiLevel := UncheckedFinalApiLevel(asInt)
return apiLevel
}
diff --git a/android/api_levels_gob_enc.go b/android/api_levels_gob_enc.go
new file mode 100644
index 000000000..4c9a53aaf
--- /dev/null
+++ b/android/api_levels_gob_enc.go
@@ -0,0 +1,58 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ApiLevelGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ApiLevel) })
+}
+
+func (r ApiLevel) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.value); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int64(r.number)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.isPreview); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ApiLevel) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.value)
+ if err != nil {
+ return err
+ }
+
+ var val2 int64
+ err = gobtools.DecodeSimple[int64](buf, &val2)
+ if err != nil {
+ return err
+ }
+ r.number = int(val2)
+
+ err = gobtools.DecodeSimple[bool](buf, &r.isPreview)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ApiLevelGobRegId int16
+
+func (r ApiLevel) GetTypeId() int16 {
+ return ApiLevelGobRegId
+}
diff --git a/android/arch.go b/android/arch.go
index d6b297119..397de067b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -26,6 +26,8 @@ import (
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
/*
Example blueprints file containing all variant property groups, with comment listing what type
of variants get properties in that group:
@@ -89,6 +91,7 @@ module {
*/
// An Arch indicates a single CPU architecture.
+// @auto-generate: gob
type Arch struct {
// The type of the architecture (arm, arm64, x86, or x86_64).
ArchType ArchType
@@ -122,6 +125,7 @@ func (a Arch) String() string {
// ArchType is used to define the 4 supported architecture types (arm, arm64, x86, x86_64), as
// well as the "common" architecture used for modules that support multiple architectures, for
// example Java modules.
+// @auto-generate: gob
type ArchType struct {
// Name is the name of the architecture type, "arm", "arm64", "x86", or "x86_64".
Name string
@@ -232,6 +236,7 @@ func (class OsClass) String() string {
}
// OsType describes an OS variant of a module.
+// @auto-generate: gob
type OsType struct {
// Name is the name of the OS. It is also used as the name of the property in Android.bp
// files.
@@ -342,6 +347,7 @@ func OsTypeList() []OsType {
}
// Target specifies the OS and architecture that a module is being compiled for.
+// @auto-generate: gob
type Target struct {
// Os the OS that the module is being compiled for (e.g. "linux_glibc", "android").
Os OsType
@@ -485,6 +491,25 @@ func (o *osTransitionMutator) IncomingTransition(ctx IncomingTransitionContext,
return ""
}
+ // If the reverse dependency is the unbundled_builder, building the apps listed in
+ // TARGET_BUILD_APPS, prefer the android os, otherwise use the host os.
+ if _, ok := ctx.DepTag().(UsesUnbundledVariantDepTag); ok {
+ if allOsInfo, ok := ModuleProvider(ctx, allOsProvider); ok {
+ for _, variation := range allOsInfo.Variations {
+ if allOsInfo.Os[variation] == Android {
+ return variation
+ }
+ }
+ for _, variation := range allOsInfo.Variations {
+ if allOsInfo.Os[variation] == ctx.Config().BuildOS {
+ return variation
+ }
+ }
+ // will cause a missing variant error
+ return "os_variant_for_unbundled_not_found"
+ }
+ }
+
return incomingVariation
}
@@ -702,6 +727,15 @@ func (a *archTransitionMutator) IncomingTransition(ctx IncomingTransitionContext
if multilib == "common" {
return "common"
}
+
+ // If the reverse dependency is the unbundled_builder, building the apps listed in
+ // TARGET_BUILD_APPS, use the primary arch of this module.
+ if _, ok := ctx.DepTag().(UsesUnbundledVariantDepTag); ok {
+ if allArchInfo, ok := ModuleProvider(ctx, allArchProvider); ok {
+ return allArchInfo.Primary
+ }
+ }
+
return incomingVariation
}
@@ -1371,40 +1405,6 @@ func getArchProperties(ctx BaseModuleContext, archProperties interface{}, arch A
if ok {
result = append(result, archStruct)
- // Handle arch-variant-specific properties in the form:
- // arch: {
- // arm: {
- // variant: {
- // key: value,
- // },
- // },
- // },
- v := variantReplacer.Replace(arch.ArchVariant)
- if v != "" {
- prefix := "arch." + archType.Name + "." + v
- if variantProperties, ok := getChildPropertyStruct(ctx, archStruct, v, prefix); ok {
- result = append(result, variantProperties)
- }
- }
-
- // Handle cpu-variant-specific properties in the form:
- // arch: {
- // arm: {
- // variant: {
- // key: value,
- // },
- // },
- // },
- if arch.CpuVariant != arch.ArchVariant {
- c := variantReplacer.Replace(arch.CpuVariant)
- if c != "" {
- prefix := "arch." + archType.Name + "." + c
- if cpuVariantProperties, ok := getChildPropertyStruct(ctx, archStruct, c, prefix); ok {
- result = append(result, cpuVariantProperties)
- }
- }
- }
-
// Handle arch-feature-specific properties in the form:
// arch: {
// arm: {
diff --git a/android/arch_gob_enc.go b/android/arch_gob_enc.go
new file mode 100644
index 000000000..da9a86650
--- /dev/null
+++ b/android/arch_gob_enc.go
@@ -0,0 +1,278 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ArchGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(Arch) })
+ ArchTypeGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ArchType) })
+ OsTypeGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(OsType) })
+ TargetGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(Target) })
+}
+
+func (r Arch) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.ArchType.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.ArchVariant); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.CpuVariant); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Abi))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Abi); val1++ {
+ if err = gobtools.EncodeString(buf, r.Abi[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ArchFeatures))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.ArchFeatures); val2++ {
+ if err = gobtools.EncodeString(buf, r.ArchFeatures[val2]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *Arch) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.ArchType.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.ArchVariant)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.CpuVariant)
+ if err != nil {
+ return err
+ }
+
+ var val5 int32
+ err = gobtools.DecodeSimple[int32](buf, &val5)
+ if err != nil {
+ return err
+ }
+ if val5 > 0 {
+ r.Abi = make([]string, val5)
+ for val6 := 0; val6 < int(val5); val6++ {
+ err = gobtools.DecodeString(buf, &r.Abi[val6])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val9 int32
+ err = gobtools.DecodeSimple[int32](buf, &val9)
+ if err != nil {
+ return err
+ }
+ if val9 > 0 {
+ r.ArchFeatures = make([]string, val9)
+ for val10 := 0; val10 < int(val9); val10++ {
+ err = gobtools.DecodeString(buf, &r.ArchFeatures[val10])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var ArchGobRegId int16
+
+func (r Arch) GetTypeId() int16 {
+ return ArchGobRegId
+}
+
+func (r ArchType) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Name); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Field); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Multilib); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ArchType) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Name)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Field)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Multilib)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ArchTypeGobRegId int16
+
+func (r ArchType) GetTypeId() int16 {
+ return ArchTypeGobRegId
+}
+
+func (r OsType) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Name); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Field); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int64(int(r.Class))); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.DefaultDisabled); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *OsType) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Name)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Field)
+ if err != nil {
+ return err
+ }
+
+ var val4 int
+ var val5 int64
+ err = gobtools.DecodeSimple[int64](buf, &val5)
+ if err != nil {
+ return err
+ }
+ val4 = int(val5)
+ r.Class = OsClass(val4)
+
+ err = gobtools.DecodeSimple[bool](buf, &r.DefaultDisabled)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var OsTypeGobRegId int16
+
+func (r OsType) GetTypeId() int16 {
+ return OsTypeGobRegId
+}
+
+func (r Target) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.Os.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.Arch.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, bool(r.NativeBridge)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.NativeBridgeHostArchName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.NativeBridgeRelativePath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HostCross); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *Target) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.Os.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.Arch.Decode(buf); err != nil {
+ return err
+ }
+
+ var val4 bool
+ err = gobtools.DecodeSimple[bool](buf, &val4)
+ if err != nil {
+ return err
+ }
+ r.NativeBridge = NativeBridgeSupport(val4)
+
+ err = gobtools.DecodeString(buf, &r.NativeBridgeHostArchName)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.NativeBridgeRelativePath)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HostCross)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var TargetGobRegId int16
+
+func (r Target) GetTypeId() int16 {
+ return TargetGobRegId
+}
diff --git a/android/arch_list.go b/android/arch_list.go
index 8659549ca..c0b5bfcf8 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -25,6 +25,8 @@ var archVariants = map[ArchType][]string{
"armv8-a-branchprot",
"armv8-2a",
"armv8-2a-dotprod",
+ "armv8-5a",
+ "armv8-7a",
"armv9-a",
"armv9-2a",
"armv9-3a",
@@ -113,8 +115,14 @@ var cpuVariants = map[ArchType][]string{
X86_64: {},
}
+// Lists all possible optional features for each architecture.
var archFeatures = map[ArchType][]string{
+ Arm: {
+ // Software implementation of ceil/floor is needed in libm
+ "soft_ceil_floor",
+ },
Arm64: {
+ "branchprot",
"dotprod",
},
X86: {
@@ -142,21 +150,43 @@ var archFeatures = map[ArchType][]string{
},
}
+// Lists which optional features are automatically enabled
+// for each value of TARGET_ARCH_VARIANT.
var androidArchFeatureMap = map[ArchType]map[string][]string{
+ Arm: {
+ "armv7-a-neon": {
+ "soft_ceil_floor",
+ },
+ },
Arm64: {
+ "armv8-a-branchprot": {
+ "branchprot",
+ },
"armv8-2a-dotprod": {
"dotprod",
},
+ "armv8-5a": {
+ "branchprot",
+ "dotprod",
+ },
+ "armv8-7a": {
+ "branchprot",
+ "dotprod",
+ },
"armv9-a": {
+ "branchprot",
"dotprod",
},
"armv9-2a": {
+ "branchprot",
"dotprod",
},
"armv9-3a": {
+ "branchprot",
"dotprod",
},
"armv9-4a": {
+ "branchprot",
"dotprod",
},
},
diff --git a/android/arch_module_context.go b/android/arch_module_context.go
index a3a03af02..7c440ad00 100644
--- a/android/arch_module_context.go
+++ b/android/arch_module_context.go
@@ -30,17 +30,19 @@ type ArchModuleContext interface {
Darwin() bool
Windows() bool
PrimaryArch() bool
+ PrimaryNativeBridgeArch() bool
}
type archModuleContext struct {
// TODO: these should eventually go through a (possibly cached) provider like any other configuration instead
// of being special cased.
- ready bool
- os OsType
- target Target
- targetPrimary bool
- multiTargets []Target
- primaryArch bool
+ ready bool
+ os OsType
+ target Target
+ targetPrimary bool
+ multiTargets []Target
+ primaryArch bool
+ primaryNativeBridgeArch bool
}
// ArchReady returns true if the arch mutator has run on the module. Before this returns
@@ -89,3 +91,7 @@ func (a *archModuleContext) Windows() bool {
func (b *archModuleContext) PrimaryArch() bool {
return b.primaryArch
}
+
+func (b *archModuleContext) PrimaryNativeBridgeArch() bool {
+ return b.primaryNativeBridgeArch
+}
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 5cb9e71cf..1e8de8198 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -36,23 +36,23 @@ type BaseModuleContext interface {
// OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleName(m blueprint.Module) string
+ OtherModuleName(m ModuleOrProxy) string
// OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleDir(m blueprint.Module) string
+ OtherModuleDir(m ModuleOrProxy) string
// OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+ OtherModuleErrorf(m ModuleOrProxy, fmt string, args ...interface{})
// OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
// on the module. When called inside a Visit* method with current module being visited, and there are multiple
// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
- OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+ OtherModuleDependencyTag(m ModuleOrProxy) blueprint.DependencyTag
// OtherModuleSubDir returns the string representing the variations of a module.
- OtherModuleSubDir(m blueprint.Module) string
+ OtherModuleSubDir(m ModuleOrProxy) string
// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
@@ -80,23 +80,23 @@ type BaseModuleContext interface {
// OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleType(m blueprint.Module) string
+ OtherModuleType(m ModuleOrProxy) string
// otherModuleProvider returns the value for a provider for the given module. If the value is
// not set it returns nil and false. The value returned may be a deep copy of the value originally
// passed to SetProvider.
//
// This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
- otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(m ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool)
// OtherModuleHasProvider returns true if the module has the given provider set. This
// can avoid copying the provider if the caller only cares about the existence of
// the provider.
- OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
+ OtherModuleHasProvider(m ModuleOrProxy, provider blueprint.AnyProviderKey) bool
// OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
// instead of being defined in Android.bp file.
- OtherModuleIsAutoGenerated(m blueprint.Module) bool
+ OtherModuleIsAutoGenerated(m ModuleOrProxy) bool
// Provider returns the value for a provider for the current module. If the value is
// not set it returns nil and false. It panics if called before the appropriate
@@ -123,7 +123,7 @@ type BaseModuleContext interface {
// dependencies that are not an android.Module.
GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
- GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
+ GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) ModuleProxy
// VisitDirectDeps calls visit for each direct dependency. If there are multiple
// direct dependencies on the same module visit will be called multiple times on that module
@@ -163,10 +163,6 @@ type BaseModuleContext interface {
// The Module passed to the visit function should not be retained outside of the visit function, it may be
// invalidated by future mutators.
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirst(visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
@@ -178,11 +174,10 @@ type BaseModuleContext interface {
// invalidated by future mutators.
WalkDeps(visit func(child, parent Module) bool)
- // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
+ // WalkDepsProxy calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
// child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
- // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
- // any dependencies that are not an android.Module.
+ // (child, parent) pair. If visit returns false WalkDepsProxy will not continue recursing down to child.
//
// The Modules passed to the visit function should not be retained outside of the visit function, they may be
// invalidated by future mutators.
@@ -192,35 +187,27 @@ type BaseModuleContext interface {
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
+ // GetProxyWalkPath is supposed to be called in visit function passed in WalkDepsProxy()
+ // and returns a top-down dependency path from a start module to current child module.
+ GetProxyWalkPath() []ModuleProxy
+
// PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
// Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
// only done once for all variants of a module.
PrimaryModule() Module
- // FinalModule returns the last variant of the current module. Variants of a module are always visited in
- // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
- // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
- // singleton actions that are only done once for all variants of a module.
- FinalModule() Module
+ // IsPrimaryModule returns if the current module is the first variant. Variants of a module are always visited in
+ // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
+ // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
+ // only done once for all variants of a module.
+ IsPrimaryModule(module ModuleOrProxy) bool
// IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in
// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
// variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform
// singleton actions that are only done once for all variants of a module.
- IsFinalModule(module Module) bool
-
- // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
- // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
- // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
- // data modified by the current mutator.
- VisitAllModuleVariants(visit func(Module))
-
- // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always
- // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
- // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
- // data modified by the current mutator.
- VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
+ IsFinalModule(module ModuleOrProxy) bool
// GetTagPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency tags path from a start module to current child module.
@@ -252,41 +239,32 @@ type baseModuleContext struct {
earlyModuleContext
archModuleContext
- walkPath []Module
- tagPath []blueprint.DependencyTag
+ walkPath []Module
+ proxyWalkPath []ModuleProxy
+ tagPath []blueprint.DependencyTag
strictVisitDeps bool // If true, enforce that all dependencies are enabled
}
-func getWrappedModule(module blueprint.Module) blueprint.Module {
- if mp, isProxy := module.(*ModuleProxy); isProxy {
- return mp.module
- }
- if mp, isProxy := module.(ModuleProxy); isProxy {
- return mp.module
- }
- return module
+func EqualModules(m1, m2 ModuleOrProxy) bool {
+ return blueprint.EqualModules(m1, m2)
}
-func EqualModules(m1, m2 Module) bool {
- return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
+func (b *baseModuleContext) OtherModuleName(m ModuleOrProxy) string {
+ return b.bp.OtherModuleName(m)
}
-
-func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
- return b.bp.OtherModuleName(getWrappedModule(m))
-}
-func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string {
- return b.bp.OtherModuleDir(getWrappedModule(m))
+func (b *baseModuleContext) OtherModuleDir(m ModuleOrProxy) string {
+ return b.bp.OtherModuleDir(m)
}
-func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
- b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
+func (b *baseModuleContext) OtherModuleErrorf(m ModuleOrProxy, fmt string, args ...interface{}) {
+ b.bp.OtherModuleErrorf(m, fmt, args...)
}
-func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
- return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
+func (b *baseModuleContext) OtherModuleDependencyTag(m ModuleOrProxy) blueprint.DependencyTag {
+ return b.bp.OtherModuleDependencyTag(m)
}
-func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string {
- return b.bp.OtherModuleSubDir(getWrappedModule(m))
+func (b *baseModuleContext) OtherModuleSubDir(m ModuleOrProxy) string {
+ return b.bp.OtherModuleSubDir(m)
}
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
@@ -298,19 +276,19 @@ func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []b
func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
return b.bp.OtherModuleReverseDependencyVariantExists(name)
}
-func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
- return b.bp.OtherModuleType(getWrappedModule(m))
+func (b *baseModuleContext) OtherModuleType(m ModuleOrProxy) string {
+ return b.bp.OtherModuleType(m)
}
-func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
- return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
+func (b *baseModuleContext) otherModuleProvider(m ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool) {
+ return b.bp.OtherModuleProvider(m, provider)
}
-func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
- return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
+func (b *baseModuleContext) OtherModuleHasProvider(m ModuleOrProxy, provider blueprint.AnyProviderKey) bool {
+ return b.bp.OtherModuleHasProvider(m, provider)
}
-func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
+func (b *baseModuleContext) OtherModuleIsAutoGenerated(m ModuleOrProxy) bool {
return b.bp.OtherModuleIsAutoGenerated(m)
}
@@ -329,11 +307,11 @@ func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.Depen
return nil
}
-func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
- if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
- return &ModuleProxy{*module}
+func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) ModuleProxy {
+ if module := b.bp.GetDirectDepProxyWithTag(name, tag); !module.IsNil() {
+ return ModuleProxy{module}
}
- return nil
+ return ModuleProxy{}
}
func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
@@ -403,11 +381,11 @@ func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag b
}
func (b *baseModuleContext) validateAndroidModuleProxy(
- module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
- aModule := ModuleProxy{module: module}
+ module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) ModuleProxy {
+ aModule := ModuleProxy{module}
if !strict {
- return &aModule
+ return aModule
}
if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled {
@@ -418,10 +396,10 @@ func (b *baseModuleContext) validateAndroidModuleProxy(
b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
}
}
- return nil
+ return ModuleProxy{}
}
- return &aModule
+ return aModule
}
func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
@@ -480,8 +458,8 @@ func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) {
b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
- if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- visit(*aModule)
+ if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); !aModule.IsNil() {
+ visit(aModule)
}
})
}
@@ -503,8 +481,8 @@ func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag,
func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
if b.bp.OtherModuleDependencyTag(module) == tag {
- if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
- visit(*aModule)
+ if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); !aModule.IsNil() {
+ visit(aModule)
}
}
})
@@ -526,32 +504,9 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func
})
}
-func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
- b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- visit(aModule)
- }
- })
-}
-
-func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
- b.bp.VisitDepsDepthFirstIf(
- // pred
- func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- return pred(aModule)
- } else {
- return false
- }
- },
- // visit
- func(module blueprint.Module) {
- visit(module.(Module))
- })
-}
-
func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
b.walkPath = []Module{b.Module()}
+ b.proxyWalkPath = nil
b.tagPath = []blueprint.DependencyTag{}
b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
childAndroidModule, _ := child.(Module)
@@ -569,52 +524,56 @@ func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
return false
}
})
+ b.walkPath = nil
}
func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
- b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
+ startProxy := blueprint.CreateModuleProxy(b.Module())
+ b.proxyWalkPath = []ModuleProxy{{startProxy}}
+ b.walkPath = nil
b.tagPath = []blueprint.DependencyTag{}
b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
childAndroidModule := ModuleProxy{child}
parentAndroidModule := ModuleProxy{parent}
// record walkPath before visit
- for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
- b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
+ for b.proxyWalkPath[len(b.proxyWalkPath)-1] != parentAndroidModule {
+ b.proxyWalkPath = b.proxyWalkPath[0 : len(b.proxyWalkPath)-1]
b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
}
- b.walkPath = append(b.walkPath, childAndroidModule)
+ b.proxyWalkPath = append(b.proxyWalkPath, childAndroidModule)
b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
return visit(childAndroidModule, parentAndroidModule)
})
+ b.proxyWalkPath = nil
}
func (b *baseModuleContext) GetWalkPath() []Module {
+ if b.walkPath == nil {
+ panic("GetWalkPath called from outside WalkDeps, did you mean GetProxyWalkPath?")
+ }
return slices.Clone(b.walkPath)
}
-func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
- return b.tagPath
-}
-
-func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
- b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
- visit(module.(Module))
- })
+func (b *baseModuleContext) GetProxyWalkPath() []ModuleProxy {
+ if b.proxyWalkPath == nil {
+ panic("GetProxyWalkPath called from outside WalkDeps, did you mean GetWalkPath?")
+ }
+ return slices.Clone(b.proxyWalkPath)
}
-func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
- b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
+func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
+ return b.tagPath
}
func (b *baseModuleContext) PrimaryModule() Module {
return b.bp.PrimaryModule().(Module)
}
-func (b *baseModuleContext) FinalModule() Module {
- return b.bp.FinalModule().(Module)
+func (b *baseModuleContext) IsPrimaryModule(module ModuleOrProxy) bool {
+ return b.bp.IsPrimaryModule(module)
}
-func (b *baseModuleContext) IsFinalModule(module Module) bool {
+func (b *baseModuleContext) IsFinalModule(module ModuleOrProxy) bool {
return b.bp.IsFinalModule(module)
}
@@ -653,7 +612,18 @@ func PrettyPrintTag(tag blueprint.DependencyTag) string {
func (b *baseModuleContext) GetPathString(skipFirst bool) string {
sb := strings.Builder{}
tagPath := b.GetTagPath()
- walkPath := b.GetWalkPath()
+ var walkPath []ModuleOrProxy
+ if b.walkPath != nil {
+ for _, w := range b.walkPath {
+ walkPath = append(walkPath, w)
+ }
+ } else if b.proxyWalkPath != nil {
+ for _, w := range b.proxyWalkPath {
+ walkPath = append(walkPath, w)
+ }
+ } else {
+ panic(fmt.Errorf("GetPathString must be called inside WalkDeps or WalkDepsProxy"))
+ }
if !skipFirst {
sb.WriteString(walkPath[0].String())
}
diff --git a/android/build_prop.go b/android/build_prop.go
index 2f71bc03f..59f11655b 100644
--- a/android/build_prop.go
+++ b/android/build_prop.go
@@ -142,14 +142,11 @@ func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx))
- // shouldn't depend on BuildFingerprintFile and BuildThumbprintFile to prevent from rebuilding
- // on every incremental build.
- cmd.FlagWithArg("--build-fingerprint-file=", config.BuildFingerprintFile(ctx).String())
+ cmd.FlagWithInput("--build-fingerprint-file=", config.BuildFingerprintFile(ctx))
// Export build thumbprint only if the product has specified at least one oem fingerprint property
// b/17888863
if shouldAddBuildThumbprint(config) {
- // In the previous make implementation, a dependency was not added on the thumbprint file
- cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
+ cmd.FlagWithInput("--build-thumbprint-file=", config.BuildThumbprintFile(ctx))
}
cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
// shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental
diff --git a/android/cipd/Android.bp b/android/cipd/Android.bp
new file mode 100644
index 000000000..ee34243ad
--- /dev/null
+++ b/android/cipd/Android.bp
@@ -0,0 +1,19 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-android-cipd",
+ pkgPath: "android/soong/android/cipd",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "cipd.go",
+ ],
+ testSrcs: [
+ "cipd_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/android/cipd/cipd.go b/android/cipd/cipd.go
new file mode 100644
index 000000000..305381170
--- /dev/null
+++ b/android/cipd/cipd.go
@@ -0,0 +1,147 @@
+// Copyright 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cipd
+
+import (
+ "fmt"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterCipdComponents(android.InitRegistrationContext)
+}
+
+func RegisterCipdComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cipd_package", cipdPackageFactory)
+}
+
+var (
+ pctx = android.NewPackageContext("android/cipd")
+
+ PrebuiltOS = pctx.VariableConfigMethod("PrebuiltOS", android.Config.PrebuiltOS)
+ _ = pctx.SourcePathVariable("cipd", "prebuilts/cipd/${PrebuiltOS}/cipd")
+ soong_zip = pctx.HostBinToolVariable("soong_zip", "soong_zip")
+
+ // CIPD can be expensive for network and disk i/o, so limit the number of concurrent
+ // fetches.
+ cipdPool = pctx.StaticPool("cipdPool", blueprint.PoolParams{
+ Depth: 8,
+ })
+ // cipd will proxy its requests out of the build sandbox using the unix domain socket
+ // set up in build/soong/ui/build/cipd.go.
+ cipdExportRule = pctx.AndroidStaticRule("cipd_export",
+ blueprint.RuleParams{
+ Command: "rm -rf $root && $cipd export -ensure-file $in -root $root",
+ CommandDeps: []string{"$cipd"},
+ Pool: cipdPool,
+ }, "root",
+ )
+
+ soongZipFromDirRule = pctx.AndroidStaticRule("soong_zip_from_dir",
+ blueprint.RuleParams{
+ Command: "rm -rf $tempZipDir && " +
+ "$cipd export -ensure-file $in -root $tempZipDir && " +
+ "$soong_zip -write_if_changed -o $out -C $tempZipDir -D $tempZipDir && " +
+ "rm -rf $tempZipDir",
+ CommandDeps: []string{"$cipd", "$soong_zip"},
+ Pool: cipdPool,
+ Restat: true,
+ }, "tempZipDir",
+ )
+)
+
+type cipdPackageProperties struct {
+ // The name of the cipd package, like "android/prebuilts/GmsCorePrebuilt/arm64"
+ Package string
+
+ // The version tag of the package.
+ Version proptools.Configurable[string]
+
+ // A file containing pinned cipd instance ids. It must contain the package version
+ // specified.
+ Resolved_versions_file string `android:"path"`
+
+ // The files expected to exist in the CIPD package.
+ Files []string
+}
+
+type cipdPackageModule struct {
+ android.ModuleBase
+
+ properties cipdPackageProperties
+}
+
+func (p *cipdPackageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ensureFile := android.PathForModuleOut(ctx, "ensure.txt")
+ outPath := android.PathForModuleOut(ctx, "package")
+
+ // The resolved versions file should be relative to the ensure file, so
+ // copy it to the output directory as well.
+ const resolvedVersionsTxt = "resolved_versions.txt"
+ resolvedVersionsFile := android.PathForModuleOut(ctx, resolvedVersionsTxt)
+ android.CopyFileRule(ctx,
+ android.PathForModuleSrc(ctx, p.properties.Resolved_versions_file),
+ resolvedVersionsFile.OutputPath)
+
+ ensureContents := fmt.Sprintf("$ResolvedVersions %s\n", resolvedVersionsTxt)
+ version := p.properties.Version.Get(ctx)
+ ensureContents += fmt.Sprintf("%s %s\n", p.properties.Package, version.Get())
+ android.WriteFileRule(ctx, ensureFile, ensureContents)
+
+ if len(p.properties.Files) > 0 {
+ outFiles := make(android.WritablePaths, len(p.properties.Files))
+ for i, f := range p.properties.Files {
+ outFiles[i] = outPath.Join(ctx, f)
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: cipdExportRule,
+ Input: ensureFile,
+ Outputs: outFiles,
+ Implicit: resolvedVersionsFile,
+ Args: map[string]string{
+ "root": outPath.String(),
+ },
+ })
+ ctx.SetOutputFiles(outFiles.Paths(), "")
+ }
+
+ outputZipFile := android.PathForModuleOut(ctx, "package.zip")
+ tempZipDir := android.PathForModuleOut(ctx, "zip_temp_pkg_dir")
+ // This rule runs `cipd export` (potentially again) to ensure the zip is
+ // creatabled regardless of whether individual files are also requested.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: soongZipFromDirRule,
+ Input: ensureFile,
+ Output: outputZipFile,
+ Implicit: resolvedVersionsFile,
+ Args: map[string]string{
+ "tempZipDir": tempZipDir.String(),
+ },
+ })
+ ctx.SetOutputFiles(android.Paths{outputZipFile}, "zip")
+}
+
+// cipd_package module installs the given CIPD package version.
+func cipdPackageFactory() android.Module {
+ module := &cipdPackageModule{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ return module
+}
diff --git a/android/cipd/cipd_test.go b/android/cipd/cipd_test.go
new file mode 100644
index 000000000..1d6dee6cc
--- /dev/null
+++ b/android/cipd/cipd_test.go
@@ -0,0 +1,101 @@
+// Copyright 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cipd
+
+import (
+ "android/soong/android"
+ "slices"
+ "testing"
+)
+
+func TestCipdPackage(t *testing.T) {
+ bp := `
+ cipd_package {
+ name: "cipd_package1",
+ package: "android/prebuilts/package1",
+ version: "version1",
+ files: [
+ "package1_file1",
+ "package1_file2",
+ ],
+ resolved_versions_file: "cipd.versions",
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureRegisterWithContext(RegisterCipdComponents),
+ ).RunTestWithBp(t, bp)
+
+ module := result.ModuleForTests(t, "cipd_package1", "")
+ export := module.Rule("cipd_export")
+
+ intermediateDir := "out/soong/.intermediates/cipd_package1"
+ wantEnsureFile := intermediateDir + "/ensure.txt"
+ if export.Input.String() != wantEnsureFile {
+ t.Errorf("export.Input.String() = %v, want %v", export.Input.String(), wantEnsureFile)
+ }
+ if len(export.Inputs) != 0 {
+ t.Errorf("len(export.Inputs) = %v, want 0", len(export.Inputs))
+ }
+
+ wantRoot := intermediateDir + "/package"
+ wantExportOutputs := []string{
+ wantRoot + "/package1_file1",
+ wantRoot + "/package1_file2",
+ }
+
+ var gotExportOutputs []string
+ for _, output := range export.Outputs {
+ gotExportOutputs = append(gotExportOutputs, output.String())
+ }
+ if !slices.Equal(wantExportOutputs, gotExportOutputs) {
+ t.Errorf("export.Outputs = %v, want %v", gotExportOutputs, wantExportOutputs)
+ }
+ if export.Output != nil {
+ t.Errorf("export.Output = %v, want nil", export.Output)
+ }
+ if export.Args["root"] != wantRoot {
+ t.Errorf("export.Args{\"root\"] = %v, want %v", export.Args["root"], wantRoot)
+ }
+ if len(export.Args) != 1 {
+ t.Errorf("len(export.Args) = %v, want 1", len(export.Args))
+ }
+
+ zipRule := module.Rule("soong_zip_from_dir")
+ wantZipFile := intermediateDir + "/package.zip"
+ if zipRule.Output.String() != wantZipFile {
+ t.Errorf("zipRule.Output = %q, want %q", zipRule.Output.String(), wantZipFile)
+ }
+
+ if zipRule.Input.String() != wantEnsureFile {
+ t.Errorf("zipRule.Input.String() = %q, want %q", zipRule.Input.String(), wantEnsureFile)
+ }
+ if len(zipRule.Args) != 1 {
+ t.Fatalf("len(zipRule.Args) = %v, want 1 (was %v)", len(zipRule.Args), zipRule.Args)
+ }
+ wantTempZipDir := intermediateDir + "/zip_temp_pkg_dir"
+ if zipRule.Args["tempZipDir"] != wantTempZipDir {
+ t.Errorf("zipRule.Args[\"tempZipDir\"] = %q, want %q", zipRule.Args["tempZipDir"], wantTempZipDir)
+ }
+
+ zipTaggedOutputs := module.OutputFiles(result.TestContext, t, "zip")
+ if len(zipTaggedOutputs) != 1 {
+ t.Errorf("len(module.OutputFiles(..., \"zip\")) = %d, want 1", len(zipTaggedOutputs))
+ }
+ if val := zipTaggedOutputs[0].String(); val != wantZipFile {
+ t.Errorf("module.OutputFiles(..., \"zip\")[0] = %q, want %q", val, wantZipFile)
+ }
+}
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 16a385300..0ec9f9594 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -25,9 +25,10 @@ import (
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/gobtools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
// Constants of property names used in compliance metadata of modules
ComplianceMetadataProp = struct {
@@ -128,48 +129,27 @@ var (
// ComplianceMetadataInfo provides all metadata of a module, e.g. name, module type, package, license,
// dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility
// methods to get/set properties' values.
+// @auto-generate: gob
type ComplianceMetadataInfo struct {
- properties map[string]string
- filesContained []string
- prebuiltFilesCopied []string
-}
-
-type complianceMetadataInfoGob struct {
- Properties map[string]string
- FilesContained []string
- PrebuiltFilesCopied []string
+ properties map[string]string
+ filesContained []string
+ prebuiltFilesCopied []string
+ platformGeneratedFiles []string
+ productCopyFiles []string
+ kernelModuleCopyFiles []string
}
func NewComplianceMetadataInfo() *ComplianceMetadataInfo {
return &ComplianceMetadataInfo{
- properties: map[string]string{},
- filesContained: make([]string, 0),
- prebuiltFilesCopied: make([]string, 0),
- }
-}
-
-func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
- return &complianceMetadataInfoGob{
- Properties: m.properties,
- FilesContained: m.filesContained,
- PrebuiltFilesCopied: m.prebuiltFilesCopied,
+ properties: map[string]string{},
+ filesContained: make([]string, 0),
+ prebuiltFilesCopied: make([]string, 0),
+ platformGeneratedFiles: make([]string, 0),
+ kernelModuleCopyFiles: make([]string, 0),
+ productCopyFiles: make([]string, 0),
}
}
-func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) {
- m.properties = data.Properties
- m.filesContained = data.FilesContained
- m.prebuiltFilesCopied = data.PrebuiltFilesCopied
-}
-
-func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[complianceMetadataInfoGob](c)
-}
-
-func (c *ComplianceMetadataInfo) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[complianceMetadataInfoGob](data, c)
-}
-
func (c *ComplianceMetadataInfo) SetStringValue(propertyName string, value string) {
if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -197,6 +177,30 @@ func (c *ComplianceMetadataInfo) GetPrebuiltFilesCopied() []string {
return c.prebuiltFilesCopied
}
+func (c *ComplianceMetadataInfo) SetPlatformGeneratedFiles(files []string) {
+ c.platformGeneratedFiles = files
+}
+
+func (c *ComplianceMetadataInfo) GetPlatformGeneratedFiles() []string {
+ return c.platformGeneratedFiles
+}
+
+func (c *ComplianceMetadataInfo) SetProductCopyFiles(files []string) {
+ c.productCopyFiles = files
+}
+
+func (c *ComplianceMetadataInfo) GetProductCopyFiles() []string {
+ return c.productCopyFiles
+}
+
+func (c *ComplianceMetadataInfo) SetKernelModuleCopyFiles(files []string) {
+ c.kernelModuleCopyFiles = files
+}
+
+func (c *ComplianceMetadataInfo) GetKernelModuleCopyFiles() []string {
+ return c.kernelModuleCopyFiles
+}
+
func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string {
if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -246,6 +250,20 @@ func buildComplianceMetadataProvider(ctx *moduleContext, m *ModuleBase) {
installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
installed = append(installed, ctx.katiInitRcInstalls.InstallPaths()...)
installed = append(installed, ctx.katiVintfInstalls.InstallPaths()...)
+ // The following module types use PackageFiles instead of InstallFiles so here we need to
+ // collect the fullInstallPaths from the packagingSpecs.
+ // TODO: b/409854522
+ if strings.HasPrefix(ctx.ModuleType(), "sdk_library_internal") ||
+ ctx.ModuleType() == "bpf" ||
+ ctx.ModuleType() == "libbpf_prog" ||
+ ctx.ModuleType() == "avbpubkey__loadHookModule" ||
+ (ctx.ModuleType() == "prebuilt_etc" &&
+ slices.Contains([]string{"preloaded-classes", "public.libraries.android.txt"}, ctx.ModuleName())) ||
+ (ctx.ModuleType() == "prebuilt_root" && ctx.ModuleName() == "init.environ.rc-soong") {
+ for _, s := range ctx.packagingSpecs {
+ installed = append(installed, s.fullInstallPath)
+ }
+ }
complianceMetadataInfo.SetListValue(ComplianceMetadataProp.INSTALLED_FILES, FirstUniqueStrings(installed.Strings()))
}
ctx.setProvider(ComplianceMetadataProvider, complianceMetadataInfo)
@@ -361,6 +379,18 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext)
}
sort.Strings(allFiles)
+ destToKernelModuleMap := make(map[string]string)
+ for _, p := range metadataInfo.GetKernelModuleCopyFiles() {
+ pair := strings.Split(p, "::")
+ destToKernelModuleMap[pair[1]] = p
+ }
+
+ destToProductCopyFiles := make(map[string]string)
+ for _, pcf := range metadataInfo.GetProductCopyFiles() {
+ pair := strings.Split(pcf, ":")
+ destToProductCopyFiles[pair[1]] = pcf
+ }
+
csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text"
csvContent := make([]string, 0, len(allFiles)+1)
csvContent = append(csvContent, csvHeaders)
@@ -368,6 +398,12 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext)
if _, ok := prebuiltFilesSrcDest[file]; ok {
srcDestPair := prebuiltFilesSrcDest[file]
csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,")
+ } else if slices.Contains(metadataInfo.platformGeneratedFiles, file) {
+ csvContent = append(csvContent, file+",,,,,,Y,,,build/soong/licenses/LICENSE")
+ } else if km, ok := destToKernelModuleMap[file]; ok {
+ csvContent = append(csvContent, file+",,,,,"+km+",,,,")
+ } else if p, ok := destToProductCopyFiles[file]; ok {
+ csvContent = append(csvContent, file+",,,,"+p+",,,,,")
} else {
csvContent = append(csvContent, file+",,Y,,,,,,,")
}
diff --git a/android/compliance_metadata_gob_enc.go b/android/compliance_metadata_gob_enc.go
new file mode 100644
index 000000000..ef60c6b85
--- /dev/null
+++ b/android/compliance_metadata_gob_enc.go
@@ -0,0 +1,183 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ComplianceMetadataInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ComplianceMetadataInfo) })
+}
+
+func (r ComplianceMetadataInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.properties))); err != nil {
+ return err
+ }
+ for k, v := range r.properties {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeString(buf, v); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.filesContained))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.filesContained); val1++ {
+ if err = gobtools.EncodeString(buf, r.filesContained[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.prebuiltFilesCopied))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.prebuiltFilesCopied); val2++ {
+ if err = gobtools.EncodeString(buf, r.prebuiltFilesCopied[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.platformGeneratedFiles))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.platformGeneratedFiles); val3++ {
+ if err = gobtools.EncodeString(buf, r.platformGeneratedFiles[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.productCopyFiles))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.productCopyFiles); val4++ {
+ if err = gobtools.EncodeString(buf, r.productCopyFiles[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.kernelModuleCopyFiles))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.kernelModuleCopyFiles); val5++ {
+ if err = gobtools.EncodeString(buf, r.kernelModuleCopyFiles[val5]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *ComplianceMetadataInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val1 int32
+ err = gobtools.DecodeSimple[int32](buf, &val1)
+ if err != nil {
+ return err
+ }
+ if val1 > 0 {
+ r.properties = make(map[string]string, val1)
+ for val2 := 0; val2 < int(val1); val2++ {
+ var k string
+ var v string
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ err = gobtools.DecodeString(buf, &v)
+ if err != nil {
+ return err
+ }
+ r.properties[k] = v
+ }
+ }
+
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ r.filesContained = make([]string, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ err = gobtools.DecodeString(buf, &r.filesContained[val7])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val10 int32
+ err = gobtools.DecodeSimple[int32](buf, &val10)
+ if err != nil {
+ return err
+ }
+ if val10 > 0 {
+ r.prebuiltFilesCopied = make([]string, val10)
+ for val11 := 0; val11 < int(val10); val11++ {
+ err = gobtools.DecodeString(buf, &r.prebuiltFilesCopied[val11])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val14 int32
+ err = gobtools.DecodeSimple[int32](buf, &val14)
+ if err != nil {
+ return err
+ }
+ if val14 > 0 {
+ r.platformGeneratedFiles = make([]string, val14)
+ for val15 := 0; val15 < int(val14); val15++ {
+ err = gobtools.DecodeString(buf, &r.platformGeneratedFiles[val15])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val18 int32
+ err = gobtools.DecodeSimple[int32](buf, &val18)
+ if err != nil {
+ return err
+ }
+ if val18 > 0 {
+ r.productCopyFiles = make([]string, val18)
+ for val19 := 0; val19 < int(val18); val19++ {
+ err = gobtools.DecodeString(buf, &r.productCopyFiles[val19])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val22 int32
+ err = gobtools.DecodeSimple[int32](buf, &val22)
+ if err != nil {
+ return err
+ }
+ if val22 > 0 {
+ r.kernelModuleCopyFiles = make([]string, val22)
+ for val23 := 0; val23 < int(val22); val23++ {
+ err = gobtools.DecodeString(buf, &r.kernelModuleCopyFiles[val23])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var ComplianceMetadataInfoGobRegId int16
+
+func (r ComplianceMetadataInfo) GetTypeId() int16 {
+ return ComplianceMetadataInfoGobRegId
+}
diff --git a/android/config.go b/android/config.go
index 3d95ab59a..fc4e2900b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -29,8 +29,6 @@ import (
"sync"
"unicode"
- "android/soong/shared"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
@@ -38,6 +36,7 @@ import (
"android/soong/android/soongconfig"
"android/soong/remoteexec"
+ "android/soong/shared"
)
// Bool re-exports proptools.Bool for the android package.
@@ -86,9 +85,7 @@ type CmdArgs struct {
SoongVariables string
KatiSuffix string
- ModuleGraphFile string
- ModuleActionsFile string
- DocFile string
+ DocFile string
BuildFromSourceStub bool
@@ -100,9 +97,6 @@ const (
// Don't use bazel at all during module analysis.
AnalysisNoBazel SoongBuildMode = iota
- // Create a JSON representation of the module graph and exit.
- GenerateModuleGraph
-
// Generate a documentation file for module type definitions and exit.
GenerateDocFile
)
@@ -110,7 +104,7 @@ const (
const testKeyDir = "build/make/target/product/security"
func (c Config) genericConfig() Config {
- return Config{c.config.genericConfig}
+ return Config{c.config.genericConfigField}
}
// SoongOutDir returns the build output directory for the configuration.
@@ -143,6 +137,8 @@ func (c Config) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation
return []bootstrap.PrimaryBuilderInvocation{}
}
+func (c Config) IsBootstrap() bool { return false }
+
// RunningInsideUnitTest returns true if this code is being run as part of a Soong unit test.
func (c Config) RunningInsideUnitTest() bool {
return c.config.TestProductVariables != nil
@@ -272,21 +268,12 @@ func (c Config) ReleaseNdkAbiMonitored() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED")
}
-// Enable read flag from new storage, for C/C++
-func (c Config) ReleaseReadFromNewStorageCc() bool {
- return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE_CC")
-}
-
func (c Config) ReleaseHiddenApiExportableStubs() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_HIDDEN_API_EXPORTABLE_STUBS") ||
Bool(c.config.productVariables.HiddenapiExportableStubs)
}
// Enable read flag from new storage
-func (c Config) ReleaseReadFromNewStorage() bool {
- return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE")
-}
-
func (c Config) ReleaseCreateAconfigStorageFile() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_CREATE_ACONFIG_STORAGE_FILE")
}
@@ -295,12 +282,42 @@ func (c Config) ReleaseUseSystemFeatureBuildFlags() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS")
}
-func (c Config) ReleaseFingerprintAconfigPackages() bool {
- return c.config.productVariables.GetBuildFlagBool("RELEASE_FINGERPRINT_ACONFIG_PACKAGES")
+func (c Config) ReleaseUseSystemFeatureXmlForUnavailableFeatures() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_XML_FOR_UNAVAILABLE_FEATURES")
+}
+
+func (c Config) ReleaseRustUseArmTargetArchVariant() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_RUST_USE_ARM_TARGET_ARCH_VARIANT")
}
-func (c Config) ReleaseAconfigCheckApiLevel() bool {
- return c.config.productVariables.GetBuildFlagBool("RELEASE_ACONFIG_CHECK_API_LEVEL")
+func (c Config) ReleaseUseSparseEncoding() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_SOONG_SPARSE_ENCODING")
+}
+
+func (c Config) ReleaseUseUncompressedFonts() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_SOONG_UNCOMPRESSED_FONTS")
+}
+
+func (c Config) ReleaseAconfigStorageVersion() string {
+ if val, exists := c.GetBuildFlag("RELEASE_ACONFIG_STORAGE_VERSION"); exists {
+ return val
+ } else {
+ // Default value is 2.
+ return "2"
+ }
+}
+
+// TODO: b/414412266 Remove this flag after feature released.
+func (c Config) ReleaseJarjarFlagsInFramework() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_JARJAR_FLAGS_IN_FRAMEWORK")
+}
+
+func (c Config) ReleaseMainlineBetaNamespaceConfig() string {
+ if val, exists := c.GetBuildFlag("RELEASE_MAINLINE_BETA_NAMESPACE_CONFIG"); exists {
+ return val
+ } else {
+ return ""
+ }
}
// A DeviceConfig object represents the configuration for a particular device
@@ -397,20 +414,31 @@ type config struct {
// Copy of this config struct but some product-specific variables are
// replaced with the generic configuration values.
- genericConfig *config
+ genericConfigField *config
+
+ // modulesForTests stores the list of modules that exist during Soong tests. It is nil
+ // when not running Soong tests.
+ modulesForTests *modulesForTests
}
type partialCompileFlags struct {
// Whether to use d8 instead of r8
Use_d8 bool
- // Whether to disable stub validation. This is slightly more surgical
- // than DISABLE_STUB_VALIDATION, in that it only applies to partial
- // compile builds.
+ // Whether to disable stub validation for partial compile builds.
+ // This is similar to setting `DISABLE_STUB_VALIDATION=true`: the
+ // validation checks are still created, but are not run by default.
+ // To run the validation checks, use `m {MODULE_NAME}-stub-validation`.
Disable_stub_validation bool
- // Whether to disable api lint.
- Disable_api_lint bool
+ // Whether to enable incremental java compilation.
+ Enable_inc_javac bool
+
+ // Whether to use the kotlin-incremental-client when compiling .kt files.
+ Enable_inc_kotlin bool
+
+ // Whether to enable incremental d8
+ Enable_inc_d8 bool
// Add others as needed.
}
@@ -421,8 +449,19 @@ var defaultPartialCompileFlags = partialCompileFlags{}
// These are the flags when `SOONG_PARTIAL_COMPILE=true`.
var enabledPartialCompileFlags = partialCompileFlags{
Use_d8: true,
- Disable_stub_validation: false,
- Disable_api_lint: false,
+ Disable_stub_validation: true,
+ Enable_inc_kotlin: false,
+ Enable_inc_javac: true,
+ Enable_inc_d8: true,
+}
+
+// These are the flags when `SOONG_PARTIAL_COMPILE=all`.
+var allPartialCompileFlags = partialCompileFlags{
+ Use_d8: true,
+ Disable_stub_validation: true,
+ Enable_inc_javac: true,
+ Enable_inc_kotlin: false,
+ Enable_inc_d8: true,
}
type deviceConfig struct {
@@ -497,23 +536,29 @@ func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags,
state = "+"
}
switch tok {
- case "all":
- // Turn on **all** of the flags.
- ret = partialCompileFlags{
- Use_d8: true,
- Disable_stub_validation: true,
- Disable_api_lint: true,
- }
- case "true":
- ret = enabledPartialCompileFlags
+ // Big toggle switches.
case "false":
- // Set everything to false.
ret = partialCompileFlags{}
+ case "true":
+ ret = enabledPartialCompileFlags
+ case "all":
+ ret = allPartialCompileFlags
+
+ // Individual flags.
+ case "inc_d8", "enable_inc_d8":
+ ret.Enable_inc_d8 = makeVal(state, !defaultPartialCompileFlags.Enable_inc_d8)
+ case "disable_inc_d8":
+ ret.Enable_inc_d8 = !makeVal(state, defaultPartialCompileFlags.Enable_inc_d8)
+
+ case "inc_javac", "enable_inc_javac":
+ ret.Enable_inc_javac = makeVal(state, !defaultPartialCompileFlags.Enable_inc_javac)
+ case "disable_inc_javac":
+ ret.Enable_inc_javac = !makeVal(state, defaultPartialCompileFlags.Enable_inc_javac)
- case "api_lint", "enable_api_lint":
- ret.Disable_api_lint = !makeVal(state, !defaultPartialCompileFlags.Disable_api_lint)
- case "disable_api_lint":
- ret.Disable_api_lint = makeVal(state, defaultPartialCompileFlags.Disable_api_lint)
+ case "inc_kotlin", "enable_inc_kotlin":
+ ret.Enable_inc_kotlin = makeVal(state, defaultPartialCompileFlags.Enable_inc_kotlin)
+ case "disable_inc_kotlin":
+ ret.Enable_inc_kotlin = !makeVal(state, defaultPartialCompileFlags.Enable_inc_kotlin)
case "stub_validation", "enable_stub_validation":
ret.Disable_stub_validation = !makeVal(state, !defaultPartialCompileFlags.Disable_stub_validation)
@@ -522,6 +567,7 @@ func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags,
case "use_d8":
ret.Use_d8 = makeVal(state, defaultPartialCompileFlags.Use_d8)
+
default:
return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", tok)
}
@@ -771,7 +817,6 @@ func initConfig(cmdArgs CmdArgs, availableEnv map[string]string) (*config, error
newConfig.BuildMode = mode
}
}
- setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
setBuildMode(cmdArgs.DocFile, GenerateDocFile)
newConfig.productVariables.Build_from_text_stub = boolPtr(newConfig.BuildFromTextStub())
@@ -785,9 +830,9 @@ func initConfig(cmdArgs CmdArgs, availableEnv map[string]string) (*config, error
// A generic tag may have a string or an int value for the generic configuration.
// If the value is "unset", generic configuration will unset the variable.
func overrideGenericConfig(config *config) {
- config.genericConfig.isGeneric = true
- type_pv := reflect.TypeOf(config.genericConfig.productVariables)
- value_pv := reflect.ValueOf(&config.genericConfig.productVariables)
+ config.genericConfigField.isGeneric = true
+ type_pv := reflect.TypeOf(config.genericConfigField.productVariables)
+ value_pv := reflect.ValueOf(&config.genericConfigField.productVariables)
for i := range type_pv.NumField() {
type_pv_field := type_pv.Field(i)
generic_value := type_pv_field.Tag.Get("generic")
@@ -833,9 +878,9 @@ func overrideGenericConfig(config *config) {
}
// OncePer must be a singleton.
- config.genericConfig.OncePer = config.OncePer
+ config.genericConfigField.OncePer = config.OncePer
// keep the device name to get the install path.
- config.genericConfig.deviceNameToInstall = config.deviceNameToInstall
+ config.genericConfigField.deviceNameToInstall = config.deviceNameToInstall
}
// NewConfig creates a new Config object. It also loads the config file, if
@@ -848,7 +893,7 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error)
}
// Initialize generic configuration.
- config.genericConfig, err = initConfig(cmdArgs, availableEnv)
+ config.genericConfigField, err = initConfig(cmdArgs, availableEnv)
// Update product specific variables with the generic configuration.
overrideGenericConfig(config)
@@ -1069,9 +1114,23 @@ func (c *config) BuildThumbprintFile(ctx PathContext) Path {
return PathForArbitraryOutput(ctx, "target", "product", *c.deviceNameToInstall, String(c.productVariables.BuildThumbprintFile))
}
+func (c *config) BuildDateFile(ctx PathContext) Path {
+ buildDateFile := c.Getenv("BUILD_DATETIME_FILE")
+ relPath, err := filepath.Rel(ctx.Config().OutDir(), buildDateFile)
+ if err != nil {
+ panic("build_date.txt is outside of OUT_DIR")
+ }
+ return PathForArbitraryOutput(ctx, relPath)
+}
+
// DeviceName returns the name of the current device target.
// TODO: take an AndroidModuleContext to select the device name for multi-device builds
func (c *config) DeviceName() string {
+ if c.isGeneric {
+ // The config is called from a context of a module which returns true
+ // from UseGenericConfig(). This is not allowed.
+ panic("The DeviceName() function cannot be called when using the generic configuration. To call DeviceName(), ensure the module's UseGenericConfig() function returns \"false\".")
+ }
return *c.productVariables.DeviceName
}
@@ -1080,6 +1139,11 @@ func (c *config) DeviceName() string {
//
// NOTE: Do not base conditional logic on this value. It may break product inheritance.
func (c *config) DeviceProduct() string {
+ if c.isGeneric {
+ // The config is called from a context of a module which returns true
+ // from UseGenericConfig(). This is not allowed.
+ panic("The DeviceProduct() function cannot be called when using the generic configuration. To call DeviceProduct(), ensure the module's UseGenericConfig() function returns \"false\".")
+ }
return *c.productVariables.DeviceProduct
}
@@ -1111,7 +1175,7 @@ func (c *config) PlatformVersionName() string {
}
func (c *config) PlatformSdkVersion() ApiLevel {
- return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
+ return UncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
}
func (c *config) PlatformSdkVersionFull() string {
@@ -1167,13 +1231,13 @@ func (c *config) PlatformVersionKnownCodenames() string {
}
func (c *config) MinSupportedSdkVersion() ApiLevel {
- return uncheckedFinalApiLevel(21)
+ return UncheckedFinalApiLevel(21)
}
func (c *config) FinalApiLevels() []ApiLevel {
var levels []ApiLevel
for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ {
- levels = append(levels, uncheckedFinalApiLevel(i))
+ levels = append(levels, UncheckedFinalApiLevel(i))
}
return levels
}
@@ -1353,7 +1417,13 @@ func (c *config) UnbundledBuild() bool {
// Returns true if building apps that aren't bundled with the platform.
// UnbundledBuild() is always true when this is true.
-func (c *config) UnbundledBuildApps() bool {
+func (c *config) UnbundledBuildApps() []string {
+ return c.productVariables.Unbundled_build_apps
+}
+
+// Returns true if building apps that aren't bundled with the platform.
+// UnbundledBuild() is always true when this is true.
+func (c *config) HasUnbundledBuildApps() bool {
return len(c.productVariables.Unbundled_build_apps) > 0
}
@@ -1430,10 +1500,6 @@ func (c *config) Android64() bool {
return false
}
-func (c *config) UseGoma() bool {
- return Bool(c.productVariables.UseGoma)
-}
-
func (c *config) UseABFS() bool {
return Bool(c.productVariables.UseABFS)
}
@@ -1455,7 +1521,7 @@ func (c *config) UseRBED8() bool {
}
func (c *config) UseRemoteBuild() bool {
- return c.UseGoma() || c.UseRBE()
+ return c.UseRBE()
}
func (c *config) RunErrorProne() bool {
@@ -1658,6 +1724,10 @@ func (c *config) katiPackageMkDir() string {
return filepath.Join(c.soongOutDir, "kati_packaging"+c.katiSuffix)
}
+func (c *config) DisableNoticeXmlGeneration() bool {
+ return c.IsEnvTrue("DISABLE_NOTICE_XML_GENERATION")
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -2001,7 +2071,7 @@ func (c *config) ForceApexSymlinkOptimization() bool {
}
func (c *config) ApexCompressionEnabled() bool {
- return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps()
+ return Bool(c.productVariables.CompressedApex) && !c.HasUnbundledBuildApps()
}
func (c *config) DefaultApexPayloadType() string {
@@ -2106,16 +2176,16 @@ func (c *deviceConfig) BoardSepolicyVers() string {
return c.PlatformSepolicyVersion()
}
-func (c *deviceConfig) SystemExtSepolicyPrebuiltApiDir() string {
- return String(c.config.productVariables.SystemExtSepolicyPrebuiltApiDir)
+func (c *deviceConfig) SystemExtSepolicyPrebuiltApiDirs() []string {
+ return c.config.productVariables.SystemExtSepolicyPrebuiltApiDirs
}
-func (c *deviceConfig) ProductSepolicyPrebuiltApiDir() string {
- return String(c.config.productVariables.ProductSepolicyPrebuiltApiDir)
+func (c *deviceConfig) ProductSepolicyPrebuiltApiDirs() []string {
+ return c.config.productVariables.ProductSepolicyPrebuiltApiDirs
}
func (c *deviceConfig) IsPartnerTrebleSepolicyTestEnabled() bool {
- return c.SystemExtSepolicyPrebuiltApiDir() != "" || c.ProductSepolicyPrebuiltApiDir() != ""
+ return len(c.SystemExtSepolicyPrebuiltApiDirs()) > 0 || len(c.ProductSepolicyPrebuiltApiDirs()) > 0
}
func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) {
@@ -2149,7 +2219,7 @@ func (c *deviceConfig) ShippingApiLevel() ApiLevel {
return NoneApiLevel
}
apiLevel, _ := strconv.Atoi(*c.config.productVariables.Shipping_api_level)
- return uncheckedFinalApiLevel(apiLevel)
+ return UncheckedFinalApiLevel(apiLevel)
}
func (c *deviceConfig) BuildBrokenPluginValidation() []string {
@@ -2196,14 +2266,6 @@ func (c *deviceConfig) BuildBrokenDupSysprop() bool {
return c.config.productVariables.BuildBrokenDupSysprop
}
-func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string {
- return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist
-}
-
-func (c *deviceConfig) GenruleSandboxing() bool {
- return Bool(c.config.productVariables.GenruleSandboxing)
-}
-
func (c *deviceConfig) RequiresInsecureExecmemForSwiftshader() bool {
return c.config.productVariables.RequiresInsecureExecmemForSwiftshader
}
@@ -2260,17 +2322,6 @@ func (c *config) UseHostMusl() bool {
return Bool(c.productVariables.HostMusl)
}
-// ApiSurfaces directory returns the source path inside the api_surfaces repo
-// (relative to workspace root).
-func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
- return filepath.Join(
- "build",
- "bazel",
- "api_surfaces",
- s.String(),
- version)
-}
-
func (c *config) JavaCoverageEnabled() bool {
return c.IsEnvTrue("EMMA_INSTRUMENT") || c.IsEnvTrue("EMMA_INSTRUMENT_STATIC") || c.IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
}
@@ -2302,6 +2353,10 @@ func (c *config) GetBuildFlag(name string) (string, bool) {
return val, ok
}
+func (c *config) GetBuildFlagBool(name string) bool {
+ return c.productVariables.GetBuildFlagBool(name)
+}
+
func (c *config) UseOptimizedResourceShrinkingByDefault() bool {
return c.productVariables.GetBuildFlagBool("RELEASE_USE_OPTIMIZED_RESOURCE_SHRINKING_BY_DEFAULT")
}
@@ -2404,17 +2459,19 @@ func (c *config) OemProperties() []string {
}
func (c *config) UseDebugArt() bool {
- // If the ArtTargetIncludeDebugBuild product variable is set then return its value.
- if c.productVariables.ArtTargetIncludeDebugBuild != nil {
- return Bool(c.productVariables.ArtTargetIncludeDebugBuild)
- }
-
// If the RELEASE_APEX_CONTRIBUTIONS_ART build flag is set to use a prebuilt ART apex
// then don't use the debug apex.
if val, ok := c.GetBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART"); ok && val != "" {
return false
}
+ // If the ArtTargetIncludeDebugBuild product variable is set then return its value.
+ // The prebuilt APEX check overrides this to be tolerant wrt build logic
+ // that sets PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD regardless of module source.
+ if c.productVariables.ArtTargetIncludeDebugBuild != nil {
+ return Bool(c.productVariables.ArtTargetIncludeDebugBuild)
+ }
+
// Default to the debug apex for eng builds.
return Bool(c.productVariables.Eng)
}
@@ -2486,6 +2543,27 @@ func (c *config) DeviceManifestFiles() []string {
return c.productVariables.DeviceManifestFiles
}
+func (c *config) DeviceManifestSkus() []string {
+ return c.productVariables.DeviceManifestSkus
+}
+
func (c *config) OdmManifestFiles() []string {
return c.productVariables.OdmManifestFiles
}
+
+func (c *config) OdmManifestSkus() []string {
+ return c.productVariables.OdmManifestSkus
+}
+
+func (c *config) EnforceSELinuxTrebleLabeling() bool {
+ return Bool(c.productVariables.EnforceSELinuxTrebleLabeling)
+}
+
+func (c *config) SELinuxTrebleLabelingTrackingListFile(ctx PathContext) Path {
+ path := String(c.productVariables.SELinuxTrebleLabelingTrackingListFile)
+ if path == "" {
+ return nil
+ }
+
+ return PathForSource(ctx, path)
+}
diff --git a/android/config_test.go b/android/config_test.go
index 81b7c3eb5..681f9e71b 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -218,13 +218,23 @@ func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags {
return p
}
-func (p partialCompileFlags) updateDisableApiLint(value bool) partialCompileFlags {
- p.Disable_api_lint = value
+func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags {
+ p.Disable_stub_validation = value
return p
}
-func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags {
- p.Disable_stub_validation = value
+func (p partialCompileFlags) updateEnableIncJavac(value bool) partialCompileFlags {
+ p.Enable_inc_javac = value
+ return p
+}
+
+func (p partialCompileFlags) updateEnableIncKotlin(value bool) partialCompileFlags {
+ p.Enable_inc_kotlin = value
+ return p
+}
+
+func (p partialCompileFlags) updateEnableIncD8(value bool) partialCompileFlags {
+ p.Enable_inc_d8 = value
return p
}
@@ -246,7 +256,7 @@ func TestPartialCompile(t *testing.T) {
{"false", true, partialCompileFlags{}},
{"true", true, enabledPartialCompileFlags},
{"true", false, partialCompileFlags{}},
- {"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableApiLint(true).updateDisableStubValidation(true)},
+ {"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableStubValidation(true).updateEnableIncJavac(true).updateEnableIncKotlin(false).updateEnableIncD8(true)},
// This verifies both use_d8 and the processing order.
{"true,use_d8", true, enabledPartialCompileFlags.updateUseD8(true)},
@@ -254,14 +264,6 @@ func TestPartialCompile(t *testing.T) {
{"use_d8,false", true, partialCompileFlags{}},
{"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)},
- // disable_api_lint can be specified with any of 3 options.
- {"false,-api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
- {"false,-enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
- {"false,+disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
- {"false,+api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
- {"false,+enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
- {"false,-disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
-
// disable_stub_validation can be specified with any of 3 options.
{"false,-stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
{"false,-enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
@@ -269,6 +271,30 @@ func TestPartialCompile(t *testing.T) {
{"false,+stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
{"false,+enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
{"false,-disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
+
+ // enable_inc_javac can be specified with any of 3 options.
+ {"false,-inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(false)},
+ {"false,-enable_inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(false)},
+ {"false,+disable_inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(false)},
+ {"false,+inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(true)},
+ {"false,+enable_inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(true)},
+ {"false,-disable_inc_javac", true, partialCompileFlags{}.updateEnableIncJavac(true)},
+
+ // enable_inc_kotlin can be specified with any of 3 options.
+ {"false,-inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(false)},
+ {"false,-enable_inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(false)},
+ {"false,+disable_inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(false)},
+ {"false,+inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(true)},
+ {"false,+enable_inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(true)},
+ {"false,-disable_inc_kotlin", true, partialCompileFlags{}.updateEnableIncKotlin(true)},
+
+ // enable_inc_d8 can be specified with any of 3 options.
+ {"false,-inc_d8", true, partialCompileFlags{}.updateEnableIncD8(false)},
+ {"false,-enable_inc_d8", true, partialCompileFlags{}.updateEnableIncD8(false)},
+ {"false,+disable_inc_d8", true, partialCompileFlags{}.updateEnableIncD8(false)},
+ {"false,+inc_d8", true, partialCompileFlags{}.updateEnableIncD8(true)},
+ {"false,+enable_inc_d8", true, partialCompileFlags{}.updateEnableIncD8(true)},
+ {"false,-disable_inc_d8", true, partialCompileFlags{}.updateEnableIncD8(true)},
}
for _, test := range tests {
@@ -292,23 +318,18 @@ type configTestModule struct {
}
func (d *configTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- deviceName := ctx.Config().DeviceName()
if ctx.ModuleName() == "foo" {
if ctx.Module().UseGenericConfig() {
- ctx.PropertyErrorf("use_generic_config", "must not be set for this test")
+ ctx.ModuleErrorf("must not use generic config")
}
} else if ctx.ModuleName() == "bar" {
if !ctx.Module().UseGenericConfig() {
- ctx.ModuleErrorf("\"use_generic_config: true\" must be set for this test")
+ ctx.ModuleErrorf("must use generic config")
}
}
- if ctx.Module().UseGenericConfig() {
- if deviceName != "generic" {
- ctx.ModuleErrorf("Device name for this module must be \"generic\" but %q\n", deviceName)
- }
- } else {
- if deviceName == "generic" {
+ if !ctx.Module().UseGenericConfig() {
+ if ctx.Config().DeviceName() == "generic" {
ctx.ModuleErrorf("Device name for this module must not be \"generic\"\n")
}
}
@@ -331,11 +352,11 @@ func TestGenericConfig(t *testing.T) {
bp := `
test {
name: "foo",
+ vendor: true,
}
test {
name: "bar",
- use_generic_config: true,
}
`
diff --git a/android/container.go b/android/container.go
index 547fe816c..a5affd969 100644
--- a/android/container.go
+++ b/android/container.go
@@ -23,6 +23,8 @@ import (
"github.com/google/blueprint"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// ----------------------------------------------------------------------------
// Start of the definitions of exception functions and the lookup table.
//
@@ -177,7 +179,9 @@ var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bo
val := reflect.ValueOf(prop).Elem()
if val.Kind() == reflect.Struct {
testSuites := val.FieldByName("Test_suites")
- if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.Contains(testSuites.Interface().([]string), "cts") {
+ if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.ContainsFunc(testSuites.Interface().([]string), func(s string) bool {
+ return s == "cts" || strings.HasPrefix(s, "mts")
+ }) {
return true
}
}
@@ -185,6 +189,7 @@ var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bo
return false
}
+// @auto-generate: gob
type unstableInfo struct {
// Determines if the module contains the private APIs of the platform.
ContainsPlatformPrivateApis bool
@@ -299,7 +304,7 @@ var (
restricted: []restriction{
{
dependency: UnstableContainer,
- errorMessage: "CTS module should not depend on the modules that contain the " +
+ errorMessage: "CTS/MTS module should not depend on the modules that contain the " +
"platform implementation details, including \"framework\". Depending on these " +
"modules may lead to disclosure of implementation details and regression " +
"due to API changes across platform versions. Try depending on the stubs instead " +
@@ -448,7 +453,7 @@ func generateContainerInfo(ctx ModuleContext) ContainersInfo {
}
}
-func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) {
+func getContainerModuleInfo(ctx ModuleContext, module ModuleOrProxy) (ContainersInfo, bool) {
if EqualModules(ctx.Module(), module) {
return ctx.getContainersInfo(), true
}
diff --git a/android/container_gob_enc.go b/android/container_gob_enc.go
new file mode 100644
index 000000000..359b472b5
--- /dev/null
+++ b/android/container_gob_enc.go
@@ -0,0 +1,38 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ unstableInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(unstableInfo) })
+}
+
+func (r unstableInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.ContainsPlatformPrivateApis); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *unstableInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ContainsPlatformPrivateApis)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var unstableInfoGobRegId int16
+
+func (r unstableInfo) GetTypeId() int16 {
+ return unstableInfoGobRegId
+}
diff --git a/android/container_violations.go b/android/container_violations.go
index 4c6386df6..b6e20fe46 100644
--- a/android/container_violations.go
+++ b/android/container_violations.go
@@ -4,21 +4,29 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
package android
var ContainerDependencyViolationAllowlist = map[string][]string{
+ // go/keep-sorted start case=no block=yes newline_separated=yes
+ "AdExtServicesApkUITestsAppConsent": {
+ "framework", // cts -> unstable
+ },
+
"adservices-service-core": {
"gson", // apex [com.android.adservices, com.android.extservices] -> apex [com.android.virt]
},
+ "AdServicesSharedLibrariesUnitTests": {
+ "framework", // cts -> unstable
+ },
+
"android.car-module.impl": {
"modules-utils-preconditions", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.appsearch, com.android.cellbroadcast, com.android.extservices, com.android.ondevicepersonalization, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.cellbroadcast, test_com.android.wifi]
},
@@ -27,10 +35,30 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "AppSearchMockingServicesTests": {
+ "framework", // cts -> unstable
+ },
+
+ "AppSearchServicesTests": {
+ "framework", // cts -> unstable
+ },
+
+ "AppsIndexerTests": {
+ "framework", // cts -> unstable
+ },
+
"art-aconfig-flags-java-lib": {
"framework-api-annotations-lib", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> system
},
+ "AvfRkpdAppIntegrationTests": {
+ "framework", // cts -> unstable
+ },
+
+ "BitmapTestApp": {
+ "framework", // cts -> unstable
+ },
+
"Bluetooth": {
"app-compat-annotations", // apex [com.android.bt] -> system
"framework-bluetooth-pre-jarjar", // apex [com.android.bt] -> system
@@ -44,6 +72,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"app-compat-annotations", // apex [com.android.bt] -> system
},
+ "CaptivePortalLoginTests": {
+ "framework", // cts -> unstable
+ },
+
"CarServiceUpdatable": {
"modules-utils-os", // apex [com.android.car.framework] -> apex [com.android.permission, test_com.android.permission]
"modules-utils-preconditions", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.appsearch, com.android.cellbroadcast, com.android.extservices, com.android.ondevicepersonalization, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.cellbroadcast, test_com.android.wifi]
@@ -55,14 +87,38 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // apex [com.android.cellbroadcast, test_com.android.cellbroadcast] -> system
},
+ "CellBroadcastReceiverComplianceTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CellBroadcastReceiverOemUnitTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CellBroadcastServiceTests": {
+ "framework", // cts -> unstable
+ },
+
"connectivity-net-module-utils-bpf": {
"net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
},
+ "ConnectivityCoverageTests": {
+ "framework", // cts -> unstable
+ },
+
"conscrypt-aconfig-flags-lib": {
"aconfig-annotations-lib-sdk-none", // apex [com.android.conscrypt, test_com.android.conscrypt] -> system
},
+ "ContactsIndexerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CrashRecoveryModuleTests": {
+ "framework", // cts -> unstable
+ },
+
"cronet_aml_base_base_java": {
"framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
"jsr305", // apex [com.android.tethering] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
@@ -174,6 +230,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsAppLocalesBackupApp1": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppLocalesBackupApp2": {
+ "framework", // cts -> unstable
+ },
+
"CtsAppOpsTestCases": {
"framework", // cts -> unstable
},
@@ -198,6 +262,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsBackupRestoreEventLoggerApp": {
+ "framework", // cts -> unstable
+ },
+
"CtsBatterySavingTestCases": {
"framework", // cts -> unstable
},
@@ -230,6 +298,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsContentProviderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsContentResolverTestCases": {
+ "framework", // cts -> unstable
+ },
+
"CtsContentSuggestionsTestCases": {
"framework", // cts -> unstable
},
@@ -338,6 +414,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsFullBackupApp": {
+ "framework", // cts -> unstable
+ },
+
"CtsHostsideCompatChangeTestsApp": {
"framework", // cts -> unstable
},
@@ -374,6 +454,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsKeyValueBackupApp": {
+ "framework", // cts -> unstable
+ },
+
"CtsLegacyNotification27TestCases": {
"framework", // cts -> unstable
},
@@ -474,11 +558,6 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
- // TODO(b/387499846): Remove once migrated to sdk_version.
- "CtsMediaRouterTestCases": {
- "framework", // cts -> unstable
- },
-
"CtsMediaRouterHostSideTestBluetoothPermissionsApp": {
"framework", // cts -> unstable
},
@@ -491,6 +570,11 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ // TODO(b/387499846): Remove once migrated to sdk_version.
+ "CtsMediaRouterTestCases": {
+ "framework", // cts -> unstable
+ },
+
// TODO(b/387500109): Remove once migrated to sdk_version.
"CtsMediaSessionTestCases": {
"framework", // cts -> unstable
@@ -572,6 +656,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsPermissionBackupApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPermissionBackupApp22": {
+ "framework", // cts -> unstable
+ },
+
"CtsPermissionsSyncTestApp": {
"framework", // cts -> unstable
},
@@ -604,6 +696,26 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsRestrictedModeNoActionApp1": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsRestrictedModeNoActionApp2": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsRestrictedModeOptedInApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsRestrictedModeOptedOutApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsRootBluetoothTestCases": {
+ "framework", // cts -> unstable
+ },
+
"CtsSandboxedAdIdManagerTests": {
"framework", // cts -> unstable
},
@@ -700,6 +812,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "CtsSyncManagerTestCases": {
+ "framework", // cts -> unstable
+ },
+
"CtsSystemUiTestCases": {
"framework", // cts -> unstable
},
@@ -833,6 +949,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.bt, com.android.car.framework]
},
+ "DisruptiveTestApp": {
+ "framework", // cts -> unstable
+ },
+
+ "DocumentsUITests": {
+ "framework", // cts -> unstable
+ },
+
"FederatedCompute": {
"auto_value_annotations", // apex [com.android.ondevicepersonalization] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
@@ -849,14 +973,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"configinfra_framework_flags_java_lib", // apex [com.android.configinfrastructure] -> system
},
- "framework-connectivity-t.impl": {
+ // TODO(b/382743602): Remove "app-compat-annotations" and depend on the stub version jar
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "framework-connectivity-b.impl": {
"app-compat-annotations", // apex [com.android.tethering] -> system
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
},
- // TODO(b/382743602): Remove "app-compat-annotations" and depend on the stub version jar
- // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
- "framework-connectivity-b.impl": {
+ "framework-connectivity-t.impl": {
"app-compat-annotations", // apex [com.android.tethering] -> system
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
},
@@ -888,6 +1012,22 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"app-compat-annotations", // apex [com.android.wifi, test_com.android.wifi] -> system
},
+ "FrameworksIkeTests": {
+ "framework", // cts -> unstable
+ },
+
+ "FrameworksVcnTests": {
+ "framework", // cts -> unstable
+ },
+
+ "FrameworksWifiApiTests": {
+ "framework", // cts -> unstable
+ },
+
+ "FrameworksWifiTests": {
+ "framework", // cts -> unstable
+ },
+
"grpc-java-core-internal": {
"gson", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> apex [com.android.virt]
"perfmark-api-lib", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> system
@@ -905,6 +1045,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework-api-annotations-lib", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> system
},
+ "LibStatsPullTests": {
+ "framework", // cts -> unstable
+ },
+
+ "libtextclassifier_java_tests": {
+ "framework", // cts -> unstable
+ },
+
"loadlibrarytest_product_app": {
"libnativeloader_vendor_shared_lib", // product -> vendor
},
@@ -976,6 +1124,18 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> system
},
+ "MediaProviderClientTests": {
+ "framework", // cts -> unstable
+ },
+
+ "MediaProviderTests": {
+ "framework", // cts -> unstable
+ },
+
+ "MediaRouterServiceTests": {
+ "framework", // cts -> unstable
+ },
+
"MockSatelliteGatewayServiceApp": {
"framework", // cts -> unstable
},
@@ -984,6 +1144,30 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework", // cts -> unstable
},
+ "MtsConscryptFdSocketTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MtsConscryptTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MtsLibcoreBouncyCastleTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MtsLibcoreOkHttpTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MtsTetheringTestLatestSdk": {
+ "framework", // cts -> unstable
+ },
+
+ "MtsWifiTestCases": {
+ "framework", // cts -> unstable
+ },
+
"net-utils-device-common-netlink": {
"net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
},
@@ -992,6 +1176,26 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
},
+ "NetHttpCoverageTests": {
+ "framework", // cts -> unstable
+ },
+
+ "NetworkStackCoverageTests": {
+ "framework", // cts -> unstable
+ },
+
+ "NetworkStackRootTests": {
+ "framework", // cts -> unstable
+ },
+
+ "NetworkStackTests": {
+ "framework", // cts -> unstable
+ },
+
+ "NfcManagerTests": {
+ "framework", // cts -> unstable
+ },
+
"NfcNciApex": {
// TODO(b/383782511): Remove the violations once the infra is fixed.
"android.nfc.flags-aconfig-java", // apex [com.android.nfcservices] -> system
@@ -1000,6 +1204,14 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework-nfc.impl", // apex [com.android.nfcservices] -> system
},
+ "NfcNciUnitTests": {
+ "framework", // cts -> unstable
+ },
+
+ "NfcTestCases": {
+ "framework", // cts -> unstable
+ },
+
"okhttp-norepackage": {
"okhttp-android-util-log", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> system
},
@@ -1012,14 +1224,46 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"auto_value_annotations", // apex [com.android.devicelock] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
+ "PackageWatchdogTest": {
+ "framework", // cts -> unstable
+ },
+
"PermissionController-lib": {
"safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
},
+ "PermissionControllerOutOfProcessTests": {
+ "framework", // cts -> unstable
+ },
+
"PlatformProperties": {
"sysprop-library-stub-platform", // apex [com.android.bt, com.android.nfcservices, com.android.tethering, com.android.virt, com.android.wifi, test_com.android.wifi] -> system
},
+ "pts-bot-mts": {
+ "framework", // cts -> unstable
+ },
+
+ "RebootReadinessUnitTests": {
+ "framework", // cts -> unstable
+ },
+
+ "RkpdAppIntegrationTests": {
+ "framework", // cts -> unstable
+ },
+
+ "RkpdAppStressTests": {
+ "framework", // cts -> unstable
+ },
+
+ "RkpdAppUnitTests": {
+ "framework", // cts -> unstable
+ },
+
+ "RollbackPackageHealthObserverTests": {
+ "framework", // cts -> unstable
+ },
+
"safety-center-config": {
"safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
},
@@ -1040,14 +1284,30 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
},
+ "SdkSandboxFrameworkUnitTests": {
+ "framework", // cts -> unstable
+ },
+
"SdkSandboxManagerDisabledTests": {
"framework", // cts -> unstable
},
+ "SdkSandboxManagerServiceUnitTests": {
+ "framework", // cts -> unstable
+ },
+
"SdkSandboxManagerTests": {
"framework", // cts -> unstable
},
+ "SdkSandboxRestrictionsTests": {
+ "framework", // cts -> unstable
+ },
+
+ "SdkSandboxUnitTests": {
+ "framework", // cts -> unstable
+ },
+
"service-art.impl": {
"auto_value_annotations", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
@@ -1061,6 +1321,13 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"libprotobuf-java-nano", // apex [com.android.tethering] -> apex [com.android.wifi, test_com.android.wifi]
},
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "service-connectivity-b-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-b-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
"service-connectivity-pre-jarjar": {
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
},
@@ -1074,13 +1341,6 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
},
- // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
- "service-connectivity-b-pre-jarjar": {
- "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
- "framework-connectivity-b-pre-jarjar", // apex [com.android.tethering] -> system
- "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
- },
-
"service-entitlement": {
"auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
@@ -1115,6 +1375,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
},
+ "service-rkp-unittest": {
+ "framework", // cts -> unstable
+ },
+
"service-thread-pre-jarjar": {
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
"framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
@@ -1128,10 +1392,30 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
+ "ServiceBluetoothTests": {
+ "framework", // cts -> unstable
+ },
+
+ "ServiceUwbTests": {
+ "framework", // cts -> unstable
+ },
+
+ "StableNetHttpCoverageTests": {
+ "framework", // cts -> unstable
+ },
+
+ "StatsdTestUtilsTest": {
+ "framework", // cts -> unstable
+ },
+
"TelephonyDeviceTest": {
"framework", // cts -> unstable
},
+ "TeleServiceTests": {
+ "framework", // cts -> unstable
+ },
+
"tensorflowlite_java": {
"android-support-annotations", // apex [com.android.adservices, com.android.extservices, com.android.ondevicepersonalization] -> system
},
@@ -1152,11 +1436,35 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"connectivity-internal-api-util", // apex [com.android.tethering] -> system
},
+ "TetheringPrivilegedTests": {
+ "framework", // cts -> unstable
+ },
+
"tetheringstatsprotos": {
"ext", // apex [com.android.tethering] -> system
"framework", // apex [com.android.tethering] -> system
},
+ "TetheringTests": {
+ "framework-minus-apex", // cts -> unstable
+ },
+
+ "TextClassifierNotificationTests": {
+ "framework", // cts -> unstable
+ },
+
+ "ThreadBorderRouterIntegrationTests": {
+ "framework", // cts -> unstable
+ },
+
+ "ThreadNetworkIntegrationTests": {
+ "framework", // cts -> unstable
+ },
+
+ "ThreadNetworkTrelDisabledTests": {
+ "framework", // cts -> unstable
+ },
+
"uwb_aconfig_flags_lib": {
"ext", // apex [com.android.uwb] -> system
"framework", // apex [com.android.uwb] -> system
@@ -1172,4 +1480,5 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
"framework-wifi-pre-jarjar", // apex [com.android.wifi, test_com.android.wifi] -> system
"jsr305", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
},
+ // go/keep-sorted end
}
diff --git a/android/deapexer.go b/android/deapexer.go
index 6d00dcd72..9d93427af 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -153,6 +153,20 @@ type RequiredFilesFromPrebuiltApex interface {
UseProfileGuidedDexpreopt() bool
}
+type RequiredFilesFromPrebuiltApexInfo struct {
+ // RequiredFilesFromPrebuiltApex contains a list of the file paths (relative to the root of the
+ // APEX's contents) that the implementing module requires from within a prebuilt .apex file.
+ //
+ // For each file path this will cause the file to be extracted out of the prebuilt .apex file, and
+ // the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file
+ // path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method.
+ RequiredFilesFromPrebuiltApex []string
+ // UseProfileGuidedDexpreopt is true if a transitive dependency of an apex should use a .prof file to guide dexpreopt
+ UseProfileGuidedDexpreopt bool
+}
+
+var RequiredFilesFromPrebuiltApexInfoProvider = blueprint.NewProvider[RequiredFilesFromPrebuiltApexInfo]()
+
// Marker interface that identifies dependencies on modules that may require files from a prebuilt
// apex.
type RequiresFilesFromPrebuiltApexTag interface {
diff --git a/android/defaults_test.go b/android/defaults_test.go
index 24f14617a..f57a7a6c1 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -16,8 +16,6 @@ package android
import (
"testing"
-
- "github.com/google/blueprint"
)
type defaultsTestProperties struct {
@@ -158,7 +156,7 @@ func TestDefaultsPathProperties(t *testing.T) {
collectDeps := func(m Module) []string {
var deps []string
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ result.VisitDirectDeps(m, func(dep Module) {
deps = append(deps, result.ModuleName(dep))
})
return deps
diff --git a/android/defs.go b/android/defs.go
index 57fcc9b13..4f1e849e4 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -126,7 +126,27 @@ var (
Description: "concatenate files to $out",
})
- // Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
+ CatAndSort = pctx.AndroidStaticRule("CatAndSort",
+ blueprint.RuleParams{
+ Command: "rm -f $out && cat $in > $out && sort -o $out $out",
+ Description: "concatenate sorted file contents to $out",
+ })
+
+ CatAndSortAndUnique = pctx.AndroidStaticRule("CatAndSortAndUnique",
+ blueprint.RuleParams{
+ Command: "rm -f $out && cat $in > $out && sort -u -o $out $out",
+ Description: "concatenate sorted file contents to $out",
+ })
+
+ MergeZips = pctx.AndroidStaticRule("MergeZips",
+ blueprint.RuleParams{
+ Command: `${MergeZipsCmd} -s $out $in`,
+ CommandDeps: []string{
+ "${MergeZipsCmd}",
+ },
+ })
+
+ // Used only when USE_RBE=true is set, to restrict non-RBE jobs to the local parallelism value
localPool = blueprint.NewBuiltinPool("local_pool")
// Used only by RuleBuilder to identify remoteable rules. Does not actually get created in ninja.
@@ -142,6 +162,8 @@ func init() {
pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
return ctx.Config().RBEWrapper()
})
+
+ pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
}
// CopyFileRule creates a ninja rule to copy path to outPath.
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 300edf194..2c4f97149 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -61,7 +61,7 @@ type EarlyModuleContext interface {
Errorf(pos scanner.Position, fmt string, args ...interface{})
// OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition.
- OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property, fmt string, args ...interface{})
// Failed returns true if any errors have been reported. In most cases the module can continue with generating
// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
@@ -98,6 +98,7 @@ type EarlyModuleContext interface {
// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
// default SimpleNameInterface if Context.SetNameInterface was not called.
Namespace() *Namespace
+ OtherModuleNamespace(ModuleOrProxy) *Namespace
// HasMutatorFinished returns true if the given mutator has finished running.
// It will panic if given an invalid mutator name.
@@ -150,7 +151,7 @@ func (e *earlyModuleContext) Config() Config {
// If a module builds multiple image variations, provide the generic config only for the core
// variant which is installed in the system partition. Other image variant may still read the
// original configurations.
- if e.Module().base().UseGenericConfig() && e.Module().base().commonProperties.ImageVariation == "" {
+ if e.Module().UseGenericConfig() && e.Module().base().commonProperties.ImageVariation == "" {
return e.EarlyModuleContext.Config().(Config).genericConfig()
}
return e.EarlyModuleContext.Config().(Config)
@@ -188,8 +189,12 @@ func (e *earlyModuleContext) Namespace() *Namespace {
return e.EarlyModuleContext.Namespace().(*Namespace)
}
-func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
- e.EarlyModuleContext.OtherModulePropertyErrorf(getWrappedModule(module), property, fmt, args...)
+func (e *earlyModuleContext) OtherModuleNamespace(m ModuleOrProxy) *Namespace {
+ return e.EarlyModuleContext.OtherModuleNamespace(m).(*Namespace)
+}
+
+func (e *earlyModuleContext) OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt string, args ...interface{}) {
+ e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...)
}
func (e *earlyModuleContext) HasMutatorFinished(mutatorName string) bool {
diff --git a/android/filegroup.go b/android/filegroup.go
index 4fad52aaa..57fa4aff7 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -18,7 +18,6 @@ import (
"maps"
"strings"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -80,23 +79,6 @@ func FileGroupFactory() Module {
return module
}
-var _ blueprint.JSONActionSupplier = (*fileGroup)(nil)
-
-func (fg *fileGroup) JSONActions() []blueprint.JSONAction {
- ins := make([]string, 0, len(fg.srcs))
- outs := make([]string, 0, len(fg.srcs))
- for _, p := range fg.srcs {
- ins = append(ins, p.String())
- outs = append(outs, p.Rel())
- }
- return []blueprint.JSONAction{
- blueprint.JSONAction{
- Inputs: ins,
- Outputs: outs,
- },
- }
-}
-
func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
srcs := PathsForModuleSrcExcludes(ctx, fg.properties.Srcs.GetOrDefault(ctx, nil), fg.properties.Exclude_srcs.GetOrDefault(ctx, nil))
srcs = append(srcs, PathsForModuleSrc(ctx, fg.properties.Device_first_srcs.GetOrDefault(ctx, nil))...)
@@ -109,7 +91,7 @@ func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
var intermediateCacheOutputPaths Paths
var srcjars Paths
modeInfos := make(map[string]ModeInfo)
- ctx.VisitDirectDeps(func(module Module) {
+ ctx.VisitDirectDepsProxy(func(module ModuleProxy) {
if dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok {
aconfigDeclarations = append(aconfigDeclarations, dep.AconfigDeclarations...)
intermediateCacheOutputPaths = append(intermediateCacheOutputPaths, dep.IntermediateCacheOutputPaths...)
diff --git a/android/fixture.go b/android/fixture.go
index ea52b95f5..bafaf8dce 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -258,6 +258,7 @@ func FixtureSetTestRunner(testRunner FixtureTestRunner) FixturePreparer {
func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
return newSimpleFixturePreparer(func(f *fixture) {
mutator(f.config)
+ mutator(f.config.genericConfig())
})
}
@@ -265,6 +266,7 @@ func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
func FixtureModifyConfigAndContext(mutator func(config Config, ctx *TestContext)) FixturePreparer {
return newSimpleFixturePreparer(func(f *fixture) {
mutator(f.config, f.ctx)
+ mutator(f.config.genericConfig(), f.ctx)
})
}
@@ -828,7 +830,10 @@ func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *Te
// Ditto with config derived information in the TestContext.
ctx := fixture.ctx
ctx.config = config
+
+ // SetFs to both normal and generic configs.
ctx.SetFs(ctx.config.fs)
+ ctx.SetFs(ctx.config.genericConfigField.fs)
if ctx.config.mockBpList != "" {
ctx.SetModuleListFile(ctx.config.mockBpList)
}
@@ -902,6 +907,13 @@ func (f *fixture) RunTest() CustomTestResult {
}
}
+ // Generic config has the same configuration values with non-generic configuration except for
+ // some target-specific configuration values. However, we simply copy the non-generic config to
+ // the generic config to avoid duplicated updates for generic and non-generic configurations
+ // for each fixture. So the test fixture cannot test the configuration values of the generic
+ // configuration.
+ f.config.genericConfigField = f.config.config
+
// Create and set the Context's NameInterface. It needs to be created here as it depends on the
// configuration that has been prepared for this fixture.
resolver := NewNameResolver(ctx.config)
@@ -1051,6 +1063,11 @@ func (r *TestResult) Module(name string, variant string) Module {
return r.ModuleForTests(r.fixture.t, name, variant).Module()
}
+// ModuleProxy returns the module with the specific name and of the specified variant.
+func (r *TestResult) ModuleProxy(name string, variant string) ModuleProxy {
+ return r.ModuleForTests(r.fixture.t, name, variant).ModuleProxy()
+}
+
// CollateErrs adds additional errors to the result and returns true if there is more than one
// error in the result.
func (r *TestResult) CollateErrs(errs []error) bool {
diff --git a/android/fixture_test.go b/android/fixture_test.go
index 5b810e0b7..f11ad3923 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -24,8 +24,11 @@ func TestFixtureDedup(t *testing.T) {
list := []string{}
appendToList := func(s string) FixturePreparer {
- return FixtureModifyConfig(func(_ Config) {
- list = append(list, s)
+ return FixtureModifyConfig(func(config Config) {
+ // Skip generic config to avoid duplicated calls
+ if !config.isGeneric {
+ list = append(list, s)
+ }
})
}
diff --git a/android/hooks.go b/android/hooks.go
index 5d509a43e..6c595a3ae 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -96,6 +96,12 @@ func (l *loadHookContext) AppendProperties(props ...interface{}) {
l.appendPrependHelper(props, proptools.AppendMatchingProperties)
}
+func (l *loadHookContext) Config() Config {
+ // LoadHookContext cannot be generic, but must read all configuration values
+ // because it is called before loading module properties.
+ return l.earlyModuleContext.EarlyModuleContext.Config().(Config)
+}
+
func (l *loadHookContext) PrependProperties(props ...interface{}) {
l.appendPrependHelper(props, proptools.PrependMatchingProperties)
}
@@ -243,6 +249,26 @@ func (x *hooks) runInstallHooks(ctx ModuleContext, srcPath Path, path InstallPat
}
}
+// AddPostGenerateAndroidBuildActionsHook adds a hook that runs immediately after
+// the module's GenerateAndroidBuildActions method is called, allowing modules
+// to inject custom logic when sharing that method.
+func AddPostGenerateAndroidBuildActionsHook(m blueprint.Module, hook func(ctx ModuleContext)) {
+ h := &m.(Module).base().hooks
+ h.postGenerateAndroidBuildActions = append(h.postGenerateAndroidBuildActions, hook)
+}
+
+func (x *hooks) runPostGenerateAndroidBuildActionsHooks(ctx ModuleContext) {
+ if len(x.postGenerateAndroidBuildActions) > 0 {
+ for _, x := range x.postGenerateAndroidBuildActions {
+ x(ctx)
+ if ctx.Failed() {
+ return
+ }
+ }
+ }
+}
+
type hooks struct {
- install []func(InstallHookContext)
+ install []func(InstallHookContext)
+ postGenerateAndroidBuildActions []func(ModuleContext)
}
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 0b880dd8a..e472b53be 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -23,6 +23,8 @@ import (
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
_ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
@@ -203,6 +205,7 @@ func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths)
var LicenseMetadataProvider = blueprint.NewProvider[*LicenseMetadataInfo]()
// LicenseMetadataInfo stores the license metadata path for a module.
+// @auto-generate: gob
type LicenseMetadataInfo struct {
LicenseMetadataPath Path
LicenseMetadataDepSet depset.DepSet[Path]
diff --git a/android/license_metadata_gob_enc.go b/android/license_metadata_gob_enc.go
new file mode 100644
index 000000000..615612dfd
--- /dev/null
+++ b/android/license_metadata_gob_enc.go
@@ -0,0 +1,49 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ LicenseMetadataInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LicenseMetadataInfo) })
+}
+
+func (r LicenseMetadataInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.LicenseMetadataPath); err != nil {
+ return err
+ }
+
+ if err = r.LicenseMetadataDepSet.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *LicenseMetadataInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.LicenseMetadataPath = nil
+ } else {
+ r.LicenseMetadataPath = val2.(Path)
+ }
+
+ if err = r.LicenseMetadataDepSet.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var LicenseMetadataInfoGobRegId int16
+
+func (r LicenseMetadataInfo) GetTypeId() int16 {
+ return LicenseMetadataInfoGobRegId
+}
diff --git a/android/license_sdk_member.go b/android/license_sdk_member.go
index b17defea5..ffdcb1375 100644
--- a/android/license_sdk_member.go
+++ b/android/license_sdk_member.go
@@ -36,9 +36,9 @@ func (l *licenseSdkMemberType) AddDependencies(ctx SdkDependencyContext, depende
ctx.AddDependency(ctx.Module(), dependencyTag, names...)
}
-func (l *licenseSdkMemberType) IsInstance(module Module) bool {
+func (l *licenseSdkMemberType) IsInstance(ctx ModuleContext, module ModuleProxy) bool {
// Verify that the module being added is compatible with this module type.
- _, ok := module.(*licenseModule)
+ _, ok := OtherModuleProvider(ctx, module, LicenseInfoProvider)
return ok
}
@@ -86,12 +86,12 @@ type licenseSdkMemberProperties struct {
License_text Paths
}
-func (p *licenseSdkMemberProperties) PopulateFromVariant(_ SdkMemberContext, variant Module) {
+func (p *licenseSdkMemberProperties) PopulateFromVariant(ctx SdkMemberContext, variant ModuleProxy) {
// Populate the properties from the variant.
- l := variant.(*licenseModule)
- p.License_kinds = l.properties.License_kinds
- p.License_text = make(Paths, 0, len(l.base().commonProperties.Effective_license_text))
- for _, np := range l.base().commonProperties.Effective_license_text {
+ licenseInfo := OtherModuleProviderOrDefault(ctx.SdkModuleContext(), variant, LicenseInfoProvider)
+ p.License_kinds = licenseInfo.EffectiveLicenseKinds
+ p.License_text = make(Paths, 0, len(licenseInfo.EffectiveLicenseText))
+ for _, np := range licenseInfo.EffectiveLicenseText {
p.License_text = append(p.License_text, np.Path)
}
}
diff --git a/android/licenses.go b/android/licenses.go
index 387792144..481364ee3 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -22,9 +22,10 @@ import (
"sync"
"github.com/google/blueprint"
- "github.com/google/blueprint/gobtools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
//
// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
@@ -36,7 +37,7 @@ type licensesDependencyTag struct {
blueprint.BaseDependencyTag
}
-func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType {
+func (l licensesDependencyTag) SdkMemberType(_ ModuleContext, _ ModuleProxy) SdkMemberType {
// Add the supplied module to the sdk as a license module.
return LicenseModuleSdkMemberType
}
@@ -56,55 +57,26 @@ var (
)
// Describes the property provided by a module to reference applicable licenses.
-type applicableLicensesProperty interface {
- // The name of the property. e.g. default_applicable_licenses or licenses
- getName() string
- // The values assigned to the property. (Must reference license modules.)
- getStrings() []string
-}
-
-type applicableLicensesPropertyImpl struct {
+// @auto-generate: gob
+type applicableLicensesProperty struct {
name string
licensesProperty *[]string
}
-type applicableLicensesPropertyImplGob struct {
- Name string
- LicensesProperty []string
-}
-
-func (a *applicableLicensesPropertyImpl) ToGob() *applicableLicensesPropertyImplGob {
- return &applicableLicensesPropertyImplGob{
- Name: a.name,
- LicensesProperty: *a.licensesProperty,
- }
-}
-
-func (a *applicableLicensesPropertyImpl) FromGob(data *applicableLicensesPropertyImplGob) {
- a.name = data.Name
- a.licensesProperty = &data.LicensesProperty
-}
-
-func (a applicableLicensesPropertyImpl) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[applicableLicensesPropertyImplGob](&a)
-}
-
-func (a *applicableLicensesPropertyImpl) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[applicableLicensesPropertyImplGob](data, a)
-}
-
-func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
- return applicableLicensesPropertyImpl{
+func newApplicableLicensesProperty(name string, licensesProperty *[]string) *applicableLicensesProperty {
+ return &applicableLicensesProperty{
name: name,
licensesProperty: licensesProperty,
}
}
-func (p applicableLicensesPropertyImpl) getName() string {
+// The name of the property. e.g. default_applicable_licenses or licenses
+func (p applicableLicensesProperty) getName() string {
return p.name
}
-func (p applicableLicensesPropertyImpl) getStrings() []string {
+// The values assigned to the property. (Must reference license modules.)
+func (p applicableLicensesProperty) getStrings() []string {
return *p.licensesProperty
}
@@ -340,7 +312,7 @@ func getLicenses(ctx BaseModuleContext, module Module) []string {
}
// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
-func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
+func exemptFromRequiredApplicableLicensesProperty(module ModuleOrProxy) bool {
switch reflect.TypeOf(module).String() {
case "*android.licenseModule": // is a license, doesn't need one
case "*android.licenseKindModule": // is a license, doesn't need one
@@ -357,6 +329,7 @@ func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
}
// LicensesInfo contains information about licenses for a specific module.
+// @auto-generate: gob
type LicensesInfo struct {
// The list of license modules this depends upon, either explicitly or through default package
// configuration.
diff --git a/android/licenses_gob_enc.go b/android/licenses_gob_enc.go
new file mode 100644
index 000000000..6f9a26b99
--- /dev/null
+++ b/android/licenses_gob_enc.go
@@ -0,0 +1,118 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ applicableLicensesPropertyGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(applicableLicensesProperty) })
+ LicensesInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LicensesInfo) })
+}
+
+func (r applicableLicensesProperty) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.name); err != nil {
+ return err
+ }
+
+ val1 := r.licensesProperty == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = gobtools.EncodeSimple(buf, int32(len((*r.licensesProperty)))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len((*r.licensesProperty)); val2++ {
+ if err = gobtools.EncodeString(buf, (*r.licensesProperty)[val2]); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *applicableLicensesProperty) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.name)
+ if err != nil {
+ return err
+ }
+
+ var val3 bool
+ if err = gobtools.DecodeSimple(buf, &val3); err != nil {
+ return err
+ }
+ if !val3 {
+ var val2 []string
+ var val5 int32
+ err = gobtools.DecodeSimple[int32](buf, &val5)
+ if err != nil {
+ return err
+ }
+ if val5 > 0 {
+ val2 = make([]string, val5)
+ for val6 := 0; val6 < int(val5); val6++ {
+ err = gobtools.DecodeString(buf, &val2[val6])
+ if err != nil {
+ return err
+ }
+ }
+ }
+ r.licensesProperty = &val2
+ }
+
+ return err
+}
+
+var applicableLicensesPropertyGobRegId int16
+
+func (r applicableLicensesProperty) GetTypeId() int16 {
+ return applicableLicensesPropertyGobRegId
+}
+
+func (r LicensesInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Licenses))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Licenses); val1++ {
+ if err = gobtools.EncodeString(buf, r.Licenses[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *LicensesInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.Licenses = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.Licenses[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var LicensesInfoGobRegId int16
+
+func (r LicensesInfo) GetTypeId() int16 {
+ return LicensesInfoGobRegId
+}
diff --git a/android/logtags.go b/android/logtags.go
index 074f402e7..4aee0ca6d 100644
--- a/android/logtags.go
+++ b/android/logtags.go
@@ -20,10 +20,13 @@ import (
"github.com/google/blueprint"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterParallelSingletonType("logtags", LogtagsSingleton)
}
+// @auto-generate: gob
type LogtagsInfo struct {
Logtags Paths
}
diff --git a/android/logtags_gob_enc.go b/android/logtags_gob_enc.go
new file mode 100644
index 000000000..90eb289d0
--- /dev/null
+++ b/android/logtags_gob_enc.go
@@ -0,0 +1,56 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ LogtagsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LogtagsInfo) })
+}
+
+func (r LogtagsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Logtags))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Logtags); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.Logtags[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *LogtagsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.Logtags = make([]Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.Logtags[val4] = nil
+ } else {
+ r.Logtags[val4] = val6.(Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var LogtagsInfoGobRegId int16
+
+func (r LogtagsInfo) GetTypeId() int16 {
+ return LogtagsInfoGobRegId
+}
diff --git a/android/makevars.go b/android/makevars.go
index 7017e7db0..85d095c5e 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -72,15 +72,15 @@ type BaseMakeVarsContext interface {
type MakeVarsContext interface {
BaseMakeVarsContext
- ModuleName(module blueprint.Module) string
- ModuleDir(module blueprint.Module) string
- ModuleSubDir(module blueprint.Module) string
- ModuleType(module blueprint.Module) string
- otherModuleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool)
- BlueprintFile(module blueprint.Module) string
-
- ModuleErrorf(module blueprint.Module, format string, args ...interface{})
- OtherModulePropertyErrorf(module Module, property, format string, args ...interface{})
+ ModuleName(module ModuleOrProxy) string
+ ModuleDir(module ModuleOrProxy) string
+ ModuleSubDir(module ModuleOrProxy) string
+ ModuleType(module ModuleOrProxy) string
+ otherModuleProvider(module ModuleOrProxy, key blueprint.AnyProviderKey) (any, bool)
+ BlueprintFile(module ModuleOrProxy) string
+
+ ModuleErrorf(module ModuleOrProxy, format string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property, format string, args ...interface{})
Errorf(format string, args ...interface{})
VisitAllModules(visit func(Module))
@@ -599,6 +599,9 @@ func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool)
}
func (c *makeVarsContext) addPhony(name string, deps []string) {
+ if name == "" {
+ panic("Phony name cannot be the empty string")
+ }
c.phonies = append(c.phonies, phony{name, deps})
}
diff --git a/android/module.go b/android/module.go
index baacfa7e1..481e4107f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -27,10 +27,12 @@ import (
"github.com/google/blueprint"
"github.com/google/blueprint/depset"
- "github.com/google/blueprint/gobtools"
+ "github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
DeviceSharedLibrary = "shared_library"
DeviceStaticLibrary = "static_library"
@@ -45,6 +47,14 @@ type Module interface {
// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
GenerateAndroidBuildActions(ModuleContext)
+ // CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished.
+ // If all interactions with this module are handled via providers instead of direct access
+ // to the module then it can free memory attached to the module.
+ // This is a temporary measure to reduce memory usage, eventually blueprint's reference
+ // to the Module should be dropped after GenerateAndroidBuildActions once all accesses
+ // can be done through providers.
+ CleanupAfterBuildActions()
+
// Add dependencies to the components of a module, i.e. modules that are created
// by the module and which are considered to be part of the creating module.
//
@@ -112,7 +122,7 @@ type Module interface {
qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName
// Get information about the properties that can contain visibility rules.
- visibilityProperties() []visibilityProperty
+ visibilityProperties() []*visibilityProperty
RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
HostRequiredModuleNames() []string
@@ -132,6 +142,8 @@ type Module interface {
// If this is true, the module must not read product-specific configurations.
UseGenericConfig() bool
+
+ NoFullInstall() bool
}
// Qualified id for a module
@@ -177,6 +189,7 @@ func newPackageId(pkg string) qualifiedModuleName {
return qualifiedModuleName{pkg: pkg, name: ""}
}
+// @auto-generate: gob
type Dist struct {
// Copy the output of this module to the $DIST_DIR when `dist` is specified on the
// command line and any of these targets are also on the command line, or otherwise
@@ -413,12 +426,6 @@ type commonProperties struct {
// Whether this module is built for non-native architectures (also known as native bridge binary)
Native_bridge_supported *bool `android:"arch_variant"`
- // init.rc files to be installed if this module is installed
- Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
-
- // VINTF manifest fragments to be installed if this module is installed
- Vintf_fragments proptools.Configurable[[]string] `android:"path"`
-
// The OsType of artifacts that this module variant is responsible for creating.
//
// Set by osMutator
@@ -500,6 +507,7 @@ type commonProperties struct {
// Name and variant strings stored by mutators to enable Module.String()
DebugName string `blueprint:"mutated"`
+ DebugNamespace string `blueprint:"mutated"`
DebugMutators []string `blueprint:"mutated"`
DebugVariations []string `blueprint:"mutated"`
@@ -511,13 +519,6 @@ type commonProperties struct {
// The team (defined by the owner/vendor) who owns the property.
Team *string `android:"path"`
- // vintf_fragment Modules required from this module.
- Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
-
- // List of module names that are prevented from being installed when this module gets
- // installed.
- Overrides []string
-
// Set to true if this module must be generic and does not require product-specific information.
// To be included in the system image, this property must be set to true.
Use_generic_config *bool
@@ -539,6 +540,19 @@ type baseProperties struct {
// module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher
// just by creating a soong config module type.
Soong_config_base_module_type *string `blueprint:"mutated"`
+
+ // init.rc files to be installed if this module is installed
+ Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
+
+ // VINTF manifest fragments to be installed if this module is installed
+ Vintf_fragments proptools.Configurable[[]string] `android:"path"`
+
+ // vintf_fragment Modules required from this module.
+ Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
+
+ // List of module names that are prevented from being installed when this module gets
+ // installed.
+ Overrides []string
}
type distProperties struct {
@@ -840,6 +854,7 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport
// // ...
// }
type ModuleBase struct {
+ blueprint.ModuleBase
// Putting the curiously recurring thing pointing to the thing that contains
// the thing pattern to good use.
// TODO: remove this
@@ -862,13 +877,13 @@ type ModuleBase struct {
// Information about all the properties on the module that contains visibility rules that need
// checking.
- visibilityPropertyInfo []visibilityProperty
+ visibilityPropertyInfo []*visibilityProperty
// The primary visibility property, may be nil, that controls access to the module.
- primaryVisibilityProperty visibilityProperty
+ primaryVisibilityProperty *visibilityProperty
// The primary licenses property, may be nil, records license metadata for the module.
- primaryLicensesProperty applicableLicensesProperty
+ primaryLicensesProperty *applicableLicensesProperty
noAddressSanitizer bool
@@ -882,13 +897,6 @@ type ModuleBase struct {
variables map[string]string
}
-func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
- (*d)["Android"] = map[string]interface{}{
- // Properties set in Blueprint or in blueprint of a defaults modules
- "SetProperties": m.propertiesWithValues(),
- }
-}
-
type propInfo struct {
Name string
Type string
@@ -1032,6 +1040,9 @@ func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorCon
// addRequiredDeps adds required, target_required, and host_required as dependencies.
func addRequiredDeps(ctx BottomUpMutatorContext) {
addDep := func(target Target, depName string) {
+ if !blueprint.IsValidModuleName(depName) {
+ ctx.PropertyErrorf("required", "%s is not a valid module", depName)
+ }
if !ctx.OtherModuleExists(depName) {
if ctx.Config().AllowMissingDependencies() {
return
@@ -1118,29 +1129,21 @@ func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
return
}
- deviceConfig := ctx.DeviceConfig()
-
mod := ctx.Module()
- vintfModules := ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+ ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+}
- modPartition := mod.PartitionTag(deviceConfig)
- for _, vintf := range vintfModules {
- if vintf == nil {
- // TODO(b/372091092): Remove this. Having it gives us missing dependency errors instead
- // of nil pointer dereference errors, but we should resolve the missing dependencies.
- continue
+func checkVintfFragmentDeps(ctx ModuleContext) {
+ modPartition := ctx.Module().PartitionTag(ctx.DeviceConfig())
+ ctx.VisitDirectDepsProxyWithTag(vintfDepTag, func(vintf ModuleProxy) {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, vintf, CommonModuleInfoProvider)
+ vintfPartition := commonInfo.PartitionTag
+ if modPartition != vintfPartition {
+ ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
+ ctx.ModuleName(), modPartition,
+ vintf.Name(), vintfPartition)
}
- if vintfModule, ok := vintf.(*VintfFragmentModule); ok {
- vintfPartition := vintfModule.PartitionTag(deviceConfig)
- if modPartition != vintfPartition {
- ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
- mod.Name(), modPartition,
- vintfModule.Name(), vintfPartition)
- }
- } else {
- ctx.ModuleErrorf("Only vintf_fragment type module should be listed in vintf_fragment_modules : %q", vintf.Name())
- }
- }
+ })
}
// AddProperties "registers" the provided props
@@ -1224,7 +1227,7 @@ func (m *ModuleBase) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleNam
return qualifiedModuleName{pkg: ctx.ModuleDir(), name: ctx.ModuleName()}
}
-func (m *ModuleBase) visibilityProperties() []visibilityProperty {
+func (m *ModuleBase) visibilityProperties() []*visibilityProperty {
return m.visibilityPropertyInfo
}
@@ -1307,6 +1310,10 @@ func (m *ModuleBase) IsCommonOSVariant() bool {
return m.commonProperties.CompileOS == CommonOS
}
+func (m *ModuleBase) NoFullInstall() bool {
+ return proptools.Bool(m.commonProperties.No_full_install)
+}
+
// supportsTarget returns true if the given Target is supported by the current module.
func (m *ModuleBase) supportsTarget(target Target) bool {
switch target.Os.Class {
@@ -1424,6 +1431,8 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
partition = "vendor_ramdisk"
} else if m.InstallInRecovery() {
partition = "recovery"
+ } else if m.InstallInVendorDlkm() {
+ partition = "vendor_dlkm"
}
return partition
}
@@ -1660,45 +1669,54 @@ func (m *ModuleBase) TargetRequiredModuleNames() []string {
}
func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
- return m.base().commonProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
+ return m.base().baseProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
func (m *ModuleBase) VintfFragments(ctx ConfigurableEvaluatorContext) []string {
- return m.base().commonProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
-}
-
-func (m *ModuleBase) generateVariantTarget(ctx *moduleContext) {
- namespacePrefix := ctx.Namespace().id
- if namespacePrefix != "" {
- namespacePrefix = namespacePrefix + "-"
- }
-
- if !ctx.uncheckedModule {
- name := namespacePrefix + ctx.ModuleName() + "-" + ctx.ModuleSubDir() + "-checkbuild"
- ctx.Phony(name, ctx.checkbuildFiles...)
- ctx.checkbuildTarget = PathForPhony(ctx, name)
- }
-
+ return m.base().baseProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
// generateModuleTarget generates phony targets so that you can do `m <module-name>`.
// It will be run on every variant of the module, so it relies on the fact that phony targets
// are deduped to merge all the deps from different variants together.
-func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
+func (m *ModuleBase) generateModuleTarget(ctx *moduleContext, testSuiteInstalls []filePair) {
var namespacePrefix string
nameSpace := ctx.Namespace().Path
if nameSpace != "." {
namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-"
}
+ shouldSkipAndroidMk := shouldSkipAndroidMkProcessing(ctx, m)
+
+ phony := func(suffix string, deps Paths) string {
+ if ctx.Config().KatiEnabled() {
+ suffix += "-soong"
+ }
+ var ret string
+ // Create a target without the namespace prefix if it's exported to make. One of the
+ // conditions for being exported to make is that the namespace is in
+ // PRODUCT_SOONG_NAMESPACES, so historically that would mean that make would create the
+ // phonies for those modules as if they weren't in any namespace.
+ if !shouldSkipAndroidMk {
+ ret = ctx.module.base().BaseModuleName() + suffix
+ ctx.Phony(ret, deps...)
+ }
+ // Create another phony for building with the namespace specified. This can be used
+ // regardless of if the namespace is in PRODUCT_SOONG_NAMESPACES or not.
+ if nameSpace != "." {
+ ctx.Phony(namespacePrefix+ctx.module.base().BaseModuleName()+suffix, deps...)
+ }
+ return ret
+ }
var deps Paths
var info ModuleBuildTargetsInfo
- if len(ctx.installFiles) > 0 {
- name := namespacePrefix + ctx.ModuleName() + "-install"
+ if len(ctx.installFiles) > 0 && !shouldSkipAndroidMk {
installFiles := ctx.installFiles.Paths()
- ctx.Phony(name, installFiles...)
- info.InstallTarget = PathForPhony(ctx, name)
+ name := phony("-install", installFiles)
+ if name != "" {
+ info.InstallTarget = PathForPhony(ctx, name)
+ }
deps = append(deps, installFiles...)
}
@@ -1706,38 +1724,47 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
// not be created if the module is not exported to make.
// Those could depend on the build target and fail to compile
// for the current build target.
- if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil {
- name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
- ctx.Phony(name, ctx.checkbuildTarget)
- deps = append(deps, ctx.checkbuildTarget)
+ if !shouldSkipAndroidMk && !ctx.uncheckedModule {
+ phony("-checkbuild", ctx.checkbuildFiles)
+ checkbuildTarget := phony("-"+ctx.ModuleSubDir()+"-checkbuild", ctx.checkbuildFiles)
+ if checkbuildTarget != "" {
+ info.CheckbuildTarget = PathForPhony(ctx, checkbuildTarget)
+ }
+ deps = append(deps, ctx.checkbuildFiles...)
}
- if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 {
- name := namespacePrefix + ctx.ModuleName() + "-outputs"
- ctx.Phony(name, outputFiles...)
+ if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 && !shouldSkipAndroidMk {
+ phony("-outputs", outputFiles)
deps = append(deps, outputFiles...)
}
- if len(deps) > 0 {
- suffix := ""
- if ctx.Config().KatiEnabled() {
- suffix = "-soong"
+ // Act as if you built the required dependencies as well when building the current module
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(RequiredDepTag) {
+ if info, ok := OtherModuleProvider(ctx, dep, ModuleBuildTargetsProvider); ok {
+ deps = append(deps, info.AllDeps...)
}
+ }
- ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
+ for _, p := range testSuiteInstalls {
+ deps = append(deps, p.dst)
+ }
+
+ if len(deps) > 0 {
+ phony("", deps)
if ctx.Device() {
// Generate a target suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-target"+suffix, deps...)
+ phony("-target", deps)
} else {
// Generate a host suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host"+suffix, deps...)
+ phony("-host", deps)
if ctx.Target().HostCross {
// Generate a host-cross suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host-cross"+suffix, deps...)
+ phony("-host-cross", deps)
}
}
info.BlueprintDir = ctx.ModuleDir()
+ info.AllDeps = deps
SetProvider(ctx, ModuleBuildTargetsProvider, info)
}
}
@@ -1830,24 +1857,37 @@ func (m *ModuleBase) archModuleContextFactory(ctx archModuleContextFactoryContex
} else {
primaryArch = target.Arch.ArchType == config.Targets[target.Os][0].Arch.ArchType
}
+ primaryNativeBridgeArch := false
+ if target.NativeBridge {
+ for _, t := range config.Targets[target.Os] {
+ if t.NativeBridge {
+ if target.Arch.ArchType == t.Arch.ArchType {
+ primaryNativeBridgeArch = true
+ }
+ // Don't consider further nativebridge targets
+ break
+ }
+ }
+ }
return archModuleContext{
- ready: m.commonProperties.ArchReady,
- os: m.commonProperties.CompileOS,
- target: m.commonProperties.CompileTarget,
- targetPrimary: m.commonProperties.CompilePrimary,
- multiTargets: m.commonProperties.CompileMultiTargets,
- primaryArch: primaryArch,
+ ready: m.commonProperties.ArchReady,
+ os: m.commonProperties.CompileOS,
+ target: m.commonProperties.CompileTarget,
+ targetPrimary: m.commonProperties.CompilePrimary,
+ multiTargets: m.commonProperties.CompileMultiTargets,
+ primaryArch: primaryArch,
+ primaryNativeBridgeArch: primaryNativeBridgeArch,
}
}
+// @auto-generate: gob
type InstallFilesInfo struct {
- InstallFiles InstallPaths
- CheckbuildFiles Paths
- CheckbuildTarget Path
- UncheckedModule bool
- PackagingSpecs []PackagingSpec
+ InstallFiles InstallPaths
+ CheckbuildFiles Paths
+ UncheckedModule bool
+ PackagingSpecs []PackagingSpec
// katiInstalls tracks the install rules that were created by Soong but are being exported
// to Make to convert to ninja rules so that Make can add additional dependencies.
KatiInstalls katiInstalls
@@ -1882,18 +1922,19 @@ var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]()
// ModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and
// per-directory build targets.
+// @auto-generate: gob
type ModuleBuildTargetsInfo struct {
InstallTarget WritablePath
CheckbuildTarget WritablePath
BlueprintDir string
+ AllDeps Paths
}
var ModuleBuildTargetsProvider = blueprint.NewProvider[ModuleBuildTargetsInfo]()
+// @auto-generate: gob
type CommonModuleInfo struct {
Enabled bool
- // Whether the module has been replaced by a prebuilt
- ReplacedByPrebuilt bool
// The Target of artifacts that this module variant is responsible for creating.
Target Target
SkipAndroidMkProcessing bool
@@ -1901,7 +1942,6 @@ type CommonModuleInfo struct {
CanHaveApexVariants bool
MinSdkVersion ApiLevelOrPlatform
SdkVersion string
- NotAvailableForPlatform bool
// There some subtle differences between this one and the one above.
NotInPlatform bool
// UninstallableApexPlatformVariant is set by MakeUninstallable called by the apex
@@ -1921,7 +1961,7 @@ type CommonModuleInfo struct {
Host bool
IsApexModule bool
// The primary licenses property, may be nil, records license metadata for the module.
- PrimaryLicensesProperty applicableLicensesProperty
+ PrimaryLicensesProperty *applicableLicensesProperty
Owner string
Vendor bool
Proprietary bool
@@ -1929,6 +1969,7 @@ type CommonModuleInfo struct {
ProductSpecific bool
SystemExtSpecific bool
DeviceSpecific bool
+ UseGenericConfig bool
// When set to true, this module is not installed to the full install path (ex: under
// out/target/product/<name>/<partition>). It can be installed only to the packaging
// modules like android_filesystem.
@@ -1943,8 +1984,14 @@ type CommonModuleInfo struct {
ExportedToMake bool
Team string
PartitionTag string
+ ApexAvailable []string
+ // This field is different from the above one as it can have different values
+ // for cc, java library and sdkLibraryXml.
+ ApexAvailableFor []string
+ ImageVariation blueprint.Variation
}
+// @auto-generate: gob
type ApiLevelOrPlatform struct {
ApiLevel *ApiLevel
IsPlatform bool
@@ -1952,13 +1999,7 @@ type ApiLevelOrPlatform struct {
var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]()
-type PrebuiltModuleInfo struct {
- SourceExists bool
- UsePrebuilt bool
-}
-
-var PrebuiltModuleInfoProvider = blueprint.NewProvider[PrebuiltModuleInfo]()
-
+// @auto-generate: gob
type HostToolProviderInfo struct {
HostToolPath OptionalPath
}
@@ -1994,6 +2035,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
phonies: make(map[string]Paths),
}
+ blueprintCtx.RegisterConfigurableEvaluator(ctx)
+
+ if ctx.config.captureBuild {
+ ctx.config.modulesForTests.Insert(ctx.ModuleName(), ctx.Module())
+ }
+
setContainerInfo(ctx)
if ctx.Config().Getenv("DISABLE_CONTAINER_CHECK") != "true" {
checkContainerViolations(ctx)
@@ -2012,6 +2059,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
// TODO: This will be removed once defaults modules handle missing dependency errors
blueprintCtx.GetMissingDependencies()
+ checkVintfFragmentDeps(ctx)
+
// For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and
// are enabled. Unless the module is a CommonOS variant which may have dependencies on disabled variants
// (because the dependencies are added before the modules are disabled). The
@@ -2064,7 +2113,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
// so only a single rule is created for each init.rc or vintf fragment file.
if !m.InVendorRamdisk() {
- ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc.GetOrDefault(ctx, nil))
+ ctx.initRcPaths = PathsForModuleSrc(ctx, m.baseProperties.Init_rc.GetOrDefault(ctx, nil))
rcDir := PathForModuleInstall(ctx, "etc", "init")
for _, src := range ctx.initRcPaths {
installedInitRc := rcDir.Join(ctx, src.Base())
@@ -2080,7 +2129,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
installFiles.InstalledInitRcPaths = ctx.installedInitRcPaths
}
- ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(ctx, nil))
+ ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.baseProperties.Vintf_fragments.GetOrDefault(ctx, nil))
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
for _, src := range ctx.vintfFragmentsPaths {
installedVintfFragment := vintfDir.Join(ctx, src.Base())
@@ -2120,6 +2169,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
+ m.module.base().hooks.runPostGenerateAndroidBuildActionsHooks(ctx)
+
if x, ok := m.module.(IDEInfo); ok {
var result IdeInfo
x.IDEInfo(ctx, &result)
@@ -2136,17 +2187,18 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
- m.generateVariantTarget(ctx)
+ testData := FirstUniqueFunc(ctx.testData, func(a, b DataPath) bool {
+ return a == b
+ })
installFiles.LicenseMetadataFile = ctx.licenseMetadataFile
installFiles.InstallFiles = ctx.installFiles
installFiles.CheckbuildFiles = ctx.checkbuildFiles
- installFiles.CheckbuildTarget = ctx.checkbuildTarget
installFiles.UncheckedModule = ctx.uncheckedModule
installFiles.PackagingSpecs = ctx.packagingSpecs
installFiles.KatiInstalls = ctx.katiInstalls
installFiles.KatiSymlinks = ctx.katiSymlinks
- installFiles.TestData = ctx.testData
+ installFiles.TestData = testData
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -2166,18 +2218,27 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
}
- m.generateModuleTarget(ctx)
- if ctx.Failed() {
- return
- }
-
ctx.TransitiveInstallFiles = depset.New[InstallPath](depset.TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles)
installFiles.TransitiveInstallFiles = ctx.TransitiveInstallFiles
installFiles.TransitivePackagingSpecs = depset.New[PackagingSpec](depset.TOPOLOGICAL, ctx.packagingSpecs, dependencyPackagingSpecs)
- SetProvider(ctx, InstallFilesProvider, installFiles)
+ if m.Enabled(ctx) {
+ SetProvider(ctx, InstallFilesProvider, installFiles)
+ }
buildLicenseMetadata(ctx, ctx.licenseMetadataFile)
+ var testSuiteInstalls []filePair
+ if ctx.testSuiteInfoSet {
+ testSuiteInstalls = m.setupTestSuites(ctx, ctx.testSuiteInfo)
+ }
+
+ if m.Enabled(ctx) {
+ m.generateModuleTarget(ctx, testSuiteInstalls)
+ }
+ if ctx.Failed() {
+ return
+ }
+
if len(ctx.moduleInfoJSON) > 0 {
for _, moduleInfoJSON := range ctx.moduleInfoJSON {
if moduleInfoJSON.Disabled {
@@ -2257,7 +2318,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
}
}
- SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON)
+ SetProvider(ctx, ModuleInfoJSONProvider, ModuleInfoJSONInfo{
+ Data: ctx.moduleInfoJSON,
+ })
}
m.buildParams = ctx.buildParams
@@ -2285,7 +2348,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
commonData := CommonModuleInfo{
Enabled: m.Enabled(ctx),
- ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
Target: m.commonProperties.CompileTarget,
SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
UninstallableApexPlatformVariant: m.commonProperties.UninstallableApexPlatformVariant,
@@ -2300,6 +2362,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
ProductSpecific: Bool(m.commonProperties.Product_specific),
SystemExtSpecific: Bool(m.commonProperties.System_ext_specific),
DeviceSpecific: Bool(m.commonProperties.Device_specific),
+ UseGenericConfig: m.module.UseGenericConfig(),
NoFullInstall: proptools.Bool(m.commonProperties.No_full_install),
InVendorRamdisk: m.InVendorRamdisk(),
ExemptFromRequiredApplicableLicensesProperty: exemptFromRequiredApplicableLicensesProperty(m.module),
@@ -2311,6 +2374,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
ExportedToMake: m.ExportedToMake(),
Team: m.Team(),
PartitionTag: m.PartitionTag(ctx.DeviceConfig()),
+ ImageVariation: m.module.ImageVariation(),
}
if mm, ok := m.module.(interface {
MinSdkVersion(ctx EarlyModuleContext) ApiLevel
@@ -2341,11 +2405,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
if am, ok := m.module.(ApexModule); ok {
commonData.CanHaveApexVariants = am.CanHaveApexVariants()
- commonData.NotAvailableForPlatform = am.NotAvailableForPlatform()
commonData.NotInPlatform = am.NotInPlatform()
commonData.MinSdkVersionSupported = am.MinSdkVersionSupported(ctx)
commonData.IsInstallableToApex = am.IsInstallableToApex()
commonData.IsApexModule = true
+ commonData.ApexAvailable = am.apexModuleBase().ApexAvailable()
+ commonData.ApexAvailableFor = am.ApexAvailableFor()
}
if _, ok := m.module.(ModuleWithMinSdkVersionCheck); ok {
@@ -2359,12 +2424,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
commonData.BaseModuleName = mm.BaseModuleName()
}
SetProvider(ctx, CommonModuleInfoProvider, &commonData)
- if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
- SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{
- SourceExists: p.Prebuilt().SourceExists(),
- UsePrebuilt: p.Prebuilt().UsePrebuilt(),
- })
- }
+
if h, ok := m.module.(HostToolProvider); ok {
SetProvider(ctx, HostToolProviderInfoProvider, HostToolProviderInfo{
HostToolPath: h.HostToolPath()})
@@ -2393,6 +2453,185 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
})
}
}
+
+ if mm, ok := m.module.(RequiredFilesFromPrebuiltApex); ok {
+ SetProvider(ctx, RequiredFilesFromPrebuiltApexInfoProvider, RequiredFilesFromPrebuiltApexInfo{
+ RequiredFilesFromPrebuiltApex: mm.RequiredFilesFromPrebuiltApex(ctx),
+ UseProfileGuidedDexpreopt: mm.UseProfileGuidedDexpreopt(),
+ })
+ }
+
+ m.module.CleanupAfterBuildActions()
+}
+
+func (m *ModuleBase) CleanupAfterBuildActions() {}
+
+func (m *ModuleBase) setupTestSuites(ctx ModuleContext, info TestSuiteInfo) []filePair {
+ // We skip test suites when using the ndk or aml abis, as the extra archs (x86_64 + arm64)
+ // both try to install to the same test file. This could be fixed by always using a per-module
+ // folder and an arch folder, but as you see later in this function we only conditionally use
+ // those.
+ if ctx.Config().NdkAbis() || ctx.Config().AmlAbis() || shouldSkipAndroidMkProcessing(ctx, m) || m.IsSkipInstall() {
+ return nil
+ }
+ overriddenBy := ""
+ if b, ok := ctx.Module().(OverridableModule); ok {
+ overriddenBy = b.GetOverriddenBy()
+ }
+
+ // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
+ // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
+ // we add the full test suite to our list.
+ if PrefixInList(info.TestSuites, "mts-") && !InList("mts", info.TestSuites) {
+ info.TestSuites = append(info.TestSuites, "mts")
+ }
+ if PrefixInList(info.TestSuites, "mcts-") && !InList("mcts", info.TestSuites) {
+ info.TestSuites = append(info.TestSuites, "mcts")
+ }
+
+ if len(info.TestSuites) == 0 {
+ info.TestSuites = []string{"null-suite"}
+ }
+ info.TestSuites = SortedUniqueStrings(info.TestSuites)
+
+ name := ctx.ModuleName()
+ if overriddenBy != "" {
+ name = overriddenBy
+ }
+ name += info.NameSuffix
+
+ type testSuiteInfo struct {
+ name string
+ dir WritablePath
+ includeModuleFolder bool
+ }
+
+ suites := []testSuiteInfo{{
+ dir: PathForModuleInPartitionInstall(ctx, "testcases", name),
+ includeModuleFolder: true,
+ }}
+ for _, suite := range info.TestSuites {
+ if suiteInfo, ok := ctx.Config().productVariables.CompatibilityTestcases[suite]; ok {
+ rel, err := filepath.Rel(ctx.Config().OutDir(), suiteInfo.OutDir)
+ if err != nil {
+ panic(fmt.Sprintf("Could not make COMPATIBILITY_TESTCASES_OUT_%s (%s) relative to the out dir (%s)", suite, suiteInfo.OutDir, ctx.Config().OutDir()))
+ }
+ if suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory {
+ rel = filepath.Join(rel, name)
+ }
+ suites = append(suites, testSuiteInfo{
+ name: suite,
+ dir: PathForArbitraryOutput(ctx, rel),
+ includeModuleFolder: suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory,
+ })
+ }
+ }
+
+ var archDir string
+ if info.NeedsArchFolder {
+ archDir = ctx.Arch().ArchType.Name
+ if archDir == "common" {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ if ctx.Target().NativeBridge {
+ archDir = ctx.Target().NativeBridgeHostArchName
+ }
+ }
+
+ var installs []filePair
+ var oneVariantInstalls []filePair
+
+ for _, suite := range suites {
+ mainFileName := name
+ if info.MainFileStem != "" {
+ mainFileName = info.MainFileStem
+ }
+ mainFileName += info.MainFileExt
+ mainFileInstall := joinWriteablePath(ctx, suite.dir, archDir, mainFileName)
+ if !suite.includeModuleFolder {
+ mainFileInstall = joinWriteablePath(ctx, suite.dir, mainFileName)
+ }
+ if info.MainFile == nil {
+ panic("mainfile was nil")
+ }
+
+ installs = append(installs, filePair{
+ src: info.MainFile,
+ dst: mainFileInstall,
+ })
+
+ for _, data := range info.Data {
+ dataOut := joinWriteablePath(ctx, suite.dir, archDir, data.ToRelativeInstallPath())
+ if !suite.includeModuleFolder {
+ dataOut = joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath())
+ }
+ installs = append(installs, filePair{
+ src: data.SrcPath,
+ dst: dataOut,
+ })
+ }
+ for _, data := range info.NonArchData {
+ dataOut := joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath())
+ installs = append(installs, filePair{
+ src: data.SrcPath,
+ dst: dataOut,
+ })
+ }
+ for _, data := range info.CompatibilitySupportFiles {
+ dataOut := joinWriteablePath(ctx, suite.dir, data.Rel())
+ installs = append(installs, filePair{
+ src: data,
+ dst: dataOut,
+ })
+ }
+
+ if !info.DisableTestConfig {
+ if info.ConfigFile != nil {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: info.ConfigFile,
+ dst: joinWriteablePath(ctx, suite.dir, name+".config"+info.ConfigFileSuffix),
+ })
+ } else if config := ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml"); config.Valid() {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: config.Path(),
+ dst: joinWriteablePath(ctx, suite.dir, name+".config"),
+ })
+ }
+ }
+
+ dynamicConfig := ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: dynamicConfig.Path(),
+ dst: joinWriteablePath(ctx, suite.dir, name+".dynamic"),
+ })
+ }
+ for _, extraTestConfig := range info.ExtraConfigs {
+ if extraTestConfig == nil {
+ panic("ExtraTestConfig was nil")
+ }
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: extraTestConfig,
+ dst: joinWriteablePath(ctx, suite.dir, pathtools.ReplaceExtension(extraTestConfig.Base(), "config")),
+ })
+ }
+ }
+
+ SetProvider(ctx, TestSuiteInfoProvider, info)
+ SetProvider(ctx, testSuiteInstallsInfoProvider, testSuiteInstallsInfo{installs, oneVariantInstalls})
+
+ return slices.Concat(installs, oneVariantInstalls)
+}
+
+func joinWriteablePath(ctx PathContext, path WritablePath, toJoin ...string) WritablePath {
+ switch p := path.(type) {
+ case InstallPath:
+ return p.Join(ctx, toJoin...)
+ case OutputPath:
+ return p.Join(ctx, toJoin...)
+ default:
+ panic("unhandled path type")
+ }
}
func SetJarJarPrefixHandler(handler func(ModuleContext)) {
@@ -2465,6 +2704,7 @@ func checkDistProperties(ctx *moduleContext, property string, dist *Dist) {
}
// katiInstall stores a request from Soong to Make to create an install rule.
+// @auto-generate: gob
type katiInstall struct {
from Path
to InstallPath
@@ -2475,76 +2715,12 @@ type katiInstall struct {
absFrom string
}
-type katiInstallGob struct {
- From Path
- To InstallPath
- ImplicitDeps Paths
- OrderOnlyDeps Paths
- Executable bool
- ExtraFiles *extraFilesZip
- AbsFrom string
-}
-
-func (k *katiInstall) ToGob() *katiInstallGob {
- return &katiInstallGob{
- From: k.from,
- To: k.to,
- ImplicitDeps: k.implicitDeps,
- OrderOnlyDeps: k.orderOnlyDeps,
- Executable: k.executable,
- ExtraFiles: k.extraFiles,
- AbsFrom: k.absFrom,
- }
-}
-
-func (k *katiInstall) FromGob(data *katiInstallGob) {
- k.from = data.From
- k.to = data.To
- k.implicitDeps = data.ImplicitDeps
- k.orderOnlyDeps = data.OrderOnlyDeps
- k.executable = data.Executable
- k.extraFiles = data.ExtraFiles
- k.absFrom = data.AbsFrom
-}
-
-func (k *katiInstall) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[katiInstallGob](k)
-}
-
-func (k *katiInstall) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[katiInstallGob](data, k)
-}
-
+// @auto-generate: gob
type extraFilesZip struct {
zip Path
dir InstallPath
}
-type extraFilesZipGob struct {
- Zip Path
- Dir InstallPath
-}
-
-func (e *extraFilesZip) ToGob() *extraFilesZipGob {
- return &extraFilesZipGob{
- Zip: e.zip,
- Dir: e.dir,
- }
-}
-
-func (e *extraFilesZip) FromGob(data *extraFilesZipGob) {
- e.zip = data.Zip
- e.dir = data.Dir
-}
-
-func (e *extraFilesZip) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[extraFilesZipGob](e)
-}
-
-func (e *extraFilesZip) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[extraFilesZipGob](data, e)
-}
-
type katiInstalls []katiInstall
// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a
@@ -2599,11 +2775,13 @@ func (m *ModuleBase) DecodeMultilib(ctx ConfigContext) (string, string) {
}
func (m *ModuleBase) Overrides() []string {
- return m.commonProperties.Overrides
+ return m.baseProperties.Overrides
}
func (m *ModuleBase) UseGenericConfig() bool {
- return proptools.Bool(m.commonProperties.Use_generic_config)
+ // Platform module installed in the device must use generic config by default
+ defaultUseGenericConfig := m.Platform() && !m.Host() && !m.InstallInRamdisk() && !m.InstallInVendorRamdisk() && !m.InstallInRecovery()
+ return proptools.BoolDefault(m.commonProperties.Use_generic_config, defaultUseGenericConfig)
}
type ConfigContext interface {
@@ -2613,7 +2791,7 @@ type ConfigContext interface {
type ConfigurableEvaluatorContext interface {
OtherModuleProviderContext
Config() Config
- OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt string, args ...interface{})
HasMutatorFinished(mutatorName string) bool
}
@@ -2783,6 +2961,16 @@ func ModuleNameWithPossibleOverride(ctx BaseModuleContext) string {
return ctx.ModuleName()
}
+// OtherModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the
+// current variant of the given module, or ctx.ModuleName() if the given module is not an
+// OverridableModule or if this variant is not overridden.
+func OtherModuleNameWithPossibleOverride(ctx BaseModuleContext, m ModuleOrProxy) string {
+ if overrideInfo, ok := OtherModuleProvider(ctx, m, OverrideInfoProvider); ok && overrideInfo.OverriddenBy != "" {
+ return overrideInfo.OverriddenBy
+ }
+ return ctx.OtherModuleName(m)
+}
+
// SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name"
// into the module name, or empty string if the input was not a module reference.
func SrcIsModule(s string) (module string) {
@@ -2911,7 +3099,7 @@ type SourceFileProducer interface {
// OutputFilesForModule returns the output file paths with the given tag. On error, including if the
// module produced zero paths, it reports errors to the ctx and returns nil.
-func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths {
+func OutputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) Paths {
paths, err := outputFilesForModule(ctx, module, tag)
if err != nil {
reportPathError(ctx, err)
@@ -2924,7 +3112,7 @@ func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths {
// module produced zero or multiple paths, it reports errors to the ctx and returns nil.
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
+func OutputFileForModule(ctx PathContext, module ModuleOrProxy, tag string) Path {
paths, err := outputFilesForModule(ctx, module, tag)
if err != nil {
reportPathError(ctx, err)
@@ -2933,7 +3121,7 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
if len(paths) == 0 {
type addMissingDependenciesIntf interface {
AddMissingDependencies([]string)
- OtherModuleName(blueprint.Module) string
+ OtherModuleName(ModuleOrProxy) string
}
if mctx, ok := ctx.(addMissingDependenciesIntf); ok && ctx.Config().AllowMissingDependencies() {
mctx.AddMissingDependencies([]string{mctx.OtherModuleName(module)})
@@ -2957,6 +3145,12 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
return paths[0]
}
+// OutputFilesForModuleOrErr is the same as OutputFilesForModule except that it returns the
+// error instead of reporting it to the context
+func OutputFilesForModuleOrErr(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
+ return outputFilesForModule(ctx, module, tag)
+}
+
type OutputFilesProviderModuleContext interface {
OtherModuleProviderContext
Module() Module
@@ -2965,7 +3159,7 @@ type OutputFilesProviderModuleContext interface {
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, error) {
+func outputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
outputFilesFromProvider, err := outputFilesForModuleFromProvider(ctx, module, tag)
if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet {
return outputFilesFromProvider, err
@@ -2995,7 +3189,7 @@ func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, er
// from outputFiles property of module base, to avoid both setting and
// reading OutputFilesProvider before GenerateBuildActions is finished.
// If a module doesn't have the OutputFilesProvider, nil is returned.
-func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string) (Paths, error) {
+func outputFilesForModuleFromProvider(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
var outputFiles OutputFilesInfo
if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx {
@@ -3029,6 +3223,7 @@ func (o OutputFilesInfo) isEmpty() bool {
return o.DefaultOutputFiles == nil && o.TaggedOutputFiles == nil
}
+// @auto-generate: gob
type OutputFilesInfo struct {
// default output files when tag is an empty string ""
DefaultOutputFiles Paths
@@ -3163,9 +3358,10 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
hostCross bool
}
osDeps := map[osAndCross]Paths{}
- ctx.VisitAllModules(func(module Module) {
- if module.Enabled(ctx) {
- key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ info := OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoProvider)
+ if info.Enabled {
+ key := osAndCross{os: info.Target.Os, hostCross: info.Target.HostCross}
osDeps[key] = append(osDeps[key], OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).CheckbuildFiles...)
}
})
@@ -3219,6 +3415,8 @@ type IdeInfo struct {
Paths []string `json:"path,omitempty"`
Static_libs []string `json:"static_libs,omitempty"`
Libs []string `json:"libs,omitempty"`
+ Asset_dirs []string `json:"asset_dirs,omitempty"`
+ Resource_dirs []string `json:"resource_dirs,omitempty"`
}
// Merge merges two IdeInfos and produces a new one, leaving the origional unchanged
@@ -3235,6 +3433,8 @@ func (i IdeInfo) Merge(other IdeInfo) IdeInfo {
Paths: mergeStringLists(i.Paths, other.Paths),
Static_libs: mergeStringLists(i.Static_libs, other.Static_libs),
Libs: mergeStringLists(i.Libs, other.Libs),
+ Asset_dirs: mergeStringLists(i.Asset_dirs, other.Asset_dirs),
+ Resource_dirs: mergeStringLists(i.Resource_dirs, other.Resource_dirs),
}
}
@@ -3250,3 +3450,9 @@ func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents strin
bpctx := ctx.blueprintBaseModuleContext()
return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents)
}
+
+type HideApexVariantFromMakeInfo struct {
+ HideApexVariantFromMake bool
+}
+
+var HideApexVariantFromMakeProvider = blueprint.NewProvider[HideApexVariantFromMakeInfo]()
diff --git a/android/module_context.go b/android/module_context.go
index 0a23a745f..986ecf4f5 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -85,8 +85,6 @@ type BuildParams struct {
PhonyOutput bool
}
-type ModuleBuildParams BuildParams
-
type ModuleContext interface {
BaseModuleContext
@@ -94,21 +92,6 @@ type ModuleContext interface {
// used by the golang module types that need to call into the bootstrap module types.
BlueprintModuleContext() blueprint.ModuleContext
- // Deprecated: use ModuleContext.Build instead.
- ModuleBuild(pctx PackageContext, params ModuleBuildParams)
-
- // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
- // be tagged with `android:"path" to support automatic source module dependency resolution.
- //
- // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
- ExpandSources(srcFiles, excludes []string) Paths
-
- // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
- // be tagged with `android:"path" to support automatic source module dependency resolution.
- //
- // Deprecated: use PathForModuleSrc instead.
- ExpandSource(srcFile, prop string) Path
-
ExpandOptionalSource(srcFile *string, prop string) OptionalPath
// InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
@@ -185,6 +168,11 @@ type ModuleContext interface {
// dependency tags for which IsInstallDepNeeded returns true.
PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
+ // PackageFileWithFakeFullInstall creates a PackagingSpec, but does not require a full
+ // install by android_device.
+ // This is experimental, and is only meant to be used by Soong only builds.
+ PackageFileWithFakeFullInstall(installPath InstallPath, name string, srcPath Path) PackagingSpec
+
CheckbuildFile(srcPaths ...Path)
UncheckedModule()
@@ -267,6 +255,11 @@ type ModuleContext interface {
// goal is built.
DistForGoalWithFilename(goal string, path Path, filename string)
+ // DistForGoalWithFilenameTag creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename appended with the
+ // `-FILE_NAME_TAG_PLACEHOLDER` suffix when the specified goal is built.
+ DistForGoalWithFilenameTag(goal string, path Path, filename string)
+
// DistForGoals creates a rule to copy one or more Paths to the artifacts
// directory on the build server when any of the specified goals are built.
DistForGoals(goals []string, paths ...Path)
@@ -275,6 +268,15 @@ type ModuleContext interface {
// directory on the build server with the given filename when any of the
// specified goals are built.
DistForGoalsWithFilename(goals []string, path Path, filename string)
+
+ // Defines this module as a compatibility suite test and gives all the information needed
+ // to build the suite.
+ SetTestSuiteInfo(info TestSuiteInfo)
+
+ // FreeModuleAfterGenerateBuildActions marks this module as no longer necessary after the completion of
+ // GenerateBuildActions, i.e. all later accesses to the module will be via ModuleProxy and not direct access
+ // to the Module.
+ FreeModuleAfterGenerateBuildActions()
}
type moduleContext struct {
@@ -334,6 +336,9 @@ type moduleContext struct {
complianceMetadataInfo *ComplianceMetadataInfo
dists []dist
+
+ testSuiteInfo TestSuiteInfo
+ testSuiteInfoSet bool
}
var _ ModuleContext = &moduleContext{}
@@ -352,10 +357,6 @@ func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContex
}
}
-func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
- m.Build(pctx, BuildParams(params))
-}
-
// Convert build parameters from their concrete Android types into their string representations,
// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
func convertBuildParams(params BuildParams) blueprint.BuildParams {
@@ -417,7 +418,7 @@ func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.
if m.config.UseRemoteBuild() {
if params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // When USE_RBE=true is set and the rule is not supported by RBE, restrict
// jobs to the local parallelism value
params.Pool = localPool
} else if params.Pool == remotePool {
@@ -461,6 +462,9 @@ func (m *moduleContext) Phony(name string, deps ...Path) {
panic("Phony dep cannot be nil")
}
}
+ if name == "" {
+ panic("Phony name cannot be the empty string")
+ }
m.phonies[name] = append(m.phonies[name], deps...)
}
@@ -484,15 +488,15 @@ func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.Dependenc
}
}
-func (m *moduleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
+func (m *moduleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) ModuleProxy {
deps := m.getDirectDepsProxyInternal(name, tag)
if len(deps) == 1 {
- return &deps[0]
+ return deps[0]
} else if len(deps) >= 2 {
panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
name, m.ModuleName()))
} else {
- return nil
+ return ModuleProxy{}
}
}
@@ -622,6 +626,11 @@ func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPat
return m.packageFile(fullInstallPath, srcPath, false, false)
}
+func (m *moduleContext) PackageFileWithFakeFullInstall(installPath InstallPath, name string, srcPath Path) PackagingSpec {
+ fullInstallPath := installPath.Join(m, name)
+ return m.packageFile(fullInstallPath, srcPath, false, true)
+}
+
func (m *moduleContext) getAconfigPaths() Paths {
return m.aconfigFilePaths
}
@@ -632,7 +641,7 @@ func (m *moduleContext) setAconfigPaths(paths Paths) {
func (m *moduleContext) getOwnerAndOverrides() (string, []string) {
owner := m.ModuleName()
- overrides := slices.Clone(m.Module().base().commonProperties.Overrides)
+ overrides := slices.Clone(m.Module().base().baseProperties.Overrides)
if b, ok := m.Module().(OverridableModule); ok {
if b.GetOverriddenBy() != "" {
// overriding variant of base module
@@ -661,6 +670,7 @@ func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, e
requiresFullInstall: requiresFullInstall,
fullInstallPath: fullInstallPath,
variation: m.ModuleSubDir(),
+ prebuilt: IsModulePrebuilt(m, m.Module()),
}
m.packagingSpecs = append(m.packagingSpecs, spec)
return spec
@@ -816,6 +826,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src
requiresFullInstall: m.requiresFullInstall(),
fullInstallPath: fullInstallPath,
variation: m.ModuleSubDir(),
+ prebuilt: IsModulePrebuilt(m, m.Module()),
})
return fullInstallPath
@@ -867,6 +878,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str
requiresFullInstall: m.requiresFullInstall(),
fullInstallPath: fullInstallPath,
variation: m.ModuleSubDir(),
+ prebuilt: IsModulePrebuilt(m, m.Module()),
})
return fullInstallPath
@@ -964,22 +976,6 @@ func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
return m.complianceMetadataInfo
}
-// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
-// be tagged with `android:"path" to support automatic source module dependency resolution.
-//
-// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
-func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
- return PathsForModuleSrcExcludes(m, srcFiles, excludes)
-}
-
-// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
-// be tagged with `android:"path" to support automatic source module dependency resolution.
-//
-// Deprecated: use PathForModuleSrc instead.
-func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
- return PathForModuleSrc(m, srcFile)
-}
-
// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
// dependency resolution.
@@ -1018,6 +1014,15 @@ func (c *moduleContext) DistForGoalWithFilename(goal string, path Path, filename
c.DistForGoalsWithFilename([]string{goal}, path, filename)
}
+func (c *moduleContext) DistForGoalWithFilenameTag(goal string, path Path, filename string) {
+ insertBeforeExtension := func(file, insertion string) string {
+ ext := filepath.Ext(file)
+ return strings.TrimSuffix(file, ext) + insertion + ext
+ }
+
+ c.DistForGoalWithFilename(goal, path, insertBeforeExtension(filename, "-FILE_NAME_TAG_PLACEHOLDER"))
+}
+
func (c *moduleContext) DistForGoals(goals []string, paths ...Path) {
var copies distCopies
for _, path := range paths {
@@ -1038,3 +1043,15 @@ func (c *moduleContext) DistForGoalsWithFilename(goals []string, path Path, file
paths: distCopies{{from: path, dest: filename}},
})
}
+
+func (c *moduleContext) SetTestSuiteInfo(info TestSuiteInfo) {
+ if c.testSuiteInfoSet {
+ panic("Cannot call SetTestSuiteInfo twice")
+ }
+ c.testSuiteInfo = info
+ c.testSuiteInfoSet = true
+}
+
+func (c *moduleContext) FreeModuleAfterGenerateBuildActions() {
+ c.bp.FreeModuleAfterGenerateBuildActions()
+}
diff --git a/android/module_gob_enc.go b/android/module_gob_enc.go
new file mode 100644
index 000000000..4c64a0fb4
--- /dev/null
+++ b/android/module_gob_enc.go
@@ -0,0 +1,1497 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ DistGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(Dist) })
+ InstallFilesInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(InstallFilesInfo) })
+ ModuleBuildTargetsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleBuildTargetsInfo) })
+ CommonModuleInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CommonModuleInfo) })
+ ApiLevelOrPlatformGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ApiLevelOrPlatform) })
+ HostToolProviderInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(HostToolProviderInfo) })
+ katiInstallGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(katiInstall) })
+ extraFilesZipGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(extraFilesZip) })
+ OutputFilesInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(OutputFilesInfo) })
+}
+
+func (r Dist) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Targets))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Targets); val1++ {
+ if err = gobtools.EncodeString(buf, r.Targets[val1]); err != nil {
+ return err
+ }
+ }
+
+ val2 := r.Dest == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = gobtools.EncodeString(buf, (*r.Dest)); err != nil {
+ return err
+ }
+ }
+
+ val3 := r.Dir == nil
+ if err = gobtools.EncodeSimple(buf, val3); err != nil {
+ return err
+ }
+ if !val3 {
+ if err = gobtools.EncodeString(buf, (*r.Dir)); err != nil {
+ return err
+ }
+ }
+
+ val4 := r.Suffix == nil
+ if err = gobtools.EncodeSimple(buf, val4); err != nil {
+ return err
+ }
+ if !val4 {
+ if err = gobtools.EncodeString(buf, (*r.Suffix)); err != nil {
+ return err
+ }
+ }
+
+ val5 := r.Append_artifact_with_product == nil
+ if err = gobtools.EncodeSimple(buf, val5); err != nil {
+ return err
+ }
+ if !val5 {
+ if err = gobtools.EncodeSimple(buf, (*r.Append_artifact_with_product)); err != nil {
+ return err
+ }
+ }
+
+ val6 := r.Prepend_artifact_with_product == nil
+ if err = gobtools.EncodeSimple(buf, val6); err != nil {
+ return err
+ }
+ if !val6 {
+ if err = gobtools.EncodeSimple(buf, (*r.Prepend_artifact_with_product)); err != nil {
+ return err
+ }
+ }
+
+ val7 := r.Tag == nil
+ if err = gobtools.EncodeSimple(buf, val7); err != nil {
+ return err
+ }
+ if !val7 {
+ if err = gobtools.EncodeString(buf, (*r.Tag)); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *Dist) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.Targets = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.Targets[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val6 bool
+ if err = gobtools.DecodeSimple(buf, &val6); err != nil {
+ return err
+ }
+ if !val6 {
+ var val5 string
+ err = gobtools.DecodeString(buf, &val5)
+ if err != nil {
+ return err
+ }
+ r.Dest = &val5
+ }
+
+ var val9 bool
+ if err = gobtools.DecodeSimple(buf, &val9); err != nil {
+ return err
+ }
+ if !val9 {
+ var val8 string
+ err = gobtools.DecodeString(buf, &val8)
+ if err != nil {
+ return err
+ }
+ r.Dir = &val8
+ }
+
+ var val12 bool
+ if err = gobtools.DecodeSimple(buf, &val12); err != nil {
+ return err
+ }
+ if !val12 {
+ var val11 string
+ err = gobtools.DecodeString(buf, &val11)
+ if err != nil {
+ return err
+ }
+ r.Suffix = &val11
+ }
+
+ var val15 bool
+ if err = gobtools.DecodeSimple(buf, &val15); err != nil {
+ return err
+ }
+ if !val15 {
+ var val14 bool
+ err = gobtools.DecodeSimple[bool](buf, &val14)
+ if err != nil {
+ return err
+ }
+ r.Append_artifact_with_product = &val14
+ }
+
+ var val18 bool
+ if err = gobtools.DecodeSimple(buf, &val18); err != nil {
+ return err
+ }
+ if !val18 {
+ var val17 bool
+ err = gobtools.DecodeSimple[bool](buf, &val17)
+ if err != nil {
+ return err
+ }
+ r.Prepend_artifact_with_product = &val17
+ }
+
+ var val21 bool
+ if err = gobtools.DecodeSimple(buf, &val21); err != nil {
+ return err
+ }
+ if !val21 {
+ var val20 string
+ err = gobtools.DecodeString(buf, &val20)
+ if err != nil {
+ return err
+ }
+ r.Tag = &val20
+ }
+
+ return err
+}
+
+var DistGobRegId int16
+
+func (r Dist) GetTypeId() int16 {
+ return DistGobRegId
+}
+
+func (r InstallFilesInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.InstallFiles))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.InstallFiles); val1++ {
+ if err = r.InstallFiles[val1].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CheckbuildFiles))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.CheckbuildFiles); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.CheckbuildFiles[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.UncheckedModule); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.PackagingSpecs))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.PackagingSpecs); val3++ {
+ if err = r.PackagingSpecs[val3].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.KatiInstalls))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.KatiInstalls); val4++ {
+ if err = r.KatiInstalls[val4].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.KatiSymlinks))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.KatiSymlinks); val5++ {
+ if err = r.KatiSymlinks[val5].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TestData))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.TestData); val6++ {
+ if err = r.TestData[val6].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = r.TransitivePackagingSpecs.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.LicenseMetadataFile); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveInstallFiles.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.KatiInitRcInstalls))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.KatiInitRcInstalls); val7++ {
+ if err = r.KatiInitRcInstalls[val7].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.KatiVintfInstalls))); err != nil {
+ return err
+ }
+ for val8 := 0; val8 < len(r.KatiVintfInstalls); val8++ {
+ if err = r.KatiVintfInstalls[val8].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.InitRcPaths))); err != nil {
+ return err
+ }
+ for val9 := 0; val9 < len(r.InitRcPaths); val9++ {
+ if err = gobtools.EncodeInterface(buf, r.InitRcPaths[val9]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.VintfFragmentsPaths))); err != nil {
+ return err
+ }
+ for val10 := 0; val10 < len(r.VintfFragmentsPaths); val10++ {
+ if err = gobtools.EncodeInterface(buf, r.VintfFragmentsPaths[val10]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.InstalledInitRcPaths))); err != nil {
+ return err
+ }
+ for val11 := 0; val11 < len(r.InstalledInitRcPaths); val11++ {
+ if err = r.InstalledInitRcPaths[val11].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.InstalledVintfFragmentsPaths))); err != nil {
+ return err
+ }
+ for val12 := 0; val12 < len(r.InstalledVintfFragmentsPaths); val12++ {
+ if err = r.InstalledVintfFragmentsPaths[val12].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.DistFiles))); err != nil {
+ return err
+ }
+ for k, v := range r.DistFiles {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, int32(len(v))); err != nil {
+ return err
+ }
+ for val13 := 0; val13 < len(v); val13++ {
+ if err = gobtools.EncodeInterface(buf, v[val13]); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *InstallFilesInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.InstallFiles = make([]InstallPath, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if err = r.InstallFiles[val4].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.CheckbuildFiles = make([]Path, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ if val11, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val11 == nil {
+ r.CheckbuildFiles[val9] = nil
+ } else {
+ r.CheckbuildFiles[val9] = val11.(Path)
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.UncheckedModule)
+ if err != nil {
+ return err
+ }
+
+ var val14 int32
+ err = gobtools.DecodeSimple[int32](buf, &val14)
+ if err != nil {
+ return err
+ }
+ if val14 > 0 {
+ r.PackagingSpecs = make([]PackagingSpec, val14)
+ for val15 := 0; val15 < int(val14); val15++ {
+ if err = r.PackagingSpecs[val15].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val19 int32
+ err = gobtools.DecodeSimple[int32](buf, &val19)
+ if err != nil {
+ return err
+ }
+ if val19 > 0 {
+ r.KatiInstalls = make([]katiInstall, val19)
+ for val20 := 0; val20 < int(val19); val20++ {
+ if err = r.KatiInstalls[val20].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val24 int32
+ err = gobtools.DecodeSimple[int32](buf, &val24)
+ if err != nil {
+ return err
+ }
+ if val24 > 0 {
+ r.KatiSymlinks = make([]katiInstall, val24)
+ for val25 := 0; val25 < int(val24); val25++ {
+ if err = r.KatiSymlinks[val25].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val28 int32
+ err = gobtools.DecodeSimple[int32](buf, &val28)
+ if err != nil {
+ return err
+ }
+ if val28 > 0 {
+ r.TestData = make([]DataPath, val28)
+ for val29 := 0; val29 < int(val28); val29++ {
+ if err = r.TestData[val29].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = r.TransitivePackagingSpecs.Decode(buf); err != nil {
+ return err
+ }
+
+ if val33, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val33 == nil {
+ r.LicenseMetadataFile = nil
+ } else {
+ r.LicenseMetadataFile = val33.(WritablePath)
+ }
+
+ if err = r.TransitiveInstallFiles.Decode(buf); err != nil {
+ return err
+ }
+
+ var val37 int32
+ err = gobtools.DecodeSimple[int32](buf, &val37)
+ if err != nil {
+ return err
+ }
+ if val37 > 0 {
+ r.KatiInitRcInstalls = make([]katiInstall, val37)
+ for val38 := 0; val38 < int(val37); val38++ {
+ if err = r.KatiInitRcInstalls[val38].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val42 int32
+ err = gobtools.DecodeSimple[int32](buf, &val42)
+ if err != nil {
+ return err
+ }
+ if val42 > 0 {
+ r.KatiVintfInstalls = make([]katiInstall, val42)
+ for val43 := 0; val43 < int(val42); val43++ {
+ if err = r.KatiVintfInstalls[val43].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val47 int32
+ err = gobtools.DecodeSimple[int32](buf, &val47)
+ if err != nil {
+ return err
+ }
+ if val47 > 0 {
+ r.InitRcPaths = make([]Path, val47)
+ for val48 := 0; val48 < int(val47); val48++ {
+ if val50, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val50 == nil {
+ r.InitRcPaths[val48] = nil
+ } else {
+ r.InitRcPaths[val48] = val50.(Path)
+ }
+ }
+ }
+
+ var val53 int32
+ err = gobtools.DecodeSimple[int32](buf, &val53)
+ if err != nil {
+ return err
+ }
+ if val53 > 0 {
+ r.VintfFragmentsPaths = make([]Path, val53)
+ for val54 := 0; val54 < int(val53); val54++ {
+ if val56, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val56 == nil {
+ r.VintfFragmentsPaths[val54] = nil
+ } else {
+ r.VintfFragmentsPaths[val54] = val56.(Path)
+ }
+ }
+ }
+
+ var val59 int32
+ err = gobtools.DecodeSimple[int32](buf, &val59)
+ if err != nil {
+ return err
+ }
+ if val59 > 0 {
+ r.InstalledInitRcPaths = make([]InstallPath, val59)
+ for val60 := 0; val60 < int(val59); val60++ {
+ if err = r.InstalledInitRcPaths[val60].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val64 int32
+ err = gobtools.DecodeSimple[int32](buf, &val64)
+ if err != nil {
+ return err
+ }
+ if val64 > 0 {
+ r.InstalledVintfFragmentsPaths = make([]InstallPath, val64)
+ for val65 := 0; val65 < int(val64); val65++ {
+ if err = r.InstalledVintfFragmentsPaths[val65].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val68 int32
+ err = gobtools.DecodeSimple[int32](buf, &val68)
+ if err != nil {
+ return err
+ }
+ if val68 > 0 {
+ r.DistFiles = make(map[string]Paths, val68)
+ for val69 := 0; val69 < int(val68); val69++ {
+ var k string
+ var v Paths
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ var val73 int32
+ err = gobtools.DecodeSimple[int32](buf, &val73)
+ if err != nil {
+ return err
+ }
+ if val73 > 0 {
+ v = make([]Path, val73)
+ for val74 := 0; val74 < int(val73); val74++ {
+ if val76, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val76 == nil {
+ v[val74] = nil
+ } else {
+ v[val74] = val76.(Path)
+ }
+ }
+ }
+ r.DistFiles[k] = v
+ }
+ }
+
+ return err
+}
+
+var InstallFilesInfoGobRegId int16
+
+func (r InstallFilesInfo) GetTypeId() int16 {
+ return InstallFilesInfoGobRegId
+}
+
+func (r ModuleBuildTargetsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.InstallTarget); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.CheckbuildTarget); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.BlueprintDir); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.AllDeps))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.AllDeps); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.AllDeps[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *ModuleBuildTargetsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.InstallTarget = nil
+ } else {
+ r.InstallTarget = val2.(WritablePath)
+ }
+
+ if val4, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val4 == nil {
+ r.CheckbuildTarget = nil
+ } else {
+ r.CheckbuildTarget = val4.(WritablePath)
+ }
+
+ err = gobtools.DecodeString(buf, &r.BlueprintDir)
+ if err != nil {
+ return err
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.AllDeps = make([]Path, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ if val11, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val11 == nil {
+ r.AllDeps[val9] = nil
+ } else {
+ r.AllDeps[val9] = val11.(Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var ModuleBuildTargetsInfoGobRegId int16
+
+func (r ModuleBuildTargetsInfo) GetTypeId() int16 {
+ return ModuleBuildTargetsInfoGobRegId
+}
+
+func (r CommonModuleInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.Enabled); err != nil {
+ return err
+ }
+
+ if err = r.Target.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.SkipAndroidMkProcessing); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.BaseModuleName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.CanHaveApexVariants); err != nil {
+ return err
+ }
+
+ if err = r.MinSdkVersion.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.SdkVersion); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.NotInPlatform); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.UninstallableApexPlatformVariant); err != nil {
+ return err
+ }
+
+ if err = r.MinSdkVersionSupported.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.ModuleWithMinSdkVersionCheck); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsInstallableToApex); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HideFromMake); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.SkipInstall); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsStubsModule); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Host); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsApexModule); err != nil {
+ return err
+ }
+
+ val1 := r.PrimaryLicensesProperty == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = (*r.PrimaryLicensesProperty).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.Owner); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Vendor); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Proprietary); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.SocSpecific); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.ProductSpecific); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.SystemExtSpecific); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.DeviceSpecific); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.UseGenericConfig); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.NoFullInstall); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InVendorRamdisk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.ExemptFromRequiredApplicableLicensesProperty); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.RequiredModuleNames))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.RequiredModuleNames); val2++ {
+ if err = gobtools.EncodeString(buf, r.RequiredModuleNames[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.HostRequiredModuleNames))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.HostRequiredModuleNames); val3++ {
+ if err = gobtools.EncodeString(buf, r.HostRequiredModuleNames[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TargetRequiredModuleNames))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.TargetRequiredModuleNames); val4++ {
+ if err = gobtools.EncodeString(buf, r.TargetRequiredModuleNames[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.VintfFragmentModuleNames))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.VintfFragmentModuleNames); val5++ {
+ if err = gobtools.EncodeString(buf, r.VintfFragmentModuleNames[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Dists))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.Dists); val6++ {
+ if err = r.Dists[val6].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.ExportedToMake); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Team); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.PartitionTag); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ApexAvailable))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.ApexAvailable); val7++ {
+ if err = gobtools.EncodeString(buf, r.ApexAvailable[val7]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ApexAvailableFor))); err != nil {
+ return err
+ }
+ for val8 := 0; val8 < len(r.ApexAvailableFor); val8++ {
+ if err = gobtools.EncodeString(buf, r.ApexAvailableFor[val8]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.ImageVariation.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *CommonModuleInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Enabled)
+ if err != nil {
+ return err
+ }
+
+ if err = r.Target.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.SkipAndroidMkProcessing)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.BaseModuleName)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.CanHaveApexVariants)
+ if err != nil {
+ return err
+ }
+
+ if err = r.MinSdkVersion.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.SdkVersion)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.NotInPlatform)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.UninstallableApexPlatformVariant)
+ if err != nil {
+ return err
+ }
+
+ if err = r.MinSdkVersionSupported.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ModuleWithMinSdkVersionCheck)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsInstallableToApex)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HideFromMake)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.SkipInstall)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsStubsModule)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Host)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsApexModule)
+ if err != nil {
+ return err
+ }
+
+ var val19 bool
+ if err = gobtools.DecodeSimple(buf, &val19); err != nil {
+ return err
+ }
+ if !val19 {
+ var val18 applicableLicensesProperty
+ if err = val18.Decode(buf); err != nil {
+ return err
+ }
+ r.PrimaryLicensesProperty = &val18
+ }
+
+ err = gobtools.DecodeString(buf, &r.Owner)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Vendor)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Proprietary)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.SocSpecific)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ProductSpecific)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.SystemExtSpecific)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.DeviceSpecific)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.UseGenericConfig)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.NoFullInstall)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InVendorRamdisk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ExemptFromRequiredApplicableLicensesProperty)
+ if err != nil {
+ return err
+ }
+
+ var val33 int32
+ err = gobtools.DecodeSimple[int32](buf, &val33)
+ if err != nil {
+ return err
+ }
+ if val33 > 0 {
+ r.RequiredModuleNames = make([]string, val33)
+ for val34 := 0; val34 < int(val33); val34++ {
+ err = gobtools.DecodeString(buf, &r.RequiredModuleNames[val34])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val37 int32
+ err = gobtools.DecodeSimple[int32](buf, &val37)
+ if err != nil {
+ return err
+ }
+ if val37 > 0 {
+ r.HostRequiredModuleNames = make([]string, val37)
+ for val38 := 0; val38 < int(val37); val38++ {
+ err = gobtools.DecodeString(buf, &r.HostRequiredModuleNames[val38])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val41 int32
+ err = gobtools.DecodeSimple[int32](buf, &val41)
+ if err != nil {
+ return err
+ }
+ if val41 > 0 {
+ r.TargetRequiredModuleNames = make([]string, val41)
+ for val42 := 0; val42 < int(val41); val42++ {
+ err = gobtools.DecodeString(buf, &r.TargetRequiredModuleNames[val42])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val45 int32
+ err = gobtools.DecodeSimple[int32](buf, &val45)
+ if err != nil {
+ return err
+ }
+ if val45 > 0 {
+ r.VintfFragmentModuleNames = make([]string, val45)
+ for val46 := 0; val46 < int(val45); val46++ {
+ err = gobtools.DecodeString(buf, &r.VintfFragmentModuleNames[val46])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val49 int32
+ err = gobtools.DecodeSimple[int32](buf, &val49)
+ if err != nil {
+ return err
+ }
+ if val49 > 0 {
+ r.Dists = make([]Dist, val49)
+ for val50 := 0; val50 < int(val49); val50++ {
+ if err = r.Dists[val50].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ExportedToMake)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Team)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.PartitionTag)
+ if err != nil {
+ return err
+ }
+
+ var val56 int32
+ err = gobtools.DecodeSimple[int32](buf, &val56)
+ if err != nil {
+ return err
+ }
+ if val56 > 0 {
+ r.ApexAvailable = make([]string, val56)
+ for val57 := 0; val57 < int(val56); val57++ {
+ err = gobtools.DecodeString(buf, &r.ApexAvailable[val57])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val60 int32
+ err = gobtools.DecodeSimple[int32](buf, &val60)
+ if err != nil {
+ return err
+ }
+ if val60 > 0 {
+ r.ApexAvailableFor = make([]string, val60)
+ for val61 := 0; val61 < int(val60); val61++ {
+ err = gobtools.DecodeString(buf, &r.ApexAvailableFor[val61])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = r.ImageVariation.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var CommonModuleInfoGobRegId int16
+
+func (r CommonModuleInfo) GetTypeId() int16 {
+ return CommonModuleInfoGobRegId
+}
+
+func (r ApiLevelOrPlatform) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ val1 := r.ApiLevel == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = (*r.ApiLevel).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsPlatform); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ApiLevelOrPlatform) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 bool
+ if err = gobtools.DecodeSimple(buf, &val2); err != nil {
+ return err
+ }
+ if !val2 {
+ var val1 ApiLevel
+ if err = val1.Decode(buf); err != nil {
+ return err
+ }
+ r.ApiLevel = &val1
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsPlatform)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ApiLevelOrPlatformGobRegId int16
+
+func (r ApiLevelOrPlatform) GetTypeId() int16 {
+ return ApiLevelOrPlatformGobRegId
+}
+
+func (r HostToolProviderInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.HostToolPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *HostToolProviderInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.HostToolPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var HostToolProviderInfoGobRegId int16
+
+func (r HostToolProviderInfo) GetTypeId() int16 {
+ return HostToolProviderInfoGobRegId
+}
+
+func (r katiInstall) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.from); err != nil {
+ return err
+ }
+
+ if err = r.to.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.implicitDeps))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.implicitDeps); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.implicitDeps[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.orderOnlyDeps))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.orderOnlyDeps); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.orderOnlyDeps[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.executable); err != nil {
+ return err
+ }
+
+ val3 := r.extraFiles == nil
+ if err = gobtools.EncodeSimple(buf, val3); err != nil {
+ return err
+ }
+ if !val3 {
+ if err = (*r.extraFiles).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.absFrom); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *katiInstall) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.from = nil
+ } else {
+ r.from = val2.(Path)
+ }
+
+ if err = r.to.Decode(buf); err != nil {
+ return err
+ }
+
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ r.implicitDeps = make([]Path, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ if val9, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val9 == nil {
+ r.implicitDeps[val7] = nil
+ } else {
+ r.implicitDeps[val7] = val9.(Path)
+ }
+ }
+ }
+
+ var val12 int32
+ err = gobtools.DecodeSimple[int32](buf, &val12)
+ if err != nil {
+ return err
+ }
+ if val12 > 0 {
+ r.orderOnlyDeps = make([]Path, val12)
+ for val13 := 0; val13 < int(val12); val13++ {
+ if val15, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val15 == nil {
+ r.orderOnlyDeps[val13] = nil
+ } else {
+ r.orderOnlyDeps[val13] = val15.(Path)
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.executable)
+ if err != nil {
+ return err
+ }
+
+ var val18 bool
+ if err = gobtools.DecodeSimple(buf, &val18); err != nil {
+ return err
+ }
+ if !val18 {
+ var val17 extraFilesZip
+ if err = val17.Decode(buf); err != nil {
+ return err
+ }
+ r.extraFiles = &val17
+ }
+
+ err = gobtools.DecodeString(buf, &r.absFrom)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var katiInstallGobRegId int16
+
+func (r katiInstall) GetTypeId() int16 {
+ return katiInstallGobRegId
+}
+
+func (r extraFilesZip) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.zip); err != nil {
+ return err
+ }
+
+ if err = r.dir.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *extraFilesZip) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.zip = nil
+ } else {
+ r.zip = val2.(Path)
+ }
+
+ if err = r.dir.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var extraFilesZipGobRegId int16
+
+func (r extraFilesZip) GetTypeId() int16 {
+ return extraFilesZipGobRegId
+}
+
+func (r OutputFilesInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.DefaultOutputFiles))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.DefaultOutputFiles); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.DefaultOutputFiles[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TaggedOutputFiles))); err != nil {
+ return err
+ }
+ for k, v := range r.TaggedOutputFiles {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, int32(len(v))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(v); val2++ {
+ if err = gobtools.EncodeInterface(buf, v[val2]); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *OutputFilesInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.DefaultOutputFiles = make([]Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.DefaultOutputFiles[val4] = nil
+ } else {
+ r.DefaultOutputFiles[val4] = val6.(Path)
+ }
+ }
+ }
+
+ var val7 int32
+ err = gobtools.DecodeSimple[int32](buf, &val7)
+ if err != nil {
+ return err
+ }
+ if val7 > 0 {
+ r.TaggedOutputFiles = make(map[string]Paths, val7)
+ for val8 := 0; val8 < int(val7); val8++ {
+ var k string
+ var v Paths
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ var val12 int32
+ err = gobtools.DecodeSimple[int32](buf, &val12)
+ if err != nil {
+ return err
+ }
+ if val12 > 0 {
+ v = make([]Path, val12)
+ for val13 := 0; val13 < int(val12); val13++ {
+ if val15, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val15 == nil {
+ v[val13] = nil
+ } else {
+ v[val13] = val15.(Path)
+ }
+ }
+ }
+ r.TaggedOutputFiles[k] = v
+ }
+ }
+
+ return err
+}
+
+var OutputFilesInfoGobRegId int16
+
+func (r OutputFilesInfo) GetTypeId() int16 {
+ return OutputFilesInfoGobRegId
+}
diff --git a/android/module_info_json.go b/android/module_info_json.go
index 50c961abe..661264bcd 100644
--- a/android/module_info_json.go
+++ b/android/module_info_json.go
@@ -6,9 +6,11 @@ import (
"slices"
"github.com/google/blueprint"
- "github.com/google/blueprint/gobtools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
+// @auto-generate: gob
type CoreModuleInfoJSON struct {
RegisterName string `json:"-"`
Path []string `json:"path,omitempty"` // $(sort $(ALL_MODULES.$(m).PATH))
@@ -21,6 +23,7 @@ type CoreModuleInfoJSON struct {
Required []string `json:"required,omitempty"` // $(sort $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET))
}
+// @auto-generate: gob
type ExtraModuleInfoJSON struct {
SubName string `json:"-"`
Uninstallable bool `json:"-"`
@@ -53,6 +56,7 @@ type ExtraModuleInfoJSON struct {
ModuleNameOverride string `json:"-"`
}
+// @auto-generate: gob
type ModuleInfoJSON struct {
core CoreModuleInfoJSON
ExtraModuleInfoJSON
@@ -115,26 +119,6 @@ func encodeModuleInfoJSON(w io.Writer, moduleInfoJSON *ModuleInfoJSON) error {
return encoder.Encode(combinedModuleInfoJSON{&moduleInfoJSONCopy.core, &moduleInfoJSONCopy.ExtraModuleInfoJSON})
}
-func (p *ModuleInfoJSON) ToGob() *combinedModuleInfoJSON {
- return &combinedModuleInfoJSON{
- CoreModuleInfoJSON: &p.core,
- ExtraModuleInfoJSON: &p.ExtraModuleInfoJSON,
- }
-}
-
-func (p *ModuleInfoJSON) FromGob(data *combinedModuleInfoJSON) {
- p.core = *data.CoreModuleInfoJSON
- p.ExtraModuleInfoJSON = *data.ExtraModuleInfoJSON
-}
-
-func (m *ModuleInfoJSON) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[combinedModuleInfoJSON](m)
-}
-
-func (m *ModuleInfoJSON) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[combinedModuleInfoJSON](data, m)
-}
-
func (m *ModuleInfoJSON) GetInstalled() []string {
return m.core.Installed
}
@@ -143,4 +127,9 @@ func (m *ModuleInfoJSON) GetClass() []string {
return m.Class
}
-var ModuleInfoJSONProvider = blueprint.NewProvider[[]*ModuleInfoJSON]()
+// @auto-generate: gob
+type ModuleInfoJSONInfo struct {
+ Data []*ModuleInfoJSON
+}
+
+var ModuleInfoJSONProvider = blueprint.NewProvider[ModuleInfoJSONInfo]()
diff --git a/android/module_info_json_gob_enc.go b/android/module_info_json_gob_enc.go
new file mode 100644
index 000000000..46311ab08
--- /dev/null
+++ b/android/module_info_json_gob_enc.go
@@ -0,0 +1,865 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ CoreModuleInfoJSONGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CoreModuleInfoJSON) })
+ ExtraModuleInfoJSONGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ExtraModuleInfoJSON) })
+ ModuleInfoJSONGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleInfoJSON) })
+ ModuleInfoJSONInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleInfoJSONInfo) })
+}
+
+func (r CoreModuleInfoJSON) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.RegisterName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Path))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Path); val1++ {
+ if err = gobtools.EncodeString(buf, r.Path[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Installed))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Installed); val2++ {
+ if err = gobtools.EncodeString(buf, r.Installed[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.ModuleName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SupportedVariants))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.SupportedVariants); val3++ {
+ if err = gobtools.EncodeString(buf, r.SupportedVariants[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.HostDependencies))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.HostDependencies); val4++ {
+ if err = gobtools.EncodeString(buf, r.HostDependencies[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TargetDependencies))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.TargetDependencies); val5++ {
+ if err = gobtools.EncodeString(buf, r.TargetDependencies[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Data))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.Data); val6++ {
+ if err = gobtools.EncodeString(buf, r.Data[val6]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Required))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.Required); val7++ {
+ if err = gobtools.EncodeString(buf, r.Required[val7]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *CoreModuleInfoJSON) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.RegisterName)
+ if err != nil {
+ return err
+ }
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.Path = make([]string, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ err = gobtools.DecodeString(buf, &r.Path[val4])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val7 int32
+ err = gobtools.DecodeSimple[int32](buf, &val7)
+ if err != nil {
+ return err
+ }
+ if val7 > 0 {
+ r.Installed = make([]string, val7)
+ for val8 := 0; val8 < int(val7); val8++ {
+ err = gobtools.DecodeString(buf, &r.Installed[val8])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeString(buf, &r.ModuleName)
+ if err != nil {
+ return err
+ }
+
+ var val12 int32
+ err = gobtools.DecodeSimple[int32](buf, &val12)
+ if err != nil {
+ return err
+ }
+ if val12 > 0 {
+ r.SupportedVariants = make([]string, val12)
+ for val13 := 0; val13 < int(val12); val13++ {
+ err = gobtools.DecodeString(buf, &r.SupportedVariants[val13])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ r.HostDependencies = make([]string, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ err = gobtools.DecodeString(buf, &r.HostDependencies[val17])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val20 int32
+ err = gobtools.DecodeSimple[int32](buf, &val20)
+ if err != nil {
+ return err
+ }
+ if val20 > 0 {
+ r.TargetDependencies = make([]string, val20)
+ for val21 := 0; val21 < int(val20); val21++ {
+ err = gobtools.DecodeString(buf, &r.TargetDependencies[val21])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val24 int32
+ err = gobtools.DecodeSimple[int32](buf, &val24)
+ if err != nil {
+ return err
+ }
+ if val24 > 0 {
+ r.Data = make([]string, val24)
+ for val25 := 0; val25 < int(val24); val25++ {
+ err = gobtools.DecodeString(buf, &r.Data[val25])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val28 int32
+ err = gobtools.DecodeSimple[int32](buf, &val28)
+ if err != nil {
+ return err
+ }
+ if val28 > 0 {
+ r.Required = make([]string, val28)
+ for val29 := 0; val29 < int(val28); val29++ {
+ err = gobtools.DecodeString(buf, &r.Required[val29])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var CoreModuleInfoJSONGobRegId int16
+
+func (r CoreModuleInfoJSON) GetTypeId() int16 {
+ return CoreModuleInfoJSONGobRegId
+}
+
+func (r ExtraModuleInfoJSON) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.SubName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Uninstallable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Class))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Class); val1++ {
+ if err = gobtools.EncodeString(buf, r.Class[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Tags))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Tags); val2++ {
+ if err = gobtools.EncodeString(buf, r.Tags[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Dependencies))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Dependencies); val3++ {
+ if err = gobtools.EncodeString(buf, r.Dependencies[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SharedLibs))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.SharedLibs); val4++ {
+ if err = gobtools.EncodeString(buf, r.SharedLibs[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.StaticLibs))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.StaticLibs); val5++ {
+ if err = gobtools.EncodeString(buf, r.StaticLibs[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SystemSharedLibs))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.SystemSharedLibs); val6++ {
+ if err = gobtools.EncodeString(buf, r.SystemSharedLibs[val6]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Srcs))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.Srcs); val7++ {
+ if err = gobtools.EncodeString(buf, r.Srcs[val7]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SrcJars))); err != nil {
+ return err
+ }
+ for val8 := 0; val8 < len(r.SrcJars); val8++ {
+ if err = gobtools.EncodeString(buf, r.SrcJars[val8]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ClassesJar))); err != nil {
+ return err
+ }
+ for val9 := 0; val9 < len(r.ClassesJar); val9++ {
+ if err = gobtools.EncodeString(buf, r.ClassesJar[val9]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TestMainlineModules))); err != nil {
+ return err
+ }
+ for val10 := 0; val10 < len(r.TestMainlineModules); val10++ {
+ if err = gobtools.EncodeString(buf, r.TestMainlineModules[val10]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.IsUnitTest); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TestOptionsTags))); err != nil {
+ return err
+ }
+ for val11 := 0; val11 < len(r.TestOptionsTags); val11++ {
+ if err = gobtools.EncodeString(buf, r.TestOptionsTags[val11]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.RuntimeDependencies))); err != nil {
+ return err
+ }
+ for val12 := 0; val12 < len(r.RuntimeDependencies); val12++ {
+ if err = gobtools.EncodeString(buf, r.RuntimeDependencies[val12]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.StaticDependencies))); err != nil {
+ return err
+ }
+ for val13 := 0; val13 < len(r.StaticDependencies); val13++ {
+ if err = gobtools.EncodeString(buf, r.StaticDependencies[val13]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.DataDependencies))); err != nil {
+ return err
+ }
+ for val14 := 0; val14 < len(r.DataDependencies); val14++ {
+ if err = gobtools.EncodeString(buf, r.DataDependencies[val14]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CompatibilitySuites))); err != nil {
+ return err
+ }
+ for val15 := 0; val15 < len(r.CompatibilitySuites); val15++ {
+ if err = gobtools.EncodeString(buf, r.CompatibilitySuites[val15]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.AutoTestConfig))); err != nil {
+ return err
+ }
+ for val16 := 0; val16 < len(r.AutoTestConfig); val16++ {
+ if err = gobtools.EncodeString(buf, r.AutoTestConfig[val16]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TestConfig))); err != nil {
+ return err
+ }
+ for val17 := 0; val17 < len(r.TestConfig); val17++ {
+ if err = gobtools.EncodeString(buf, r.TestConfig[val17]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.TestModuleConfigBase); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExtraRequired))); err != nil {
+ return err
+ }
+ for val18 := 0; val18 < len(r.ExtraRequired); val18++ {
+ if err = gobtools.EncodeString(buf, r.ExtraRequired[val18]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExtraHostRequired))); err != nil {
+ return err
+ }
+ for val19 := 0; val19 < len(r.ExtraHostRequired); val19++ {
+ if err = gobtools.EncodeString(buf, r.ExtraHostRequired[val19]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SupportedVariantsOverride))); err != nil {
+ return err
+ }
+ for val20 := 0; val20 < len(r.SupportedVariantsOverride); val20++ {
+ if err = gobtools.EncodeString(buf, r.SupportedVariantsOverride[val20]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Disabled); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.RegisterNameOverride); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.ModuleNameOverride); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ExtraModuleInfoJSON) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.SubName)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Uninstallable)
+ if err != nil {
+ return err
+ }
+
+ var val4 int32
+ err = gobtools.DecodeSimple[int32](buf, &val4)
+ if err != nil {
+ return err
+ }
+ if val4 > 0 {
+ r.Class = make([]string, val4)
+ for val5 := 0; val5 < int(val4); val5++ {
+ err = gobtools.DecodeString(buf, &r.Class[val5])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.Tags = make([]string, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ err = gobtools.DecodeString(buf, &r.Tags[val9])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val12 int32
+ err = gobtools.DecodeSimple[int32](buf, &val12)
+ if err != nil {
+ return err
+ }
+ if val12 > 0 {
+ r.Dependencies = make([]string, val12)
+ for val13 := 0; val13 < int(val12); val13++ {
+ err = gobtools.DecodeString(buf, &r.Dependencies[val13])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ r.SharedLibs = make([]string, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ err = gobtools.DecodeString(buf, &r.SharedLibs[val17])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val20 int32
+ err = gobtools.DecodeSimple[int32](buf, &val20)
+ if err != nil {
+ return err
+ }
+ if val20 > 0 {
+ r.StaticLibs = make([]string, val20)
+ for val21 := 0; val21 < int(val20); val21++ {
+ err = gobtools.DecodeString(buf, &r.StaticLibs[val21])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val24 int32
+ err = gobtools.DecodeSimple[int32](buf, &val24)
+ if err != nil {
+ return err
+ }
+ if val24 > 0 {
+ r.SystemSharedLibs = make([]string, val24)
+ for val25 := 0; val25 < int(val24); val25++ {
+ err = gobtools.DecodeString(buf, &r.SystemSharedLibs[val25])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val28 int32
+ err = gobtools.DecodeSimple[int32](buf, &val28)
+ if err != nil {
+ return err
+ }
+ if val28 > 0 {
+ r.Srcs = make([]string, val28)
+ for val29 := 0; val29 < int(val28); val29++ {
+ err = gobtools.DecodeString(buf, &r.Srcs[val29])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val32 int32
+ err = gobtools.DecodeSimple[int32](buf, &val32)
+ if err != nil {
+ return err
+ }
+ if val32 > 0 {
+ r.SrcJars = make([]string, val32)
+ for val33 := 0; val33 < int(val32); val33++ {
+ err = gobtools.DecodeString(buf, &r.SrcJars[val33])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val36 int32
+ err = gobtools.DecodeSimple[int32](buf, &val36)
+ if err != nil {
+ return err
+ }
+ if val36 > 0 {
+ r.ClassesJar = make([]string, val36)
+ for val37 := 0; val37 < int(val36); val37++ {
+ err = gobtools.DecodeString(buf, &r.ClassesJar[val37])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val40 int32
+ err = gobtools.DecodeSimple[int32](buf, &val40)
+ if err != nil {
+ return err
+ }
+ if val40 > 0 {
+ r.TestMainlineModules = make([]string, val40)
+ for val41 := 0; val41 < int(val40); val41++ {
+ err = gobtools.DecodeString(buf, &r.TestMainlineModules[val41])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeString(buf, &r.IsUnitTest)
+ if err != nil {
+ return err
+ }
+
+ var val45 int32
+ err = gobtools.DecodeSimple[int32](buf, &val45)
+ if err != nil {
+ return err
+ }
+ if val45 > 0 {
+ r.TestOptionsTags = make([]string, val45)
+ for val46 := 0; val46 < int(val45); val46++ {
+ err = gobtools.DecodeString(buf, &r.TestOptionsTags[val46])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val49 int32
+ err = gobtools.DecodeSimple[int32](buf, &val49)
+ if err != nil {
+ return err
+ }
+ if val49 > 0 {
+ r.RuntimeDependencies = make([]string, val49)
+ for val50 := 0; val50 < int(val49); val50++ {
+ err = gobtools.DecodeString(buf, &r.RuntimeDependencies[val50])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val53 int32
+ err = gobtools.DecodeSimple[int32](buf, &val53)
+ if err != nil {
+ return err
+ }
+ if val53 > 0 {
+ r.StaticDependencies = make([]string, val53)
+ for val54 := 0; val54 < int(val53); val54++ {
+ err = gobtools.DecodeString(buf, &r.StaticDependencies[val54])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val57 int32
+ err = gobtools.DecodeSimple[int32](buf, &val57)
+ if err != nil {
+ return err
+ }
+ if val57 > 0 {
+ r.DataDependencies = make([]string, val57)
+ for val58 := 0; val58 < int(val57); val58++ {
+ err = gobtools.DecodeString(buf, &r.DataDependencies[val58])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val61 int32
+ err = gobtools.DecodeSimple[int32](buf, &val61)
+ if err != nil {
+ return err
+ }
+ if val61 > 0 {
+ r.CompatibilitySuites = make([]string, val61)
+ for val62 := 0; val62 < int(val61); val62++ {
+ err = gobtools.DecodeString(buf, &r.CompatibilitySuites[val62])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val65 int32
+ err = gobtools.DecodeSimple[int32](buf, &val65)
+ if err != nil {
+ return err
+ }
+ if val65 > 0 {
+ r.AutoTestConfig = make([]string, val65)
+ for val66 := 0; val66 < int(val65); val66++ {
+ err = gobtools.DecodeString(buf, &r.AutoTestConfig[val66])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val69 int32
+ err = gobtools.DecodeSimple[int32](buf, &val69)
+ if err != nil {
+ return err
+ }
+ if val69 > 0 {
+ r.TestConfig = make([]string, val69)
+ for val70 := 0; val70 < int(val69); val70++ {
+ err = gobtools.DecodeString(buf, &r.TestConfig[val70])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeString(buf, &r.TestModuleConfigBase)
+ if err != nil {
+ return err
+ }
+
+ var val74 int32
+ err = gobtools.DecodeSimple[int32](buf, &val74)
+ if err != nil {
+ return err
+ }
+ if val74 > 0 {
+ r.ExtraRequired = make([]string, val74)
+ for val75 := 0; val75 < int(val74); val75++ {
+ err = gobtools.DecodeString(buf, &r.ExtraRequired[val75])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val78 int32
+ err = gobtools.DecodeSimple[int32](buf, &val78)
+ if err != nil {
+ return err
+ }
+ if val78 > 0 {
+ r.ExtraHostRequired = make([]string, val78)
+ for val79 := 0; val79 < int(val78); val79++ {
+ err = gobtools.DecodeString(buf, &r.ExtraHostRequired[val79])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val82 int32
+ err = gobtools.DecodeSimple[int32](buf, &val82)
+ if err != nil {
+ return err
+ }
+ if val82 > 0 {
+ r.SupportedVariantsOverride = make([]string, val82)
+ for val83 := 0; val83 < int(val82); val83++ {
+ err = gobtools.DecodeString(buf, &r.SupportedVariantsOverride[val83])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Disabled)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.RegisterNameOverride)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.ModuleNameOverride)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ExtraModuleInfoJSONGobRegId int16
+
+func (r ExtraModuleInfoJSON) GetTypeId() int16 {
+ return ExtraModuleInfoJSONGobRegId
+}
+
+func (r ModuleInfoJSON) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.core.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ExtraModuleInfoJSON.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModuleInfoJSON) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.core.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ExtraModuleInfoJSON.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModuleInfoJSONGobRegId int16
+
+func (r ModuleInfoJSON) GetTypeId() int16 {
+ return ModuleInfoJSONGobRegId
+}
+
+func (r ModuleInfoJSONInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Data))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Data); val1++ {
+ val2 := r.Data[val1] == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = (*r.Data[val1]).Encode(buf); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *ModuleInfoJSONInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.Data = make([]*ModuleInfoJSON, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ var val5 bool
+ if err = gobtools.DecodeSimple(buf, &val5); err != nil {
+ return err
+ }
+ if !val5 {
+ var val4 ModuleInfoJSON
+ if err = val4.Decode(buf); err != nil {
+ return err
+ }
+ r.Data[val3] = &val4
+ }
+ }
+ }
+
+ return err
+}
+
+var ModuleInfoJSONInfoGobRegId int16
+
+func (r ModuleInfoJSONInfo) GetTypeId() int16 {
+ return ModuleInfoJSONInfoGobRegId
+}
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 561c4770c..c442e08f3 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -2,236 +2,12 @@ package android
import (
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
type ModuleProxy struct {
- module blueprint.ModuleProxy
+ blueprint.ModuleProxy
}
-var _ Module = (*ModuleProxy)(nil)
-
-func (m ModuleProxy) IsNil() bool {
- return m.module.IsNil()
-}
-
-func (m ModuleProxy) Name() string {
- return m.module.Name()
-}
-
-func (m ModuleProxy) GenerateBuildActions(context blueprint.ModuleContext) {
- m.module.GenerateBuildActions(context)
-}
-
-func (m ModuleProxy) GenerateAndroidBuildActions(context ModuleContext) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) DepsMutator(context BottomUpMutatorContext) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) base() *ModuleBase {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) Disable() {
-
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) Enabled(ctx ConfigurableEvaluatorContext) bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) Target() Target {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) MultiTargets() []Target {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) ImageVariation() blueprint.Variation {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) Owner() string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInData() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInTestcases() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInSanitizerDir() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInRamdisk() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInVendorRamdisk() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInDebugRamdisk() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInRecovery() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInRoot() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInOdm() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInProduct() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInVendor() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInSystemExt() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInSystemDlkm() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInVendorDlkm() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallInOdmDlkm() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) InstallForceOS() (*OsType, *ArchType) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) PartitionTag(d DeviceConfig) string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) HideFromMake() {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) IsHideFromMake() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) SkipInstall() {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) IsSkipInstall() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) MakeUninstallable() {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) ReplacedByPrebuilt() {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) IsReplacedByPrebuilt() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) ExportedToMake() bool {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) EffectiveLicenseFiles() Paths {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) AddProperties(props ...interface{}) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) GetProperties() []interface{} {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) BuildParamsForTests() []BuildParams {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) VariablesForTests() map[string]string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) String() string {
- return m.module.String()
-}
-
-func (m ModuleProxy) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) visibilityProperties() []visibilityProperty {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) HostRequiredModuleNames() []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) TargetRequiredModuleNames() []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) DecodeMultilib(ctx ConfigContext) (string, string) {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) Overrides() []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) VintfFragments(ctx ConfigurableEvaluatorContext) []string {
- panic("method is not implemented on ModuleProxy")
-}
-
-func (m ModuleProxy) UseGenericConfig() bool {
- panic("method is not implemented on ModuleProxy")
+type ModuleOrProxy interface {
+ blueprint.ModuleOrProxy
}
diff --git a/android/module_test.go b/android/module_test.go
index 5331e4970..0556624af 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -18,8 +18,6 @@ import (
"path/filepath"
"runtime"
"testing"
-
- "github.com/google/blueprint"
)
func TestSrcIsModule(t *testing.T) {
@@ -983,17 +981,18 @@ func (o outputFilesTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
type pathContextAddMissingDependenciesWrapper struct {
PathContext
OtherModuleProviderContext
+ module Module
missingDeps []string
}
func (p *pathContextAddMissingDependenciesWrapper) AddMissingDependencies(deps []string) {
p.missingDeps = append(p.missingDeps, deps...)
}
-func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module blueprint.Module) string {
+func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module ModuleOrProxy) string {
return module.Name()
}
-func (p *pathContextAddMissingDependenciesWrapper) Module() Module { return nil }
+func (p *pathContextAddMissingDependenciesWrapper) Module() Module { return p.module }
func (p *pathContextAddMissingDependenciesWrapper) GetOutputFiles() OutputFilesInfo {
return OutputFilesInfo{}
@@ -1030,7 +1029,7 @@ func TestOutputFileForModule(t *testing.T) {
a: "",
b: "empty.txt",
}
- `,
+ `,
tag: "",
expected: "empty.txt",
},
@@ -1050,7 +1049,7 @@ func TestOutputFileForModule(t *testing.T) {
bp: `oft_module {
name: "test_module",
}
- `,
+ `,
tag: "missing",
expected: "missing_output_file/test_module",
missingDeps: []string{"test_module"},
@@ -1062,13 +1061,16 @@ func TestOutputFileForModule(t *testing.T) {
for _, tt := range testcases {
t.Run(tt.name, func(t *testing.T) {
+ extraBp := `oft_module {
+ name: "other_module"
+ }`
result := GroupFixturePreparers(
PrepareForTestWithDefaults,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("spt_module", sourceProducerTestModuleFactory)
ctx.RegisterModuleType("oft_module", outputFilesTestModuleFactory)
}),
- FixtureWithRootAndroidBp(tt.bp),
+ FixtureWithRootAndroidBp(tt.bp+extraBp),
).RunTest(t)
config := TestConfig(buildDir, tt.env, tt.bp, nil)
@@ -1078,6 +1080,7 @@ func TestOutputFileForModule(t *testing.T) {
ctx := &pathContextAddMissingDependenciesWrapper{
PathContext: PathContextForTesting(config),
OtherModuleProviderContext: result.TestContext.OtherModuleProviderAdaptor(),
+ module: result.ModuleForTests(t, "other_module", "").Module(),
}
got := OutputFileForModule(ctx, result.ModuleForTests(t, "test_module", "").Module(), tt.tag)
AssertPathRelativeToTopEquals(t, "expected output path", tt.expected, got)
diff --git a/android/mutator.go b/android/mutator.go
index 12861c074..424cf3aac 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -274,6 +274,7 @@ var (
outgoingTransitionContextPool = pool.New[outgoingTransitionContextImpl]()
incomingTransitionContextPool = pool.New[incomingTransitionContextImpl]()
bottomUpMutatorContextPool = pool.New[bottomUpMutatorContext]()
+ baseModuleContextPool = pool.New[baseModuleContext]()
)
type bottomUpMutatorContext struct {
@@ -302,6 +303,9 @@ func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) Mutat
if a, ok := ctx.Module().(Module); ok {
mctx := bottomUpMutatorContextFactory(ctx, a, finalPhase)
defer bottomUpMutatorContextPool.Put(mctx)
+ if mctx.config.captureBuild {
+ mctx.config.modulesForTests.Insert(mctx.ModuleName(), mctx.Module())
+ }
m(mctx)
}
}
@@ -494,6 +498,9 @@ func registerDepsMutator(ctx RegisterMutatorsContext) {
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
+ if b.config.captureBuild {
+ b.config.modulesForTests.Rename(b.Module().base().commonProperties.DebugName, name)
+ }
b.Module().base().commonProperties.DebugName = name
}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index f7ee7d857..cd4b68f0d 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -129,7 +129,7 @@ func TestFinalDepsPhase(t *testing.T) {
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
counter, _ := finalGot.LoadOrStore(ctx.Module().String(), &atomic.Int64{})
counter.(*atomic.Int64).Add(1)
- ctx.VisitDirectDeps(func(mod Module) {
+ ctx.VisitDirectDepsProxy(func(mod ModuleProxy) {
counter, _ := finalGot.LoadOrStore(fmt.Sprintf("%s -> %s", ctx.Module().String(), mod), &atomic.Int64{})
counter.(*atomic.Int64).Add(1)
})
diff --git a/android/namespace.go b/android/namespace.go
index d0e90b002..a856a84e6 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -24,6 +24,7 @@ import (
"sync"
"github.com/google/blueprint"
+ "github.com/google/blueprint/syncmap"
)
func init() {
@@ -85,7 +86,7 @@ type NameResolver struct {
sortedNamespaces sortedNamespaces
// Map from dir to namespace. Will have duplicates if two dirs are part of the same namespace.
- namespacesByDir sync.Map // if generics were supported, this would be sync.Map[string]*Namespace
+ namespacesByDir syncmap.SyncMap[string, *Namespace]
// func telling whether to export a namespace to Kati
namespaceExportFilter func(*Namespace) bool
@@ -113,7 +114,6 @@ func NewNameResolver(config NameResolverConfig) *NameResolver {
}
r := &NameResolver{
- namespacesByDir: sync.Map{},
namespaceExportFilter: namespaceExportFilter,
}
r.rootNamespace = r.newNamespace(".")
@@ -167,11 +167,7 @@ func (r *NameResolver) addNamespace(namespace *Namespace) (err error) {
// non-recursive check for namespace
func (r *NameResolver) namespaceAt(path string) (namespace *Namespace, found bool) {
- mapVal, found := r.namespacesByDir.Load(path)
- if !found {
- return nil, false
- }
- return mapVal.(*Namespace), true
+ return r.namespacesByDir.Load(path)
}
// recursive search upward for a namespace
@@ -223,6 +219,7 @@ func (r *NameResolver) NewModule(ctx blueprint.NamespaceContext, moduleGroup blu
// inform the module whether its namespace is one that we want to export to Make
amod.base().commonProperties.NamespaceExportedToMake = ns.exportToKati
amod.base().commonProperties.DebugName = module.Name()
+ amod.base().commonProperties.DebugNamespace = ns.Path
}
return ns, nil
diff --git a/android/namespace_test.go b/android/namespace_test.go
index a183bbf0d..0026aa78c 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -664,7 +664,7 @@ func dirBpToPreparer(bps map[string]string) FixturePreparer {
func dependsOn(result *TestResult, module TestingModule, possibleDependency TestingModule) bool {
depends := false
- visit := func(dependency blueprint.Module) {
+ visit := func(dependency Module) {
if dependency == possibleDependency.module {
depends = true
}
@@ -675,7 +675,7 @@ func dependsOn(result *TestResult, module TestingModule, possibleDependency Test
func numDeps(result *TestResult, module TestingModule) int {
count := 0
- visit := func(dependency blueprint.Module) {
+ visit := func(dependency Module) {
count++
}
result.VisitDirectDeps(module.module, visit)
@@ -687,11 +687,11 @@ func getModule(result *TestResult, moduleName string) TestingModule {
}
func findModuleById(result *TestResult, id string) (module TestingModule) {
- visit := func(candidate blueprint.Module) {
+ visit := func(candidate Module) {
testModule, ok := candidate.(*testModule)
if ok {
if testModule.properties.Id == id {
- module = newTestingModule(result.fixture.t, result.config, testModule)
+ module = newTestingModule(result.fixture.t, result.config, testModule, result.ModuleToProxy(testModule))
}
}
}
@@ -734,6 +734,7 @@ func newTestModule() Module {
type blueprintTestModule struct {
blueprint.SimpleName
+ blueprint.ModuleBase
properties struct {
Deps []string
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 98b443ee4..7004751d9 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -253,6 +253,7 @@ func createInstallInRootAllowingRules() []Rule {
NotModuleType("prebuilt_first_stage_ramdisk").
NotModuleType("prebuilt_res").
NotModuleType("prebuilt_any").
+ NotModuleType("prebuilt_lib").
Because("install_in_root is only for init_first_stage or librecovery_ui_ext."),
}
}
@@ -741,7 +742,7 @@ func (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool {
}
matches := false
- ctx.VisitDirectDeps(func(m Module) {
+ ctx.VisitDirectDepsProxy(func(m ModuleProxy) {
if !matches {
name := ctx.OtherModuleName(m)
matches = r.directDeps[name]
diff --git a/android/override_module.go b/android/override_module.go
index 96620ef7a..a3d3a10d9 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -29,8 +29,8 @@ package android
import (
"fmt"
- "sort"
- "sync"
+ "reflect"
+ "slices"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -40,6 +40,8 @@ import (
type OverrideModule interface {
Module
+ GetOverriddenModuleName() string
+
getOverridingProperties() []interface{}
setOverridingProperties(properties []interface{})
@@ -49,10 +51,6 @@ type OverrideModule interface {
// i.e. cases where an overriding module, too, is overridden by a prebuilt module.
setOverriddenByPrebuilt(prebuilt Module)
getOverriddenByPrebuilt() Module
-
- // Directory containing the Blueprint definition of the overriding module
- setModuleDir(string)
- ModuleDir() string
}
// Base module struct for override module types
@@ -62,8 +60,6 @@ type OverrideModuleBase struct {
overridingProperties []interface{}
overriddenByPrebuilt Module
-
- moduleDir string
}
type OverrideModuleProperties struct {
@@ -73,14 +69,6 @@ type OverrideModuleProperties struct {
// TODO(jungjw): Add an optional override_name bool flag.
}
-func (o *OverrideModuleBase) setModuleDir(d string) {
- o.moduleDir = d
-}
-
-func (o *OverrideModuleBase) ModuleDir() string {
- return o.moduleDir
-}
-
func (o *OverrideModuleBase) getOverridingProperties() []interface{} {
return o.overridingProperties
}
@@ -118,12 +106,8 @@ type OverridableModule interface {
setOverridableProperties(prop []interface{})
- addOverride(o OverrideModule)
- getOverrides() []OverrideModule
-
- override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule)
+ override(ctx BaseModuleContext, bm OverridableModule, info overrideTransitionMutatorInfo)
GetOverriddenBy() string
- GetOverriddenByModuleDir() string
setOverridesProperty(overridesProperties *[]string)
@@ -133,20 +117,11 @@ type OverridableModule interface {
}
type overridableModuleProperties struct {
- OverriddenBy string `blueprint:"mutated"`
- OverriddenByModuleDir string `blueprint:"mutated"`
+ OverriddenBy string `blueprint:"mutated"`
}
// Base module struct for overridable module types
type OverridableModuleBase struct {
- // List of OverrideModules that override this base module
- overrides []OverrideModule
- // Used to parallelize registerOverrideMutator executions. Note that only addOverride locks this
- // mutex. It is because addOverride and getOverride are used in different mutators, and so are
- // guaranteed to be not mixed. (And, getOverride only reads from overrides, and so don't require
- // mutex locking.)
- overridesLock sync.Mutex
-
overridableProperties []interface{}
// If an overridable module has a property to list other modules that itself overrides, it should
@@ -171,30 +146,14 @@ func (b *OverridableModuleBase) setOverridableProperties(prop []interface{}) {
b.overridableProperties = prop
}
-func (b *OverridableModuleBase) addOverride(o OverrideModule) {
- b.overridesLock.Lock()
- b.overrides = append(b.overrides, o)
- b.overridesLock.Unlock()
-}
-
-// Should NOT be used in the same mutator as addOverride.
-func (b *OverridableModuleBase) getOverrides() []OverrideModule {
- b.overridesLock.Lock()
- sort.Slice(b.overrides, func(i, j int) bool {
- return b.overrides[i].Name() < b.overrides[j].Name()
- })
- b.overridesLock.Unlock()
- return b.overrides
-}
-
func (b *OverridableModuleBase) setOverridesProperty(overridesProperty *[]string) {
b.overridesProperty = overridesProperty
}
// Overrides a base module with the given OverrideModule.
-func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule) {
+func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableModule, info overrideTransitionMutatorInfo) {
for _, p := range b.overridableProperties {
- for _, op := range o.getOverridingProperties() {
+ for _, op := range info.overridingProperties {
if proptools.TypeEqual(p, op) {
err := proptools.ExtendProperties(p, op, nil, proptools.OrderReplace)
if err != nil {
@@ -212,8 +171,7 @@ func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableMo
if b.overridesProperty != nil {
*b.overridesProperty = append(*b.overridesProperty, ctx.OtherModuleName(bm))
}
- b.overridableModuleProperties.OverriddenBy = o.Name()
- b.overridableModuleProperties.OverriddenByModuleDir = o.ModuleDir()
+ b.overridableModuleProperties.OverriddenBy = info.name
}
// GetOverriddenBy returns the name of the override module that has overridden this module.
@@ -224,19 +182,14 @@ func (b *OverridableModuleBase) GetOverriddenBy() string {
return b.overridableModuleProperties.OverriddenBy
}
-func (b *OverridableModuleBase) GetOverriddenByModuleDir() string {
- return b.overridableModuleProperties.OverriddenByModuleDir
-}
-
func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
}
// Mutators for override/overridable modules. All the fun happens in these functions. It is critical
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("override_deps", overrideModuleDepsMutator).MutatesDependencies() // modifies deps via addOverride
- ctx.Transition("override", &overrideTransitionMutator{})
- ctx.BottomUp("override_apply", overrideApplyMutator).MutatesDependencies()
+ ctx.BottomUp("override_deps", overrideModuleDepsMutator)
+ ctx.InfoBasedTransition("override", NewGenericTransitionMutatorAdapter(&overrideTransitionMutator{}))
// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
// add deps from overridable properties.
ctx.BottomUp("overridable_deps", overridableModuleDepsMutator)
@@ -272,97 +225,127 @@ func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
ctx.PropertyErrorf("base", "%q is not a valid module name", base)
return
}
- baseModule := ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)[0]
- if o, ok := baseModule.(OverridableModule); ok {
- overrideModule := ctx.Module().(OverrideModule)
- overrideModule.setModuleDir(ctx.ModuleDir())
- o.addOverride(overrideModule)
+
+ ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
+
+ // Make a copy of module.getOverridingProperties so that it won't be modified by any future
+ // mutators, which would violate the immutable providers requirement.
+ overridingProps := slices.Clone(module.getOverridingProperties())
+ for i, props := range overridingProps {
+ overridingProps[i] = proptools.CloneProperties(reflect.ValueOf(props)).Interface()
+ }
+
+ info := overrideTransitionMutatorInfo{
+ name: module.Name(),
+ overridingProperties: overridingProps,
+ }
+
+ prebuiltDeps := ctx.GetDirectDepsWithTag(PrebuiltDepTag)
+ for _, prebuiltDep := range prebuiltDeps {
+ prebuilt := GetEmbeddedPrebuilt(prebuiltDep)
+ if prebuilt == nil {
+ panic("PrebuiltDepTag leads to a non-prebuilt module " + prebuiltDep.Name())
+ }
+ info.overrideModuleUsePrebuilt = info.overrideModuleUsePrebuilt || prebuilt.UsePrebuilt()
+ info.overrideModulePrebuiltPartitions = append(info.overrideModulePrebuiltPartitions,
+ prebuiltDep.PartitionTag(ctx.DeviceConfig()))
+ info.overrideModulePrebuiltNames = append(info.overrideModulePrebuiltNames,
+ ctx.OtherModuleName(prebuiltDep))
}
+ SetProvider(ctx, overrideModuleDefaultInfoProvider, info)
}
}
+var overrideModuleDefaultInfoProvider = blueprint.NewMutatorProvider[overrideTransitionMutatorInfo]("override_deps")
+
+var OverrideInfoProvider = blueprint.NewMutatorProvider[OverrideInfo]("override_mutate")
+
+type OverrideInfo struct {
+ OverriddenBy string
+}
+
// Now, goes through all overridable modules, finds all modules overriding them, creates a local
// variant for each of them, and performs the actual overriding operation by calling override().
type overrideTransitionMutator struct{}
-func (overrideTransitionMutator) Split(ctx BaseModuleContext) []string {
- if b, ok := ctx.Module().(OverridableModule); ok {
- overrides := b.getOverrides()
- if len(overrides) == 0 {
- return []string{""}
- }
- variants := make([]string, len(overrides)+1)
- // The first variant is for the original, non-overridden, base module.
- variants[0] = ""
- for i, o := range overrides {
- variants[i+1] = o.(Module).Name()
- }
- return variants
- } else if o, ok := ctx.Module().(OverrideModule); ok {
+var _ TransitionMutator[overrideTransitionMutatorInfo] = (*overrideTransitionMutator)(nil)
+
+type overrideTransitionMutatorInfo struct {
+ name string
+ overridingProperties []interface{} `blueprint:"allow_configurable_in_provider"`
+
+ overrideModuleUsePrebuilt bool
+ overrideModulePrebuiltPartitions []string
+ overrideModulePrebuiltNames []string
+}
+
+var overrideTransitionMutatorEmptyVariation = overrideTransitionMutatorInfo{name: ""}
+
+func (info overrideTransitionMutatorInfo) Variation() string {
+ return info.name
+}
+
+func (overrideTransitionMutator) Split(ctx BaseModuleContext) []overrideTransitionMutatorInfo {
+ if _, ok := ctx.Module().(OverrideModule); ok {
// Create a variant of the overriding module with its own name. This matches the above local
// variant name rule for overridden modules, and thus allows ReplaceDependencies to match the
// two.
- return []string{o.Name()}
+ info, _ := ModuleProvider(ctx, overrideModuleDefaultInfoProvider)
+ return []overrideTransitionMutatorInfo{info}
}
- return []string{""}
+ return []overrideTransitionMutatorInfo{overrideTransitionMutatorEmptyVariation}
}
-func (overrideTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
- if o, ok := ctx.Module().(OverrideModule); ok {
+func (overrideTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceInfo overrideTransitionMutatorInfo) overrideTransitionMutatorInfo {
+ if _, ok := ctx.Module().(OverrideModule); ok {
if ctx.DepTag() == overrideBaseDepTag {
- return o.Name()
+ return sourceInfo
}
}
// Variations are always local and shouldn't affect the variant used for dependencies
- return ""
+ return overrideTransitionMutatorEmptyVariation
}
-func (overrideTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+func (overrideTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingInfo overrideTransitionMutatorInfo) overrideTransitionMutatorInfo {
if _, ok := ctx.Module().(OverridableModule); ok {
- return incomingVariation
- } else if o, ok := ctx.Module().(OverrideModule); ok {
+ return incomingInfo
+ } else if _, ok := ctx.Module().(OverrideModule); ok {
// To allow dependencies to be added without having to know the variation.
- return o.Name()
+ info, _ := ModuleProvider(ctx, overrideModuleDefaultInfoProvider)
+ return info
}
- return ""
-}
-
-func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ return overrideTransitionMutatorEmptyVariation
}
-func overrideApplyMutator(ctx BottomUpMutatorContext) {
- if o, ok := ctx.Module().(OverrideModule); ok {
- overridableDeps := ctx.GetDirectDepsWithTag(overrideBaseDepTag)
- if len(overridableDeps) > 1 {
- panic(fmt.Errorf("expected a single dependency with overrideBaseDepTag, found %q", overridableDeps))
- } else if len(overridableDeps) == 1 {
- b := overridableDeps[0].(OverridableModule)
- b.override(ctx, b, o)
+func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, info overrideTransitionMutatorInfo) {
+ if info.name != "" {
+ if b, ok := ctx.Module().(OverridableModule); ok {
+ b.override(ctx, b, info)
- checkPrebuiltReplacesOverride(ctx, b)
+ checkPrebuiltReplacesOverride(ctx, b, info)
}
+ SetProvider(ctx, OverrideInfoProvider, OverrideInfo{
+ OverriddenBy: info.name,
+ })
}
}
-func checkPrebuiltReplacesOverride(ctx BottomUpMutatorContext, b OverridableModule) {
+func (overrideTransitionMutator) TransitionInfoFromVariation(variation string) overrideTransitionMutatorInfo {
+ panic(fmt.Errorf("not implemented"))
+}
+
+func checkPrebuiltReplacesOverride(ctx BottomUpMutatorContext, bm OverridableModule, info overrideTransitionMutatorInfo) {
// See if there's a prebuilt module that overrides this override module with prefer flag,
// in which case we call HideFromMake on the corresponding variant later.
- prebuiltDeps := ctx.GetDirectDepsWithTag(PrebuiltDepTag)
- for _, prebuiltDep := range prebuiltDeps {
- prebuilt := GetEmbeddedPrebuilt(prebuiltDep)
- if prebuilt == nil {
- panic("PrebuiltDepTag leads to a non-prebuilt module " + prebuiltDep.Name())
- }
- if prebuilt.UsePrebuilt() {
- // The overriding module itself, too, is overridden by a prebuilt.
- // Perform the same check for replacement
- checkInvariantsForSourceAndPrebuilt(ctx, b, prebuiltDep)
- // Copy the flag and hide it in make
- b.ReplacedByPrebuilt()
- }
+ if info.overrideModuleUsePrebuilt {
+ // The overriding module itself, too, is overridden by a prebuilt.
+ // Perform the same check for replacement
+ checkInvariantsForSourceAndPrebuilt(ctx, bm.PartitionTag(ctx.DeviceConfig()), info.overrideModulePrebuiltPartitions, info.overrideModulePrebuiltNames)
+ // Copy the flag and hide it in make
+ bm.ReplacedByPrebuilt()
}
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index c348c82b6..957de1705 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -125,8 +125,8 @@ func (p PackageContext) RuleFunc(name string,
return params, ctx.errors[0]
}
if ctx.Config().UseRemoteBuild() && params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
- // goma/RBE, restrict jobs to the local parallelism value
+ // When USE_RBE=true is set and the rule is not supported by
+ // RBE, restrict jobs to the local parallelism value
params.Pool = localPool
}
return params, nil
@@ -247,25 +247,18 @@ func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
}, argNames...)
}
-// RemoteRuleSupports configures rules with whether they have Goma and/or RBE support.
+// RemoteRuleSupports configures rules with whether they have RBE support.
type RemoteRuleSupports struct {
- Goma bool
- RBE bool
+ RBE bool
}
-// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
+// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses RBE's parallelism if RBE is enabled
// and the appropriate SUPPORTS_* flag is set.
func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
ctx := &configErrorWrapper{p, config.(Config), nil}
- if ctx.Config().UseGoma() && !supports.Goma {
- // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
- // local parallelism value
- params.Pool = localPool
- }
-
if ctx.Config().UseRBE() && !supports.RBE {
// When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
// local parallelism value
diff --git a/android/packaging.go b/android/packaging.go
index bf1840929..f91892629 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -20,15 +20,17 @@ import (
"sort"
"github.com/google/blueprint"
- "github.com/google/blueprint/gobtools"
"github.com/google/blueprint/proptools"
"github.com/google/blueprint/uniquelist"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
// running on a VM), or a zip archive for some of the host tools.
+// @auto-generate: gob
type PackagingSpec struct {
// Path relative to the root of the package
relPathInPackage string
@@ -75,23 +77,9 @@ type PackagingSpec struct {
// String representation of the variation of the module where this packaging spec is output of
variation string
-}
-type packagingSpecGob struct {
- RelPathInPackage string
- SrcPath Path
- SymlinkTarget string
- Executable bool
- EffectiveLicenseFiles Paths
- Partition string
- SkipInstall bool
- AconfigPaths Paths
- ArchType ArchType
- Overrides []string
- Owner string
- RequiresFullInstall bool
- FullInstallPath InstallPath
- Variation string
+ // Whether the owner module is a prebuilt module or not
+ prebuilt bool
}
func (p *PackagingSpec) Owner() string {
@@ -102,48 +90,8 @@ func (p *PackagingSpec) Variation() string {
return p.variation
}
-func (p *PackagingSpec) ToGob() *packagingSpecGob {
- return &packagingSpecGob{
- RelPathInPackage: p.relPathInPackage,
- SrcPath: p.srcPath,
- SymlinkTarget: p.symlinkTarget,
- Executable: p.executable,
- EffectiveLicenseFiles: p.effectiveLicenseFiles.ToSlice(),
- Partition: p.partition,
- SkipInstall: p.skipInstall,
- AconfigPaths: p.aconfigPaths.ToSlice(),
- ArchType: p.archType,
- Overrides: p.overrides.ToSlice(),
- Owner: p.owner,
- RequiresFullInstall: p.requiresFullInstall,
- FullInstallPath: p.fullInstallPath,
- Variation: p.variation,
- }
-}
-
-func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
- p.relPathInPackage = data.RelPathInPackage
- p.srcPath = data.SrcPath
- p.symlinkTarget = data.SymlinkTarget
- p.executable = data.Executable
- p.effectiveLicenseFiles = uniquelist.Make(data.EffectiveLicenseFiles)
- p.partition = data.Partition
- p.skipInstall = data.SkipInstall
- p.aconfigPaths = uniquelist.Make(data.AconfigPaths)
- p.archType = data.ArchType
- p.overrides = uniquelist.Make(data.Overrides)
- p.owner = data.Owner
- p.requiresFullInstall = data.RequiresFullInstall
- p.fullInstallPath = data.FullInstallPath
- p.variation = data.Variation
-}
-
-func (p *PackagingSpec) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[packagingSpecGob](p)
-}
-
-func (p *PackagingSpec) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[packagingSpecGob](data, p)
+func (p *PackagingSpec) Prebuilt() bool {
+ return p.prebuilt
}
func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -279,19 +227,21 @@ type DepsProperty struct {
}
type packagingMultilibProperties struct {
- First DepsProperty `android:"arch_variant"`
- Common DepsProperty `android:"arch_variant"`
- Lib32 DepsProperty `android:"arch_variant"`
- Lib64 DepsProperty `android:"arch_variant"`
- Both DepsProperty `android:"arch_variant"`
- Prefer32 DepsProperty `android:"arch_variant"`
+ First DepsProperty `android:"arch_variant"`
+ Common DepsProperty `android:"arch_variant"`
+ Lib32 DepsProperty `android:"arch_variant"`
+ Lib64 DepsProperty `android:"arch_variant"`
+ Both DepsProperty `android:"arch_variant"`
+ Prefer32 DepsProperty `android:"arch_variant"`
+ Native_bridge DepsProperty `android:"arch_variant"`
}
type packagingArchProperties struct {
- Arm64 DepsProperty
- Arm DepsProperty
- X86_64 DepsProperty
- X86 DepsProperty
+ Arm64 DepsProperty
+ Arm DepsProperty
+ X86_64 DepsProperty
+ X86 DepsProperty
+ Riscv64 DepsProperty
}
type PackagingProperties struct {
@@ -315,7 +265,8 @@ func (p *PackagingBase) packagingBase() *PackagingBase {
// multi target, deps is selected for each of the targets and is NOT selected for the current
// architecture which would be Common.
// It returns two lists, the normal and high priority deps, respectively.
-func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
+func (p *PackagingBase) getDepsForTarget(ctx BaseModuleContext, target Target) ([]string, []string) {
+ arch := target.Arch.ArchType
var normalDeps []string
var highPriorityDeps []string
@@ -327,7 +278,10 @@ func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]
return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
}
- if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
+ if target.NativeBridge == NativeBridgeEnabled {
+ get(p.properties.Multilib.Native_bridge)
+ return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
+ } else if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
get(p.properties.DepsProperty)
} else if arch.Multilib == "lib32" {
get(p.properties.Multilib.Lib32)
@@ -395,6 +349,8 @@ func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]
get(p.properties.Arch.X86_64)
case X86:
get(p.properties.Arch.X86)
+ case Riscv64:
+ get(p.properties.Arch.Riscv64)
}
}
@@ -488,7 +444,7 @@ func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.Dep
ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
}
for _, t := range getSupportedTargets(ctx) {
- normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
+ normalDeps, highPriorityDeps := p.getDepsForTarget(ctx, t)
for _, dep := range normalDeps {
addDep(t, dep, false)
}
@@ -508,6 +464,7 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont
// list of module names overridden
overridden := make(map[string]bool)
+ nativeBridgeOverridden := make(map[string]bool)
// all installed modules which are not overridden.
modulesToInstall := make(map[string]bool)
@@ -527,6 +484,11 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont
return false
}
+ isNativeBridgeVariant := func(m ModuleOrProxy) bool {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider)
+ return commonInfo.Target.NativeBridge == NativeBridgeEnabled
+ }
+
// find all overridden modules and packaging specs
ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
depTag := ctx.OtherModuleDependencyTag(child)
@@ -556,21 +518,26 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont
}
for o := range ps.overrides.Iter() {
- overridden[o] = true
+ if !isNativeBridgeVariant(child) {
+ overridden[o] = true
+ } else {
+ nativeBridgeOverridden[o] = true
+ }
}
}
})
// gather modules to install, skipping overridden modules
- ctx.WalkDeps(func(child, parent Module) bool {
- owner := ctx.OtherModuleName(child)
- if o, ok := child.(OverridableModule); ok {
- if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" {
- owner = overriddenBy
+ ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool {
+ owner := OtherModuleNameWithPossibleOverride(ctx, child)
+ if !isNativeBridgeVariant(child) {
+ if overridden[owner] {
+ return false
+ }
+ } else {
+ if nativeBridgeOverridden[owner] {
+ return false
}
- }
- if overridden[owner] {
- return false
}
modulesToInstall[owner] = true
return true
diff --git a/android/packaging_gob_enc.go b/android/packaging_gob_enc.go
new file mode 100644
index 000000000..4ae4e90d8
--- /dev/null
+++ b/android/packaging_gob_enc.go
@@ -0,0 +1,226 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+ "github.com/google/blueprint/uniquelist"
+)
+
+func init() {
+ PackagingSpecGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(PackagingSpec) })
+}
+
+func (r PackagingSpec) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.relPathInPackage); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.srcPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.symlinkTarget); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.executable); err != nil {
+ return err
+ }
+
+ val1 := r.effectiveLicenseFiles.ToSlice()
+ if err = gobtools.EncodeSimple(buf, int32(len(val1))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(val1); val2++ {
+ if err = gobtools.EncodeInterface(buf, val1[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.partition); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.skipInstall); err != nil {
+ return err
+ }
+
+ val3 := r.aconfigPaths.ToSlice()
+ if err = gobtools.EncodeSimple(buf, int32(len(val3))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(val3); val4++ {
+ if err = gobtools.EncodeInterface(buf, val3[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.archType.Encode(buf); err != nil {
+ return err
+ }
+
+ val5 := r.overrides.ToSlice()
+ if err = gobtools.EncodeSimple(buf, int32(len(val5))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(val5); val6++ {
+ if err = gobtools.EncodeString(buf, val5[val6]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.owner); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.requiresFullInstall); err != nil {
+ return err
+ }
+
+ if err = r.fullInstallPath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.variation); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.prebuilt); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *PackagingSpec) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.relPathInPackage)
+ if err != nil {
+ return err
+ }
+
+ if val3, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val3 == nil {
+ r.srcPath = nil
+ } else {
+ r.srcPath = val3.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.symlinkTarget)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.executable)
+ if err != nil {
+ return err
+ }
+
+ var val7 []Path
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ val7 = make([]Path, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ if val11, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val11 == nil {
+ val7[val9] = nil
+ } else {
+ val7[val9] = val11.(Path)
+ }
+ }
+ }
+ r.effectiveLicenseFiles = uniquelist.Make(val7)
+
+ err = gobtools.DecodeString(buf, &r.partition)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.skipInstall)
+ if err != nil {
+ return err
+ }
+
+ var val15 []Path
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ val15 = make([]Path, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ if val19, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val19 == nil {
+ val15[val17] = nil
+ } else {
+ val15[val17] = val19.(Path)
+ }
+ }
+ }
+ r.aconfigPaths = uniquelist.Make(val15)
+
+ if err = r.archType.Decode(buf); err != nil {
+ return err
+ }
+
+ var val22 []string
+ var val23 int32
+ err = gobtools.DecodeSimple[int32](buf, &val23)
+ if err != nil {
+ return err
+ }
+ if val23 > 0 {
+ val22 = make([]string, val23)
+ for val24 := 0; val24 < int(val23); val24++ {
+ err = gobtools.DecodeString(buf, &val22[val24])
+ if err != nil {
+ return err
+ }
+ }
+ }
+ r.overrides = uniquelist.Make(val22)
+
+ err = gobtools.DecodeString(buf, &r.owner)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.requiresFullInstall)
+ if err != nil {
+ return err
+ }
+
+ if err = r.fullInstallPath.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.variation)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.prebuilt)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var PackagingSpecGobRegId int16
+
+func (r PackagingSpec) GetTypeId() int16 {
+ return PackagingSpecGobRegId
+}
diff --git a/android/path_properties.go b/android/path_properties.go
index d769d58c4..6438c06af 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -20,6 +20,7 @@ import (
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "github.com/google/blueprint/syncmap"
)
// This file implements support for automatically adding dependencies on any module referenced
@@ -55,13 +56,18 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
var pathDeviceCommonProperties []string
var pathCommonOsProperties []string
var pathHostCommonProperties []string
+ var pathHostFirstProperties []string
+ var pathHostSecondProperties []string
for _, ps := range props {
- pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...)
- pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...)
- pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_prefer32")...)
- pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...)
- pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...)
- pathHostCommonProperties = append(pathHostCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_host_common")...)
+ pathPropertyIndexes := pathPropertyIndexesForPropertyStruct(ps)
+ pathProperties = append(pathProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.path)...)
+ pathDeviceFirstProperties = append(pathDeviceFirstProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathDeviceFirst)...)
+ pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathDeviceFirstPrefer32)...)
+ pathDeviceCommonProperties = append(pathDeviceCommonProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathDeviceCommon)...)
+ pathCommonOsProperties = append(pathCommonOsProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathCommonOs)...)
+ pathHostCommonProperties = append(pathHostCommonProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathHostCommon)...)
+ pathHostFirstProperties = append(pathHostFirstProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathHostFirst)...)
+ pathHostSecondProperties = append(pathHostSecondProperties, indexedPropertiesForPropertyStruct(ctx, ps, pathPropertyIndexes.pathHostSecond)...)
}
// Remove duplicates to avoid multiple dependencies.
@@ -71,6 +77,8 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties)
pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties)
pathHostCommonProperties = FirstUniqueStrings(pathHostCommonProperties)
+ pathHostFirstProperties = FirstUniqueStrings(pathHostFirstProperties)
+ pathHostSecondProperties = FirstUniqueStrings(pathHostSecondProperties)
// Add dependencies to anything that is a module reference.
for _, s := range pathProperties {
@@ -117,6 +125,27 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
}
}
+ // properties tagged "path_host_first" get the host os variant
+ for _, s := range pathHostFirstProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), sourceOrOutputDepTag(m, t), m)
+ }
+ }
+ // properties tagged "path_host_second" get the host 2nd os variant
+ if len(pathHostSecondProperties) > 0 {
+ var targets []Target
+ targets, _ = decodeMultilibTargets("32", ctx.Config().Targets[ctx.Config().BuildOS], false)
+ if len(targets) == 0 {
+ ctx.ModuleErrorf("Could not find a 32 bit host target")
+ } else {
+ for _, s := range pathHostSecondProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies(targets[0].Variations(), sourceOrOutputDepTag(m, t), m)
+ }
+ }
+ }
+ }
+
// properties tagged "path_common_os" get the CommonOs variant
for _, s := range pathCommonOsProperties {
if m, t := SrcIsModuleWithTag(s); m != "" {
@@ -128,10 +157,9 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
}
}
-// taggedPropertiesForPropertyStruct uses the indexes of properties that are tagged with
-// android:"tagValue" to extract all their values from a property struct, returning them as a single
-// slice of strings.
-func taggedPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}, tagValue string) []string {
+// indexedPropertiesForPropertyStruct uses the indexes of properties extract all their values from a
+// property struct, returning them as a single slice of strings.
+func indexedPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}, pathPropertyIndexes [][]int) []string {
v := reflect.ValueOf(ps)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
@@ -145,10 +173,7 @@ func taggedPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{
// v is now the reflect.Value for the concrete property struct.
v = v.Elem()
- // Get or create the list of indexes of properties that are tagged with `android:"path"`.
- pathPropertyIndexes := taggedPropertyIndexesForPropertyStruct(ps, tagValue)
-
- var ret []string
+ ret := make([]string, 0, len(pathPropertyIndexes))
for _, i := range pathPropertyIndexes {
var values []reflect.Value
@@ -237,22 +262,40 @@ func isSliceOfStruct(v reflect.Value) bool {
return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Struct
}
-var pathPropertyIndexesCache OncePer
+type pathPropertyIndexes struct {
+ path [][]int
+ pathDeviceFirst [][]int
+ pathDeviceFirstPrefer32 [][]int
+ pathDeviceCommon [][]int
+ pathCommonOs [][]int
+ pathHostCommon [][]int
+ pathHostFirst [][]int
+ pathHostSecond [][]int
+}
+
+var pathPropertyIndexesCache syncmap.SyncMap[reflect.Type, *pathPropertyIndexes]
+
+// pathPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in
+// property struct type that are tagged as path properties with `android:"path"` or similar.
+// Each index is a []int suitable for passing to reflect.Value.FieldByIndex. The value is cached
+// in a global cache by type.
+func pathPropertyIndexesForPropertyStruct(ps interface{}) *pathPropertyIndexes {
+ key := reflect.TypeOf(ps)
+
+ if indexes, loaded := pathPropertyIndexesCache.Load(key); loaded {
+ return indexes
+ }
-// taggedPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in
-// property struct type that are tagged with `android:"tagValue"`. Each index is a []int suitable
-// for passing to reflect.Value.FieldByIndex. The value is cached in a global cache by type and
-// tagValue.
-func taggedPropertyIndexesForPropertyStruct(ps interface{}, tagValue string) [][]int {
- type pathPropertyIndexesOnceKey struct {
- propStructType reflect.Type
- tagValue string
+ indexes := &pathPropertyIndexes{
+ path: proptools.PropertyIndexesWithTag(ps, "android", "path"),
+ pathDeviceFirst: proptools.PropertyIndexesWithTag(ps, "android", "path_device_first"),
+ pathDeviceFirstPrefer32: proptools.PropertyIndexesWithTag(ps, "android", "path_device_first_prefer32"),
+ pathDeviceCommon: proptools.PropertyIndexesWithTag(ps, "android", "path_device_common"),
+ pathCommonOs: proptools.PropertyIndexesWithTag(ps, "android", "path_common_os"),
+ pathHostCommon: proptools.PropertyIndexesWithTag(ps, "android", "path_host_common"),
+ pathHostFirst: proptools.PropertyIndexesWithTag(ps, "android", "path_host_first"),
+ pathHostSecond: proptools.PropertyIndexesWithTag(ps, "android", "path_host_second"),
}
- key := NewCustomOnceKey(pathPropertyIndexesOnceKey{
- propStructType: reflect.TypeOf(ps),
- tagValue: tagValue,
- })
- return pathPropertyIndexesCache.Once(key, func() interface{} {
- return proptools.PropertyIndexesWithTag(ps, "android", tagValue)
- }).([][]int)
+ indexes, _ = pathPropertyIndexesCache.LoadOrStore(key, indexes)
+ return indexes
}
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 6f44f2872..81bb5c1bc 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -55,7 +55,7 @@ func pathDepsMutatorTestModuleFactory() Module {
}
func (p *pathDepsMutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- ctx.VisitDirectDeps(func(dep Module) {
+ ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
if _, ok := ctx.OtherModuleDependencyTag(dep).(sourceOrOutputDependencyTag); ok {
p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
}
@@ -64,7 +64,7 @@ func (p *pathDepsMutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContex
if p.props.Foo != "" {
// Make sure there is only one dependency on a module listed in a property present in multiple property structs
m := SrcIsModule(p.props.Foo)
- if GetModuleProxyFromPathDep(ctx, m, "") == nil {
+ if GetModuleProxyFromPathDep(ctx, m, "").IsNil() {
ctx.ModuleErrorf("GetDirectDepWithTag failed")
}
}
diff --git a/android/paths.go b/android/paths.go
index 7baf71f5b..3f768e5fc 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -24,10 +24,11 @@ import (
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/gobtools"
"github.com/google/blueprint/pathtools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var absSrcDir string
// PathContext is the subset of a (Module|Singleton)Context required by the
@@ -60,7 +61,7 @@ type EarlyModulePathContext interface {
ModuleDir() string
ModuleErrorf(fmt string, args ...interface{})
- OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property, fmt string, args ...interface{})
}
var _ EarlyModulePathContext = ModuleContext(nil)
@@ -93,7 +94,7 @@ type ModuleWithDepsPathContext interface {
VisitDirectDeps(visit func(Module))
VisitDirectDepsProxy(visit func(ModuleProxy))
VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(ModuleProxy))
- OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+ OtherModuleDependencyTag(m ModuleOrProxy) blueprint.DependencyTag
HasMutatorFinished(mutatorName string) bool
}
@@ -235,12 +236,14 @@ func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
}
}
-// TODO(b/397766191): Change the signature to take ModuleProxy
-// Please only access the module's internal data through providers.
-func pathContextName(ctx PathContext, module blueprint.Module) string {
- if x, ok := ctx.(interface{ ModuleName(blueprint.Module) string }); ok {
+func pathContextName(ctx PathContext, module ModuleOrProxy) string {
+ if x, ok := ctx.(interface {
+ ModuleName(ModuleOrProxy) string
+ }); ok {
return x.ModuleName(module)
- } else if x, ok := ctx.(interface{ OtherModuleName(blueprint.Module) string }); ok {
+ } else if x, ok := ctx.(interface {
+ OtherModuleName(ModuleOrProxy) string
+ }); ok {
return x.OtherModuleName(module)
}
return "unknown"
@@ -360,16 +363,12 @@ func ResPathWithName(ctx ModuleOutPathContext, p Path, name string) ModuleResPat
}
// OptionalPath is a container that may or may not contain a valid Path.
+// @auto-generate: gob
type OptionalPath struct {
path Path // nil if invalid.
invalidReason string // Not applicable if path != nil. "" if the reason is unknown.
}
-type optionalPathGob struct {
- Path Path
- InvalidReason string
-}
-
// OptionalPathForPath returns an OptionalPath containing the path.
func OptionalPathForPath(path Path) OptionalPath {
return OptionalPath{path: path}
@@ -381,26 +380,6 @@ func InvalidOptionalPath(reason string) OptionalPath {
return OptionalPath{invalidReason: reason}
}
-func (p *OptionalPath) ToGob() *optionalPathGob {
- return &optionalPathGob{
- Path: p.path,
- InvalidReason: p.invalidReason,
- }
-}
-
-func (p *OptionalPath) FromGob(data *optionalPathGob) {
- p.path = data.Path
- p.invalidReason = data.InvalidReason
-}
-
-func (p OptionalPath) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[optionalPathGob](&p)
-}
-
-func (p *OptionalPath) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[optionalPathGob](data, p)
-}
-
// Valid returns whether there is a valid path
func (p OptionalPath) Valid() bool {
return p.path != nil
@@ -461,6 +440,7 @@ func (p OptionalPath) String() string {
}
// Paths is a slice of Path objects, with helpers to operate on the collection.
+// @auto-generate: gob
type Paths []Path
// RelativeToTop creates a new Paths containing the result of calling Path.RelativeToTop on each
@@ -598,6 +578,14 @@ var _ DirectoryPath = (*directoryPath)(nil)
type DirectoryPaths []DirectoryPath
+func (paths DirectoryPaths) Strings() []string {
+ ret := make([]string, 0, len(paths))
+ for _, path := range paths {
+ ret = append(ret, path.String())
+ }
+ return ret
+}
+
// DirectoryPathsForModuleSrcExcludes returns a Paths{} containing the resolved references in
// directory paths. Elements of paths are resolved as:
// - filepath, relative to local module directory, resolves as a filepath relative to the local
@@ -609,7 +597,7 @@ func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string
for _, path := range paths {
if m, t := SrcIsModuleWithTag(path); m != "" {
module := GetModuleProxyFromPathDep(ctx, m, t)
- if module == nil {
+ if module.IsNil() {
ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
continue
}
@@ -621,7 +609,7 @@ func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string
if !ok {
panic(fmt.Errorf("%s is not an OtherModuleProviderContext", ctx))
}
- if dirProvider, ok := OtherModuleProvider(mctx, *module, DirProvider); ok {
+ if dirProvider, ok := OtherModuleProvider(mctx, module, DirProvider); ok {
ret = append(ret, dirProvider.Dirs...)
} else {
ReportPathErrorf(ctx, "module %q does not implement DirProvider", module)
@@ -680,14 +668,14 @@ func (p OutputPaths) Strings() []string {
// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag string) (Paths, error) {
module := GetModuleProxyFromPathDep(ctx, moduleName, tag)
- if module == nil {
+ if module.IsNil() {
return nil, missingDependencyError{[]string{moduleName}}
}
- if !OtherModulePointerProviderOrDefault(ctx, *module, CommonModuleInfoProvider).Enabled {
+ if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Enabled {
return nil, missingDependencyError{[]string{moduleName}}
}
- outputFiles, err := outputFilesForModule(ctx, *module, tag)
+ outputFiles, err := outputFilesForModule(ctx, module, tag)
if outputFiles != nil && err == nil {
return outputFiles, nil
} else {
@@ -705,8 +693,8 @@ func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag
//
// If tag is "" then the returned module will be the dependency that was added for ":moduleName".
// Otherwise, it is the dependency that was added for ":moduleName{tag}".
-func GetModuleProxyFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string) *ModuleProxy {
- var found *ModuleProxy
+func GetModuleProxyFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string) ModuleProxy {
+ var found ModuleProxy
// The sourceOrOutputDepTag uniquely identifies the module dependency as it contains both the
// module name and the tag. Dependencies added automatically for properties tagged with
// `android:"path"` are deduped so are guaranteed to be unique. It is possible for duplicate
@@ -720,7 +708,7 @@ func GetModuleProxyFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag st
// this finds the matching dependency module.
expectedTag := sourceOrOutputDepTag(moduleName, tag)
ctx.VisitDirectDepsProxyWithTag(expectedTag, func(module ModuleProxy) {
- found = &module
+ found = module
})
return found
}
@@ -1202,36 +1190,12 @@ func (p WritablePaths) Paths() Paths {
return ret
}
+// @auto-generate: gob
type basePath struct {
path string
rel string
}
-type basePathGob struct {
- Path string
- Rel string
-}
-
-func (p *basePath) ToGob() *basePathGob {
- return &basePathGob{
- Path: p.path,
- Rel: p.rel,
- }
-}
-
-func (p *basePath) FromGob(data *basePathGob) {
- p.path = data.Path
- p.rel = data.Rel
-}
-
-func (p basePath) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[basePathGob](&p)
-}
-
-func (p *basePath) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[basePathGob](data, p)
-}
-
func (p basePath) Ext() string {
return filepath.Ext(p.path)
}
@@ -1263,6 +1227,8 @@ func (p basePath) withoutRel() basePath {
}
// SourcePath is a Path representing a file path rooted from SrcDir
+//
+// @auto-generate: gob
type SourcePath struct {
basePath
}
@@ -1496,6 +1462,8 @@ func (p SourcePath) join(ctx PathContext, paths ...string) SourcePath {
}
// OutputPath is a Path representing an intermediates file path rooted from the build directory
+//
+// @auto-generate: gob
type OutputPath struct {
basePath
@@ -1505,34 +1473,6 @@ type OutputPath struct {
fullPath string
}
-type outputPathGob struct {
- BasePath basePath
- OutDir string
- FullPath string
-}
-
-func (p *OutputPath) ToGob() *outputPathGob {
- return &outputPathGob{
- BasePath: p.basePath,
- OutDir: p.outDir,
- FullPath: p.fullPath,
- }
-}
-
-func (p *OutputPath) FromGob(data *outputPathGob) {
- p.basePath = data.BasePath
- p.outDir = data.OutDir
- p.fullPath = data.FullPath
-}
-
-func (p OutputPath) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[outputPathGob](&p)
-}
-
-func (p *OutputPath) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[outputPathGob](data, p)
-}
-
func (p OutputPath) withRel(rel string) OutputPath {
p.basePath = p.basePath.withRel(rel)
p.fullPath = filepath.Join(p.fullPath, rel)
@@ -1572,6 +1512,7 @@ var _ WritablePath = OutputPath{}
var _ objPathProvider = OutputPath{}
// toolDepPath is a Path representing a dependency of the build tool.
+// @auto-generate: gob
type toolDepPath struct {
basePath
}
@@ -1690,10 +1631,10 @@ func PathForModuleSrc(ctx ModuleMissingDepsPathContext, pathComponents ...string
} else {
reportPathError(ctx, err)
}
- return nil
+ return pathForModuleSrc(ctx, "Missing_PathForModuleSrc_file")
} else if len(paths) == 0 {
ReportPathErrorf(ctx, "%q produced no files, expected exactly one", p)
- return nil
+ return pathForModuleSrc(ctx, "Missing_PathForModuleSrc_file")
} else if len(paths) > 1 {
ReportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths))
}
@@ -1771,6 +1712,7 @@ func (p SourcePath) resPathWithName(ctx ModuleOutPathContext, name string) Modul
}
// ModuleOutPath is a Path representing a module's output directory.
+// @auto-generate: gob
type ModuleOutPath struct {
OutputPath
}
@@ -1814,6 +1756,7 @@ func PathForModuleOut(ctx ModuleOutPathContext, paths ...string) ModuleOutPath {
// ModuleGenPath is a Path representing the 'gen' directory in a module's output
// directory. Mainly used for generated sources.
+// @auto-generate: gob
type ModuleGenPath struct {
ModuleOutPath
}
@@ -1864,6 +1807,7 @@ func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext stri
// ModuleObjPath is a Path representing the 'obj' directory in a module's output
// directory. Used for compiled objects.
+// @auto-generate: gob
type ModuleObjPath struct {
ModuleOutPath
}
@@ -1888,6 +1832,7 @@ func PathForModuleObj(ctx ModuleOutPathContext, pathComponents ...string) Module
// ModuleResPath is a a Path representing the 'res' directory in a module's
// output directory.
+// @auto-generate: gob
type ModuleResPath struct {
ModuleOutPath
}
@@ -1912,6 +1857,8 @@ func PathForModuleRes(ctx ModuleOutPathContext, pathComponents ...string) Module
}
// InstallPath is a Path representing a installed file path rooted from the build directory
+//
+// @auto-generate: gob
type InstallPath struct {
basePath
@@ -1930,43 +1877,6 @@ type InstallPath struct {
fullPath string
}
-type installPathGob struct {
- BasePath basePath
- SoongOutDir string
- PartitionDir string
- Partition string
- MakePath bool
- FullPath string
-}
-
-func (p *InstallPath) ToGob() *installPathGob {
- return &installPathGob{
- BasePath: p.basePath,
- SoongOutDir: p.soongOutDir,
- PartitionDir: p.partitionDir,
- Partition: p.partition,
- MakePath: p.makePath,
- FullPath: p.fullPath,
- }
-}
-
-func (p *InstallPath) FromGob(data *installPathGob) {
- p.basePath = data.BasePath
- p.soongOutDir = data.SoongOutDir
- p.partitionDir = data.PartitionDir
- p.partition = data.Partition
- p.makePath = data.MakePath
- p.fullPath = data.FullPath
-}
-
-func (p InstallPath) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[installPathGob](&p)
-}
-
-func (p *InstallPath) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[installPathGob](data, p)
-}
-
// Will panic if called from outside a test environment.
func ensureTestOnly() {
if PrefixInList(os.Args, "-test.") {
@@ -2303,6 +2213,7 @@ func PathForPhony(ctx PathContext, phony string) WritablePath {
return PhonyPath{basePath{phony, ""}}
}
+// @auto-generate: gob
type PhonyPath struct {
basePath
}
@@ -2333,6 +2244,7 @@ func (p PhonyPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
var _ Path = PhonyPath{}
var _ WritablePath = PhonyPath{}
+// @auto-generate: gob
type testPath struct {
basePath
}
@@ -2578,6 +2490,7 @@ func absolutePath(path string) string {
// The data file should be installed (copied from `<SrcPath>`) to
// `<install_root>/<RelativeInstallPath>/<filename>`, or
// `<install_root>/<filename>` if RelativeInstallPath is empty.
+// @auto-generate: gob
type DataPath struct {
// The path of the data file that should be copied into the data directory
SrcPath Path
diff --git a/android/paths_gob_enc.go b/android/paths_gob_enc.go
new file mode 100644
index 000000000..12884e799
--- /dev/null
+++ b/android/paths_gob_enc.go
@@ -0,0 +1,502 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ OptionalPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(OptionalPath) })
+ PathsGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(Paths) })
+ basePathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(basePath) })
+ SourcePathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SourcePath) })
+ OutputPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(OutputPath) })
+ toolDepPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(toolDepPath) })
+ ModuleOutPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleOutPath) })
+ ModuleGenPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleGenPath) })
+ ModuleObjPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleObjPath) })
+ ModuleResPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModuleResPath) })
+ InstallPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(InstallPath) })
+ PhonyPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(PhonyPath) })
+ testPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(testPath) })
+ DataPathGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(DataPath) })
+}
+
+func (r OptionalPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.path); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.invalidReason); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *OptionalPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.path = nil
+ } else {
+ r.path = val2.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.invalidReason)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var OptionalPathGobRegId int16
+
+func (r OptionalPath) GetTypeId() int16 {
+ return OptionalPathGobRegId
+}
+
+func (r Paths) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r); val1++ {
+ if err = gobtools.EncodeInterface(buf, r[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *Paths) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ (*r) = make([]Path, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ if val5, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val5 == nil {
+ (*r)[val3] = nil
+ } else {
+ (*r)[val3] = val5.(Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var PathsGobRegId int16
+
+func (r Paths) GetTypeId() int16 {
+ return PathsGobRegId
+}
+
+func (r basePath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.path); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.rel); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *basePath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.path)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.rel)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var basePathGobRegId int16
+
+func (r basePath) GetTypeId() int16 {
+ return basePathGobRegId
+}
+
+func (r SourcePath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *SourcePath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var SourcePathGobRegId int16
+
+func (r SourcePath) GetTypeId() int16 {
+ return SourcePathGobRegId
+}
+
+func (r OutputPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.outDir); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.fullPath); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *OutputPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.outDir)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.fullPath)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var OutputPathGobRegId int16
+
+func (r OutputPath) GetTypeId() int16 {
+ return OutputPathGobRegId
+}
+
+func (r toolDepPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *toolDepPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var toolDepPathGobRegId int16
+
+func (r toolDepPath) GetTypeId() int16 {
+ return toolDepPathGobRegId
+}
+
+func (r ModuleOutPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.OutputPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModuleOutPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.OutputPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModuleOutPathGobRegId int16
+
+func (r ModuleOutPath) GetTypeId() int16 {
+ return ModuleOutPathGobRegId
+}
+
+func (r ModuleGenPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.ModuleOutPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModuleGenPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.ModuleOutPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModuleGenPathGobRegId int16
+
+func (r ModuleGenPath) GetTypeId() int16 {
+ return ModuleGenPathGobRegId
+}
+
+func (r ModuleObjPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.ModuleOutPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModuleObjPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.ModuleOutPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModuleObjPathGobRegId int16
+
+func (r ModuleObjPath) GetTypeId() int16 {
+ return ModuleObjPathGobRegId
+}
+
+func (r ModuleResPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.ModuleOutPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ModuleResPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.ModuleOutPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ModuleResPathGobRegId int16
+
+func (r ModuleResPath) GetTypeId() int16 {
+ return ModuleResPathGobRegId
+}
+
+func (r InstallPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.soongOutDir); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.partitionDir); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.partition); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.makePath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.fullPath); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *InstallPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.soongOutDir)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.partitionDir)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.partition)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.makePath)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.fullPath)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var InstallPathGobRegId int16
+
+func (r InstallPath) GetTypeId() int16 {
+ return InstallPathGobRegId
+}
+
+func (r PhonyPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *PhonyPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var PhonyPathGobRegId int16
+
+func (r PhonyPath) GetTypeId() int16 {
+ return PhonyPathGobRegId
+}
+
+func (r testPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.basePath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *testPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.basePath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var testPathGobRegId int16
+
+func (r testPath) GetTypeId() int16 {
+ return testPathGobRegId
+}
+
+func (r DataPath) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.SrcPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.RelativeInstallPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.WithoutRel); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *DataPath) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.SrcPath = nil
+ } else {
+ r.SrcPath = val2.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.RelativeInstallPath)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.WithoutRel)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var DataPathGobRegId int16
+
+func (r DataPath) GetTypeId() int16 {
+ return DataPathGobRegId
+}
diff --git a/android/paths_test.go b/android/paths_test.go
index b125c4e73..814d1f9ba 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -1537,7 +1537,7 @@ func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
- AssertStringEquals(t, "foo src", "", foo.src)
+ AssertStringEquals(t, "foo src", "Missing_PathForModuleSrc_file", foo.src)
bar := result.ModuleForTests(t, "bar", "").Module().(*pathForModuleSrcTestModule)
diff --git a/android/phony.go b/android/phony.go
index 99ff0aaa4..50280bbd7 100644
--- a/android/phony.go
+++ b/android/phony.go
@@ -15,18 +15,22 @@
package android
import (
+ "fmt"
"strings"
"sync"
"github.com/google/blueprint"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var phonyMapOnceKey = NewOnceKey("phony")
type phonyMap map[string]Paths
var phonyMapLock sync.Mutex
+// @auto-generate: gob
type ModulePhonyInfo struct {
Phonies map[string]Paths
}
@@ -40,6 +44,9 @@ func getSingletonPhonyMap(config Config) phonyMap {
}
func addSingletonPhony(config Config, name string, deps ...Path) {
+ if name == "" {
+ panic("Phony name cannot be the empty string")
+ }
phonyMap := getSingletonPhonyMap(config)
phonyMapLock.Lock()
defer phonyMapLock.Unlock()
@@ -73,7 +80,15 @@ func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
// be generated in the packaging step. Instead of emitting a blueprint/ninja phony directly,
// create a makefile that defines the phonies that will be included in the packaging step.
// Make will dedup the phonies there.
+ phonyFileSize := 0
+ for _, phony := range p.phonyList {
+ phonyFileSize += 2*len(phony) + 11
+ for _, dep := range p.phonyMap[phony] {
+ phonyFileSize += len(dep.String()) + 1
+ }
+ }
var buildPhonyFileContents strings.Builder
+ buildPhonyFileContents.Grow(phonyFileSize)
for _, phony := range p.phonyList {
buildPhonyFileContents.WriteString(".PHONY: ")
buildPhonyFileContents.WriteString(phony)
@@ -86,6 +101,9 @@ func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
}
buildPhonyFileContents.WriteString("\n")
}
+ if buildPhonyFileContents.Len() != phonyFileSize {
+ panic(fmt.Sprintf("phonyFileSize calculation incorrect, expected %d, actual len: %d", phonyFileSize, buildPhonyFileContents.Len()))
+ }
buildPhonyFile := PathForOutput(ctx, "soong_phony_targets.mk")
writeValueIfChanged(ctx, absolutePath(buildPhonyFile.String()), buildPhonyFileContents.String())
}
diff --git a/android/phony_gob_enc.go b/android/phony_gob_enc.go
new file mode 100644
index 000000000..d9df373fe
--- /dev/null
+++ b/android/phony_gob_enc.go
@@ -0,0 +1,81 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ModulePhonyInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ModulePhonyInfo) })
+}
+
+func (r ModulePhonyInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Phonies))); err != nil {
+ return err
+ }
+ for k, v := range r.Phonies {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, int32(len(v))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(v); val1++ {
+ if err = gobtools.EncodeInterface(buf, v[val1]); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *ModulePhonyInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val1 int32
+ err = gobtools.DecodeSimple[int32](buf, &val1)
+ if err != nil {
+ return err
+ }
+ if val1 > 0 {
+ r.Phonies = make(map[string]Paths, val1)
+ for val2 := 0; val2 < int(val1); val2++ {
+ var k string
+ var v Paths
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ v = make([]Path, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ if val9, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val9 == nil {
+ v[val7] = nil
+ } else {
+ v[val7] = val9.(Path)
+ }
+ }
+ }
+ r.Phonies[k] = v
+ }
+ }
+
+ return err
+}
+
+var ModulePhonyInfoGobRegId int16
+
+func (r ModulePhonyInfo) GetTypeId() int16 {
+ return ModulePhonyInfoGobRegId
+}
diff --git a/android/plugin.go b/android/plugin.go
index 4348f1475..87545320f 100644
--- a/android/plugin.go
+++ b/android/plugin.go
@@ -19,7 +19,7 @@ import (
"os"
"strings"
- "github.com/google/blueprint"
+ "github.com/google/blueprint/bootstrap"
)
func init() {
@@ -59,6 +59,7 @@ var allowedPluginsByName = map[string]bool{
"soong-java-config-error_prone": true,
"soong-libchrome": true,
"soong-llvm": true,
+ "soong-noto-fonts": true,
"soong-robolectric": true,
"soong-rust-prebuilts": true,
"soong-selinux": true,
@@ -68,16 +69,13 @@ var allowedPluginsByName = map[string]bool{
"treble_report_module": true,
"vintf-compatibility-matrix-soong-rules": true,
"xsdc-soong-rules": true,
+ "xtensa": true,
}
var internalPluginsPaths = []string{
"vendor/google/build/soong/internal_plugins.json",
}
-type pluginProvider interface {
- IsPluginFor(string) bool
-}
-
func maybeAddInternalPluginsToAllowlist(ctx SingletonContext) {
for _, internalPluginsPath := range internalPluginsPaths {
if path := ExistentPathForSource(ctx, internalPluginsPath); path.Valid() {
@@ -105,34 +103,35 @@ func (p *pluginSingleton) GenerateBuildActions(ctx SingletonContext) {
maybeAddInternalPluginsToAllowlist(ctx)
disallowedPlugins := map[string]bool{}
- ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
- if ctx.ModuleType(module) != "bootstrap_go_package" {
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ if ctx.ModuleName(module) != "soong_build" {
return
}
- p, ok := module.(pluginProvider)
- if !ok || !p.IsPluginFor("soong_build") {
- return
- }
+ ctx.VisitDirectDepsProxies(module, func(module ModuleProxy) {
+ if ctx.OtherModuleDependencyTag(module) != bootstrap.PluginDepTag {
+ return
+ }
- name := ctx.ModuleName(module)
- if _, ok := allowedPluginsByName[name]; ok {
- return
- }
+ name := ctx.ModuleName(module)
+ if _, ok := allowedPluginsByName[name]; ok {
+ return
+ }
- dir := ctx.ModuleDir(module)
+ dir := ctx.ModuleDir(module)
- // allow use of plugins within Soong to not allowlist everything
- if strings.HasPrefix(dir, "build/soong") {
- return
- }
+ // allow use of plugins within Soong to not allowlist everything
+ if strings.HasPrefix(dir, "build/soong") {
+ return
+ }
- // allow third party users outside of external to create new plugins, i.e. non-google paths
- // under vendor or hardware
- if !strings.HasPrefix(dir, "external/") && IsThirdPartyPath(dir) {
- return
- }
- disallowedPlugins[name] = true
+ // allow third party users outside of external to create new plugins, i.e. non-google paths
+ // under vendor or hardware
+ if !strings.HasPrefix(dir, "external/") && IsThirdPartyPath(dir) {
+ return
+ }
+ disallowedPlugins[name] = true
+ })
})
if len(disallowedPlugins) > 0 {
ctx.Errorf("New plugins are not supported; however %q were found. Please reach out to the build team or use BUILD_BROKEN_PLUGIN_VALIDATION (see Changes.md for more info).", SortedKeys(disallowedPlugins))
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 1ff009bf5..deb898421 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -357,13 +357,15 @@ func IsModulePreferred(module Module) bool {
return true
}
-func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool {
- if OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt {
- // A source module that has been replaced by a prebuilt counterpart.
- return false
- }
- if p, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
- return p.UsePrebuilt
+func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleOrProxy) bool {
+ if info, ok := OtherModuleProvider(ctx, module, PrebuiltInfoProvider); ok {
+ if info.ReplacedByPrebuilt {
+ // A source module that has been replaced by a prebuilt counterpart.
+ return false
+ }
+ if info.IsPrebuilt {
+ return info.UsePrebuilt
+ }
}
return true
}
@@ -371,8 +373,13 @@ func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy)
// IsModulePrebuilt returns true if the module implements PrebuiltInterface and
// has been initialized as a prebuilt and so returns a non-nil value from the
// PrebuiltInterface.Prebuilt() method.
-func IsModulePrebuilt(module Module) bool {
- return GetEmbeddedPrebuilt(module) != nil
+func IsModulePrebuilt(ctx BaseModuleContext, module ModuleOrProxy) bool {
+ if EqualModules(ctx.Module(), module) {
+ return GetEmbeddedPrebuilt(ctx.Module()) != nil
+ } else {
+ info := OtherModuleProviderOrDefault(ctx, module, PrebuiltInfoProvider)
+ return info.IsPrebuilt
+ }
}
// GetEmbeddedPrebuilt returns a pointer to the embedded Prebuilt structure or
@@ -396,25 +403,27 @@ func GetEmbeddedPrebuilt(module Module) *Prebuilt {
// run - any dependency that is registered before that will already reference
// the right module. This function is only safe to call after all TransitionMutators
// have run, e.g. in GenerateAndroidBuildActions.
-func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
- if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt {
- return module
- }
- if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
- // If we're given a prebuilt then assume there's no source module around.
- return module
+func PrebuiltGetPreferred(ctx BaseModuleContext, module ModuleProxy) ModuleProxy {
+ if info, ok := OtherModuleProvider(ctx, module, PrebuiltInfoProvider); ok {
+ if !info.ReplacedByPrebuilt {
+ return module
+ }
+ if info.IsPrebuilt {
+ // If we're given a prebuilt then assume there's no source module around.
+ return module
+ }
}
sourceModDepFound := false
- var prebuiltMod Module
+ var prebuiltMod ModuleProxy
ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool {
- if prebuiltMod != nil {
+ if !prebuiltMod.IsNil() {
return false
}
if EqualModules(parent, ctx.Module()) {
// First level: Only recurse if the module is found as a direct dependency.
- sourceModDepFound = child == module
+ sourceModDepFound = EqualModules(child, module)
return sourceModDepFound
}
// Second level: Follow PrebuiltDepTag to the prebuilt.
@@ -424,7 +433,7 @@ func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
return false
})
- if prebuiltMod == nil {
+ if prebuiltMod.IsNil() {
if !sourceModDepFound {
panic(fmt.Errorf("Failed to find source module as a direct dependency: %s", module))
} else {
@@ -444,6 +453,7 @@ func RegisterPrebuiltsPreDepsMutators(ctx RegisterMutatorsContext) {
}
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("prebuilt_provider", prebuiltProviderMutator)
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies()
}
@@ -496,15 +506,13 @@ func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
// checkInvariantsForSourceAndPrebuilt checks if invariants are kept when replacing
// source with prebuilt. Note that the current module for the context is the source module.
-func checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, s, p Module) {
- if _, ok := s.(OverrideModule); ok {
- // skip the check when the source module is `override_X` because it's only a placeholder
- // for the actual source module. The check will be invoked for the actual module.
- return
- }
- if sourcePartition, prebuiltPartition := s.PartitionTag(ctx.DeviceConfig()), p.PartitionTag(ctx.DeviceConfig()); sourcePartition != prebuiltPartition {
- ctx.OtherModuleErrorf(p, "partition is different: %s(%s) != %s(%s)",
- sourcePartition, ctx.ModuleName(), prebuiltPartition, ctx.OtherModuleName(p))
+func checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, sourcePartition string,
+ prebuiltPartitions, prebuiltModuleNames []string) {
+ for i, prebuiltPartition := range prebuiltPartitions {
+ if sourcePartition != prebuiltPartition {
+ ctx.ModuleErrorf("partition is different: %s(%s) != %s(%s)",
+ sourcePartition, ctx.ModuleName(), prebuiltPartition, prebuiltModuleNames[i])
+ }
}
}
@@ -541,7 +549,15 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
p := GetEmbeddedPrebuilt(prebuiltModule)
if p.usePrebuilt(ctx, s, prebuiltModule) {
- checkInvariantsForSourceAndPrebuilt(ctx, s, prebuiltModule)
+ // skip the check when the source module is `override_X` because it's only a placeholder
+ // for the actual source module. The check will be invoked for the actual module.
+ if _, isOverride := s.(OverrideModule); !isOverride {
+ sourcePartition := s.PartitionTag(ctx.DeviceConfig())
+ prebuiltPartition := prebuiltModule.PartitionTag(ctx.DeviceConfig())
+ checkInvariantsForSourceAndPrebuilt(ctx, sourcePartition, []string{prebuiltPartition},
+ []string{ctx.OtherModuleName(prebuiltModule)})
+
+ }
p.properties.UsePrebuilt = true
s.ReplacedByPrebuilt()
@@ -556,7 +572,10 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
allModules = append(allModules, prebuiltModule)
})
hideUnflaggedModules(ctx, psi, allModules)
+ }
+ if ac, ok := m.(*apexContributions); ok {
+ ac.setApexContributionsInfoProvider(ctx)
}
// If this is `all_apex_contributions`, set a provider containing
@@ -566,6 +585,31 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
}
}
+var PrebuiltInfoProvider = blueprint.NewMutatorProvider[PrebuiltInfo]("prebuilt_provider")
+
+type PrebuiltInfo struct {
+ IsPrebuilt bool
+ PrebuiltSourceExists bool
+ UsePrebuilt bool
+ // Whether the module has been replaced by a prebuilt
+ ReplacedByPrebuilt bool
+}
+
+// prebuiltProviderMutator sets the PrebuiltInfoProvider.
+func prebuiltProviderMutator(ctx BottomUpMutatorContext) {
+ m := ctx.Module()
+
+ info := PrebuiltInfo{}
+
+ if p, ok := m.(PrebuiltInterface); ok && p.Prebuilt() != nil {
+ info.IsPrebuilt = true
+ info.PrebuiltSourceExists = p.Prebuilt().SourceExists()
+ info.UsePrebuilt = p.Prebuilt().UsePrebuilt()
+ }
+ info.ReplacedByPrebuilt = m.IsReplacedByPrebuilt()
+ SetProvider(ctx, PrebuiltInfoProvider, info)
+}
+
// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) {
var selectedModuleInFamily Module
@@ -756,7 +800,7 @@ func (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Mo
// Skip prebuilt modules under unexported namespaces so that we won't
// end up shadowing non-prebuilt module when prebuilt module under same
// name happens to have a `Prefer` property set to true.
- if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
+ if !prebuilt.ExportedToMake() {
return false
}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index d31fc4fcd..f215be8a9 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -16,8 +16,6 @@ package android
import (
"testing"
-
- "github.com/google/blueprint"
)
func TestPrebuilts(t *testing.T) {
@@ -338,7 +336,7 @@ func TestPrebuilts(t *testing.T) {
foo := result.ModuleForTests(t, "foo", variant)
t.Run(foo.Module().Target().Os.String(), func(t *testing.T) {
var dependsOnSourceModule, dependsOnPrebuiltModule bool
- result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
+ result.VisitDirectDeps(foo.Module(), func(m Module) {
if _, ok := m.(*sourceModule); ok {
dependsOnSourceModule = true
}
diff --git a/android/product_config.go b/android/product_config.go
index 850f00334..2549f7967 100644
--- a/android/product_config.go
+++ b/android/product_config.go
@@ -14,10 +14,6 @@
package android
-import (
- "github.com/google/blueprint/proptools"
-)
-
func init() {
ctx := InitRegistrationContext
ctx.RegisterModuleType("product_config", productConfigFactory)
@@ -27,6 +23,10 @@ type productConfigModule struct {
ModuleBase
}
+func (p *productConfigModule) UseGenericConfig() bool {
+ return false
+}
+
func (p *productConfigModule) GenerateAndroidBuildActions(ctx ModuleContext) {
if ctx.ModuleName() != "product_config" || ctx.ModuleDir() != "build/soong" {
ctx.ModuleErrorf("There can only be one product_config module in build/soong")
@@ -34,10 +34,10 @@ func (p *productConfigModule) GenerateAndroidBuildActions(ctx ModuleContext) {
}
outputFilePath := PathForModuleOut(ctx, p.Name()+".json")
- // DeviceProduct can be null so calling ctx.Config().DeviceProduct() may cause null dereference
- targetProduct := proptools.String(ctx.Config().config.productVariables.DeviceProduct)
- if targetProduct != "" {
- targetProduct += "."
+ // DeviceProduct can be null, so check before calling ctx.Config().DeviceProduct()
+ targetProduct := ""
+ if ctx.Config().HasDeviceProduct() {
+ targetProduct = ctx.Config().DeviceProduct() + "."
}
coverageSuffix := ctx.Config().CoverageSuffix()
diff --git a/android/provider.go b/android/provider.go
index aae93ef88..85fc08c0c 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -7,7 +7,7 @@ import (
// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
// for use in OtherModuleProvider.
type OtherModuleProviderContext interface {
- otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(m ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool)
}
var _ OtherModuleProviderContext = BaseModuleContext(nil)
@@ -22,13 +22,14 @@ type ConfigAndOtherModuleProviderContext interface {
ConfigContext
}
-// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is
-// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
-// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
+// OtherModuleProvider reads the provider for the given module. If the provider has been set the
+// value is returned and the boolean is true. If it has not been set or the module is nil, the zero
+// value of the provider's type is returned and the boolean is false. The value returned may be a
+// deep copy of the value originally passed to SetProvider.
//
// OtherModuleProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
-func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
- value, ok := ctx.otherModuleProvider(getWrappedModule(module), provider)
+func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module ModuleOrProxy, provider blueprint.ProviderKey[K]) (K, bool) {
+ value, ok := ctx.otherModuleProvider(module, provider)
if !ok {
var k K
return k, false
@@ -36,12 +37,12 @@ func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint
return value.(K), ok
}
-func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K {
+func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module ModuleOrProxy, provider blueprint.ProviderKey[K]) K {
value, _ := OtherModuleProvider(ctx, module, provider)
return value
}
-func OtherModulePointerProviderOrDefault[K *T, T any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K {
+func OtherModulePointerProviderOrDefault[K *T, T any](ctx OtherModuleProviderContext, module ModuleOrProxy, provider blueprint.ProviderKey[K]) K {
if value, ok := OtherModuleProvider(ctx, module, provider); ok {
return value
}
@@ -97,13 +98,13 @@ var _ OtherModuleProviderContext = (*otherModuleProviderAdaptor)(nil)
// An OtherModuleProviderFunc can be passed to NewOtherModuleProviderAdaptor to create an OtherModuleProviderContext
// for use in tests.
-type OtherModuleProviderFunc func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+type OtherModuleProviderFunc func(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool)
type otherModuleProviderAdaptor struct {
otherModuleProviderFunc OtherModuleProviderFunc
}
-func (p *otherModuleProviderAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+func (p *otherModuleProviderAdaptor) otherModuleProvider(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool) {
return p.otherModuleProviderFunc(module, provider)
}
diff --git a/android/provider_keys.go b/android/provider_keys.go
index 60b383f53..1f99414c2 100644
--- a/android/provider_keys.go
+++ b/android/provider_keys.go
@@ -22,3 +22,11 @@ type AndroidDeviceInfo struct {
}
var AndroidDeviceInfoProvider = blueprint.NewProvider[AndroidDeviceInfo]()
+
+// Providers of prebuilt_kernel_modules
+type PrebuiltKernelModulesComplianceMetadata struct {
+ Srcs []string
+ Dests []string
+}
+
+var PrebuiltKernelModulesComplianceMetadataProvider = blueprint.NewProvider[PrebuiltKernelModulesComplianceMetadata]()
diff --git a/android/raw_files.go b/android/raw_files.go
index ebba4d145..128b6feb0 100644
--- a/android/raw_files.go
+++ b/android/raw_files.go
@@ -271,7 +271,7 @@ func (rawFilesSingleton) GenerateBuildActions(ctx SingletonContext) {
// Checking that the path matches allows changing the structure of the raw directory, for example to increase
// the sharding.
rawFileInfo, written := rawFileSet.Load(key)
- if !written || rawFileInfo.relPath != relPath {
+ if !ctx.GetIncrementalAnalysis() && (!written || rawFileInfo.relPath != relPath) {
os.Remove(path)
}
return nil
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 01fe6d8ea..c0699ee88 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -22,17 +22,20 @@ import (
"strings"
"testing"
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
"android/soong/cmd/sbox/sbox_proto"
"android/soong/remoteexec"
"android/soong/response"
"android/soong/shared"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
const sboxSandboxBaseDir = "__SBOX_SANDBOX_DIR__"
const sboxOutSubDir = "out"
const sboxToolsSubDir = "tools"
@@ -66,6 +69,7 @@ type RuleBuilder struct {
nsjailKeepGendir bool
nsjailBasePath WritablePath
nsjailImplicits Paths
+ dirDepsFile WritablePath
}
// NewRuleBuilder returns a newly created RuleBuilder.
@@ -98,6 +102,7 @@ func (rb *RuleBuilder) SetPhonyOutput() {
}
// RuleBuilderInstall is a tuple of install from and to locations.
+// @auto-generate: gob
type RuleBuilderInstall struct {
From Path
To string
@@ -198,6 +203,14 @@ func (r *RuleBuilder) Nsjail(outputDir WritablePath, baseDir WritablePath) *Rule
return r
}
+func (r *RuleBuilder) DirDepsFile(dirDepsFile WritablePath) *RuleBuilder {
+ if r.dirDepsFile != nil {
+ panic("Cannot call DirDepsFile() twice")
+ }
+ r.dirDepsFile = dirDepsFile
+ return r
+}
+
// NsjailImplicits adds implicit inputs that are not directly mounted. This is useful when
// the rule mounts directories, as files within those directories can be globbed and
// tracked as dependencies with NsjailImplicits().
@@ -476,6 +489,21 @@ func (r *RuleBuilder) rspFiles() []rspFileAndPaths {
return rspFiles
}
+// implicitDirectories returns the list of paths that were passed to the RuleBuilderCommand.ImplicitDirectory method.
+// The list is sorted and duplicates removed.
+func (r *RuleBuilder) implicitDirectories() DirectoryPaths {
+ var dirsList DirectoryPaths
+ for _, c := range r.commands {
+ dirsList = append(dirsList, c.implicitDirectories...)
+ }
+
+ sort.Slice(dirsList, func(i, j int) bool {
+ return dirsList[i].String() < dirsList[j].String()
+ })
+
+ return dirsList
+}
+
// Commands returns a slice containing the built command line for each call to RuleBuilder.Command.
func (r *RuleBuilder) Commands() []string {
var commands []string
@@ -501,6 +529,17 @@ func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderComma
Inputs(depFiles.Paths())
}
+func (r *RuleBuilder) dirsToDepFileCmd(dirs DirectoryPaths, target WritablePath) *RuleBuilderCommand {
+ if r.dirDepsFile == nil {
+ panic("You must call DirDepsFile() to use directory inputs")
+ }
+ return r.Command().
+ builtToolWithoutDeps("dir_to_depfile").
+ FlagWithDepFile("-o ", r.dirDepsFile).
+ FlagWithArg("-t ", target.String()).
+ Text(strings.Join(dirs.Strings(), " "))
+}
+
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs.
func (r *RuleBuilder) Build(name string, desc string) {
@@ -524,22 +563,26 @@ func (r *RuleBuilder) build(name string, desc string) {
return
}
+ if dirs := r.implicitDirectories(); len(dirs) > 0 {
+ r.dirsToDepFileCmd(dirs, r.Outputs()[0])
+ }
+
var depFile WritablePath
var depFormat blueprint.Deps
if depFiles := r.DepFiles(); len(depFiles) > 0 {
+ if r.sbox || r.nsjail {
+ // Check for Rel() errors, as all depfiles should be in the output dir. Errors
+ // will be reported to the ctx.
+ for _, path := range depFiles {
+ Rel(r.ctx, r.outDir.String(), path.String())
+ }
+ }
+
depFile = depFiles[0]
depFormat = blueprint.DepsGCC
if len(depFiles) > 1 {
// Add a command locally that merges all depfiles together into the first depfile.
r.depFileMergerCmd(depFiles)
-
- if r.sbox {
- // Check for Rel() errors, as all depfiles should be in the output dir. Errors
- // will be reported to the ctx.
- for _, path := range depFiles[1:] {
- Rel(r.ctx, r.outDir.String(), path.String())
- }
- }
}
}
@@ -601,6 +644,9 @@ func (r *RuleBuilder) build(name string, desc string) {
for _, input := range inputs {
addBindMount(input.String(), r.nsjailPathForInputRel(input))
}
+ for _, input := range r.OrderOnlys() {
+ addBindMount(input.String(), r.nsjailPathForInputRel(input))
+ }
for _, tool := range tools {
addBindMount(tool.String(), nsjailPathForToolRel(r.ctx, tool))
}
@@ -608,8 +654,6 @@ func (r *RuleBuilder) build(name string, desc string) {
for _, c := range r.commands {
for _, directory := range c.implicitDirectories {
addBindMount(directory.String(), directory.String())
- // TODO(b/375551969): Add implicitDirectories to BuildParams, rather than relying on implicits
- inputs = append(inputs, SourcePath{basePath: directory.base()})
}
for _, tool := range c.packagedTools {
addBindMount(tool.srcPath.String(), nsjailPathForPackagedToolRel(tool))
@@ -645,10 +689,6 @@ func (r *RuleBuilder) build(name string, desc string) {
manifest.Commands = append(manifest.Commands, &command)
command.Command = proto.String(commandString)
- if depFile != nil {
- manifest.OutputDepfile = proto.String(depFile.String())
- }
-
// If sandboxing tools is enabled, add copy rules to the manifest to copy each tool
// into the sbox directory.
if r.sboxTools {
@@ -690,6 +730,14 @@ func (r *RuleBuilder) build(name string, desc string) {
To: proto.String(r.sboxPathForInputRel(input)),
})
}
+ for _, c := range r.commands {
+ for _, directory := range c.implicitDirectories {
+ command.CopyDirBefore = append(command.CopyDirBefore, &sbox_proto.CopyDir{
+ From: proto.String(directory.String()),
+ To: proto.String(directory.String()),
+ })
+ }
+ }
// If using rsp files copy them and their contents into the sbox directory with
// the appropriate path mappings.
@@ -760,6 +808,13 @@ func (r *RuleBuilder) build(name string, desc string) {
To: proto.String(output.String()),
})
}
+ if depFile != nil {
+ rel := Rel(r.ctx, r.outDir.String(), depFile.String())
+ command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{
+ From: proto.String(filepath.Join(r.sboxOutSubDir, rel)),
+ To: proto.String(depFile.String()),
+ })
+ }
// Outputs that were marked Temporary will not be checked that they are in the output
// directory by the loop above, check them here.
@@ -869,9 +924,7 @@ func (r *RuleBuilder) build(name string, desc string) {
}
var pool blueprint.Pool
- if r.ctx.Config().UseGoma() && r.remoteable.Goma {
- // When USE_GOMA=true is set and the rule is supported by goma, allow jobs to run outside the local pool.
- } else if r.ctx.Config().UseRBE() && r.remoteable.RBE {
+ if r.ctx.Config().UseRBE() && r.remoteable.RBE {
// When USE_RBE=true is set and the rule is supported by RBE, use the remotePool.
pool = remotePool
} else if r.highmem {
@@ -964,10 +1017,6 @@ func (c *RuleBuilderCommand) addImplicit(path Path) {
c.implicits = append(c.implicits, path)
}
-func (c *RuleBuilderCommand) addImplicitDirectory(path DirectoryPath) {
- c.implicitDirectories = append(c.implicitDirectories, path)
-}
-
func (c *RuleBuilderCommand) addOrderOnly(path Path) {
checkPathNotNil(path)
c.orderOnlys = append(c.orderOnlys, path)
@@ -1337,10 +1386,10 @@ func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand {
// ImplicitDirectory adds the specified input directory to the dependencies without modifying the
// command line. Added directories will be bind-mounted for the nsjail.
func (c *RuleBuilderCommand) ImplicitDirectory(path DirectoryPath) *RuleBuilderCommand {
- if !c.rule.nsjail {
- panic("ImplicitDirectory() must be called after Nsjail()")
+ if !c.rule.nsjail && !c.rule.sbox {
+ panic("ImplicitDirectory() must be called after Nsjail() or Sbox()")
}
- c.addImplicitDirectory(path)
+ c.implicitDirectories = append(c.implicitDirectories, path)
return c
}
diff --git a/android/rule_builder_gob_enc.go b/android/rule_builder_gob_enc.go
new file mode 100644
index 000000000..da9705aea
--- /dev/null
+++ b/android/rule_builder_gob_enc.go
@@ -0,0 +1,50 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ RuleBuilderInstallGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(RuleBuilderInstall) })
+}
+
+func (r RuleBuilderInstall) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.From); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.To); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *RuleBuilderInstall) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.From = nil
+ } else {
+ r.From = val2.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.To)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var RuleBuilderInstallGobRegId int16
+
+func (r RuleBuilderInstall) GetTypeId() int16 {
+ return RuleBuilderInstallGobRegId
+}
diff --git a/android/sbom.go b/android/sbom.go
index fc61c41dd..322aa2682 100644
--- a/android/sbom.go
+++ b/android/sbom.go
@@ -77,7 +77,7 @@ func (this *sbomSingleton) GenerateBuildActions(ctx SingletonContext) {
},
})
- if !ctx.Config().UnbundledBuildApps() {
+ if !ctx.Config().HasUnbundledBuildApps() {
// When building SBOM of products, phony rule "sbom" is for generating product SBOM in Soong.
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
diff --git a/android/sdk.go b/android/sdk.go
index ab9a91ccb..007fa2980 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -23,6 +23,8 @@ import (
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
type minApiLevelForSdkSnapshot interface {
MinSdkVersion(ctx EarlyModuleContext) ApiLevel
@@ -31,14 +33,14 @@ type minApiLevelForSdkSnapshot interface {
// MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module.
//
// If the module does not provide a min_sdk_version then it defaults to 1.
-func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel {
+func MinApiLevelForSdkSnapshot(commonInfo *CommonModuleInfo) ApiLevel {
minApiLevel := NoneApiLevel
- if m, ok := module.(minApiLevelForSdkSnapshot); ok {
- minApiLevel = m.MinSdkVersion(ctx)
+ if commonInfo.MinSdkVersion.ApiLevel != nil {
+ minApiLevel = *commonInfo.MinSdkVersion.ApiLevel
}
if minApiLevel == NoneApiLevel {
// The default min API level is 1.
- minApiLevel = uncheckedFinalApiLevel(1)
+ minApiLevel = UncheckedFinalApiLevel(1)
}
return minApiLevel
}
@@ -410,7 +412,7 @@ type SdkMember interface {
Name() string
// Variants returns all the variants of this module depended upon by the SDK.
- Variants() []Module
+ Variants() []ModuleProxy
}
// SdkMemberDependencyTag is the interface that a tag must implement in order to allow the
@@ -422,7 +424,7 @@ type SdkMemberDependencyTag interface {
// to the sdk.
//
// Returning nil will prevent the module being added to the sdk.
- SdkMemberType(child Module) SdkMemberType
+ SdkMemberType(ctx ModuleContext, child ModuleProxy) SdkMemberType
// ExportMember determines whether a module added to the sdk through this tag will be exported
// from the sdk or not.
@@ -449,7 +451,7 @@ type sdkMemberDependencyTag struct {
export bool
}
-func (t *sdkMemberDependencyTag) SdkMemberType(_ Module) SdkMemberType {
+func (t *sdkMemberDependencyTag) SdkMemberType(_ ModuleContext, _ ModuleProxy) SdkMemberType {
return t.memberType
}
@@ -534,7 +536,7 @@ type SdkMemberType interface {
// This is used to check the type of each variant before added to the SdkMember. Returning false
// will cause an error to be logged explaining that the module is not allowed in whichever sdk
// property it was added.
- IsInstance(module Module) bool
+ IsInstance(ctx ModuleContext, module ModuleProxy) bool
// UsesSourceModuleTypeInSnapshot returns true when the AddPrebuiltModule() method returns a
// source module type.
@@ -611,6 +613,7 @@ type SdkDependencyContext interface {
// SdkMemberTypeBase is the base type for SdkMemberType implementations and must be embedded in any
// struct that implements SdkMemberType.
+// @auto-generate: gob
type SdkMemberTypeBase struct {
PropertyName string
@@ -800,7 +803,7 @@ type SdkMemberProperties interface {
// PopulateFromVariant populates this structure with information from a module variant.
//
// It will typically be called once for each variant of a member module that the SDK depends upon.
- PopulateFromVariant(ctx SdkMemberContext, variant Module)
+ PopulateFromVariant(ctx SdkMemberContext, variant ModuleProxy)
// AddToPropertySet adds the information from this structure to the property set.
//
diff --git a/android/sdk_gob_enc.go b/android/sdk_gob_enc.go
new file mode 100644
index 000000000..59e70a04c
--- /dev/null
+++ b/android/sdk_gob_enc.go
@@ -0,0 +1,200 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ SdkMemberTypeBaseGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SdkMemberTypeBase) })
+}
+
+func (r SdkMemberTypeBase) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.PropertyName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.OverridesPropertyNames))); err != nil {
+ return err
+ }
+ for k, v := range r.OverridesPropertyNames {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeSimple(buf, v); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SupportedLinkageNames))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.SupportedLinkageNames); val1++ {
+ if err = gobtools.EncodeString(buf, r.SupportedLinkageNames[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.StripDisabled); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.BpPropertyNotRequired); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.SupportedBuildReleaseSpecification); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.SupportsSdk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HostOsDependent); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.UseSourceModuleTypeInSnapshot); err != nil {
+ return err
+ }
+
+ val2 := r.PrebuiltsRequired == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = gobtools.EncodeSimple(buf, (*r.PrebuiltsRequired)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Traits))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Traits); val3++ {
+ if err = gobtools.EncodeInterface(buf, r.Traits[val3]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *SdkMemberTypeBase) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.PropertyName)
+ if err != nil {
+ return err
+ }
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.OverridesPropertyNames = make(map[string]bool, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ var k string
+ var v bool
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ err = gobtools.DecodeSimple[bool](buf, &v)
+ if err != nil {
+ return err
+ }
+ r.OverridesPropertyNames[k] = v
+ }
+ }
+
+ var val7 int32
+ err = gobtools.DecodeSimple[int32](buf, &val7)
+ if err != nil {
+ return err
+ }
+ if val7 > 0 {
+ r.SupportedLinkageNames = make([]string, val7)
+ for val8 := 0; val8 < int(val7); val8++ {
+ err = gobtools.DecodeString(buf, &r.SupportedLinkageNames[val8])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.StripDisabled)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.BpPropertyNotRequired)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.SupportedBuildReleaseSpecification)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.SupportsSdk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HostOsDependent)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.UseSourceModuleTypeInSnapshot)
+ if err != nil {
+ return err
+ }
+
+ var val17 bool
+ if err = gobtools.DecodeSimple(buf, &val17); err != nil {
+ return err
+ }
+ if !val17 {
+ var val16 bool
+ err = gobtools.DecodeSimple[bool](buf, &val16)
+ if err != nil {
+ return err
+ }
+ r.PrebuiltsRequired = &val16
+ }
+
+ var val20 int32
+ err = gobtools.DecodeSimple[int32](buf, &val20)
+ if err != nil {
+ return err
+ }
+ if val20 > 0 {
+ r.Traits = make([]SdkMemberTrait, val20)
+ for val21 := 0; val21 < int(val20); val21++ {
+ if val23, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val23 == nil {
+ r.Traits[val21] = nil
+ } else {
+ r.Traits[val21] = val23.(SdkMemberTrait)
+ }
+ }
+ }
+
+ return err
+}
+
+var SdkMemberTypeBaseGobRegId int16
+
+func (r SdkMemberTypeBase) GetTypeId() int16 {
+ return SdkMemberTypeBaseGobRegId
+}
diff --git a/android/sdk_version.go b/android/sdk_version.go
index fa3abaa7c..3c49c5264 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -231,7 +231,7 @@ func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
if s.Kind == SdkPublic || s.Kind == SdkSystem {
if s.ApiLevel.IsCurrent() {
if i, err := strconv.Atoi(currentSdkVersion); err == nil {
- apiLevel := uncheckedFinalApiLevel(i)
+ apiLevel := UncheckedFinalApiLevel(i)
return SdkSpec{s.Kind, apiLevel, s.Raw}
}
panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
diff --git a/android/selects_test.go b/android/selects_test.go
index 8e469f8e3..c3dc5c84e 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -770,7 +770,7 @@ func TestSelects(t *testing.T) {
}),
}
`,
- expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool". This requires a small soong change to enable`,
},
{
name: "Assigning select to nonconfigurable string",
@@ -783,7 +783,7 @@ func TestSelects(t *testing.T) {
}),
}
`,
- expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string". This requires a small soong change to enable`,
},
{
name: "Assigning appended selects to nonconfigurable string",
@@ -799,7 +799,7 @@ func TestSelects(t *testing.T) {
}),
}
`,
- expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string". This requires a small soong change to enable`,
},
{
name: "Assigning select to nonconfigurable string list",
@@ -812,7 +812,20 @@ func TestSelects(t *testing.T) {
}),
}
`,
- expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list". This requires a small soong change to enable`,
+ },
+ {
+ name: "Assigning select to defaults property",
+ bp: `
+ my_module_type {
+ name: "foo",
+ defaults: select(soong_config_variable("foo", "bar"), {
+ "x": ["foo"],
+ default: [],
+ }),
+ }
+ `,
+ expectedError: `can't assign select statement to non-configurable property "defaults". We explicitly don't support selects on this property`,
},
{
name: "Select in variable",
diff --git a/android/singleton.go b/android/singleton.go
index e5f26842a..786b2794f 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -15,7 +15,9 @@
package android
import (
+ "path/filepath"
"slices"
+ "strings"
"sync"
"github.com/google/blueprint"
@@ -28,19 +30,19 @@ type SingletonContext interface {
Config() Config
DeviceConfig() DeviceConfig
- ModuleName(module blueprint.Module) string
- ModuleDir(module blueprint.Module) string
- ModuleSubDir(module blueprint.Module) string
- ModuleType(module blueprint.Module) string
- BlueprintFile(module blueprint.Module) string
+ ModuleName(module ModuleOrProxy) string
+ ModuleDir(module ModuleOrProxy) string
+ ModuleSubDir(module ModuleOrProxy) string
+ ModuleType(module ModuleOrProxy) string
+ BlueprintFile(module ModuleOrProxy) string
// ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules.
// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy
- otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool)
- ModuleErrorf(module blueprint.Module, format string, args ...interface{})
+ ModuleErrorf(module ModuleOrProxy, format string, args ...interface{})
Errorf(format string, args ...interface{})
Failed() bool
@@ -69,25 +71,23 @@ type SingletonContext interface {
VisitAllModules(visit func(Module))
VisitAllModuleProxies(visit func(proxy ModuleProxy))
VisitAllModulesIf(pred func(Module) bool, visit func(Module))
+ VisitAllModulesOrProxies(visit func(ModuleOrProxy))
VisitDirectDeps(module Module, visit func(Module))
VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirst(module Module, visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
- visit func(Module))
+ VisitDirectDepsProxies(module ModuleProxy, visit func(ModuleProxy))
VisitAllModuleVariants(module Module, visit func(Module))
- VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))
+ VisitAllModuleVariantProxies(module ModuleProxy, visit func(proxy ModuleProxy))
PrimaryModule(module Module) Module
PrimaryModuleProxy(module ModuleProxy) ModuleProxy
- IsFinalModule(module Module) bool
+ IsPrimaryModule(module ModuleOrProxy) bool
+ IsFinalModule(module ModuleOrProxy) bool
AddNinjaFileDeps(deps ...string)
@@ -98,7 +98,7 @@ type SingletonContext interface {
GlobWithDeps(pattern string, excludes []string) ([]string, error)
// OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
- OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property string, format string, args ...interface{})
// HasMutatorFinished returns true if the given mutator has finished running.
// It will panic if given an invalid mutator name.
@@ -113,6 +113,11 @@ type SingletonContext interface {
// goal is built.
DistForGoalWithFilename(goal string, path Path, filename string)
+ // DistForGoalWithFilenameTag creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename appended with the
+ // `-FILE_NAME_TAG_PLACEHOLDER` suffix when the specified goal is built.
+ DistForGoalWithFilenameTag(goal string, path Path, filename string)
+
// DistForGoals creates a rule to copy one or more Paths to the artifacts
// directory on the build server when any of the specified goals are built.
DistForGoals(goals []string, paths ...Path)
@@ -121,6 +126,16 @@ type SingletonContext interface {
// directory on the build server with the given filename when any of the
// specified goals are built.
DistForGoalsWithFilename(goals []string, path Path, filename string)
+
+ // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
+ // on the module. When called inside a Visit* method with current module being visited, and there are multiple
+ // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
+ OtherModuleDependencyTag(module ModuleOrProxy) blueprint.DependencyTag
+
+ GetIncrementalAnalysis() bool
+
+ // OtherModuleNamespace returns the namespace of the module.
+ OtherModuleNamespace(module ModuleOrProxy) *Namespace
}
type singletonAdaptor struct {
@@ -203,7 +218,7 @@ func (s *singletonContextAdaptor) Variable(pctx PackageContext, name, value stri
func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
if s.Config().UseRemoteBuild() {
if params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // When USE_RBE=true is set and the rule is not supported by RBE, restrict
// jobs to the local parallelism value
params.Pool = localPool
} else if params.Pool == remotePool {
@@ -240,6 +255,10 @@ func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (st
return s.SingletonContext.Eval(pctx.PackageContext, ninjaStr)
}
+func (s *singletonContextAdaptor) ModuleErrorf(module ModuleOrProxy, fmt string, args ...any) {
+ s.SingletonContext.ModuleErrorf(module, fmt, args...)
+}
+
// visitAdaptor wraps a visit function that takes an android.Module parameter into
// a function that takes a blueprint.Module parameter and only calls the visit function if the
// blueprint.Module is an android.Module.
@@ -255,9 +274,7 @@ func visitAdaptor(visit func(Module)) func(blueprint.Module) {
// a function that takes a blueprint.ModuleProxy parameter.
func visitProxyAdaptor(visit func(proxy ModuleProxy)) func(proxy blueprint.ModuleProxy) {
return func(module blueprint.ModuleProxy) {
- visit(ModuleProxy{
- module: module,
- })
+ visit(ModuleProxy{module})
}
}
@@ -274,24 +291,24 @@ func predAdaptor(pred func(Module) bool) func(blueprint.Module) bool {
}
}
-func (s *singletonContextAdaptor) ModuleName(module blueprint.Module) string {
- return s.SingletonContext.ModuleName(getWrappedModule(module))
+func (s *singletonContextAdaptor) ModuleName(module ModuleOrProxy) string {
+ return s.SingletonContext.ModuleName(module)
}
-func (s *singletonContextAdaptor) ModuleDir(module blueprint.Module) string {
- return s.SingletonContext.ModuleDir(getWrappedModule(module))
+func (s *singletonContextAdaptor) ModuleDir(module ModuleOrProxy) string {
+ return s.SingletonContext.ModuleDir(module)
}
-func (s *singletonContextAdaptor) ModuleSubDir(module blueprint.Module) string {
- return s.SingletonContext.ModuleSubDir(getWrappedModule(module))
+func (s *singletonContextAdaptor) ModuleSubDir(module ModuleOrProxy) string {
+ return s.SingletonContext.ModuleSubDir(module)
}
-func (s *singletonContextAdaptor) ModuleType(module blueprint.Module) string {
- return s.SingletonContext.ModuleType(getWrappedModule(module))
+func (s *singletonContextAdaptor) ModuleType(module ModuleOrProxy) string {
+ return s.SingletonContext.ModuleType(module)
}
-func (s *singletonContextAdaptor) BlueprintFile(module blueprint.Module) string {
- return s.SingletonContext.BlueprintFile(getWrappedModule(module))
+func (s *singletonContextAdaptor) BlueprintFile(module ModuleOrProxy) string {
+ return s.SingletonContext.BlueprintFile(module)
}
func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
@@ -306,6 +323,12 @@ func (s *singletonContextAdaptor) VisitAllModuleProxies(visit func(proxy ModuleP
s.SingletonContext.VisitAllModuleProxies(visitProxyAdaptor(visit))
}
+func (s *singletonContextAdaptor) VisitAllModulesOrProxies(visit func(ModuleOrProxy)) {
+ s.SingletonContext.VisitAllModulesOrProxies(func(module blueprint.ModuleOrProxy) {
+ visit(module)
+ })
+}
+
func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) {
s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit))
}
@@ -318,20 +341,20 @@ func (s *singletonContextAdaptor) VisitDirectDepsIf(module Module, pred func(Mod
s.SingletonContext.VisitDirectDepsIf(module, predAdaptor(pred), visitAdaptor(visit))
}
-func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) {
- s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit))
+func (s *singletonContextAdaptor) VisitDirectDepsProxies(module ModuleProxy, visit func(ModuleProxy)) {
+ s.SingletonContext.VisitDirectDepsProxies(module.ModuleProxy, visitProxyAdaptor(visit))
}
-func (s *singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
- s.SingletonContext.VisitDepsDepthFirstIf(module, predAdaptor(pred), visitAdaptor(visit))
+func (s *singletonContextAdaptor) OtherModuleDependencyTag(module ModuleOrProxy) blueprint.DependencyTag {
+ return s.SingletonContext.OtherModuleDependencyTag(module)
}
func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) {
s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit))
}
-func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) {
- s.SingletonContext.VisitAllModuleVariantProxies(getWrappedModule(module), visitProxyAdaptor(visit))
+func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module ModuleProxy, visit func(proxy ModuleProxy)) {
+ s.SingletonContext.VisitAllModuleVariantProxies(module.ModuleProxy, visitProxyAdaptor(visit))
}
func (s *singletonContextAdaptor) PrimaryModule(module Module) Module {
@@ -339,18 +362,22 @@ func (s *singletonContextAdaptor) PrimaryModule(module Module) Module {
}
func (s *singletonContextAdaptor) PrimaryModuleProxy(module ModuleProxy) ModuleProxy {
- return ModuleProxy{s.SingletonContext.PrimaryModuleProxy(module.module)}
+ return ModuleProxy{s.SingletonContext.PrimaryModuleProxy(module.ModuleProxy)}
}
-func (s *singletonContextAdaptor) IsFinalModule(module Module) bool {
- return s.SingletonContext.IsFinalModule(getWrappedModule(module))
+func (s *singletonContextAdaptor) IsPrimaryModule(module ModuleOrProxy) bool {
+ return s.SingletonContext.IsPrimaryModule(module)
+}
+
+func (s *singletonContextAdaptor) IsFinalModule(module ModuleOrProxy) bool {
+ return s.SingletonContext.IsFinalModule(module)
}
func (s *singletonContextAdaptor) ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy {
// get module reference for visibility enforcement
qualified := createVisibilityModuleProxyReference(s, s.ModuleName(referer), s.ModuleDir(referer), referer)
- modules := s.SingletonContext.ModuleVariantsFromName(referer.module, name)
+ modules := s.SingletonContext.ModuleVariantsFromName(referer.ModuleProxy, name)
result := make([]ModuleProxy, 0, len(modules))
for _, module := range modules {
// enforce visibility
@@ -371,11 +398,11 @@ func (s *singletonContextAdaptor) ModuleVariantsFromName(referer ModuleProxy, na
return result
}
-func (s *singletonContextAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+func (s *singletonContextAdaptor) otherModuleProvider(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool) {
return s.SingletonContext.ModuleProvider(module, provider)
}
-func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
+func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module ModuleOrProxy, property string, format string, args ...interface{}) {
s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...)
}
@@ -390,6 +417,15 @@ func (s *singletonContextAdaptor) DistForGoalWithFilename(goal string, path Path
s.DistForGoalsWithFilename([]string{goal}, path, filename)
}
+func (s *singletonContextAdaptor) DistForGoalWithFilenameTag(goal string, path Path, filename string) {
+ insertBeforeExtension := func(file, insertion string) string {
+ ext := filepath.Ext(file)
+ return strings.TrimSuffix(file, ext) + insertion + ext
+ }
+
+ s.DistForGoalWithFilename(goal, path, insertBeforeExtension(filename, "-FILE_NAME_TAG_PLACEHOLDER"))
+}
+
func (s *singletonContextAdaptor) DistForGoals(goals []string, paths ...Path) {
var copies distCopies
for _, path := range paths {
@@ -410,3 +446,11 @@ func (s *singletonContextAdaptor) DistForGoalsWithFilename(goals []string, path
paths: distCopies{{from: path, dest: filename}},
})
}
+
+func (s *singletonContextAdaptor) GetIncrementalAnalysis() bool {
+ return s.SingletonContext.GetIncrementalAnalysis()
+}
+
+func (s *singletonContextAdaptor) OtherModuleNamespace(module ModuleOrProxy) *Namespace {
+ return s.SingletonContext.OtherModuleNamespace(module).(*Namespace)
+}
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index a61c9d33d..e8b271abc 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -139,7 +139,7 @@ type soongConfigModuleTypeImportProperties struct {
// }
//
// If an acme BoardConfig.mk file contained:
-// $(call add_sonng_config_namespace, acme)
+// $(call add_soong_config_namespace, acme)
// $(call add_soong_config_var_value, acme, board, soc_a)
// $(call add_soong_config_var_value, acme, feature, true)
// $(call add_soong_config_var_value, acme, width, 200)
diff --git a/android/symbols.go b/android/symbols.go
new file mode 100644
index 000000000..aa0ccaa7e
--- /dev/null
+++ b/android/symbols.go
@@ -0,0 +1,107 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "github.com/google/blueprint"
+)
+
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
+func init() {
+ pctx.HostBinToolVariable("symbols_map", "symbols_map")
+}
+
+var zipFiles = pctx.AndroidStaticRule("SnapshotZipFiles", blueprint.RuleParams{
+ Command: `${SoongZipCmd} -r $out.rsp -o $out`,
+ CommandDeps: []string{"${SoongZipCmd}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+})
+
+var mergeSymbolsMapProtos = pctx.AndroidStaticRule("merge_symbol_map_protos", blueprint.RuleParams{
+ Command: `${symbols_map} -merge $out @$out.rsp`,
+ CommandDeps: []string{"${symbols_map}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+})
+
+// Provider for generating symbols.zip
+// @auto-generate: gob
+type SymbolicOutputInfo struct {
+ UnstrippedOutputFile Path
+ SymbolicOutputPath InstallPath
+ ElfMappingProtoPath InstallPath
+}
+
+// @auto-generate: gob
+type SymbolicOutputInfos []*SymbolicOutputInfo
+
+// SymbolInfosProvider provides necessary information to generate the symbols.zip
+var SymbolInfosProvider = blueprint.NewProvider[SymbolicOutputInfos]()
+
+func (s *SymbolicOutputInfos) SortedUniqueSymbolicOutputPaths() Paths {
+ ret := make(Paths, len(*s))
+ for i, info := range *s {
+ ret[i] = info.SymbolicOutputPath
+ }
+ return SortedUniquePaths(ret)
+}
+
+func (s *SymbolicOutputInfos) SortedUniqueElfMappingProtoPaths() Paths {
+ ret := make(Paths, len(*s))
+ for i, info := range *s {
+ ret[i] = info.ElfMappingProtoPath
+ }
+ return SortedUniquePaths(ret)
+}
+
+// symbolsContext allows calling [BuildSymbolsZip] in both modules and singletons
+type symbolsContext interface {
+ OtherModuleProviderContext
+ BuilderContext
+}
+
+// Defines the build rules to generate the symbols.zip file and the merged elf mapping textproto
+// file. Modules in depModules that provide [SymbolInfosProvider] and are exported to make
+// will be listed in the symbols.zip and the merged proto file.
+func BuildSymbolsZip(ctx symbolsContext, depModules []ModuleOrProxy, symbolsZipFile, mergedMappingProtoFile WritablePath) (Paths, Paths) {
+ var allSymbolicOutputPaths, allElfMappingProtoPaths Paths
+ for _, mod := range depModules {
+ if commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoProvider); commonInfo.SkipAndroidMkProcessing {
+ continue
+ }
+ if symbolInfos, ok := OtherModuleProvider(ctx, mod, SymbolInfosProvider); ok {
+ allSymbolicOutputPaths = append(allSymbolicOutputPaths, symbolInfos.SortedUniqueSymbolicOutputPaths()...)
+ allElfMappingProtoPaths = append(allElfMappingProtoPaths, symbolInfos.SortedUniqueElfMappingProtoPaths()...)
+ }
+ }
+ allSymbolicOutputPaths = SortedUniquePaths(allSymbolicOutputPaths)
+ allElfMappingProtoPaths = SortedUniquePaths(allElfMappingProtoPaths)
+
+ ctx.Build(pctx, BuildParams{
+ Rule: zipFiles,
+ Inputs: allSymbolicOutputPaths,
+ Output: symbolsZipFile,
+ })
+
+ ctx.Build(pctx, BuildParams{
+ Rule: mergeSymbolsMapProtos,
+ Output: mergedMappingProtoFile,
+ Inputs: allElfMappingProtoPaths,
+ })
+
+ return allSymbolicOutputPaths, allElfMappingProtoPaths
+}
diff --git a/android/symbols_gob_enc.go b/android/symbols_gob_enc.go
new file mode 100644
index 000000000..65b3dee2d
--- /dev/null
+++ b/android/symbols_gob_enc.go
@@ -0,0 +1,112 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ SymbolicOutputInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SymbolicOutputInfo) })
+ SymbolicOutputInfosGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SymbolicOutputInfos) })
+}
+
+func (r SymbolicOutputInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.UnstrippedOutputFile); err != nil {
+ return err
+ }
+
+ if err = r.SymbolicOutputPath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ElfMappingProtoPath.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *SymbolicOutputInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.UnstrippedOutputFile = nil
+ } else {
+ r.UnstrippedOutputFile = val2.(Path)
+ }
+
+ if err = r.SymbolicOutputPath.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ElfMappingProtoPath.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var SymbolicOutputInfoGobRegId int16
+
+func (r SymbolicOutputInfo) GetTypeId() int16 {
+ return SymbolicOutputInfoGobRegId
+}
+
+func (r SymbolicOutputInfos) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r); val1++ {
+ val2 := r[val1] == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = (*r[val1]).Encode(buf); err != nil {
+ return err
+ }
+ }
+ }
+ return err
+}
+
+func (r *SymbolicOutputInfos) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ (*r) = make([]*SymbolicOutputInfo, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ var val5 bool
+ if err = gobtools.DecodeSimple(buf, &val5); err != nil {
+ return err
+ }
+ if !val5 {
+ var val4 SymbolicOutputInfo
+ if err = val4.Decode(buf); err != nil {
+ return err
+ }
+ (*r)[val3] = &val4
+ }
+ }
+ }
+
+ return err
+}
+
+var SymbolicOutputInfosGobRegId int16
+
+func (r SymbolicOutputInfos) GetTypeId() int16 {
+ return SymbolicOutputInfosGobRegId
+}
diff --git a/android/system_dev_certificate.go b/android/system_dev_certificate.go
new file mode 100644
index 000000000..646b5447f
--- /dev/null
+++ b/android/system_dev_certificate.go
@@ -0,0 +1,45 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+func init() {
+ ctx := InitRegistrationContext
+ ctx.RegisterModuleType("system_dev_certificate", systemDevCertificateFactory)
+}
+
+type systemDevCertificateModule struct {
+ ModuleBase
+}
+
+func (s *systemDevCertificateModule) UseGenericConfig() bool {
+ return false
+}
+
+func (s *systemDevCertificateModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ if ctx.ModuleName() != "system_dev_certificate" || ctx.ModuleDir() != "build/soong" {
+ ctx.ModuleErrorf("There can only be one system_dev_certificate module in build/soong")
+ return
+ }
+
+ pem, pk8 := ctx.Config().DefaultAppCertificate(ctx)
+ ctx.SetOutputFiles(Paths{pem}, "pem")
+ ctx.SetOutputFiles(Paths{pk8}, "pk8")
+}
+
+func systemDevCertificateFactory() Module {
+ module := &systemDevCertificateModule{}
+ InitAndroidModule(module)
+ return module
+}
diff --git a/android/team.go b/android/team.go
index ad37f28c9..0036eb11e 100644
--- a/android/team.go
+++ b/android/team.go
@@ -16,6 +16,8 @@ package android
import "github.com/google/blueprint"
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterTeamBuildComponents(InitRegistrationContext)
}
@@ -45,6 +47,7 @@ type teamModule struct {
properties teamProperties
}
+// @auto-generate: gob
type TestModuleInformation struct {
TestOnly bool
TopLevelTarget bool
diff --git a/android/team_gob_enc.go b/android/team_gob_enc.go
new file mode 100644
index 000000000..001d44f28
--- /dev/null
+++ b/android/team_gob_enc.go
@@ -0,0 +1,47 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ TestModuleInformationGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(TestModuleInformation) })
+}
+
+func (r TestModuleInformation) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.TestOnly); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.TopLevelTarget); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *TestModuleInformation) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.TestOnly)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.TopLevelTarget)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var TestModuleInformationGobRegId int16
+
+func (r TestModuleInformation) GetTypeId() int16 {
+ return TestModuleInformationGobRegId
+}
diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS
index 1eb820b4c..bfbe4348b 100644
--- a/android/team_proto/OWNERS
+++ b/android/team_proto/OWNERS
@@ -1,4 +1,3 @@
dariofreni@google.com
-joeo@google.com
ronish@google.com
rbraunstein@google.com
diff --git a/android/test_config.go b/android/test_config.go
index 5d79df099..f59ba4127 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -32,6 +32,7 @@ func initTestConfig(buildDir string, env map[string]string) *config {
// Copy the real PATH value to the test environment, it's needed by
// NonHermeticHostSystemTool() used in x86_darwin_host.go
envCopy["PATH"] = os.Getenv("PATH")
+ envCopy["TARGET_PRODUCT"] = "test_product"
config := &config{
productVariables: ProductVariables{
@@ -56,8 +57,11 @@ func initTestConfig(buildDir string, env map[string]string) *config {
outDir: buildDir,
soongOutDir: filepath.Join(buildDir, "soong"),
captureBuild: true,
- env: envCopy,
- OncePer: &OncePer{},
+ modulesForTests: &modulesForTests{
+ moduleGroups: make(map[string]*moduleGroupForTests),
+ },
+ env: envCopy,
+ OncePer: &OncePer{},
// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
// passed to PathForSource or PathForModuleSrc.
@@ -82,7 +86,10 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
config.mockFileSystem(bp, fs)
- config.genericConfig = initTestConfig(buildDir, env)
+ // RunTest() from fixture copies the reference of config to generic config. However, old test
+ // cases that do not use the test fixture still require initialized generic config.
+ config.genericConfigField = initTestConfig(buildDir, env)
+ config.genericConfigField.mockFileSystem(bp, fs)
overrideGenericConfig(config)
return Config{config}
@@ -143,6 +150,7 @@ func modifyTestConfigForMuslArm64HostCross(config Config) {
func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
testConfig := TestConfig(buildDir, env, bp, fs)
modifyTestConfigToSupportArchMutator(testConfig)
+ modifyTestConfigToSupportArchMutator(testConfig.genericConfig())
return testConfig
}
diff --git a/android/test_suites.go b/android/test_suites.go
index dbcd48c79..3d705cfb5 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -15,12 +15,18 @@
package android
import (
+ "fmt"
+ "maps"
"path/filepath"
+ "slices"
+ "sort"
"strings"
"github.com/google/blueprint"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterParallelSingletonType("testsuites", testSuiteFilesFactory)
}
@@ -36,34 +42,234 @@ type TestSuiteModule interface {
TestSuites() []string
}
+// @auto-generate: gob
type TestSuiteInfo struct {
+ // A suffix to append to the name of the test.
+ // Useful because historically different variants of soong modules became differently-named
+ // make modules, like "my_test.vendor" for the vendor variant.
+ NameSuffix string
+
TestSuites []string
+
+ NeedsArchFolder bool
+
+ MainFile Path
+
+ MainFileStem string
+
+ MainFileExt string
+
+ ConfigFile Path
+
+ ConfigFileSuffix string
+
+ ExtraConfigs Paths
+
+ PerTestcaseDirectory bool
+
+ Data []DataPath
+
+ NonArchData []DataPath
+
+ CompatibilitySupportFiles []Path
+
+ // Eqivalent of LOCAL_DISABLE_TEST_CONFIG in make
+ DisableTestConfig bool
}
var TestSuiteInfoProvider = blueprint.NewProvider[TestSuiteInfo]()
-type SupportFilesInfo struct {
- SupportFiles InstallPaths
+// TestSuiteSharedLibsInfo is a provider of AndroidMk names of shared lib modules, for packaging
+// shared libs into test suites. It's not intended as a general-purpose shared lib tracking
+// mechanism. It's added to both test modules (to track their shared libs) and also shared lib
+// modules (to track their transitive shared libs).
+// @auto-generate: gob
+type TestSuiteSharedLibsInfo struct {
+ MakeNames []string
+}
+
+var TestSuiteSharedLibsInfoProvider = blueprint.NewProvider[TestSuiteSharedLibsInfo]()
+
+// MakeNameInfoProvider records the AndroidMk name for the module. This will match the names
+// referenced in TestSuiteSharedLibsInfo
+// @auto-generate: gob
+type MakeNameInfo struct {
+ Name string
}
-var SupportFilesInfoProvider = blueprint.NewProvider[SupportFilesInfo]()
+var MakeNameInfoProvider = blueprint.NewProvider[MakeNameInfo]()
+
+// @auto-generate: gob
+type filePair struct {
+ src Path
+ dst WritablePath
+}
+
+// @auto-generate: gob
+type testSuiteInstallsInfo struct {
+ Files []filePair
+ OneVariantInstalls []filePair
+}
+
+var testSuiteInstallsInfoProvider = blueprint.NewProvider[testSuiteInstallsInfo]()
+
+type testModulesInstallsMap map[ModuleOrProxy]InstallPaths
+
+func (t testModulesInstallsMap) testModules() []ModuleOrProxy {
+ return slices.Collect(maps.Keys(t))
+}
func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
- files := make(map[string]map[string]InstallPaths)
+ hostOutTestCases := pathForInstall(ctx, ctx.Config().BuildOSTarget.Os, ctx.Config().BuildOSTarget.Arch.ArchType, "testcases")
+ files := make(map[string]testModulesInstallsMap)
+ sharedLibRoots := make(map[string][]string)
+ sharedLibGraph := make(map[string][]string)
+ allTestSuiteInstalls := make(map[string][]Path)
+ var toInstall []filePair
+ var oneVariantInstalls []filePair
ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ commonInfo := OtherModuleProviderOrDefault(ctx, m, CommonModuleInfoProvider)
+ testSuiteSharedLibsInfo := OtherModuleProviderOrDefault(ctx, m, TestSuiteSharedLibsInfoProvider)
+ makeName := OtherModuleProviderOrDefault(ctx, m, MakeNameInfoProvider).Name
+ if makeName != "" && commonInfo.Target.Os.Class == Host {
+ sharedLibGraph[makeName] = append(sharedLibGraph[makeName], testSuiteSharedLibsInfo.MakeNames...)
+ }
+
if tsm, ok := OtherModuleProvider(ctx, m, TestSuiteInfoProvider); ok {
+ installFilesProvider := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
+
for _, testSuite := range tsm.TestSuites {
if files[testSuite] == nil {
- files[testSuite] = make(map[string]InstallPaths)
+ files[testSuite] = make(testModulesInstallsMap)
+ }
+ files[testSuite][m] = append(files[testSuite][m],
+ installFilesProvider.InstallFiles...)
+
+ if makeName != "" {
+ sharedLibRoots[testSuite] = append(sharedLibRoots[testSuite], makeName)
}
- name := ctx.ModuleName(m)
- files[testSuite][name] = append(files[testSuite][name],
- OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider).InstallFiles...)
}
+
+ if testSuiteInstalls, ok := OtherModuleProvider(ctx, m, testSuiteInstallsInfoProvider); ok {
+ for _, testSuite := range tsm.TestSuites {
+ for _, f := range testSuiteInstalls.Files {
+ allTestSuiteInstalls[testSuite] = append(allTestSuiteInstalls[testSuite], f.dst)
+ }
+ for _, f := range testSuiteInstalls.OneVariantInstalls {
+ allTestSuiteInstalls[testSuite] = append(allTestSuiteInstalls[testSuite], f.dst)
+ }
+ }
+ installs := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider).InstallFiles
+ oneVariantInstalls = append(oneVariantInstalls, testSuiteInstalls.OneVariantInstalls...)
+ for _, f := range testSuiteInstalls.Files {
+ alreadyInstalled := false
+ for _, install := range installs {
+ if install.String() == f.dst.String() {
+ alreadyInstalled = true
+ break
+ }
+ }
+ if !alreadyInstalled {
+ toInstall = append(toInstall, f)
+ }
+ }
+ }
+ }
+ })
+
+ for suite, suiteInstalls := range allTestSuiteInstalls {
+ allTestSuiteInstalls[suite] = SortedUniquePaths(suiteInstalls)
+ }
+
+ hostSharedLibs := gatherHostSharedLibs(ctx, sharedLibRoots, sharedLibGraph)
+
+ if !ctx.Config().KatiEnabled() {
+ for _, testSuite := range SortedKeys(files) {
+ testSuiteSymbolsZipFile := pathForTestSymbols(ctx, fmt.Sprintf("%s-symbols.zip", testSuite))
+ testSuiteMergedMappingProtoFile := pathForTestSymbols(ctx, fmt.Sprintf("%s-symbols-mapping.textproto", testSuite))
+ allTestModules := files[testSuite].testModules()
+ BuildSymbolsZip(ctx, allTestModules, testSuiteSymbolsZipFile, testSuiteMergedMappingProtoFile)
+
+ ctx.DistForGoalWithFilenameTag(testSuite, testSuiteSymbolsZipFile, testSuiteSymbolsZipFile.Base())
+ ctx.DistForGoalWithFilenameTag(testSuite, testSuiteMergedMappingProtoFile, testSuiteMergedMappingProtoFile.Base())
+ }
+ }
+
+ // https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:build/make/core/main.mk;l=674;drc=46bd04e115d34fd62b3167128854dfed95290eb0
+ testInstalledSharedLibs := make(map[string]Paths)
+ testInstalledSharedLibsDeduper := make(map[string]bool)
+ for _, install := range toInstall {
+ testInstalledSharedLibsDeduper[install.dst.String()] = true
+ }
+ for _, suite := range []string{"general-tests", "device-tests", "vts", "tvts", "art-host-tests", "host-unit-tests", "camera-hal-tests"} {
+ var myTestCases WritablePath = hostOutTestCases
+ switch suite {
+ case "vts", "tvts":
+ suiteInfo := ctx.Config().productVariables.CompatibilityTestcases[suite]
+ outDir := suiteInfo.OutDir
+ if outDir == "" {
+ continue
+ }
+ rel, err := filepath.Rel(ctx.Config().OutDir(), outDir)
+ if err != nil || strings.HasPrefix(rel, "..") {
+ panic(fmt.Sprintf("Could not make COMPATIBILITY_TESTCASES_OUT_%s (%s) relative to the out dir (%s)", suite, suiteInfo.OutDir, ctx.Config().OutDir()))
+ }
+ myTestCases = PathForArbitraryOutput(ctx, rel)
+ }
+
+ for _, f := range hostSharedLibs[suite] {
+ dir := filepath.Base(filepath.Dir(f.String()))
+ out := joinWriteablePath(ctx, myTestCases, dir, filepath.Base(f.String()))
+ if _, ok := testInstalledSharedLibsDeduper[out.String()]; !ok {
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Input: f,
+ Output: out,
+ })
+ }
+ testInstalledSharedLibsDeduper[out.String()] = true
+ testInstalledSharedLibs[suite] = append(testInstalledSharedLibs[suite], out)
+ }
+ }
+
+ filePairSorter := func(arr []filePair) func(i, j int) bool {
+ return func(i, j int) bool {
+ c := strings.Compare(arr[i].dst.String(), arr[j].dst.String())
+ if c < 0 {
+ return true
+ } else if c > 0 {
+ return false
+ }
+ return arr[i].src.String() < arr[j].src.String()
}
+ }
+
+ sort.Slice(toInstall, filePairSorter(toInstall))
+ // Dedup, as multiple tests may install the same test data to the same folder
+ toInstall = slices.Compact(toInstall)
+
+ // Dedup the oneVariant files by only the dst locations, and ignore installs from other variants
+ sort.Slice(oneVariantInstalls, filePairSorter(oneVariantInstalls))
+ oneVariantInstalls = slices.CompactFunc(oneVariantInstalls, func(a, b filePair) bool {
+ return a.dst.String() == b.dst.String()
})
+ for _, install := range toInstall {
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Input: install.src,
+ Output: install.dst,
+ })
+ }
+ for _, install := range oneVariantInstalls {
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Input: install.src,
+ Output: install.dst,
+ })
+ }
+
robolectricZip, robolectrictListZip := buildTestSuite(ctx, "robolectric-tests", files["robolectric-tests"])
ctx.Phony("robolectric-tests", robolectricZip, robolectrictListZip)
ctx.DistForGoal("robolectric-tests", robolectricZip, robolectrictListZip)
@@ -71,13 +277,118 @@ func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
ravenwoodZip, ravenwoodListZip := buildTestSuite(ctx, "ravenwood-tests", files["ravenwood-tests"])
ctx.Phony("ravenwood-tests", ravenwoodZip, ravenwoodListZip)
ctx.DistForGoal("ravenwood-tests", ravenwoodZip, ravenwoodListZip)
+
+ packageTestSuite(ctx, allTestSuiteInstalls["performance-tests"], nil, performanceTests)
+ packageTestSuite(ctx, allTestSuiteInstalls["device-platinum-tests"], nil, devicePlatinumTests)
+ packageTestSuite(ctx, allTestSuiteInstalls["device-tests"], testInstalledSharedLibs["device-tests"], deviceTests)
+}
+
+// Get a mapping from testSuite -> list of host shared libraries, given:
+// - sharedLibRoots: Mapping from testSuite -> androidMk name of all test modules in the suite
+// - sharedLibGraph: Mapping from androidMk name of module -> androidMk names of its shared libs
+//
+// This mimics how make did it historically, which is filled with inaccuracies. Make didn't
+// track variants and treated all variants as if they were merged into one big module. This means
+// you can have a test that's only included in the "vts" test suite on the device variant, and
+// only has a shared library on the host variant, and that shared library will still be included
+// into the vts test suite.
+func gatherHostSharedLibs(ctx SingletonContext, sharedLibRoots, sharedLibGraph map[string][]string) map[string]Paths {
+ hostOutTestCases := pathForInstall(ctx, ctx.Config().BuildOSTarget.Os, ctx.Config().BuildOSTarget.Arch.ArchType, "testcases")
+ hostOut := filepath.Dir(hostOutTestCases.String())
+
+ for k, v := range sharedLibGraph {
+ sharedLibGraph[k] = SortedUniqueStrings(v)
+ }
+
+ suiteToSharedLibModules := make(map[string]map[string]bool)
+ for suite, modules := range sharedLibRoots {
+ suiteToSharedLibModules[suite] = make(map[string]bool)
+ var queue []string
+ for _, root := range SortedUniqueStrings(modules) {
+ queue = append(queue, sharedLibGraph[root]...)
+ }
+ for len(queue) > 0 {
+ mod := queue[len(queue)-1]
+ queue = queue[:len(queue)-1]
+ if suiteToSharedLibModules[suite][mod] {
+ continue
+ }
+ suiteToSharedLibModules[suite][mod] = true
+ queue = append(queue, sharedLibGraph[mod]...)
+ }
+ }
+
+ hostSharedLibs := make(map[string]Paths)
+
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ if makeName, ok := OtherModuleProvider(ctx, m, MakeNameInfoProvider); ok {
+ commonInfo := OtherModuleProviderOrDefault(ctx, m, CommonModuleInfoProvider)
+ if commonInfo.SkipInstall {
+ return
+ }
+ installFilesProvider := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
+ for suite, sharedLibModulesInSuite := range suiteToSharedLibModules {
+ if sharedLibModulesInSuite[makeName.Name] {
+ for _, f := range installFilesProvider.InstallFiles {
+ if strings.HasSuffix(f.String(), ".so") && strings.HasPrefix(f.String(), hostOut) {
+ hostSharedLibs[suite] = append(hostSharedLibs[suite], f)
+ }
+ }
+ }
+ }
+ }
+ })
+ for suite, files := range hostSharedLibs {
+ hostSharedLibs[suite] = SortedUniquePaths(files)
+ }
+
+ return hostSharedLibs
}
-func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]InstallPaths) (Path, Path) {
- var installedPaths InstallPaths
- for _, module := range SortedKeys(files) {
- installedPaths = append(installedPaths, files[module]...)
+type suiteKind int
+
+const (
+ performanceTests suiteKind = iota
+ deviceTests
+ devicePlatinumTests
+)
+
+func (sk suiteKind) String() string {
+ switch sk {
+ case performanceTests:
+ return "performance-tests"
+ case deviceTests:
+ return "device-tests"
+ case devicePlatinumTests:
+ return "device-platinum-tests"
+ default:
+ panic(fmt.Sprintf("Unrecognized suite kind %d for use in packageTestSuite", sk))
+ }
+}
+
+func (sk suiteKind) buildHostSharedLibsZip() bool {
+ switch sk {
+ case devicePlatinumTests:
+ return true
+ }
+ return false
+}
+
+func (sk suiteKind) includeHostSharedLibsInMainZip() bool {
+ switch sk {
+ case deviceTests:
+ return true
}
+ return false
+}
+
+func buildTestSuite(ctx SingletonContext, suiteName string, files testModulesInstallsMap) (Path, Path) {
+ var installedPaths Paths
+ for _, module := range files.testModules() {
+ installedPaths = append(installedPaths, files[module].Paths()...)
+ }
+
+ installedPaths = SortedUniquePaths(installedPaths)
outputFile := pathForPackaging(ctx, suiteName+".zip")
rule := NewRuleBuilder(pctx, ctx)
@@ -85,7 +396,7 @@ func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]Ins
FlagWithOutput("-o ", outputFile).
FlagWithArg("-P ", "host/testcases").
FlagWithArg("-C ", pathForTestCases(ctx).String()).
- FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
+ FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths).
Flag("-sha256") // necessary to save cas_uploader's time
testList := buildTestList(ctx, suiteName+"_list", installedPaths)
@@ -102,7 +413,7 @@ func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]Ins
return outputFile, testListZipOutputFile
}
-func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path {
+func buildTestList(ctx SingletonContext, listFile string, installedPaths Paths) Path {
buf := &strings.Builder{}
for _, p := range installedPaths {
if p.Ext() != ".config" {
@@ -137,3 +448,128 @@ func pathForPackaging(ctx PathContext, pathComponents ...string) OutputPath {
func pathForTestCases(ctx PathContext) InstallPath {
return pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
}
+
+func pathForTestSymbols(ctx PathContext, pathComponents ...string) InstallPath {
+ return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", pathComponents...)
+}
+
+func packageTestSuite(ctx SingletonContext, files Paths, sharedLibs Paths, sk suiteKind) {
+ hostOutTestCases := pathForInstall(ctx, ctx.Config().BuildOSTarget.Os, ctx.Config().BuildOSTarget.Arch.ArchType, "testcases")
+ targetOutTestCases := pathForInstall(ctx, ctx.Config().AndroidFirstDeviceTarget.Os, ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType, "testcases")
+ hostOut := filepath.Dir(hostOutTestCases.String())
+ targetOut := filepath.Dir(targetOutTestCases.String())
+
+ testsZip := pathForPackaging(ctx, sk.String()+".zip")
+ testsListTxt := pathForPackaging(ctx, sk.String()+"_list.txt")
+ testsListZip := pathForPackaging(ctx, sk.String()+"_list.zip")
+ testsConfigsZip := pathForPackaging(ctx, sk.String()+"_configs.zip")
+ testsHostSharedLibsZip := pathForPackaging(ctx, sk.String()+"_host-shared-libs.zip")
+ var listLines []string
+
+ // use intermediate files to hold the file inputs, to prevent argument list from being too long
+ testsZipCmdHostFileInput := PathForIntermediates(ctx, sk.String()+"_host_list.txt")
+ testsZipCmdTargetFileInput := PathForIntermediates(ctx, sk.String()+"_target_list.txt")
+ var testsZipCmdHostFileInputContent, testsZipCmdTargetFileInputContent []string
+
+ testsZipBuilder := NewRuleBuilder(pctx, ctx)
+ testsZipCmd := testsZipBuilder.Command().
+ BuiltTool("soong_zip").
+ Flag("-sha256").
+ Flag("-d").
+ FlagWithOutput("-o ", testsZip).
+ FlagWithArg("-P ", "host").
+ FlagWithArg("-C ", hostOut)
+
+ testsConfigsZipBuilder := NewRuleBuilder(pctx, ctx)
+ testsConfigsZipCmd := testsConfigsZipBuilder.Command().
+ BuiltTool("soong_zip").
+ Flag("-d").
+ FlagWithOutput("-o ", testsConfigsZip).
+ FlagWithArg("-P ", "host").
+ FlagWithArg("-C ", hostOut)
+
+ for _, f := range files {
+ if strings.HasPrefix(f.String(), hostOutTestCases.String()) {
+ testsZipCmdHostFileInputContent = append(testsZipCmdHostFileInputContent, f.String())
+ testsZipCmd.Implicit(f)
+
+ if strings.HasSuffix(f.String(), ".config") {
+ testsConfigsZipCmd.FlagWithInput("-f ", f)
+ listLines = append(listLines, strings.Replace(f.String(), hostOut, "host", 1))
+ }
+ }
+ }
+
+ if sk.includeHostSharedLibsInMainZip() {
+ for _, f := range sharedLibs {
+ if strings.HasPrefix(f.String(), hostOutTestCases.String()) {
+ testsZipCmdHostFileInputContent = append(testsZipCmdHostFileInputContent, f.String())
+ testsZipCmd.Implicit(f)
+ }
+ }
+ }
+
+ WriteFileRule(ctx, testsZipCmdHostFileInput, strings.Join(testsZipCmdHostFileInputContent, " "))
+
+ testsZipCmd.
+ FlagWithInput("-l ", testsZipCmdHostFileInput).
+ FlagWithArg("-P ", "target").
+ FlagWithArg("-C ", targetOut)
+ testsConfigsZipCmd.
+ FlagWithArg("-P ", "target").
+ FlagWithArg("-C ", targetOut)
+
+ for _, f := range files {
+ if strings.HasPrefix(f.String(), targetOutTestCases.String()) {
+ testsZipCmdTargetFileInputContent = append(testsZipCmdTargetFileInputContent, f.String())
+ testsZipCmd.Implicit(f)
+
+ if strings.HasSuffix(f.String(), ".config") {
+ testsConfigsZipCmd.FlagWithInput("-f ", f)
+ listLines = append(listLines, strings.Replace(f.String(), targetOut, "target", 1))
+ }
+ }
+ }
+
+ WriteFileRule(ctx, testsZipCmdTargetFileInput, strings.Join(testsZipCmdTargetFileInputContent, " "))
+ testsZipCmd.FlagWithInput("-l ", testsZipCmdTargetFileInput)
+
+ testsZipBuilder.Build(sk.String(), "building "+sk.String()+" zip")
+ testsConfigsZipBuilder.Build(sk.String()+"-configs", "building "+sk.String()+" configs zip")
+
+ if sk.buildHostSharedLibsZip() {
+ testsHostSharedLibsZipBuilder := NewRuleBuilder(pctx, ctx)
+ testsHostSharedLibsZipCmd := testsHostSharedLibsZipBuilder.Command().
+ BuiltTool("soong_zip").
+ Flag("-d").
+ FlagWithOutput("-o ", testsHostSharedLibsZip).
+ FlagWithArg("-P ", "host").
+ FlagWithArg("-C ", hostOut)
+
+ for _, f := range sharedLibs {
+ if strings.HasPrefix(f.String(), hostOutTestCases.String()) && strings.HasSuffix(f.String(), ".so") {
+ testsHostSharedLibsZipCmd.FlagWithInput("-f ", f)
+ }
+ }
+
+ testsHostSharedLibsZipBuilder.Build(sk.String()+"-host-shared-libs", "building "+sk.String()+"host shared libs")
+ }
+
+ WriteFileRule(ctx, testsListTxt, strings.Join(listLines, "\n"))
+
+ testsListZipBuilder := NewRuleBuilder(pctx, ctx)
+ testsListZipBuilder.Command().
+ BuiltTool("soong_zip").
+ Flag("-d").
+ FlagWithOutput("-o ", testsListZip).
+ FlagWithArg("-e ", sk.String()+"_list").
+ FlagWithInput("-f ", testsListTxt)
+ testsListZipBuilder.Build(sk.String()+"_list_zip", "building "+sk.String()+" list zip")
+
+ ctx.Phony(sk.String(), testsZip)
+ ctx.DistForGoal(sk.String(), testsZip, testsListZip, testsConfigsZip)
+ if sk.buildHostSharedLibsZip() {
+ ctx.DistForGoal(sk.String(), testsHostSharedLibsZip)
+ }
+ ctx.Phony("tests", PathForPhony(ctx, sk.String()))
+}
diff --git a/android/test_suites_gob_enc.go b/android/test_suites_gob_enc.go
new file mode 100644
index 000000000..ebd233a9e
--- /dev/null
+++ b/android/test_suites_gob_enc.go
@@ -0,0 +1,415 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package android
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ TestSuiteInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(TestSuiteInfo) })
+ TestSuiteSharedLibsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(TestSuiteSharedLibsInfo) })
+ MakeNameInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(MakeNameInfo) })
+ filePairGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(filePair) })
+ testSuiteInstallsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(testSuiteInstallsInfo) })
+}
+
+func (r TestSuiteInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.NameSuffix); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TestSuites))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.TestSuites); val1++ {
+ if err = gobtools.EncodeString(buf, r.TestSuites[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.NeedsArchFolder); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.MainFile); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.MainFileStem); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.MainFileExt); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.ConfigFile); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.ConfigFileSuffix); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExtraConfigs))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.ExtraConfigs); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.ExtraConfigs[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.PerTestcaseDirectory); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Data))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Data); val3++ {
+ if err = r.Data[val3].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.NonArchData))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.NonArchData); val4++ {
+ if err = r.NonArchData[val4].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CompatibilitySupportFiles))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.CompatibilitySupportFiles); val5++ {
+ if err = gobtools.EncodeInterface(buf, r.CompatibilitySupportFiles[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.DisableTestConfig); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *TestSuiteInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.NameSuffix)
+ if err != nil {
+ return err
+ }
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.TestSuites = make([]string, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ err = gobtools.DecodeString(buf, &r.TestSuites[val4])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.NeedsArchFolder)
+ if err != nil {
+ return err
+ }
+
+ if val8, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val8 == nil {
+ r.MainFile = nil
+ } else {
+ r.MainFile = val8.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.MainFileStem)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.MainFileExt)
+ if err != nil {
+ return err
+ }
+
+ if val12, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val12 == nil {
+ r.ConfigFile = nil
+ } else {
+ r.ConfigFile = val12.(Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.ConfigFileSuffix)
+ if err != nil {
+ return err
+ }
+
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ r.ExtraConfigs = make([]Path, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ if val19, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val19 == nil {
+ r.ExtraConfigs[val17] = nil
+ } else {
+ r.ExtraConfigs[val17] = val19.(Path)
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.PerTestcaseDirectory)
+ if err != nil {
+ return err
+ }
+
+ var val22 int32
+ err = gobtools.DecodeSimple[int32](buf, &val22)
+ if err != nil {
+ return err
+ }
+ if val22 > 0 {
+ r.Data = make([]DataPath, val22)
+ for val23 := 0; val23 < int(val22); val23++ {
+ if err = r.Data[val23].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val26 int32
+ err = gobtools.DecodeSimple[int32](buf, &val26)
+ if err != nil {
+ return err
+ }
+ if val26 > 0 {
+ r.NonArchData = make([]DataPath, val26)
+ for val27 := 0; val27 < int(val26); val27++ {
+ if err = r.NonArchData[val27].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val30 int32
+ err = gobtools.DecodeSimple[int32](buf, &val30)
+ if err != nil {
+ return err
+ }
+ if val30 > 0 {
+ r.CompatibilitySupportFiles = make([]Path, val30)
+ for val31 := 0; val31 < int(val30); val31++ {
+ if val33, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val33 == nil {
+ r.CompatibilitySupportFiles[val31] = nil
+ } else {
+ r.CompatibilitySupportFiles[val31] = val33.(Path)
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.DisableTestConfig)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var TestSuiteInfoGobRegId int16
+
+func (r TestSuiteInfo) GetTypeId() int16 {
+ return TestSuiteInfoGobRegId
+}
+
+func (r TestSuiteSharedLibsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.MakeNames))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.MakeNames); val1++ {
+ if err = gobtools.EncodeString(buf, r.MakeNames[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *TestSuiteSharedLibsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.MakeNames = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.MakeNames[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var TestSuiteSharedLibsInfoGobRegId int16
+
+func (r TestSuiteSharedLibsInfo) GetTypeId() int16 {
+ return TestSuiteSharedLibsInfoGobRegId
+}
+
+func (r MakeNameInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.Name); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *MakeNameInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.Name)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var MakeNameInfoGobRegId int16
+
+func (r MakeNameInfo) GetTypeId() int16 {
+ return MakeNameInfoGobRegId
+}
+
+func (r filePair) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.src); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.dst); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *filePair) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.src = nil
+ } else {
+ r.src = val2.(Path)
+ }
+
+ if val4, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val4 == nil {
+ r.dst = nil
+ } else {
+ r.dst = val4.(WritablePath)
+ }
+
+ return err
+}
+
+var filePairGobRegId int16
+
+func (r filePair) GetTypeId() int16 {
+ return filePairGobRegId
+}
+
+func (r testSuiteInstallsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Files))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Files); val1++ {
+ if err = r.Files[val1].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.OneVariantInstalls))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.OneVariantInstalls); val2++ {
+ if err = r.OneVariantInstalls[val2].Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *testSuiteInstallsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.Files = make([]filePair, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ if err = r.Files[val3].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ r.OneVariantInstalls = make([]filePair, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ if err = r.OneVariantInstalls[val7].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var testSuiteInstallsInfoGobRegId int16
+
+func (r testSuiteInstallsInfo) GetTypeId() int16 {
+ return testSuiteInstallsInfoGobRegId
+}
diff --git a/android/test_suites_test.go b/android/test_suites_test.go
index 03aa42413..955adef9d 100644
--- a/android/test_suites_test.go
+++ b/android/test_suites_test.go
@@ -15,7 +15,6 @@
package android
import (
- "path/filepath"
"testing"
)
@@ -53,30 +52,16 @@ func TestBuildTestList(t *testing.T) {
`)
config := ctx.SingletonForTests(t, "testsuites")
- allOutputs := config.AllOutputs()
wantContents := map[string]string{
- "robolectric-tests.zip": "",
- "robolectric-tests_list.zip": "",
- "robolectric-tests_list": `host/testcases/Test2/Test21/Test21.config
+ "out/soong/packaging/robolectric-tests_list": `host/testcases/Test2/Test21/Test21.config
`,
- "ravenwood-tests.zip": "",
- "ravenwood-tests_list.zip": "",
- "ravenwood-tests_list": `host/testcases/Test1/Test1.config
+ "out/soong/packaging/ravenwood-tests_list": `host/testcases/Test1/Test1.config
host/testcases/Test2/Test21/Test21.config
`,
}
- for _, output := range allOutputs {
- want, ok := wantContents[filepath.Base(output)]
- if !ok {
- t.Errorf("unexpected output: %q", output)
- continue
- }
-
- got := ""
- if want != "" {
- got = ContentFromFileRuleForTests(t, ctx.TestContext, config.MaybeOutput(output))
- }
+ for file, want := range wantContents {
+ got := ContentFromFileRuleForTests(t, ctx.TestContext, config.Output(file))
if want != got {
t.Errorf("want %q, got %q", want, got)
diff --git a/android/testing.go b/android/testing.go
index d2949ec8e..400a7e8de 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -17,9 +17,12 @@ package android
import (
"bytes"
"fmt"
+ "iter"
+ "maps"
"path/filepath"
"regexp"
"runtime"
+ "slices"
"sort"
"strings"
"sync"
@@ -238,7 +241,7 @@ func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
ctx.PreArchMutators(f)
}
-func (ctx *TestContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
+func (ctx *TestContext) otherModuleProvider(m ModuleOrProxy, p blueprint.AnyProviderKey) (any, bool) {
return ctx.Context.ModuleProvider(m, p)
}
@@ -259,15 +262,72 @@ func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
}
func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext {
- return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+ return NewOtherModuleProviderAdaptor(func(module ModuleOrProxy, provider blueprint.AnyProviderKey) (any, bool) {
return ctx.otherModuleProvider(module, provider)
})
}
-func (ctx *TestContext) OtherModulePropertyErrorf(module Module, property string, fmt_ string, args ...interface{}) {
+func (ctx *TestContext) ModuleDir(module ModuleOrProxy) string {
+ return ctx.Context.ModuleDir(module)
+}
+
+func (ctx *TestContext) ModuleSubDir(module ModuleOrProxy) string {
+ return ctx.Context.ModuleSubDir(module)
+}
+
+func (ctx *TestContext) ModuleType(module ModuleOrProxy) string {
+ return ctx.Context.ModuleType(module)
+}
+
+func (ctx *TestContext) ModuleErrorf(module ModuleOrProxy, fmt string, args ...any) error {
+ return ctx.Context.ModuleErrorf(module, fmt, args...)
+}
+
+func (ctx *TestContext) OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt_ string, args ...interface{}) {
panic(fmt.Sprintf(fmt_, args...))
}
+// VisitAllModules iterates over all modules tracked through the test config.
+func (ctx *TestContext) VisitAllModules(visit func(Module)) {
+ for module := range ctx.config.modulesForTests.Iter() {
+ visit(module)
+ }
+}
+
+// VisitAllModulesProxies wraps blueprint.Context.VisitAllModulesProxies, converting blueprint.ModuleProxy to
+// android.ModuleProxy.
+func (ctx *TestContext) VisitAllModulesProxies(visit func(ModuleProxy)) {
+ ctx.Context.VisitAllModulesProxies(func(module blueprint.ModuleProxy) {
+ visit(ModuleProxy{module})
+ })
+}
+
+// VisitDirectDeps wraps blueprint.Context.VisitDirectDepsProxies, converting blueprint.ModuleProxy to android.Module
+// using the list of modules in the test config.
+func (ctx *TestContext) VisitDirectDeps(module Module, visit func(Module)) {
+ allModules := slices.Collect(ctx.config.modulesForTests.Iter())
+ ctx.VisitDirectDepsProxies(module, func(dep ModuleProxy) {
+ i := slices.IndexFunc(allModules, func(m Module) bool { return EqualModules(m, dep) })
+ if i < 0 {
+ panic(fmt.Errorf("failed to find Module for ModuleProxy %s", dep))
+ } else {
+ visit(allModules[i])
+ }
+ })
+}
+
+// VisitDirectDepsProxies wraps blueprint.Context.VisitDirectDepsProxies, converting blueprint.ModuleProxy to
+// android.ModuleProxy.
+func (ctx *TestContext) VisitDirectDepsProxies(module ModuleOrProxy, visit func(ModuleProxy)) {
+ ctx.Context.VisitDirectDepsProxies(module, func(dep blueprint.ModuleProxy) {
+ visit(ModuleProxy{dep})
+ })
+}
+
+func (ctx *TestContext) ModuleToProxy(module ModuleOrProxy) ModuleProxy {
+ return ModuleProxy{ctx.Context.ModuleToProxy(module)}
+}
+
// registeredComponentOrder defines the order in which a sortableComponent type is registered at
// runtime and provides support for reordering the components registered for a test in the same
// way.
@@ -533,7 +593,7 @@ func (ctx *TestContext) RegisterParallelSingletonType(name string, factory Singl
func (ctx *TestContext) ModuleVariantForTests(t *testing.T, name string, matchVariations map[string]string) TestingModule {
t.Helper()
modules := []Module{}
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m Module) {
if ctx.ModuleName(m) == name {
am := m.(Module)
amMut := am.base().commonProperties.DebugMutators
@@ -555,7 +615,7 @@ func (ctx *TestContext) ModuleVariantForTests(t *testing.T, name string, matchVa
// Show all the modules or module variants that do exist.
var allModuleNames []string
var allVariants []string
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m Module) {
allModuleNames = append(allModuleNames, ctx.ModuleName(m))
if ctx.ModuleName(m) == name {
allVariants = append(allVariants, m.(Module).String())
@@ -582,15 +642,15 @@ func (ctx *TestContext) ModuleVariantForTests(t *testing.T, name string, matchVa
name, matchVariations, strings.Join(moduleStrings, "\n "))
}
- return newTestingModule(t, ctx.config, modules[0])
+ return newTestingModule(t, ctx.config, modules[0], ctx.ModuleToProxy(modules[0]))
}
func (ctx *TestContext) ModuleForTests(t *testing.T, name, variant string) TestingModule {
t.Helper()
var module Module
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m Module) {
if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
- module = m.(Module)
+ module = m
}
})
@@ -598,7 +658,7 @@ func (ctx *TestContext) ModuleForTests(t *testing.T, name, variant string) Testi
// find all the modules that do exist
var allModuleNames []string
var allVariants []string
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m Module) {
allModuleNames = append(allModuleNames, ctx.ModuleName(m))
if ctx.ModuleName(m) == name {
allVariants = append(allVariants, ctx.ModuleSubDir(m))
@@ -615,12 +675,12 @@ func (ctx *TestContext) ModuleForTests(t *testing.T, name, variant string) Testi
}
}
- return newTestingModule(t, ctx.config, module)
+ return newTestingModule(t, ctx.config, module, ctx.ModuleToProxy(module))
}
func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
var variants []string
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m Module) {
if ctx.ModuleName(m) == name {
variants = append(variants, ctx.ModuleSubDir(m))
}
@@ -1053,12 +1113,14 @@ func (b baseTestingComponent) AllOutputs() []string {
type TestingModule struct {
baseTestingComponent
module Module
+ proxy ModuleProxy
}
-func newTestingModule(t *testing.T, config Config, module Module) TestingModule {
+func newTestingModule(t *testing.T, config Config, module Module, proxy ModuleProxy) TestingModule {
return TestingModule{
newBaseTestingComponent(t, config, module),
module,
+ proxy,
}
}
@@ -1067,6 +1129,11 @@ func (m TestingModule) Module() Module {
return m.module
}
+// ModuleProxy returns the ModuleProxy wrapped by the TestingModule.
+func (m TestingModule) ModuleProxy() ModuleProxy {
+ return m.proxy
+}
+
// VariablesForTestsRelativeToTop returns a copy of the Module.VariablesForTests() with every value
// having any temporary build dir usages replaced with paths relative to a notional top.
func (m TestingModule) VariablesForTestsRelativeToTop() map[string]string {
@@ -1167,6 +1234,12 @@ func SetKatiEnabledForTests(config Config) {
config.katiEnabled = true
}
+func SetBuildDateFileEnvVarForTests() FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ config.env["BUILD_DATETIME_FILE"] = filepath.Join(config.outDir, "build_date.txt")
+ })
+}
+
func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod Module) []AndroidMkEntries {
t.Helper()
var p AndroidMkEntriesProvider
@@ -1378,7 +1451,7 @@ type panickingConfigAndErrorContext struct {
ctx *TestContext
}
-func (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) {
+func (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module ModuleOrProxy, property, fmt string, args ...interface{}) {
panic(ctx.ctx.PropertyErrorf(module, property, fmt, args...).Error())
}
@@ -1390,7 +1463,7 @@ func (ctx *panickingConfigAndErrorContext) HasMutatorFinished(mutatorName string
return ctx.ctx.HasMutatorFinished(mutatorName)
}
-func (ctx *panickingConfigAndErrorContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
+func (ctx *panickingConfigAndErrorContext) otherModuleProvider(m ModuleOrProxy, p blueprint.AnyProviderKey) (any, bool) {
return ctx.ctx.otherModuleProvider(m, p)
}
@@ -1399,3 +1472,112 @@ func PanickingConfigAndErrorContext(ctx *TestContext) ConfigurableEvaluatorConte
ctx: ctx,
}
}
+
+// modulesForTests stores the list of modules that exist for use during tests.
+type modulesForTests struct {
+ moduleGroups map[string]*moduleGroupForTests
+ lock sync.Mutex
+}
+
+// moduleGroupForTests stores the list of variants that exist for a single module name.
+type moduleGroupForTests struct {
+ modules []Module
+ // nextInsertIndex is the position in modules where the last module is inserted.
+ // It is used when inserting new variants to place them after the variant they
+ // were created from.
+ nextInsertIndex int
+}
+
+// Insert inserts a module into modulesForTests. If the Module matches and existing
+// Module in the list (either by being the same pointer or by being a clone with
+// identical name, namespace and variations) then it replaces the entry currently
+// in the list. Otherwise, it is inserted after the most recently updated entry in
+// the list.
+func (m *modulesForTests) Insert(name string, module Module) {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+ if existing, ok := m.moduleGroups[name]; ok {
+ // A name that is already present
+ if i := slices.IndexFunc(existing.modules, func(old Module) bool {
+ return old == module ||
+ (old.base().commonProperties.DebugName == module.base().commonProperties.DebugName &&
+ old.base().commonProperties.DebugNamespace == module.base().commonProperties.DebugNamespace &&
+ slices.Equal(old.base().commonProperties.DebugVariations, module.base().commonProperties.DebugVariations) &&
+ slices.Equal(old.base().commonProperties.DebugMutators, module.base().commonProperties.DebugMutators))
+ }); i >= 0 {
+ // The module matches an existing module, either by being the same Module or by being a clone.
+ // Replace the current entry, and set the insertion point to after the current entry.
+ // This path is reached when TransitionMutator is creating new variants, and relies on the
+ // Blueprint optimization that the existing variant is reused as the first new variant so that
+ // the list doesn't collect old obsolete variants.
+ existing.modules[i] = module
+ existing.nextInsertIndex = i + 1
+ } else {
+ // The module doesn't match an existing module, insert it at the insertion point and update the
+ // insertion point to point after it.
+ existing.modules = slices.Concat(existing.modules[:existing.nextInsertIndex],
+ []Module{module},
+ existing.modules[existing.nextInsertIndex:])
+ existing.nextInsertIndex += 1
+ }
+ } else {
+ // The name is not present, add a new entry for it.
+ m.moduleGroups[name] = &moduleGroupForTests{
+ modules: []Module{module},
+ nextInsertIndex: 0,
+ }
+ }
+}
+
+// Rename updates the name of a module group.
+func (m *modulesForTests) Rename(from, to string) {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+ m.moduleGroups[to] = m.moduleGroups[from]
+ delete(m.moduleGroups, from)
+}
+
+// Iter returns a Seq of all the modules in a deterministic order (alphabetically by module name,
+// and then in variant order).
+func (m *modulesForTests) Iter() iter.Seq[Module] {
+ return func(yield func(Module) bool) {
+ groups := slices.Collect(maps.Keys(m.moduleGroups))
+ slices.Sort(groups)
+ for _, group := range groups {
+ for _, module := range m.moduleGroups[group].modules {
+ if !yield(module) {
+ return
+ }
+ }
+ }
+ }
+}
+
+type visitDirectDepsInterface interface {
+ VisitDirectDepsProxies(ModuleOrProxy, func(dep ModuleProxy))
+}
+
+// HasDirectDep returns true if wantDep is a direct dependency of m.
+func HasDirectDep(ctx visitDirectDepsInterface, m Module, wantDep ModuleOrProxy) bool {
+ var found bool
+ ctx.VisitDirectDepsProxies(m, func(dep ModuleProxy) {
+ if EqualModules(dep, wantDep) {
+ found = true
+ }
+ })
+ return found
+}
+
+// AssertHasDirectDep asserts that wantDep is a direct dependency of m.
+func AssertHasDirectDep(t *testing.T, ctx visitDirectDepsInterface, m Module, wantDep ModuleOrProxy) {
+ t.Helper()
+ found := false
+ ctx.VisitDirectDepsProxies(m, func(dep ModuleProxy) {
+ if EqualModules(dep, wantDep) {
+ found = true
+ }
+ })
+ if !found {
+ t.Errorf("Could not find a dependency from %v to %v\n", m, wantDep)
+ }
+}
diff --git a/android/transition.go b/android/transition.go
index 0677ca1dd..af33517b5 100644
--- a/android/transition.go
+++ b/android/transition.go
@@ -190,8 +190,10 @@ func (a *androidTransitionMutatorAdapter) Split(ctx blueprint.BaseModuleContext)
panic("TransitionMutator not allowed in FinalDepsMutators")
}
m := ctx.Module().(Module)
- moduleContext := m.base().baseModuleContextFactory(ctx)
- return a.mutator.Split(&moduleContext)
+ moduleContext := baseModuleContextPool.Get()
+ defer baseModuleContextPool.Put(moduleContext)
+ *moduleContext = m.base().baseModuleContextFactory(ctx)
+ return a.mutator.Split(moduleContext)
}
func (a *androidTransitionMutatorAdapter) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext,
@@ -228,6 +230,9 @@ func (a *androidTransitionMutatorAdapter) Mutate(ctx blueprint.BottomUpMutatorCo
base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
}
+ if config := ctx.Config().(Config); config.captureBuild {
+ config.modulesForTests.Insert(ctx.ModuleName(), am)
+ }
mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
defer bottomUpMutatorContextPool.Put(mctx)
@@ -408,3 +413,11 @@ func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
return c.bp.Provider(provider)
}
+
+// UsesUnbundledVariantDepTag is an interface that dependency tags can implement to indicate they
+// want the variant of the module that would be used for unbundled builds. This is used by
+// unbundled_builder. Historically, make did not know/care about individual variants, so when
+// you listed apps in TARGET_BUILD_APPS, make would build whatever variant was available.
+type UsesUnbundledVariantDepTag interface {
+ UsesUnbundledVariant()
+}
diff --git a/android/util.go b/android/util.go
index 4520f400e..197bbcacb 100644
--- a/android/util.go
+++ b/android/util.go
@@ -209,8 +209,8 @@ func PrettyConcat(list []string, quote bool, lastSep string) string {
// that are in l1 but not l2, and l2 but not l1.
func ListSetDifference[T comparable](l1, l2 []T) (bool, []T, []T) {
listsDiffer := false
- l1 = firstUnique(l1)
- l2 = firstUnique(l2)
+ l1 = FirstUnique(l1)
+ l2 = FirstUnique(l2)
diff1 := []T{}
diff2 := []T{}
m1 := setFromList(l1)
@@ -379,21 +379,21 @@ outer:
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
// each. It does not modify the input slice.
func FirstUniqueStrings(list []string) []string {
- return firstUnique(list)
+ return FirstUnique(list)
}
-// firstUnique returns all unique elements of a slice, keeping the first copy of each. It
+// FirstUnique returns all unique elements of a slice, keeping the first copy of each. It
// does not modify the input slice.
-func firstUnique[T comparable](slice []T) []T {
+func FirstUnique[T comparable](slice []T) []T {
// Do not modify the input in-place, operate on a copy instead.
slice = CopyOf(slice)
- return firstUniqueInPlace(slice)
+ return FirstUniqueInPlace(slice)
}
-// firstUniqueInPlace returns all unique elements of a slice, keeping the first copy of
+// FirstUniqueInPlace returns all unique elements of a slice, keeping the first copy of
// each. It modifies the slice contents in place, and returns a subslice of the original
// slice.
-func firstUniqueInPlace[T comparable](slice []T) []T {
+func FirstUniqueInPlace[T comparable](slice []T) []T {
// 128 was chosen based on BenchmarkFirstUniqueStrings results.
if len(slice) > 128 {
return firstUniqueMap(slice)
@@ -401,7 +401,7 @@ func firstUniqueInPlace[T comparable](slice []T) []T {
return firstUniqueList(slice)
}
-// firstUniqueList is an implementation of firstUnique using an O(N^2) list comparison to look for
+// firstUniqueList is an implementation of FirstUnique using an O(N^2) list comparison to look for
// duplicates.
func firstUniqueList[T any](in []T) []T {
writeIndex := 0
@@ -422,7 +422,7 @@ outer:
return in[0:writeIndex]
}
-// firstUniqueMap is an implementation of firstUnique using an O(N) hash set lookup to look for
+// firstUniqueMap is an implementation of FirstUnique using an O(N) hash set lookup to look for
// duplicates.
func firstUniqueMap[T comparable](in []T) []T {
writeIndex := 0
diff --git a/android/variable.go b/android/variable.go
index e9ba1b34e..9b0605592 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -295,7 +295,6 @@ type ProductVariables struct {
Safestack *bool `json:",omitempty"`
HostStaticBinaries *bool `json:",omitempty"`
Binder32bit *bool `json:",omitempty"`
- UseGoma *bool `json:",omitempty"`
UseABFS *bool `json:",omitempty"`
UseRBE *bool `json:",omitempty"`
UseRBEJAVAC *bool `json:",omitempty"`
@@ -397,8 +396,8 @@ type ProductVariables struct {
BoardSepolicyVers *string `json:",omitempty"`
PlatformSepolicyVersion *string `json:",omitempty"`
- SystemExtSepolicyPrebuiltApiDir *string `json:",omitempty"`
- ProductSepolicyPrebuiltApiDir *string `json:",omitempty"`
+ SystemExtSepolicyPrebuiltApiDirs []string `json:",omitempty"`
+ ProductSepolicyPrebuiltApiDirs []string `json:",omitempty"`
PlatformSepolicyCompatVersions []string `json:",omitempty"`
@@ -455,7 +454,6 @@ type ProductVariables struct {
BuildBrokenClangAsFlags bool `json:",omitempty"`
BuildBrokenClangCFlags bool `json:",omitempty"`
BuildBrokenClangProperty bool `json:",omitempty"`
- GenruleSandboxing *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
@@ -464,8 +462,6 @@ type ProductVariables struct {
BuildBrokenDontCheckSystemSdk bool `json:",omitempty"`
BuildBrokenDupSysprop bool `json:",omitempty"`
- BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
-
BuildDebugfsRestrictionsEnabled bool `json:",omitempty"`
RequiresInsecureExecmemForSwiftshader bool `json:",omitempty"`
@@ -546,11 +542,27 @@ type ProductVariables struct {
SystemManifestFile []string `json:",omitempty"`
SystemExtManifestFiles []string `json:",omitempty"`
DeviceManifestFiles []string `json:",omitempty"`
+ DeviceManifestSkus []string `json:",omitempty"`
OdmManifestFiles []string `json:",omitempty"`
+ OdmManifestSkus []string `json:",omitempty"`
UseSoongNoticeXML *bool `json:",omitempty"`
StripByDefault *bool `json:",omitempty"`
+
+ CompatibilityTestcases map[string]CompatibilityTestcaseJSON
+
+ // Will be used to install host tools in soong only builds
+ ProductHostPackages []string `json:",omitempty"`
+
+ EnforceSELinuxTrebleLabeling *bool `json:",omitempty"`
+
+ SELinuxTrebleLabelingTrackingListFile *string `json:",omitempty"`
+}
+
+type CompatibilityTestcaseJSON struct {
+ OutDir string `json:",omitempty"`
+ IncludeModuleFolder bool `json:",omitempty"`
}
type PartitionQualifiedVariablesType struct {
@@ -638,6 +650,7 @@ type PartitionVariables struct {
BoardVendorBootimagePartitionSize string `json:",omitempty"`
BoardInitBootimagePartitionSize string `json:",omitempty"`
BoardBootHeaderVersion string `json:",omitempty"`
+ BoardInitBootHeaderVersion string `json:",omitempty"`
TargetKernelPath string `json:",omitempty"`
BoardUsesGenericKernelImage bool `json:",omitempty"`
BootSecurityPatch string `json:",omitempty"`
@@ -676,31 +689,41 @@ type PartitionVariables struct {
BuildingVbmetaImage bool `json:",omitempty"`
ChainedVbmetaPartitions map[string]ChainedAvbPartitionProps `json:",omitempty"`
- ProductPackages []string `json:",omitempty"`
- ProductPackagesDebug []string `json:",omitempty"`
- VendorLinkerConfigSrcs []string `json:",omitempty"`
- ProductLinkerConfigSrcs []string `json:",omitempty"`
+ ProductPackages []string `json:",omitempty"`
+ ProductPackagesDebug []string `json:",omitempty"`
+ ProductPackagesEng []string `json:",omitempty"`
+ ProductPackagesDebugAsan []string `json:",omitempty"`
+ ProductPackagesDebugJavaCoverage []string `json:",omitempty"`
+ ProductPackagesArm64 []string `json:",omitempty"`
+ ProductPackagesShippingApiLevel29 []string `json:",omitempty"`
+ ProductPackagesShippingApiLevel33 []string `json:",omitempty"`
+ ProductPackagesShippingApiLevel34 []string `json:",omitempty"`
+ VendorLinkerConfigSrcs []string `json:",omitempty"`
+ ProductLinkerConfigSrcs []string `json:",omitempty"`
BoardInfoFiles []string `json:",omitempty"`
BootLoaderBoardName string `json:",omitempty"`
ProductCopyFiles []string `json:",omitempty"`
- BuildingSystemDlkmImage bool `json:",omitempty"`
- SystemKernelModules []string `json:",omitempty"`
- SystemKernelBlocklistFile string `json:",omitempty"`
- SystemKernelLoadModules []string `json:",omitempty"`
- BuildingVendorDlkmImage bool `json:",omitempty"`
- VendorKernelModules []string `json:",omitempty"`
- VendorKernelBlocklistFile string `json:",omitempty"`
- BuildingOdmDlkmImage bool `json:",omitempty"`
- OdmKernelModules []string `json:",omitempty"`
- OdmKernelBlocklistFile string `json:",omitempty"`
+ BuildingSystemDlkmImage bool `json:",omitempty"`
+ SystemKernelModules []string `json:",omitempty"`
+ SystemKernelBlocklistFile string `json:",omitempty"`
+ SystemKernelLoadModules []string `json:",omitempty"`
+ BuildingVendorDlkmImage bool `json:",omitempty"`
+ VendorKernelModules []string `json:",omitempty"`
+ VendorKernelBlocklistFile string `json:",omitempty"`
+ VendorKernelModules2ndStage16kbMode []string `json:",omitempty"`
+ BuildingOdmDlkmImage bool `json:",omitempty"`
+ OdmKernelModules []string `json:",omitempty"`
+ OdmKernelBlocklistFile string `json:",omitempty"`
VendorRamdiskKernelModules []string `json:",omitempty"`
VendorRamdiskKernelBlocklistFile string `json:",omitempty"`
VendorRamdiskKernelLoadModules []string `json:",omitempty"`
VendorRamdiskKernelOptionsFile string `json:",omitempty"`
+ DoNotStripVendorRamdiskModules bool `json:",omitempty"`
+ DoNotStripVendorModules bool `json:",omitempty"`
ProductFsverityGenerateMetadata bool `json:",omitempty"`
@@ -721,6 +744,8 @@ type PartitionVariables struct {
BootloaderInUpdatePackage bool `json:",omitempty"`
BoardFastbootInfoFile string `json:",omitempty"`
+
+ TargetRecoveryWipe string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/android/vendor_api_levels.go b/android/vendor_api_levels.go
index d32bc56a5..3a45b2ee2 100644
--- a/android/vendor_api_levels.go
+++ b/android/vendor_api_levels.go
@@ -41,11 +41,11 @@ func GetSdkVersionForVendorApiLevel(vendorApiLevel string) (ApiLevel, error) {
return NoneApiLevel, fmt.Errorf("The vendor API level %q must be able to be parsed as an integer", vendorApiLevel)
}
if vendorApiLevelInt < 35 {
- return uncheckedFinalApiLevel(vendorApiLevelInt), nil
+ return UncheckedFinalApiLevel(vendorApiLevelInt), nil
}
if sdkInt, ok := getSdkVersionOfVendorApiLevel(vendorApiLevelInt); ok {
- return uncheckedFinalApiLevel(sdkInt), nil
+ return UncheckedFinalApiLevel(sdkInt), nil
}
return NoneApiLevel, fmt.Errorf("Unknown vendor API level %q. Requires updating the map in vendor_api_level.go?", vendorApiLevel)
}
diff --git a/android/visibility.go b/android/visibility.go
index 915368710..218cdb5da 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -94,28 +94,23 @@ type visibilityRule interface {
}
// Describes the properties provided by a module that contain visibility rules.
-type visibilityPropertyImpl struct {
+type visibilityProperty struct {
name string
stringsProperty *[]string
}
-type visibilityProperty interface {
- getName() string
- getStrings() []string
-}
-
-func newVisibilityProperty(name string, stringsProperty *[]string) visibilityProperty {
- return visibilityPropertyImpl{
+func newVisibilityProperty(name string, stringsProperty *[]string) *visibilityProperty {
+ return &visibilityProperty{
name: name,
stringsProperty: stringsProperty,
}
}
-func (p visibilityPropertyImpl) getName() string {
+func (p visibilityProperty) getName() string {
return p.name
}
-func (p visibilityPropertyImpl) getStrings() []string {
+func (p visibilityProperty) getStrings() []string {
return *p.stringsProperty
}
@@ -533,7 +528,7 @@ func visibilityRuleEnforcer(ctx BottomUpMutatorContext) {
qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.Module())
// Visit all the dependencies making sure that this module has access to them all.
- ctx.VisitDirectDeps(func(dep Module) {
+ ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
// Ignore dependencies that have an ExcludeFromVisibilityEnforcementTag
tag := ctx.OtherModuleDependencyTag(dep)
if _, ok := tag.(ExcludeFromVisibilityEnforcementTag); ok {
@@ -680,7 +675,7 @@ func AddVisibilityProperty(module Module, name string, stringsProperty *[]string
addVisibilityProperty(module, name, stringsProperty)
}
-func addVisibilityProperty(module Module, name string, stringsProperty *[]string) visibilityProperty {
+func addVisibilityProperty(module Module, name string, stringsProperty *[]string) *visibilityProperty {
base := module.base()
property := newVisibilityProperty(name, stringsProperty)
base.visibilityPropertyInfo = append(base.visibilityPropertyInfo, property)
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index a2486fdf5..ed4465716 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -189,9 +189,7 @@ func (s *sdkRepoHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Flag("-o -name '*.txt' -o -name '*.windows' -o -name '*.xml' -print0").
// Using -n 500 for xargs to limit the max number of arguments per call to line_endings
// to 500. This avoids line_endings failing with "arguments too long".
- Text("| xargs -0 -n 500 ").
- BuiltTool("line_endings").
- Flag("unix")
+ Text("| xargs -0 -n 500 dos2unix")
// Exclude some file types (roughly matching sdk.exclude.atree)
builder.Command().
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 0a5644ae3..386bacb16 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -21,9 +21,7 @@ import (
"strings"
"android/soong/android"
- "android/soong/cc"
"android/soong/java"
- "android/soong/rust"
)
func (a *apexBundle) AndroidMk() android.AndroidMkData {
@@ -118,8 +116,8 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
}
fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
- if fi.module != nil && fi.module.Owner() != "" {
- fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", fi.module.Owner())
+ if fi.providers != nil && fi.providers.commonInfo.Owner != "" {
+ fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", fi.providers.commonInfo.Owner)
}
// /apex/<apexBundleName>/{lib|framework|...}
pathForSymbol := filepath.Join("$(PRODUCT_OUT)", "apex", apexBundleName, fi.installDir)
@@ -143,15 +141,15 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
fmt.Fprintln(w, "LOCAL_CHECKED_MODULE :=", fi.builtFile.String())
}
fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.nameInMake())
- if fi.module != nil {
+ if fi.providers != nil {
// This apexFile's module comes from Soong
- if fi.module.Target().Arch.ArchType != android.Common {
- archStr := fi.module.Target().Arch.ArchType.String()
+ if fi.providers.commonInfo.Target.Arch.ArchType != android.Common {
+ archStr := fi.providers.commonInfo.Target.Arch.ArchType.String()
fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
}
}
- if fi.jacocoReportClassesFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
+ if fi.jacocoInfo.ReportClassesFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoInfo.ReportClassesFile.String())
}
switch fi.class {
case javaSharedLib:
@@ -159,9 +157,10 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
// we will have foo.jar.jar
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.stem(), ".jar"))
- if javaModule, ok := fi.module.(java.ApexDependency); ok {
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ if fi.providers != nil && fi.providers.javaInfo != nil && fi.providers.javaInfo.ApexDependencyInfo != nil {
+ apexInfo := fi.providers.javaInfo.ApexDependencyInfo
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", apexInfo.ImplementationAndResourcesJars[0].String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", apexInfo.HeaderJars[0].String())
} else {
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", fi.builtFile.String())
@@ -175,34 +174,35 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
// we will have foo.apk.apk
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.stem(), ".apk"))
- if app, ok := fi.module.(*java.AndroidApp); ok {
- android.AndroidMkEmitAssignList(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.JniCoverageOutputs().Strings())
- if jniLibSymbols := app.JNISymbolsInstalls(modulePath); len(jniLibSymbols) > 0 {
+ if fi.providers != nil && fi.providers.appInfo != nil {
+ appInfo := fi.providers.appInfo
+ android.AndroidMkEmitAssignList(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE", appInfo.JniCoverageOutputs.Strings())
+ if jniLibSymbols := java.JNISymbolsInstalls(appInfo.JniLibs, modulePath); len(jniLibSymbols) > 0 {
fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_SYMBOLS :=", jniLibSymbols.String())
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
case appSet:
- as, ok := fi.module.(*java.AndroidAppSet)
- if !ok {
+ if fi.providers == nil || fi.providers.appInfo == nil {
panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
}
- fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.PackedAdditionalOutputs().String())
- fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String())
+ appInfo := fi.providers.appInfo
+ fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", appInfo.PackedAdditionalOutputs.String())
+ fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", appInfo.ApkCertsFile.String())
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
case nativeSharedLib, nativeExecutable, nativeTest:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
- if ccMod, ok := fi.module.(*cc.Module); ok {
- if ccMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
- }
- ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- if ccMod.CoverageOutputFile().Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
- }
- } else if rustMod, ok := fi.module.(*rust.Module); ok {
- if rustMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
+ if fi.providers != nil && fi.providers.linkableInfo != nil {
+ linkableInfo := fi.providers.linkableInfo
+ if fi.providers.ccInfo != nil {
+ if linkableInfo.UnstrippedOutputFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", linkableInfo.UnstrippedOutputFile.String())
+ }
+ if linkableInfo.CoverageOutputFile.Valid() {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", linkableInfo.CoverageOutputFile.String())
+ }
+ } else if fi.providers.rustInfo != nil && linkableInfo.UnstrippedOutputFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", linkableInfo.UnstrippedOutputFile.String())
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
@@ -284,7 +284,6 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
- android.AndroidMkEmitAssignList(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS", a.lintReports.Strings())
if a.installedFilesFile != nil {
goal := "checkbuild"
@@ -301,17 +300,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).SYMBOLIC_OUTPUT_PATH))\n", strings.Join(moduleNames, " "))
fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).ELF_SYMBOL_MAPPING_PATH))\n", strings.Join(moduleNames, " "))
- distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
- distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String())
- distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
+ fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).JACOCO_REPORT_SOONG_ZIP_ARGUMENTS := $(foreach m,%s,$(ALL_MODULES.$(m).JACOCO_REPORT_SOONG_ZIP_ARGUMENTS))\n", strings.Join(moduleNames, " "))
+ fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).JACOCO_REPORT_FILES := $(foreach m,%s,$(ALL_MODULES.$(m).JACOCO_REPORT_FILES))\n", strings.Join(moduleNames, " "))
}}
}
-
-func distCoverageFiles(w io.Writer, dir string, distfile string) {
- if distfile != "" {
- goal := "apps_only"
- fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
- " $(call dist-for-goals,%s,%s:%s/$(notdir %s))\n"+
- "endif\n", goal, distfile, dir, distfile)
- }
-}
diff --git a/apex/apex.go b/apex/apex.go
index a726098c6..7e6f03c16 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -367,7 +367,7 @@ type overridableProperties struct {
Prebuilts proptools.Configurable[[]string]
// List of BPF programs inside this APEX bundle.
- Bpfs []string
+ Bpfs proptools.Configurable[[]string]
// Names of modules to be overridden. Listed modules can only be other binaries (in Make or
// Soong). This does not completely prevent installation of the overridden binaries, but if
@@ -541,18 +541,13 @@ type apexBundle struct {
isCompressed bool
- // Path of API coverage generate file
- nativeApisUsedByModuleFile android.ModuleOutPath
- nativeApisBackedByModuleFile android.ModuleOutPath
- javaApisUsedByModuleFile android.ModuleOutPath
-
aconfigFiles []android.Path
// Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk
required []string
- // appinfo of the apk-in-apex of this module
- appInfos java.AppInfos
+ // apkCerts of the apk-in-apex of this module
+ apkCerts java.ApkCertsInfo
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -596,10 +591,10 @@ type apexFile struct {
// systemServerDexJars stores the list of dexjars for a system server jar.
systemServerDexJars android.Paths
- jacocoReportClassesFile android.Path // only for javalibs and apps
- lintInfo *java.LintInfo // only for javalibs and apps
- certificate java.Certificate // only for apps
- overriddenPackageName string // only for apps
+ jacocoInfo java.JacocoInfo // only for javalibs and apps
+ lintInfo *java.LintInfo // only for javalibs and apps
+ certificate java.Certificate // only for apps
+ overriddenPackageName string // only for apps
transitiveDep bool
isJniLib bool
@@ -607,12 +602,23 @@ type apexFile struct {
multilib string
// TODO(jiyong): remove this
- module android.Module
+ module android.ModuleProxy
+ providers *providerInfoForApexFile
+}
+
+type providerInfoForApexFile struct {
+ commonInfo *android.CommonModuleInfo
+ javaInfo *java.JavaInfo
+ appInfo *java.AppInfo
+ ccInfo *cc.CcInfo
+ rustInfo *rust.RustInfo
+ linkableInfo *cc.LinkableInfo
+ vintfFragmentInfo *android.VintfFragmentInfo
}
// TODO(jiyong): shorten the arglist using an option struct
func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string,
- installDir string, class apexFileClass, module android.Module) apexFile {
+ installDir string, class apexFileClass, module android.ModuleProxy) apexFile {
ret := apexFile{
builtFile: builtFile,
installDir: installDir,
@@ -620,13 +626,36 @@ func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidM
class: class,
module: module,
}
- if module != nil {
- if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok {
- ret.checkbuildTarget = installFilesInfo.CheckbuildTarget
+ if !module.IsNil() {
+ if buildTargetsInfo, ok := android.OtherModuleProvider(ctx, module, android.ModuleBuildTargetsProvider); ok {
+ ret.checkbuildTarget = buildTargetsInfo.CheckbuildTarget
}
ret.moduleDir = ctx.OtherModuleDir(module)
- ret.partition = module.PartitionTag(ctx.DeviceConfig())
- ret.multilib = module.Target().Arch.ArchType.Multilib
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ ret.partition = commonInfo.PartitionTag
+ ret.multilib = commonInfo.Target.Arch.ArchType.Multilib
+ ret.providers = &providerInfoForApexFile{}
+ if commonInfo, ok := android.OtherModuleProvider(ctx, module, android.CommonModuleInfoProvider); ok {
+ ret.providers.commonInfo = commonInfo
+ }
+ if javaInfo, ok := android.OtherModuleProvider(ctx, module, java.JavaInfoProvider); ok {
+ ret.providers.javaInfo = javaInfo
+ }
+ if appInfo, ok := android.OtherModuleProvider(ctx, module, java.AppInfoProvider); ok {
+ ret.providers.appInfo = appInfo
+ }
+ if ccInfo, ok := android.OtherModuleProvider(ctx, module, cc.CcInfoProvider); ok {
+ ret.providers.ccInfo = ccInfo
+ }
+ if linkableInfo, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ ret.providers.linkableInfo = linkableInfo
+ }
+ if rustInfo, ok := android.OtherModuleProvider(ctx, module, rust.RustInfoProvider); ok {
+ ret.providers.rustInfo = rustInfo
+ }
+ if vintfInfo, ok := android.OtherModuleProvider(ctx, module, android.VintfFragmentInfoProvider); ok {
+ ret.providers.vintfFragmentInfo = &vintfInfo
+ }
}
return ret
}
@@ -667,11 +696,11 @@ func (af *apexFile) symlinkPaths() []string {
// availableToPlatform tests whether this apexFile is from a module that can be installed to the
// platform.
func (af *apexFile) availableToPlatform() bool {
- if af.module == nil {
+ if af.providers == nil || af.providers.commonInfo == nil {
return false
}
- if am, ok := af.module.(android.ApexModule); ok {
- return am.AvailableFor(android.AvailableToPlatform)
+ if af.providers.commonInfo.IsApexModule {
+ return android.CheckAvailableForApex(android.AvailableToPlatform, af.providers.commonInfo.ApexAvailableFor)
}
return false
}
@@ -712,7 +741,7 @@ type dependencyTag struct {
installable bool
}
-func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
+func (d *dependencyTag) SdkMemberType(_ android.ModuleContext, _ android.ModuleProxy) android.SdkMemberType {
return d.memberType
}
@@ -947,7 +976,7 @@ func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps.GetOrDefault(ctx, nil)...)
- ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
+ ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs.GetOrDefault(ctx, nil)...)
if prebuilts := a.overridableProperties.Prebuilts.GetOrDefault(ctx, nil); len(prebuilts) > 0 {
// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
// regardless of the TARGET_PREFER_* setting. See b/144532908
@@ -1141,12 +1170,13 @@ func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
// If any of the dep is not available to platform, this module is also considered as being
// not available to platform even if it has "//apex_available:platform"
- mctx.VisitDirectDeps(func(child android.Module) {
+ mctx.VisitDirectDepsProxy(func(child android.ModuleProxy) {
if !android.IsDepInSameApex(mctx, am, child) {
// if the dependency crosses apex boundary, don't consider it
return
}
- if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
+ info := android.OtherModuleProviderOrDefault(mctx, child, android.PlatformAvailabilityInfoProvider)
+ if info.NotAvailableToPlatform {
availableToPlatform = false
// TODO(b/154889534) trigger an error when 'am' has
// "//apex_available:platform"
@@ -1164,8 +1194,11 @@ func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
}
if !availableToPlatform {
- am.SetNotAvailableForPlatform()
+ android.SetProvider(mctx, android.PlatformAvailabilityInfoProvider, android.PlatformAvailabilityInfo{
+ NotAvailableToPlatform: true,
+ })
}
+
}
type apexTransitionMutator struct{}
@@ -1372,7 +1405,7 @@ func setDirInApexForNativeBridge(commonInfo *android.CommonModuleInfo, dir *stri
// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The
// returned apexFile saves information about the Soong module that will be used for creating the
// build rules.
-func apexFileForNativeLibrary(ctx android.BaseModuleContext, module android.Module,
+func apexFileForNativeLibrary(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo, ccMod *cc.LinkableInfo, handleSpecialLibs bool) apexFile {
// Decide the APEX-local directory by the multilib of the library In the future, we may
// query this to the module.
@@ -1407,7 +1440,7 @@ func apexFileForNativeLibrary(ctx android.BaseModuleContext, module android.Modu
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, module)
}
-func apexFileForExecutable(ctx android.BaseModuleContext, module android.Module,
+func apexFileForExecutable(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo, ccInfo *cc.CcInfo) apexFile {
linkableInfo := android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoProvider)
dirInApex := "bin"
@@ -1421,7 +1454,7 @@ func apexFileForExecutable(ctx android.BaseModuleContext, module android.Module,
return af
}
-func apexFileForRustExecutable(ctx android.BaseModuleContext, module android.Module,
+func apexFileForRustExecutable(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo) apexFile {
linkableInfo := android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoProvider)
dirInApex := "bin"
@@ -1433,7 +1466,7 @@ func apexFileForRustExecutable(ctx android.BaseModuleContext, module android.Mod
return af
}
-func apexFileForShBinary(ctx android.BaseModuleContext, module android.Module,
+func apexFileForShBinary(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo, sh *sh.ShBinaryInfo) apexFile {
dirInApex := filepath.Join("bin", sh.SubDir)
setDirInApexForNativeBridge(commonInfo, &dirInApex)
@@ -1443,21 +1476,21 @@ func apexFileForShBinary(ctx android.BaseModuleContext, module android.Module,
return af
}
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, module android.Module,
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, module android.ModuleProxy,
prebuilt *prebuilt_etc.PrebuiltEtcInfo, outputFile android.Path) apexFile {
dirInApex := filepath.Join(prebuilt.BaseDir, prebuilt.SubDir)
makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, module)
}
-func apexFileForCompatConfig(ctx android.BaseModuleContext, module android.Module,
+func apexFileForCompatConfig(ctx android.BaseModuleContext, module android.ModuleProxy,
config *java.PlatformCompatConfigInfo, depName string) apexFile {
dirInApex := filepath.Join("etc", config.SubDir)
fileToCopy := config.CompatConfig
return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, module)
}
-func apexFileForVintfFragment(ctx android.BaseModuleContext, module android.Module,
+func apexFileForVintfFragment(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo, vf *android.VintfFragmentInfo) apexFile {
dirInApex := filepath.Join("etc", "vintf")
@@ -1470,7 +1503,6 @@ type javaModule interface {
android.Module
BaseModuleName() string
DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath
- JacocoReportClassesFile() android.Path
Stem() string
}
@@ -1481,17 +1513,17 @@ var _ javaModule = (*java.DexImport)(nil)
var _ javaModule = (*java.SdkLibraryImport)(nil)
// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
-func apexFileForJavaModule(ctx android.ModuleContext, module android.Module, javaInfo *java.JavaInfo) apexFile {
+func apexFileForJavaModule(ctx android.ModuleContext, module android.ModuleProxy, javaInfo *java.JavaInfo) apexFile {
return apexFileForJavaModuleWithFile(ctx, module, javaInfo, javaInfo.DexJarBuildPath.PathOrNil())
}
// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
-func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module android.Module,
+func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module android.ModuleProxy,
javaInfo *java.JavaInfo, dexImplementationJar android.Path) apexFile {
dirInApex := "javalib"
commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
af := newApexFile(ctx, dexImplementationJar, commonInfo.BaseModuleName, dirInApex, javaSharedLib, module)
- af.jacocoReportClassesFile = javaInfo.JacocoReportClassesFile
+ af.jacocoInfo = javaInfo.JacocoInfo
if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
af.lintInfo = lintInfo
}
@@ -1510,7 +1542,7 @@ func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, commonInfo *and
javaInfo *java.JavaInfo) *apexFile {
if profilePathOnHost := javaInfo.DexpreopterInfo.OutputProfilePathOnHost; profilePathOnHost != nil {
dirInApex := "javalib"
- af := newApexFile(ctx, profilePathOnHost, commonInfo.BaseModuleName+"-profile", dirInApex, etc, nil)
+ af := newApexFile(ctx, profilePathOnHost, commonInfo.BaseModuleName+"-profile", dirInApex, etc, android.ModuleProxy{})
af.customStem = javaInfo.Stem + ".jar.prof"
return &af
}
@@ -1532,7 +1564,7 @@ func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string {
return buildId
}
-func apexFilesForAndroidApp(ctx android.BaseModuleContext, module android.Module,
+func apexFilesForAndroidApp(ctx android.BaseModuleContext, module android.ModuleProxy,
commonInfo *android.CommonModuleInfo, aapp *java.AppInfo) []apexFile {
appDir := "app"
if aapp.Privileged {
@@ -1546,7 +1578,7 @@ func apexFilesForAndroidApp(ctx android.BaseModuleContext, module android.Module
fileToCopy := aapp.OutputFile
af := newApexFile(ctx, fileToCopy, commonInfo.BaseModuleName, dirInApex, app, module)
- af.jacocoReportClassesFile = aapp.JacocoReportClassesFile
+ af.jacocoInfo = aapp.JacocoInfo
if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
af.lintInfo = lintInfo
}
@@ -1569,7 +1601,7 @@ func apexFilesForAndroidApp(ctx android.BaseModuleContext, module android.Module
return apexFiles
}
-func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, module android.Module, rro java.RuntimeResourceOverlayInfo) apexFile {
+func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, module android.ModuleProxy, rro java.RuntimeResourceOverlayInfo) apexFile {
rroDir := "overlay"
dirInApex := filepath.Join(rroDir, rro.Theme)
fileToCopy := rro.OutputFile
@@ -1579,12 +1611,12 @@ func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, module and
return af
}
-func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram android.Module) apexFile {
+func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram android.ModuleProxy) apexFile {
dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
-func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, module android.Module) apexFile {
+func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, module android.ModuleProxy) apexFile {
dirInApex := filepath.Join("etc", "fs")
return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, module)
}
@@ -1640,6 +1672,15 @@ func (f fsType) string() string {
}
func (a *apexBundle) setCompression(ctx android.ModuleContext) {
+ if a.isCompressable() {
+ if !a.Updatable() {
+ ctx.PropertyErrorf("compressible", "do not compress non-updatable APEX")
+ }
+ if a.PartitionTag(ctx.DeviceConfig()) != "system" {
+ ctx.PropertyErrorf("compressible", "do not compress non-system APEX")
+ }
+ }
+
if a.testOnlyShouldForceCompression() {
a.isCompressed = true
} else {
@@ -1686,13 +1727,7 @@ func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) {
}
func (a *apexBundle) isCompressable() bool {
- if a.testApex {
- return false
- }
- if a.payloadFsType == erofs {
- return false
- }
- return proptools.Bool(a.overridableProperties.Compressible)
+ return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex
}
func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool {
@@ -1741,7 +1776,7 @@ func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
// TODO(b/295593640)
// Needs additional verification for the resulting APEX to ensure that skipped artifacts don't make problems.
// For example, DT_NEEDED modules should be found within the APEX unless they are marked in `requiredNativeLibs`.
- if f.transitiveDep && f.module != nil && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) {
+ if f.transitiveDep && !f.module.IsNil() && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) {
vctx.unwantedTransitiveFilesInfo = append(vctx.unwantedTransitiveFilesInfo, f)
continue
}
@@ -1803,7 +1838,7 @@ func (a *apexBundle) enforcePartitionTagOnApexSystemServerJar(ctx android.Module
})
}
-func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.Module) bool {
+func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.ModuleProxy) bool {
depTag := ctx.OtherModuleDependencyTag(child)
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
return false
@@ -1894,7 +1929,6 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
}
case androidAppTag:
if appInfo, ok := android.OtherModuleProvider(ctx, child, java.AppInfoProvider); ok {
- a.appInfos = append(a.appInfos, *appInfo)
if appInfo.AppSet {
appDir := "app"
if appInfo.Privileged {
@@ -1910,10 +1944,19 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
vctx.filesInfo = append(vctx.filesInfo, af)
} else {
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, commonInfo, appInfo)...)
- if !appInfo.Prebuilt && !appInfo.TestHelperApp {
- return true // track transitive dependencies
+ }
+
+ // androidMkForFiles is only called if a.installable(), so historically make would
+ // only see certs from apks inside installable apexes
+ if a.installable() {
+ if apkCertInfo, ok := android.OtherModuleProvider(ctx, child, java.ApkCertInfoProvider); ok {
+ a.apkCerts = append(a.apkCerts, apkCertInfo)
}
}
+
+ if !appInfo.AppSet && !appInfo.Prebuilt && !appInfo.TestHelperApp {
+ return true // track transitive dependencies
+ }
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
@@ -2148,7 +2191,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
checkDuplicate: a.shouldCheckDuplicate(ctx),
unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
}
- ctx.WalkDeps(func(child, parent android.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { return a.depVisitor(&vctx, ctx, child, parent) })
vctx.normalizeFileInfo(ctx)
if a.privateKeyFile == nil {
if ctx.Config().AllowMissingDependencies() {
@@ -2214,6 +2257,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.buildApex(ctx)
a.buildApexDependencyInfo(ctx)
a.buildLintReports(ctx)
+ a.reexportJacocoInfo(ctx)
// Set a provider for dexpreopt of bootjars
a.provideApexExportsInfo(ctx)
@@ -2236,17 +2280,24 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath})
- android.SetProvider(ctx, java.AppInfosProvider, a.appInfos)
+ android.SetProvider(ctx, java.ApkCertsInfoProvider, a.apkCerts)
+ a.setSymbolInfosProvider(ctx)
+
+ pem, key := a.getCertificateAndPrivateKey(ctx)
+ android.SetProvider(ctx, android.ApexBundleTypeInfoProvider, android.ApexBundleTypeInfo{
+ Pem: pem,
+ Key: key,
+ })
}
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
// with information about whether source or prebuilt of an apex was used during the build.
func (a *apexBundle) providePrebuiltInfo(ctx android.ModuleContext) {
- info := android.PrebuiltInfo{
+ info := android.PrebuiltJsonInfo{
Name: a.Name(),
Is_prebuilt: false,
}
- android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+ android.SetProvider(ctx, android.PrebuiltJsonInfoProvider, info)
}
// Set a provider containing information about the jars and .prof provided by the apex
@@ -2297,7 +2348,7 @@ func (a *apexBundle) enforceAppUpdatability(mctx android.ModuleContext) {
// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
// the bootclasspath_fragment contributes to the apex.
-func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module android.Module) []apexFile {
+func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module android.ModuleProxy) []apexFile {
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, module, java.BootclasspathFragmentApexContentInfoProvider)
var filesToAdd []apexFile
@@ -2337,7 +2388,7 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module android.Mo
}
androidMkModuleName := filepath.Base(pathInApex)
- af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil)
+ af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, android.ModuleProxy{})
filesToAdd = append(filesToAdd, af)
}
@@ -2346,19 +2397,19 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module android.Mo
// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
// the module contributes to the apex; or nil if the proto config was not generated.
-func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module android.Module) *apexFile {
+func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module android.ModuleProxy) *apexFile {
info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
if !info.ClasspathFragmentProtoGenerated {
return nil
}
classpathProtoOutput := info.ClasspathFragmentProtoOutput
- af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
+ af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, android.ModuleProxy{})
return &af
}
// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
// content module, i.e. a library that is part of the bootclasspath.
-func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule, javaModule android.Module) apexFile {
+func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule, javaModule android.ModuleProxy) apexFile {
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragmentModule, java.BootclasspathFragmentApexContentInfoProvider)
// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
@@ -2857,7 +2908,7 @@ func (a *apexBundle) verifyNativeImplementationLibs(ctx android.ModuleContext) {
if !inApex && !inApkInApex {
ctx.ModuleErrorf("library in apex transitively linked against implementation library %q not in apex", lib)
- var depPath []android.Module
+ var depPath []android.ModuleProxy
ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
if depPath != nil {
return false
@@ -2873,7 +2924,7 @@ func (a *apexBundle) verifyNativeImplementationLibs(ctx android.ModuleContext) {
if checkTransitiveTag(tag) {
if android.OutputFileForModule(ctx, child, "") == lib {
- depPath = ctx.GetWalkPath()
+ depPath = ctx.GetProxyWalkPath()
}
return true
}
@@ -2903,3 +2954,52 @@ func (a *apexBundle) enforceNoVintfInUpdatable(ctx android.ModuleContext) {
}
}
}
+
+func (a *apexBundle) setSymbolInfosProvider(ctx android.ModuleContext) {
+ if !a.properties.HideFromMake && a.installable() {
+ infos := &cc.SymbolInfos{}
+ for _, fi := range a.filesInfo {
+ linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
+ if linkToSystemLib {
+ // No need to copy the file since it's linked to the system file
+ continue
+ }
+ moduleDir := android.PathForModuleInPartitionInstall(ctx, "apex", a.BaseModuleName(), fi.installDir)
+ info := &cc.SymbolInfo{
+ Name: a.fullModuleName(a.BaseModuleName(), linkToSystemLib, &fi),
+ ModuleDir: moduleDir.String(),
+ Uninstallable: !a.installable(),
+ }
+ switch fi.class {
+ case nativeSharedLib, nativeExecutable, nativeTest:
+ info.Stem = fi.stem()
+ if fi.providers != nil && fi.providers.linkableInfo != nil {
+ linkableInfo := fi.providers.linkableInfo
+ if linkableInfo.UnstrippedOutputFile != nil {
+ info.UnstrippedBinaryPath = linkableInfo.UnstrippedOutputFile
+ }
+ }
+ if info.UnstrippedBinaryPath != nil {
+ infos.AppendSymbols(info)
+ }
+ case app:
+ if fi.providers != nil && fi.providers.appInfo != nil {
+ appInfo := fi.providers.appInfo
+ // The following logic comes from java.GetJniSymbolInfos
+ for _, install := range java.JNISymbolsInstalls(appInfo.JniLibs, moduleDir.String()) {
+ info := &cc.SymbolInfo{
+ Name: fi.providers.commonInfo.BaseModuleName,
+ ModuleDir: filepath.Dir(install.To),
+ Uninstallable: fi.providers.commonInfo.SkipInstall || !fi.providers.javaInfo.Installable || fi.providers.commonInfo.NoFullInstall,
+ UnstrippedBinaryPath: install.From,
+ InstalledStem: filepath.Base(install.To),
+ }
+ infos.AppendSymbols(info)
+ }
+ }
+ }
+ }
+
+ cc.CopySymbolsAndSetSymbolsInfoProvider(ctx, infos)
+ }
+}
diff --git a/apex/apex_sdk_member.go b/apex/apex_sdk_member.go
index 284158f07..2a7a5c5b4 100644
--- a/apex/apex_sdk_member.go
+++ b/apex/apex_sdk_member.go
@@ -44,8 +44,8 @@ func (mt *apexSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, d
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (mt *apexSdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*apexBundle)
+func (mt *apexSdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ _, ok := android.OtherModuleProvider(ctx, module, android.ApexBundleTypeInfoProvider)
return ok
}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 797f47b09..e3363f4b6 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -158,10 +158,10 @@ type apexPrebuiltInfo struct {
}
func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) {
- prebuiltInfos := []android.PrebuiltInfo{}
+ prebuiltInfos := []android.PrebuiltJsonInfo{}
ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
- prebuiltInfo, exists := android.OtherModuleProvider(ctx, m, android.PrebuiltInfoProvider)
+ prebuiltInfo, exists := android.OtherModuleProvider(ctx, m, android.PrebuiltJsonInfoProvider)
// Use prebuiltInfoProvider to filter out non apex soong modules.
// Use HideFromMake to filter out the unselected variants of a specific apex.
if exists && !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).HideFromMake {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 327e018f4..b35d8c995 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -26,8 +26,8 @@ import (
"testing"
"android/soong/aconfig/codegen"
+ "android/soong/provenance"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -5197,8 +5197,9 @@ func TestPrebuilt(t *testing.T) {
if prebuilt.inputApex.String() != expectedInput {
t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
}
+ provenanceInfo, _ := android.OtherModuleProvider(ctx, prebuilt, provenance.ProvenanceMetadataInfoProvider)
android.AssertStringDoesContain(t, "Invalid provenance metadata file",
- prebuilt.ProvenanceMetaDataFile().String(), "soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto")
+ provenanceInfo.ProvenanceMetaDataFile.String(), "soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto")
rule := testingModule.Rule("genProvenanceMetaData")
android.AssertStringEquals(t, "Invalid input", "myapex-arm64.apex", rule.Inputs[0].String())
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
@@ -7195,14 +7196,14 @@ func TestApexAvailable_CheckForPlatform(t *testing.T) {
// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
// because it depends on libbar which isn't available to platform
libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
- if libfoo.NotAvailableForPlatform() != true {
+ if android.OtherModuleProviderOrDefault(ctx, libfoo, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform != true {
t.Errorf("%q shouldn't be available to platform", libfoo.String())
}
// libfoo2 however can be available to platform because it depends on libbaz which provides
// stubs
libfoo2 := ctx.ModuleForTests(t, "libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
- if libfoo2.NotAvailableForPlatform() == true {
+ if android.OtherModuleProviderOrDefault(ctx, libfoo2, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform == true {
t.Errorf("%q should be available to platform", libfoo2.String())
}
}
@@ -7234,11 +7235,11 @@ func TestApexAvailable_CreatedForApex(t *testing.T) {
}`)
libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
- if libfooShared.NotAvailableForPlatform() != true {
+ if android.OtherModuleProviderOrDefault(ctx, libfooShared, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform != true {
t.Errorf("%q shouldn't be available to platform", libfooShared.String())
}
libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
- if libfooStatic.NotAvailableForPlatform() != false {
+ if android.OtherModuleProviderOrDefault(ctx, libfooStatic, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform != false {
t.Errorf("%q should be available to platform", libfooStatic.String())
}
}
@@ -9260,7 +9261,8 @@ func TestCompressedApex(t *testing.T) {
name: "myapex",
key: "myapex.key",
compressible: true,
- updatable: false,
+ updatable: true,
+ min_sdk_version: "29",
}
apex_key {
name: "myapex.key",
@@ -9291,31 +9293,38 @@ func TestCompressedApex(t *testing.T) {
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.capex\n")
}
-func TestCompressedApexIsDisabledWhenUsingErofs(t *testing.T) {
+func TestCompressedApex_NonUpdatable(t *testing.T) {
t.Parallel()
- ctx := testApex(t, `
+
+ testApexError(t, `do not compress non-updatable`, `
apex {
name: "myapex",
key: "myapex.key",
compressible: true,
updatable: false,
- payload_fs_type: "erofs",
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.CompressedApex = proptools.BoolPtr(true)
- }),
- )
+ `)
- compressRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").MaybeRule("compressRule")
- if compressRule.Rule != nil {
- t.Error("erofs apex should not be compressed")
- }
+ testApexError(t, `do not compress non-system`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ compressible: true,
+ updatable: true,
+ min_sdk_version: "29",
+ vendor: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
}
func TestApexSet_ShouldRespectCompressedApexFlag(t *testing.T) {
@@ -9879,7 +9888,8 @@ func TestApexOutputFileProducer(t *testing.T) {
name: "myapex",
key: "myapex.key",
compressible: true,
- updatable: false,
+ updatable: true,
+ min_sdk_version: "29",
}
apex_key {
@@ -10635,8 +10645,8 @@ func TestAconfigFilesJavaDeps(t *testing.T) {
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info.*/image.apex/etc/flag.info")
inputs := []string{
- "my_aconfig_declarations_foo/intermediate.pb",
- "my_aconfig_declarations_bar/intermediate.pb",
+ "my_aconfig_declarations_foo/aconfig-cache.pb",
+ "my_aconfig_declarations_bar/aconfig-cache.pb",
}
VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
@@ -10774,9 +10784,9 @@ func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
- "my_aconfig_declarations_foo/intermediate.pb",
- "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb",
- "my_aconfig_declarations_baz/intermediate.pb",
+ "my_aconfig_declarations_foo/aconfig-cache.pb",
+ "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/merged_aconfig_files/myapex/aconfig_merged.pb",
+ "my_aconfig_declarations_baz/aconfig-cache.pb",
}
VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
@@ -10936,10 +10946,10 @@ func TestAconfigFilesRustDeps(t *testing.T) {
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
- "my_aconfig_declarations_foo/intermediate.pb",
- "my_aconfig_declarations_bar/intermediate.pb",
- "my_aconfig_declarations_baz/intermediate.pb",
- "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb",
+ "my_aconfig_declarations_foo/aconfig-cache.pb",
+ "my_aconfig_declarations_bar/aconfig-cache.pb",
+ "my_aconfig_declarations_baz/aconfig-cache.pb",
+ "my_rust_binary/android_arm64_armv8-a_apex10000/merged_aconfig_files/myapex/aconfig_merged.pb",
}
VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
@@ -11045,13 +11055,13 @@ func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
if len(aconfigArgs) != 1 {
t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
}
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/aconfig-cache.pb")
buildParams := combineAconfigRule.BuildParams
if len(buildParams.Inputs) != 1 {
t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
}
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/aconfig-cache.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
@@ -11125,13 +11135,13 @@ func TestAconfigFilesRemoveDuplicates(t *testing.T) {
if len(aconfigArgs) != 1 {
t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
}
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/aconfig-cache.pb")
buildParams := combineAconfigRule.BuildParams
if len(buildParams.Inputs) != 1 {
t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
}
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/aconfig-cache.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
@@ -11684,27 +11694,27 @@ func TestAconfifDeclarationsValidation(t *testing.T) {
// to aconfig.
android.AssertStringDoesContain(t, "cache file of a java_aconfig_library static_lib "+
"passed as an input",
- aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "bar"))
+ aconfigFlagArgs, fmt.Sprintf("%s/%s/aconfig-cache.pb", outDir, "bar"))
// "baz-java-lib", which statically depends on "baz-lib", is a lib of "foo" and is passed
// to metalava as classpath. Thus the cache file provided by the associated
// aconfig_declarations module "baz" should be passed to aconfig.
android.AssertStringDoesContain(t, "cache file of a lib that statically depends on "+
"java_aconfig_library passed as an input",
- aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "baz"))
+ aconfigFlagArgs, fmt.Sprintf("%s/%s/aconfig-cache.pb", outDir, "baz"))
// "qux-lib" is passed to metalava as src via the filegroup, thus the cache file provided by
// the associated aconfig_declarations module "qux" should be passed to aconfig.
android.AssertStringDoesContain(t, "cache file of srcs java_aconfig_library passed as an "+
"input",
- aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "qux"))
+ aconfigFlagArgs, fmt.Sprintf("%s/%s/aconfig-cache.pb", outDir, "qux"))
// "quux-java-lib" is a lib of "foo" and is passed to metalava as classpath, but does not
// statically depend on "quux-lib". Therefore, the cache file provided by the associated
// aconfig_declarations module "quux" should not be passed to aconfig.
android.AssertStringDoesNotContain(t, "cache file of a lib that does not statically "+
"depend on java_aconfig_library not passed as an input",
- aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "quux"))
+ aconfigFlagArgs, fmt.Sprintf("%s/%s/aconfig-cache.pb", outDir, "quux"))
}
func TestMultiplePrebuiltsWithSameBase(t *testing.T) {
@@ -11757,19 +11767,6 @@ func TestApexMinSdkVersionOverride(t *testing.T) {
}
}
- checkHasDep := func(t *testing.T, ctx *android.TestContext, m android.Module, wantDep android.Module) {
- t.Helper()
- found := false
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- if !found {
- t.Errorf("Could not find a dependency from %v to %v\n", m, wantDep)
- }
- }
-
ctx := testApex(t, `
apex {
name: "com.android.apex30",
@@ -11816,13 +11813,13 @@ func TestApexMinSdkVersionOverride(t *testing.T) {
overridingModuleSameMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex30_com.mycompany.android.apex30")
javalibApex30Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex30")
checkMinSdkVersion(t, overridingModuleSameMinSdkVersion, "30")
- checkHasDep(t, ctx, overridingModuleSameMinSdkVersion.Module(), javalibApex30Variant.Module())
+ android.AssertHasDirectDep(t, ctx, overridingModuleSameMinSdkVersion.Module(), javalibApex30Variant.Module())
// Override module, uses different min_sdk_version
overridingModuleDifferentMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex31_com.mycompany.android.apex31")
javalibApex31Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex31")
checkMinSdkVersion(t, overridingModuleDifferentMinSdkVersion, "31")
- checkHasDep(t, ctx, overridingModuleDifferentMinSdkVersion.Module(), javalibApex31Variant.Module())
+ android.AssertHasDirectDep(t, ctx, overridingModuleDifferentMinSdkVersion.Module(), javalibApex31Variant.Module())
}
func TestOverrideApexWithPrebuiltApexPreferred(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 23c2ed8aa..4d1624dcb 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -78,7 +78,7 @@ func init() {
pctx.HostBinToolVariable("apex_ls", "apex-ls")
pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
pctx.HostBinToolVariable("deapexer", "deapexer")
- pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
+ pctx.HostBinToolVariable("debugfs", "debugfs")
pctx.HostBinToolVariable("fsck_erofs", "fsck.erofs")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
@@ -226,9 +226,9 @@ var (
}, "image_dir")
apexHostVerifierRule = pctx.StaticRule("apexHostVerifierRule", blueprint.RuleParams{
- Command: `${host_apex_verifier} --deapexer=${deapexer} --debugfs=${debugfs_static} ` +
+ Command: `${host_apex_verifier} --deapexer=${deapexer} --debugfs=${debugfs} ` +
`--fsckerofs=${fsck_erofs} --apex=${in} --partition_tag=${partition_tag} && touch ${out}`,
- CommandDeps: []string{"${host_apex_verifier}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}"},
+ CommandDeps: []string{"${host_apex_verifier}", "${deapexer}", "${debugfs}", "${fsck_erofs}"},
Description: "run host_apex_verifier",
}, "partition_tag")
@@ -240,7 +240,7 @@ var (
apexElfCheckerUnwantedRule = pctx.StaticRule("apexElfCheckerUnwantedRule", blueprint.RuleParams{
Command: `${apex_elf_checker} --tool_path ${tool_path} --unwanted ${unwanted} ${in} && touch ${out}`,
- CommandDeps: []string{"${apex_elf_checker}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}", "${config.ClangBin}/llvm-readelf"},
+ CommandDeps: []string{"${apex_elf_checker}", "${deapexer}", "${debugfs}", "${fsck_erofs}", "${config.ClangBin}/llvm-readelf"},
Description: "run apex_elf_checker --unwanted",
}, "tool_path", "unwanted")
)
@@ -248,7 +248,7 @@ var (
func (a *apexBundle) buildAconfigFiles(ctx android.ModuleContext) []apexFile {
var aconfigFiles android.Paths
for _, file := range a.filesInfo {
- if file.module == nil {
+ if file.module.IsNil() {
continue
}
if dep, ok := android.OtherModuleProvider(ctx, file.module, android.AconfigPropagatingProviderKey); ok {
@@ -276,14 +276,9 @@ func (a *apexBundle) buildAconfigFiles(ctx android.ModuleContext) []apexFile {
"cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "),
},
})
- files = append(files, newApexFile(ctx, apexAconfigFile, "aconfig_flags", "etc", etc, nil))
-
- // To enable fingerprint, we need to have v2 storage files. The default version is 1.
- storageFilesVersion := 1
- if ctx.Config().ReleaseFingerprintAconfigPackages() {
- storageFilesVersion = 2
- }
+ files = append(files, newApexFile(ctx, apexAconfigFile, "aconfig_flags", "etc", etc, android.ModuleProxy{}))
+ storageFilesVersion := ctx.Config().ReleaseAconfigStorageVersion()
for _, info := range createStorageInfo {
outputFile := android.PathForModuleOut(ctx, info.Output_file)
ctx.Build(pctx, android.BuildParams{
@@ -295,10 +290,10 @@ func (a *apexBundle) buildAconfigFiles(ctx android.ModuleContext) []apexFile {
"container": ctx.ModuleName(),
"file_type": info.File_type,
"cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "),
- "version": strconv.Itoa(storageFilesVersion),
+ "version": storageFilesVersion,
},
})
- files = append(files, newApexFile(ctx, outputFile, info.File_type, "etc", etc, nil))
+ files = append(files, newApexFile(ctx, outputFile, info.File_type, "etc", etc, android.ModuleProxy{}))
}
}
return files
@@ -408,8 +403,8 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Path {
if m, t := android.SrcIsModuleWithTag(*a.properties.File_contexts); m != "" {
isFileContextsModule = true
otherModule := android.GetModuleProxyFromPathDep(ctx, m, t)
- if otherModule != nil {
- fileContextsDir = ctx.OtherModuleDir(*otherModule)
+ if !otherModule.IsNil() {
+ fileContextsDir = ctx.OtherModuleDir(otherModule)
}
}
fileContexts = android.PathForModuleSrc(ctx, *a.properties.File_contexts)
@@ -526,7 +521,7 @@ func markManifestTestOnly(ctx android.ModuleContext, androidManifestFile android
func shouldApplyAssembleVintf(fi apexFile) bool {
isVintfFragment, _ := path.Match("etc/vintf/*", fi.path())
- _, fromVintfFragmentModule := fi.module.(*android.VintfFragmentModule)
+ fromVintfFragmentModule := fi.providers != nil && fi.providers.vintfFragmentInfo != nil
return isVintfFragment && !fromVintfFragmentModule
}
@@ -566,7 +561,7 @@ func (a *apexBundle) installApexSystemServerFiles(ctx android.ModuleContext) {
}
psi := android.PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDeps(func(am android.Module) {
+ ctx.VisitDirectDepsProxy(func(am android.ModuleProxy) {
if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists {
psi = info
}
@@ -580,6 +575,9 @@ func (a *apexBundle) installApexSystemServerFiles(ctx android.ModuleContext) {
for _, install := range fi.systemServerDexpreoptInstalls {
var installedFile android.InstallPath
if performInstalls {
+ // android_device will create the install rule in soong-only builds.
+ // Skip creating the installation rule from the base variant
+ // in soong-only builds to prevent duplicate installation rules.
installedFile = ctx.InstallFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
} else {
// Another module created the install rules, but this module should still depend on
@@ -588,7 +586,7 @@ func (a *apexBundle) installApexSystemServerFiles(ctx android.ModuleContext) {
}
a.extraInstalledFiles = append(a.extraInstalledFiles, installedFile)
a.extraInstalledPairs = append(a.extraInstalledPairs, installPair{install.OutputPathOnHost, installedFile})
- ctx.PackageFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
+ ctx.PackageFileWithFakeFullInstall(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
}
if performInstalls {
for _, dexJar := range fi.systemServerDexJars {
@@ -653,10 +651,10 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
// are zipped. So we need to unzip them.
copyCommands = append(copyCommands,
fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
- fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs().String()))
+ fi.providers.appInfo.PackedAdditionalOutputs.String()))
if installSymbolFiles {
installedPath = ctx.InstallFileWithExtraFilesZip(apexDir.Join(ctx, fi.installDir),
- fi.stem(), fi.builtFile, fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs())
+ fi.stem(), fi.builtFile, fi.providers.appInfo.PackedAdditionalOutputs)
}
} else {
if installSymbolFiles {
@@ -903,7 +901,6 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
"readelf": "${config.ClangBin}/llvm-readelf",
},
})
- a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
var nativeLibNames []string
for _, f := range a.filesInfo {
@@ -918,7 +915,6 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
Output(apisBackedbyOutputFile).
Flags(nativeLibNames)
rb.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
- a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
var javaLibOrApkPath []android.Path
for _, f := range a.filesInfo {
@@ -934,7 +930,12 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
Output(javaApiUsedbyOutputFile).
Inputs(javaLibOrApkPath)
javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
- a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
+
+ if slices.Contains(ctx.Config().UnbundledBuildApps(), a.Name()) && !android.ShouldSkipAndroidMkProcessing(ctx, a) {
+ ctx.DistForGoalWithFilename("apps_only", apisUsedbyOutputFile, "ndk_apis_usedby_apex/"+apisUsedbyOutputFile.Base())
+ ctx.DistForGoalWithFilename("apps_only", apisBackedbyOutputFile, "ndk_apis_backedby_apex/"+apisBackedbyOutputFile.Base())
+ ctx.DistForGoalWithFilename("apps_only", javaApiUsedbyOutputFile, "java_apis_used_by_apex/"+javaApiUsedbyOutputFile.Base())
+ }
bundleConfig := a.buildBundleConfig(ctx)
@@ -1111,7 +1112,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
// Skip dependencies that are only available to APEXes; they are developed with updatability
// in mind and don't need manual approval.
- if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform {
+ if android.OtherModuleProviderOrDefault(ctx, to, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform {
return !externalDep
}
@@ -1179,6 +1180,18 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations)
}
+func (a *apexBundle) reexportJacocoInfo(ctx android.ModuleContext) {
+ var jacocoInfos []java.JacocoInfo
+ for _, fi := range a.filesInfo {
+ if fi.jacocoInfo.ReportClassesFile != nil {
+ jacocoInfos = append(jacocoInfos, fi.jacocoInfo)
+ }
+ }
+
+ android.SetProvider(ctx, java.ApexJacocoInfoProvider, jacocoInfos)
+ android.SetProvider(ctx, java.BundleProvider, java.BundleInfo{Bundle: a.bundleModuleFile})
+}
+
func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.Path {
var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
var executablePaths []string // this also includes dirs
@@ -1200,7 +1213,7 @@ func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.Path
readOnlyPaths = append(readOnlyPaths, pathInApex)
// Additional APKs
appSetDirs = append(appSetDirs, f.installDir)
- appSetFiles[f.installDir] = f.module.(*java.AndroidAppSet).PackedAdditionalOutputs()
+ appSetFiles[f.installDir] = f.providers.appInfo.PackedAdditionalOutputs
} else {
readOnlyPaths = append(readOnlyPaths, pathInApex)
}
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index c2f2fc5b9..41fe16d56 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -29,7 +29,7 @@ import (
type testClasspathElementContext struct {
android.OtherModuleProviderContext
testContext *android.TestContext
- module android.Module
+ module android.ModuleProxy
errs []error
}
@@ -198,18 +198,18 @@ func TestCreateClasspathElements(t *testing.T) {
result := preparer.RunTest(t)
- artFragment := result.Module("art-bootclasspath-fragment", "android_common_com.android.art")
- artBaz := result.Module("baz", "android_common_apex10000")
- artQuuz := result.Module("quuz", "android_common_apex10000")
+ artFragment := result.ModuleProxy("art-bootclasspath-fragment", "android_common_com.android.art")
+ artBaz := result.ModuleProxy("baz", "android_common_apex10000")
+ artQuuz := result.ModuleProxy("quuz", "android_common_apex10000")
- myFragment := result.Module("mybootclasspath-fragment", "android_common_myapex")
- myBar := result.Module("bar", "android_common_apex10000")
+ myFragment := result.ModuleProxy("mybootclasspath-fragment", "android_common_myapex")
+ myBar := result.ModuleProxy("bar", "android_common_apex10000")
- otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
+ otherApexLibrary := result.ModuleProxy("otherapexlibrary", "android_common_apex10000")
- platformFoo := result.Module("quuz", "android_common")
+ platformFoo := result.ModuleProxy("quuz", "android_common")
- bootclasspath := result.Module("myplatform-bootclasspath", "android_common")
+ bootclasspath := result.ModuleProxy("myplatform-bootclasspath", "android_common")
// Use a custom assertion method instead of AssertDeepEquals as the latter formats the output
// using %#v which results in meaningless output as ClasspathElements are pointers.
@@ -219,10 +219,10 @@ func TestCreateClasspathElements(t *testing.T) {
}
}
- expectFragmentElement := func(module android.Module, contents ...android.Module) java.ClasspathElement {
+ expectFragmentElement := func(module android.ModuleProxy, contents ...android.ModuleProxy) java.ClasspathElement {
return &java.ClasspathFragmentElement{module, contents}
}
- expectLibraryElement := func(module android.Module) java.ClasspathElement {
+ expectLibraryElement := func(module android.ModuleProxy) java.ClasspathElement {
return &java.ClasspathLibraryElement{module}
}
@@ -239,10 +239,10 @@ func TestCreateClasspathElements(t *testing.T) {
t.Parallel()
ctx := newCtx()
elements := java.CreateClasspathElements(ctx,
- []android.Module{artBaz, artQuuz, myBar, platformFoo},
- []android.Module{artFragment, myFragment},
- map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
- map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
+ []android.ModuleProxy{artBaz, artQuuz, myBar, platformFoo},
+ []android.ModuleProxy{artFragment, myFragment},
+ map[android.ModuleProxy]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.ModuleProxy{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -257,10 +257,10 @@ func TestCreateClasspathElements(t *testing.T) {
t.Parallel()
ctx := newCtx()
elements := java.CreateClasspathElements(ctx,
- []android.Module{artBaz, myBar, artQuuz, platformFoo},
- []android.Module{artFragment, myFragment},
- map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
- map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
+ []android.ModuleProxy{artBaz, myBar, artQuuz, platformFoo},
+ []android.ModuleProxy{artFragment, myFragment},
+ map[android.ModuleProxy]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.ModuleProxy{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -276,10 +276,10 @@ func TestCreateClasspathElements(t *testing.T) {
t.Parallel()
ctx := newCtx()
elements := java.CreateClasspathElements(ctx,
- []android.Module{artBaz, platformFoo, artQuuz, myBar},
- []android.Module{artFragment, myFragment},
- map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
- map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
+ []android.ModuleProxy{artBaz, platformFoo, artQuuz, myBar},
+ []android.ModuleProxy{artFragment, myFragment},
+ map[android.ModuleProxy]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.ModuleProxy{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectLibraryElement(platformFoo),
@@ -296,10 +296,10 @@ func TestCreateClasspathElements(t *testing.T) {
t.Parallel()
ctx := newCtx()
elements := java.CreateClasspathElements(ctx,
- []android.Module{artBaz, otherApexLibrary},
- []android.Module{artFragment},
- map[android.Module]string{artBaz: "com.android.art", otherApexLibrary: "otherapex"},
- map[string]android.Module{"com.android.art": artFragment})
+ []android.ModuleProxy{artBaz, otherApexLibrary},
+ []android.ModuleProxy{artFragment},
+ map[android.ModuleProxy]string{artBaz: "com.android.art", otherApexLibrary: "otherapex"},
+ map[string]android.ModuleProxy{"com.android.art": artFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz),
}
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 2c7c4598a..dd59f4844 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -179,6 +179,7 @@ func TestDexpreoptBootJarsWithSourceArtApex(t *testing.T) {
"out/soong/.intermediates/art-bootclasspath-fragment/android_common_com.android.art/art-bootclasspath-fragment/boot.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
+ "out/soong/dexpreopt/assume_value_flags.txt",
}
expectedOutputs := []string{
@@ -218,6 +219,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
"out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
+ "out/soong/dexpreopt/assume_value_flags.txt",
}
expectedOutputs := []string{
diff --git a/apex/key.go b/apex/key.go
index cc66a131f..b43ac1e4a 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -196,9 +196,9 @@ type allApexCerts struct {
func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var avbpubkeys android.Paths
var certificatesPem android.Paths
- ctx.VisitDirectDeps(func(m android.Module) {
- if apex, ok := m.(*apexBundle); ok {
- pem, _ := apex.getCertificateAndPrivateKey(ctx)
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
+ if apex, ok := android.OtherModuleProvider(ctx, m, android.ApexBundleTypeInfoProvider); ok {
+ pem := apex.Pem
if !android.ExistentPathForSource(ctx, pem.String()).Valid() {
if ctx.Config().AllowMissingDependencies() {
return
@@ -208,7 +208,7 @@ func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
certificatesPem = append(certificatesPem, pem)
// avbpubkey for signing the apex payload
- avbpubkeys = append(avbpubkeys, apex.publicKeyFile)
+ avbpubkeys = append(avbpubkeys, apex.Key)
}
})
certificatesPem = android.SortedUniquePaths(certificatesPem) // For hermiticity
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index fdd9a75d7..7d9a128d6 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -15,7 +15,6 @@
package apex
import (
- "fmt"
"slices"
"sort"
"strconv"
@@ -48,6 +47,16 @@ var (
CommandDeps: []string{"${deapexer}"},
Description: "decompress $out",
})
+ // Compares the declared apps of `prebuilt_apex` with the actual apks
+ validateApkInPrebuiltApex = pctx.StaticRule("validateApkinPrebuiltApex", blueprint.RuleParams{
+ Command: `rm -rf ${out} ${actualApks} &&` +
+ ` ${apex_ls} ${in} | grep apk$$ | awk -F '/' '{print $$NF}' | sort -u > ${actualApks} &&` +
+ ` cmp -s ${expectedApks} ${actualApks} && touch ${out}` +
+ ` || (echo "Found diffs between "apps" property of ${apexName} and actual contents of ${in}.` +
+ ` Please ensure that all apk-in-apexes are declared in 'apps' property." && exit 1)`,
+ CommandDeps: []string{"${apex_ls}"},
+ Description: "validate apk in prebuilt_apex $out",
+ }, "expectedApks", "actualApks", "apexName")
)
type prebuilt interface {
@@ -335,19 +344,19 @@ func (m ApexPrebuiltDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.
}
func (p *prebuiltCommon) checkExportedDependenciesArePrebuilts(ctx android.ModuleContext) {
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(dep)
depName := ctx.OtherModuleName(dep)
if exportedTag, ok := tag.(exportedDependencyTag); ok {
propertyName := exportedTag.name
// It is an error if the other module is not a prebuilt.
- if !android.IsModulePrebuilt(dep) {
+ if !android.IsModulePrebuilt(ctx, dep) {
ctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
}
// It is an error if the other module is not an ApexModule.
- if _, ok := dep.(android.ApexModule); !ok {
+ if _, ok := android.OtherModuleProvider(ctx, dep, android.ApexInfoProvider); !ok {
ctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
}
}
@@ -370,8 +379,6 @@ type Prebuilt struct {
properties PrebuiltProperties
inputApex android.Path
-
- provenanceMetaDataFile android.Path
}
type ApexFileProperties struct {
@@ -483,7 +490,7 @@ func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext
commonModules := []string{}
dexpreoptProfileGuidedModules := []string{}
exportedFiles := []string{}
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
tag := ctx.OtherModuleDependencyTag(child)
// If the child is not in the same apex as the parent then ignore it and all its children.
@@ -491,15 +498,14 @@ func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext
return false
}
- name := java.ModuleStemForDeapexing(child)
+ name := java.ModuleStemForDeapexing(ctx, child)
if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
commonModules = append(commonModules, name)
- extract := child.(android.RequiredFilesFromPrebuiltApex)
- requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx)
- exportedFiles = append(exportedFiles, requiredFiles...)
+ info := android.OtherModuleProviderOrDefault(ctx, child, android.RequiredFilesFromPrebuiltApexInfoProvider)
+ exportedFiles = append(exportedFiles, info.RequiredFilesFromPrebuiltApex...)
- if extract.UseProfileGuidedDexpreopt() {
+ if info.UseProfileGuidedDexpreopt {
dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name)
}
@@ -627,7 +633,7 @@ func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext, di *a
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
// with information about whether source or prebuilt of an apex was used during the build.
func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
- info := android.PrebuiltInfo{
+ info := android.PrebuiltJsonInfo{
Name: p.BaseModuleName(),
Is_prebuilt: true,
}
@@ -635,14 +641,14 @@ func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
if p.prebuiltCommonProperties.Prebuilt_info != nil {
info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String()
}
- android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+ android.SetProvider(ctx, android.PrebuiltJsonInfoProvider, info)
}
// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global
// PRODUCT_APEX_BOOT_JARS
// This validation will only run on the apex which is active for this product/release_config
func validateApexClasspathFragments(ctx android.ModuleContext) {
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists {
ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName)
}
@@ -701,7 +707,7 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.installApexSystemServerFiles(ctx)
installDeps := slices.Concat(p.compatSymlinks, p.extraInstalledFiles)
p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, installDeps...)
- p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
+ provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
}
p.addApkCertsInfo(ctx)
@@ -711,19 +717,40 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{p.apexKeysPath})
}
-// `addApkCertsInfo` sets a provider that will be used to create apkcerts.txt
-func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) {
- formatLine := func(cert java.Certificate, name, partition string) string {
- pem := cert.AndroidMkString()
- var key string
- if cert.Key == nil {
- key = ""
- } else {
- key = cert.Key.String()
- }
- return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
+// Creates a timestamp file that will be used to validate that there is no mismtach
+// between apks declared via `apps` and the actual apks inside the apex.
+func (p *Prebuilt) validateApkInPrebuiltApex(ctx android.ModuleContext, appInfos java.AppInfos) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "apk_in_prebuilt_apex.timestamp")
+ // Create a list of expected installed apks.
+ var installedApks []string
+ for _, appInfo := range appInfos {
+ installedApks = append(installedApks, appInfo.InstallApkName+".apk")
+ }
+ expectedApksFile := android.PathForModuleOut(ctx, "expected_apk_in_prebuilt_apex.txt")
+ if len(installedApks) == 0 {
+ android.WriteFileRuleVerbatim(ctx, expectedApksFile, "") // Without newline
+ } else {
+ android.WriteFileRule(ctx, expectedApksFile, strings.Join(android.SortedUniqueStrings(installedApks), "\n")) // With newline
}
+ actualApksFile := android.PathForModuleOut(ctx, "actual_apk_in_prebuilt_apex.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: validateApkInPrebuiltApex,
+ Input: p.inputApex,
+ Output: timestamp,
+ Implicit: expectedApksFile,
+ ImplicitOutput: actualApksFile,
+ Args: map[string]string{
+ "expectedApks": expectedApksFile.String(),
+ "actualApks": actualApksFile.String(),
+ "apexName": p.Name(),
+ },
+ })
+ return timestamp
+}
+
+// `addApkCertsInfo` sets a provider that will be used to create apkcerts.txt
+func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) {
// Determine if this prebuilt_apex contains any .apks
var appInfos java.AppInfos
ctx.VisitDirectDepsProxyWithTag(appInPrebuiltApexTag, func(app android.ModuleProxy) {
@@ -737,28 +764,29 @@ func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) {
return appInfos[i].InstallApkName < appInfos[j].InstallApkName
})
- if len(appInfos) == 0 {
- return
- }
-
- // Set a provider for use by `android_device`.
- // `android_device` will create an apkcerts.txt with the list of installed apps for that device.
- android.SetProvider(ctx, java.AppInfosProvider, appInfos)
-
- // Set a Make variable for legacy apkcerts.txt creation
- // p.apkCertsFile will become `LOCAL_APKCERTS_FILE`
+ // Create p.apkCertsFile with information about apk-in-apex
+ // p.apkCertsFile will become `LOCAL_APKCERTS_FILE` for Make packaging system
+ // p.apkCertsFile will be propagated to android_device for Soong packaging system
var lines []string
for _, appInfo := range appInfos {
- lines = append(lines, formatLine(appInfo.Certificate, appInfo.InstallApkName+".apk", p.PartitionTag(ctx.DeviceConfig())))
+ lines = append(lines, java.FormatApkCertsLine(appInfo.Certificate, appInfo.InstallApkName+".apk", p.PartitionTag(ctx.DeviceConfig())))
}
- if len(lines) > 0 {
- p.apkCertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
- android.WriteFileRule(ctx, p.apkCertsFile, strings.Join(lines, "\n"))
+ apkCertsFile := android.PathForModuleOut(ctx, "apkcerts.txt")
+ var validations android.Paths
+ if p.IsInstallable() {
+ // Skip the validation for non-installable prebuilt apexes (e.g. used in CTS tests).
+ validations = append(validations, p.validateApkInPrebuiltApex(ctx, appInfos))
}
-}
+ android.WriteFileRule(ctx, apkCertsFile, strings.Join(lines, "\n"), validations...)
-func (p *Prebuilt) ProvenanceMetaDataFile() android.Path {
- return p.provenanceMetaDataFile
+ // Skip exporting the apkcerts file if there were missing dependencies, because soong will
+ // cause all build rules of a module with missing dependencies to fail to build.
+ if len(ctx.GetMissingDependencies()) == 0 {
+ p.apkCertsFile = apkCertsFile
+ android.SetProvider(ctx, java.ApkCertInfoProvider, java.ApkCertInfo{
+ ApkCertsFile: p.apkCertsFile,
+ })
+ }
}
// extract registers the build actions to extract an apex from .apks file
diff --git a/bin/printflags b/bin/printflags
new file mode 100755
index 000000000..feea76aba
--- /dev/null
+++ b/bin/printflags
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+require_top
+
+aconfig="$ANDROID_SOONG_HOST_OUT"/bin/aconfig
+flags_file="$(getoutdir)"/soong/.intermediates/all_aconfig_declarations.pb
+if [[ ! -f "$aconfig" || ! -f "$flags_file" ]]; then
+ echo "Missing dependencies: please run 'm all_aconfig_declarations' and try again."
+ exit 1
+fi
+$aconfig dump-cache --cache "$flags_file" "$@"
diff --git a/bpf/bpf.go b/bpf/bpf.go
index deb465dd6..9c5f9cd85 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -37,11 +37,11 @@ func init() {
var (
pctx = android.NewPackageContext("android/soong/bpf")
- ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true},
+ ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{},
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
+ Command: "$relPwd $ccCmd --target=bpf -mcpu=v1 -c $cFlags -MD -MF ${out}.d -o $out $in",
CommandDeps: []string{"$ccCmd"},
},
"ccCmd", "cFlags")
diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go
index 44013e5e3..07b35a7be 100644
--- a/bpf/libbpf/libbpf_prog.go
+++ b/bpf/libbpf/libbpf_prog.go
@@ -25,6 +25,7 @@ import (
"android/soong/genrule"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
type libbpfProgDepType struct {
@@ -93,6 +94,12 @@ type LibbpfProgProperties struct {
// optional subdirectory under which this module is installed into.
Relative_install_path string
+
+ // whether this module is specific to an SoC (System-On-a-Chip).
+ // When set to true, it is installed into /vendor.
+ Vendor *bool
+
+ VendorInternal bool `blueprint:"mutated"`
}
type libbpfProg struct {
@@ -107,7 +114,7 @@ var _ android.ImageInterface = (*libbpfProg)(nil)
func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
- return false
+ return proptools.Bool(libbpf.properties.Vendor)
}
func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
@@ -115,7 +122,7 @@ func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.ImageInterfaceContext
}
func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
- return true
+ return !proptools.Bool(libbpf.properties.Vendor)
}
func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
@@ -139,6 +146,7 @@ func (libbpf *libbpfProg) ExtraImageVariations(ctx android.ImageInterfaceContext
}
func (libbpf *libbpfProg) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
+ libbpf.properties.VendorInternal = variation == "vendor"
}
func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -173,12 +181,12 @@ func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext)
cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
}
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
depTag := ctx.OtherModuleDependencyTag(dep)
if depTag == libbpfProgDepTag {
- if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
- cFlagsDeps = append(cFlagsDeps, genRule.GeneratedDeps()...)
- dirs := genRule.GeneratedHeaderDirs()
+ if info, ok := android.OtherModuleProvider(ctx, dep, android.GeneratedSourceInfoProvider); ok {
+ cFlagsDeps = append(cFlagsDeps, info.GeneratedDeps...)
+ dirs := info.GeneratedHeaderDirs
for _, dir := range dirs {
cflags = append(cflags, "-I "+dir.String())
}
@@ -250,7 +258,11 @@ func (libbpf *libbpfProg) AndroidMk() android.AndroidMkData {
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w)
var localModulePath string
- localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ if libbpf.properties.VendorInternal {
+ localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
+ } else {
+ localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ }
if len(libbpf.properties.Relative_install_path) > 0 {
localModulePath += "/" + libbpf.properties.Relative_install_path
}
diff --git a/bpf/libbpf/libbpf_prog_test.go b/bpf/libbpf/libbpf_prog_test.go
index 2b3b37841..bfe2d62b5 100644
--- a/bpf/libbpf/libbpf_prog_test.go
+++ b/bpf/libbpf/libbpf_prog_test.go
@@ -16,6 +16,7 @@ package libbpf_prog
import (
"os"
+ "strings"
"testing"
"android/soong/android"
@@ -68,3 +69,27 @@ func TestLibbpfProgSourceName(t *testing.T) {
`invalid character '_' in source name`)).
RunTestWithBp(t, bp)
}
+
+func TestLibbpfProgVendor(t *testing.T) {
+ bp := `
+ libbpf_prog {
+ name: "bpf.bpf",
+ srcs: ["bpf.c"],
+ vendor: true,
+ relative_install_path: "prefix",
+ }
+ `
+
+ result := prepareForLibbpfProgTest.RunTestWithBp(t, bp)
+ module := result.ModuleForTests(t, "bpf.bpf", "android_vendor_arm64_armv8-a").Module().(*libbpfProg)
+ data := android.AndroidMkDataForTest(t, result.TestContext, module)
+ name := module.BaseModuleName()
+ var builder strings.Builder
+ data.Custom(&builder, name, "", "", data)
+ androidMk := android.StringRelativeToTop(result.Config, builder.String())
+
+ expected := "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf/prefix"
+ if !strings.Contains(androidMk, expected) {
+ t.Errorf("%q is not found in %q", expected, androidMk)
+ }
+}
diff --git a/build_kzip.bash b/build_kzip.bash
index 850aedaf0..8ec5406bb 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -42,7 +42,7 @@ kzip_targets=(
xref_java
xref_kotlin
# TODO: b/286390153 - reenable rust
- # xref_rust
+ xref_rust
)
build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k --skip-soong-tests --ninja_weight_source=not_used "${kzip_targets[@]}"
@@ -66,7 +66,7 @@ for dir in "${go_modules[@]}"; do
outfile=$(echo "$dir" | sed -r 's|/|_|g;s|(.*)|\1.go.kzip|');
KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" \
--rules=<(printf '[{"pattern": "(.*)","vname": {"path": "@1@", "corpus":"%s"}}]' "${XREF_CORPUS}") \
- --canonicalize_package_corpus --output "${abspath_out}/soong/$outfile" ./...
+ --canonicalize_package_corpus --output "${abspath_out}/soong/$outfile" --gocgo=false ./...
)
done
set +e
diff --git a/cc/Android.bp b/cc/Android.bp
index 1ac5a4a8f..fd9ad0e93 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -25,7 +25,9 @@ bootstrap_go_package {
"androidmk.go",
"api_level.go",
"builder.go",
+ "builder_gob_enc.go",
"cc.go",
+ "cc_gob_enc.go",
"ccdeps.go",
"cc_preprocess_no_configuration.go",
"check.go",
@@ -34,6 +36,8 @@ bootstrap_go_package {
"generated_cc_library.go",
"image.go",
"linkable.go",
+ "linkable_gob_enc.go",
+ "llvm_coverage_tools_zip.go",
"lto.go",
"makevars.go",
"misc_disted_files.go",
@@ -42,6 +46,7 @@ bootstrap_go_package {
"proto.go",
"rs.go",
"sanitize.go",
+ "sanitize_gob_enc.go",
"sabi.go",
"sdk.go",
"snapshot_prebuilt.go",
@@ -61,6 +66,7 @@ bootstrap_go_package {
"binary.go",
"binary_sdk_member.go",
+ "binary_sdk_member_gob_enc.go",
"fuzz.go",
"image_sdk_traits.go",
"library.go",
@@ -75,6 +81,8 @@ bootstrap_go_package {
"ndk_library.go",
"ndk_sysroot.go",
+ "ndk_translation_package.go",
+
"llndk_library.go",
"kernel_headers.go",
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index d2d5584ff..940cb697f 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -20,24 +20,8 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
-type visitDirectDepsInterface interface {
- VisitDirectDeps(blueprint.Module, func(dep blueprint.Module))
-}
-
-func hasDirectDep(ctx visitDirectDepsInterface, m android.Module, wantDep android.Module) bool {
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
-}
-
func TestAfdoDeps(t *testing.T) {
t.Parallel()
bp := `
@@ -129,11 +113,11 @@ func TestAfdoDeps(t *testing.T) {
}
// Check dependency edge from afdo-enabled module to static deps
- if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
+ if !android.HasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libBar")
}
@@ -157,11 +141,11 @@ func TestAfdoDeps(t *testing.T) {
}
// Check dependency edges of static deps
- if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest should not depend on non-afdo variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
@@ -191,11 +175,11 @@ func TestAfdoDeps(t *testing.T) {
}
// Check dependency edge from afdo-enabled module to static deps
- if !hasDirectDep(result, libTest32.Module(), libFooAfdoVariant32.Module()) {
+ if !android.HasDirectDep(result, libTest32.Module(), libFooAfdoVariant32.Module()) {
t.Errorf("arm32 libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libFooAfdoVariant32.Module(), libBarAfdoVariant32.Module()) {
+ if !android.HasDirectDep(result, libFooAfdoVariant32.Module(), libBarAfdoVariant32.Module()) {
t.Errorf("arm32 libTest missing dependency on afdo variant of libBar")
}
@@ -240,11 +224,11 @@ func TestAfdoDeps(t *testing.T) {
}
// Check dependency edge from afdo-enabled module to static deps
- if !hasDirectDep(result, libTestHost.Module(), libFooHost.Module()) {
+ if !android.HasDirectDep(result, libTestHost.Module(), libFooHost.Module()) {
t.Errorf("host libTest missing dependency on non-afdo variant of libFoo")
}
- if !hasDirectDep(result, libFooHost.Module(), libBarHost.Module()) {
+ if !android.HasDirectDep(result, libFooHost.Module(), libBarHost.Module()) {
t.Errorf("host libTest missing dependency on non-afdo variant of libBar")
}
@@ -305,11 +289,11 @@ func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static").Module()
- if !hasDirectDep(result, libTest, libFoo.Module()) {
+ if !android.HasDirectDep(result, libTest, libFoo.Module()) {
t.Errorf("libTest missing dependency on non-afdo variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar) {
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
@@ -503,11 +487,11 @@ func TestMultipleAfdoRDeps(t *testing.T) {
}
// Check dependency edges of static deps
- if !hasDirectDep(result, libTest.Module(), libFooAfdoVariantWithLibTest.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFooAfdoVariantWithLibTest.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libBar.Module(), libFooAfdoVariantWithLibBar.Module()) {
+ if !android.HasDirectDep(result, libBar.Module(), libFooAfdoVariantWithLibBar.Module()) {
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
}
@@ -563,11 +547,11 @@ func TestAfdoDepsWithoutProfile(t *testing.T) {
t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
}
// Check dependency edge from afdo-enabled module to static deps
- if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
+ if !android.HasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libBar")
}
@@ -585,11 +569,11 @@ func TestAfdoDepsWithoutProfile(t *testing.T) {
}
// Check dependency edges of static deps
- if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest should not depend on non-afdo variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index b016788ee..f6255829f 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -16,7 +16,6 @@ package cc
import (
"fmt"
- "io"
"path/filepath"
"strings"
@@ -212,19 +211,6 @@ func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.An
}
}
-func (library *libraryDecorator) androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries *android.AndroidMkInfo) {
- if !library.static() {
- entries.AddPaths("LOCAL_ADDITIONAL_DEPENDENCIES", library.sAbiDiff)
- }
-}
-
-// TODO(ccross): remove this once apex/androidmk.go is converted to AndroidMkEntries
-func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
- if !library.static() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", strings.Join(library.sAbiDiff.Strings(), " "))
- }
-}
-
func (library *libraryDecorator) prepareAndroidMKProviderInfo(config android.Config, ctx AndroidMkContext, entries *android.AndroidMkInfo) {
if library.static() {
entries.Class = "STATIC_LIBRARIES"
@@ -245,7 +231,6 @@ func (library *libraryDecorator) prepareAndroidMKProviderInfo(config android.Con
}
library.androidMkWriteExportedFlags(entries)
- library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
if entries.OutputFile.Valid() {
_, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
@@ -391,10 +376,6 @@ func (fuzz *fuzzBinary) prepareAndroidMKProviderInfo(config android.Config, ctx
ctx.subAndroidMk(config, entries, fuzz.binaryDecorator)
entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
- if fuzz.installedSharedDeps != nil {
- // TOOD: move to install dep
- entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
- }
}
func (test *testLibrary) prepareAndroidMKProviderInfo(config android.Config, ctx AndroidMkContext, entries *android.AndroidMkInfo) {
diff --git a/cc/binary.go b/cc/binary.go
index 608251afc..627d5e560 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -551,10 +551,6 @@ func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON
binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
}
-func (binary *binaryDecorator) testSuiteInfo(ctx ModuleContext) {
- // not a test
-}
-
var _ overridable = (*binaryDecorator)(nil)
func init() {
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 4063714ab..eabdb8c19 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -15,6 +15,7 @@
package cc
import (
+ "fmt"
"path/filepath"
"android/soong/android"
@@ -23,6 +24,8 @@ import (
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
android.RegisterSdkMemberType(ccBinarySdkMemberType)
}
@@ -34,6 +37,7 @@ var ccBinarySdkMemberType = &binarySdkMemberType{
},
}
+// @auto-generate: gob
type binarySdkMemberType struct {
android.SdkMemberTypeBase
}
@@ -52,11 +56,11 @@ func (mt *binarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext,
}
}
-func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
+func (mt *binarySdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
// Check the module to see if it can be used with this module type.
- if m, ok := module.(*Module); ok {
- for _, allowableMemberType := range m.sdkMemberTypes {
- if allowableMemberType == mt {
+ if m, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ for _, allowableMemberType := range m.SdkMemberTypes {
+ if allowableMemberType.SdkPropertyName() == mt.SdkPropertyName() {
return true
}
}
@@ -68,10 +72,13 @@ func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
func (mt *binarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary")
- ccModule := member.Variants()[0].(*Module)
+ info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), member.Variants()[0], CcInfoProvider)
+ if !ok {
+ panic(fmt.Errorf("not a cc module: %s", member.Variants()[0]))
+ }
- if stl := ccModule.stl.Properties.Stl; stl != nil {
- pbm.AddProperty("stl", proptools.String(stl))
+ if info.StlInfo != nil && info.StlInfo.Stl != nil {
+ pbm.AddProperty("stl", proptools.String(info.StlInfo.Stl))
}
return pbm
@@ -120,19 +127,49 @@ type nativeBinaryInfoProperties struct {
Nocrt bool
}
-func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- ccModule := variant.(*Module)
+func setSharedAndSystemLibs(specifiedDeps *specifiedDeps, sharedLibs []string, systemLibs []string) {
+ specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, sharedLibs...)
+ // Must distinguish nil and [] in system_shared_libs - ensure that [] in
+ // either input list doesn't come out as nil.
+ if specifiedDeps.systemSharedLibs == nil {
+ specifiedDeps.systemSharedLibs = systemLibs
+ } else {
+ specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, systemLibs...)
+ }
+}
+
+func setLinkerSpecifiedDeps(linker *LinkerInfo, specifiedDeps *specifiedDeps) {
+ if linker.ObjectLinkerInfo != nil {
+ setSharedAndSystemLibs(specifiedDeps, linker.ObjectLinkerInfo.SharedLibs, linker.ObjectLinkerInfo.SystemSharedLibs)
+ return
+ }
+
+ setSharedAndSystemLibs(specifiedDeps, linker.SharedLibs, linker.SystemSharedLibs)
+
+ if linker.LibraryDecoratorInfo != nil {
+ setSharedAndSystemLibs(specifiedDeps, linker.LibraryDecoratorInfo.SharedLibs, linker.LibraryDecoratorInfo.SystemSharedLibs)
+ specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
+ if len(specifiedDeps.systemSharedLibs) > 0 {
+ // Skip this if systemSharedLibs is either nil or [], to ensure they are
+ // retained.
+ specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
+ }
+ }
+}
- p.archType = ccModule.Target().Arch.ArchType.String()
- p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
+func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider)
+ ccInfo := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, CcInfoProvider)
+ p.archType = commonInfo.Target.Arch.ArchType.String()
+ p.outputFile = getRequiredMemberOutputFile(ctx, variant)
- binaryLinker := ccModule.linker.(*binaryDecorator)
- p.StaticExecutable = binaryLinker.static()
- p.Nocrt = Bool(binaryLinker.baseLinker.Properties.Nocrt)
+ if ccInfo.LinkerInfo != nil {
+ binaryLinker := ccInfo.LinkerInfo.BinaryDecoratorInfo
+ p.StaticExecutable = binaryLinker.StaticExecutable
+ p.Nocrt = binaryLinker.Nocrt
- if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
- specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx.SdkModuleContext(), ccModule, specifiedDeps)
+ setLinkerSpecifiedDeps(ccInfo.LinkerInfo, &specifiedDeps)
p.SharedLibs = specifiedDeps.sharedLibs
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
diff --git a/cc/binary_sdk_member_gob_enc.go b/cc/binary_sdk_member_gob_enc.go
new file mode 100644
index 000000000..d9e38473c
--- /dev/null
+++ b/cc/binary_sdk_member_gob_enc.go
@@ -0,0 +1,37 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package cc
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ binarySdkMemberTypeGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(binarySdkMemberType) })
+}
+
+func (r binarySdkMemberType) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.SdkMemberTypeBase.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *binarySdkMemberType) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.SdkMemberTypeBase.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var binarySdkMemberTypeGobRegId int16
+
+func (r binarySdkMemberType) GetTypeId() int16 {
+ return binarySdkMemberTypeGobRegId
+}
diff --git a/cc/builder.go b/cc/builder.go
index f4f85962d..ed1bad2f4 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -34,6 +34,8 @@ import (
"android/soong/remoteexec"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
const (
objectExtension = ".o"
staticLibraryExtension = ".a"
@@ -43,7 +45,7 @@ var (
pctx = android.NewPackageContext("android/soong/cc")
// Rule to invoke gcc with given command, flags, and dependencies. Outputs a .d depfile.
- cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true},
+ cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{RBE: true},
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
@@ -304,8 +306,10 @@ var (
sAbiDiff = pctx.RuleFunc("sAbiDiff",
func(ctx android.PackageRuleContext) blueprint.RuleParams {
commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
- commandStr += "|| (echo '${errorMessage}'"
- commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
+ commandStr += "|| (echo 'First 50 lines of abidiff:'"
+ commandStr += " && head -n 50 ${out}"
+ commandStr += " && echo '${errorMessage}'"
+ commandStr += " && (test -n \"$$DIST_DIR\" && mkdir -p $$DIST_DIR/abidiffs && cp ${out} ${in} $$DIST_DIR/abidiffs/)"
commandStr += " && exit 1)"
return blueprint.RuleParams{
Command: commandStr,
@@ -345,6 +349,13 @@ var (
},
"cFlags")
+ // Rule to generate the elf mapping textproto file from the symbols file.
+ elfSymbolsToProto = pctx.AndroidStaticRule("elf_symbols_to_proto", blueprint.RuleParams{
+ Command: `${symbols_map} -elf $in -write_if_changed $out`,
+ Restat: true,
+ CommandDeps: []string{"${symbols_map}"},
+ })
+
// Function pointer for producting staticlibs from rlibs. Corresponds to
// rust.TransformRlibstoStaticlib(), initialized in soong-rust (rust/builder.go init())
//
@@ -370,6 +381,8 @@ func init() {
pctx.StaticVariable("relPwd", PwdPrefix())
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+
+ pctx.HostBinToolVariable("symbols_map", "symbols_map")
}
// builderFlags contains various types of command line flags (and settings) for use in building
@@ -440,6 +453,7 @@ type StripFlags struct {
}
// Objects is a collection of file paths corresponding to outputs for C++ related build statements.
+// @auto-generate: gob
type Objects struct {
objFiles android.Paths
tidyFiles android.Paths
@@ -471,6 +485,17 @@ func (a Objects) Append(b Objects) Objects {
}
}
+func (a Objects) Dedup() Objects {
+ return Objects{
+ objFiles: android.FirstUniquePaths(a.objFiles),
+ tidyFiles: android.FirstUniquePaths(a.tidyFiles),
+ tidyDepFiles: android.FirstUniquePaths(a.tidyDepFiles),
+ coverageFiles: android.FirstUniquePaths(a.coverageFiles),
+ sAbiDumpFiles: android.FirstUniquePaths(a.sAbiDumpFiles),
+ kytheFiles: android.FirstUniquePaths(a.kytheFiles),
+ }
+}
+
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths,
flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths, sharedFlags *SharedFlags) Objects {
@@ -508,7 +533,7 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no
coverageFiles = make(android.Paths, 0, len(srcObjFiles))
}
var kytheFiles android.Paths
- if flags.emitXrefs && ctx.Module() == ctx.PrimaryModule() {
+ if flags.emitXrefs && ctx.IsPrimaryModule(ctx.Module()) {
kytheFiles = make(android.Paths, 0, len(srcObjFiles))
}
@@ -685,7 +710,7 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no
})
// Register post-process build statements (such as for tidy or kythe).
- if emitXref && ctx.Module() == ctx.PrimaryModule() {
+ if emitXref && ctx.IsPrimaryModule(ctx.Module()) {
kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip")
ctx.Build(pctx, android.BuildParams{
Rule: kytheExtract,
diff --git a/cc/builder_gob_enc.go b/cc/builder_gob_enc.go
new file mode 100644
index 000000000..a02b4d347
--- /dev/null
+++ b/cc/builder_gob_enc.go
@@ -0,0 +1,192 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package cc
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ObjectsGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(Objects) })
+}
+
+func (r Objects) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.objFiles))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.objFiles); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.objFiles[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.tidyFiles))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.tidyFiles); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.tidyFiles[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.tidyDepFiles))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.tidyDepFiles); val3++ {
+ if err = gobtools.EncodeInterface(buf, r.tidyDepFiles[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.coverageFiles))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.coverageFiles); val4++ {
+ if err = gobtools.EncodeInterface(buf, r.coverageFiles[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.sAbiDumpFiles))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.sAbiDumpFiles); val5++ {
+ if err = gobtools.EncodeInterface(buf, r.sAbiDumpFiles[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.kytheFiles))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.kytheFiles); val6++ {
+ if err = gobtools.EncodeInterface(buf, r.kytheFiles[val6]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *Objects) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.objFiles = make([]android.Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.objFiles[val4] = nil
+ } else {
+ r.objFiles[val4] = val6.(android.Path)
+ }
+ }
+ }
+
+ var val9 int32
+ err = gobtools.DecodeSimple[int32](buf, &val9)
+ if err != nil {
+ return err
+ }
+ if val9 > 0 {
+ r.tidyFiles = make([]android.Path, val9)
+ for val10 := 0; val10 < int(val9); val10++ {
+ if val12, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val12 == nil {
+ r.tidyFiles[val10] = nil
+ } else {
+ r.tidyFiles[val10] = val12.(android.Path)
+ }
+ }
+ }
+
+ var val15 int32
+ err = gobtools.DecodeSimple[int32](buf, &val15)
+ if err != nil {
+ return err
+ }
+ if val15 > 0 {
+ r.tidyDepFiles = make([]android.Path, val15)
+ for val16 := 0; val16 < int(val15); val16++ {
+ if val18, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val18 == nil {
+ r.tidyDepFiles[val16] = nil
+ } else {
+ r.tidyDepFiles[val16] = val18.(android.Path)
+ }
+ }
+ }
+
+ var val21 int32
+ err = gobtools.DecodeSimple[int32](buf, &val21)
+ if err != nil {
+ return err
+ }
+ if val21 > 0 {
+ r.coverageFiles = make([]android.Path, val21)
+ for val22 := 0; val22 < int(val21); val22++ {
+ if val24, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val24 == nil {
+ r.coverageFiles[val22] = nil
+ } else {
+ r.coverageFiles[val22] = val24.(android.Path)
+ }
+ }
+ }
+
+ var val27 int32
+ err = gobtools.DecodeSimple[int32](buf, &val27)
+ if err != nil {
+ return err
+ }
+ if val27 > 0 {
+ r.sAbiDumpFiles = make([]android.Path, val27)
+ for val28 := 0; val28 < int(val27); val28++ {
+ if val30, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val30 == nil {
+ r.sAbiDumpFiles[val28] = nil
+ } else {
+ r.sAbiDumpFiles[val28] = val30.(android.Path)
+ }
+ }
+ }
+
+ var val33 int32
+ err = gobtools.DecodeSimple[int32](buf, &val33)
+ if err != nil {
+ return err
+ }
+ if val33 > 0 {
+ r.kytheFiles = make([]android.Path, val33)
+ for val34 := 0; val34 < int(val33); val34++ {
+ if val36, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val36 == nil {
+ r.kytheFiles[val34] = nil
+ } else {
+ r.kytheFiles[val34] = val36.(android.Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var ObjectsGobRegId int16
+
+func (r Objects) GetTypeId() int16 {
+ return ObjectsGobRegId
+}
diff --git a/cc/cc.go b/cc/cc.go
index b15ed6c7f..1e8731b10 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -21,7 +21,7 @@ package cc
import (
"errors"
"fmt"
- "io"
+ "path/filepath"
"slices"
"strconv"
"strings"
@@ -36,6 +36,9 @@ import (
"android/soong/fuzz"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
+// @auto-generate: gob
type CcMakeVarsInfo struct {
WarningsAllowed string
UsingWnoError string
@@ -44,6 +47,7 @@ type CcMakeVarsInfo struct {
var CcMakeVarsInfoProvider = blueprint.NewProvider[*CcMakeVarsInfo]()
+// @auto-generate: gob
type CcObjectInfo struct {
ObjFiles android.Paths
TidyFiles android.Paths
@@ -52,6 +56,7 @@ type CcObjectInfo struct {
var CcObjectInfoProvider = blueprint.NewProvider[CcObjectInfo]()
+// @auto-generate: gob
type AidlInterfaceInfo struct {
// list of aidl_interface sources
Sources []string
@@ -63,6 +68,7 @@ type AidlInterfaceInfo struct {
Flags []string
}
+// @auto-generate: gob
type CompilerInfo struct {
Srcs android.Paths
// list of module-specific flags that will be used for C and C++ compiles.
@@ -71,6 +77,7 @@ type CompilerInfo struct {
LibraryDecoratorInfo *LibraryDecoratorInfo
}
+// @auto-generate: gob
type LinkerInfo struct {
WholeStaticLibs []string
// list of modules that should be statically linked into this module.
@@ -79,6 +86,7 @@ type LinkerInfo struct {
SharedLibs []string
// list of modules that should only provide headers for this module.
HeaderLibs []string
+ SystemSharedLibs []string
ImplementationModuleName *string
BinaryDecoratorInfo *BinaryDecoratorInfo
@@ -90,7 +98,13 @@ type LinkerInfo struct {
PrebuiltLibraryLinkerInfo *PrebuiltLibraryLinkerInfo
}
-type BinaryDecoratorInfo struct{}
+// @auto-generate: gob
+type BinaryDecoratorInfo struct {
+ StaticExecutable bool
+ Nocrt bool
+}
+
+// @auto-generate: gob
type LibraryDecoratorInfo struct {
ExportIncludeDirs []string
InjectBsslHash bool
@@ -98,17 +112,27 @@ type LibraryDecoratorInfo struct {
// not included in the NDK.
NdkSysrootPath android.Path
VndkFileName string
+ // rename host libraries to prevent overlap with system installed libraries
+ UniqueHostSoname *bool
+ SharedLibs []string
+ SystemSharedLibs []string
+ StubsSymbolFilePath android.Path
}
+// @auto-generate: gob
type SnapshotInfo struct {
SnapshotAndroidMkSuffix string
}
+// @auto-generate: gob
type TestBinaryInfo struct {
Gtest bool
}
+
+// @auto-generate: gob
type BenchmarkDecoratorInfo struct{}
+// @auto-generate: gob
type StubDecoratorInfo struct {
AbiDumpPath android.OutputPath
HasAbiDump bool
@@ -116,24 +140,32 @@ type StubDecoratorInfo struct {
InstallPath android.Path
}
+// @auto-generate: gob
type ObjectLinkerInfo struct {
// Location of the object in the sysroot. Empty if the object is not
// included in the NDK.
- NdkSysrootPath android.Path
+ NdkSysrootPath android.Path
+ SharedLibs []string
+ SystemSharedLibs []string
}
+// @auto-generate: gob
type PrebuiltLibraryLinkerInfo struct {
VndkFileName string
}
+// @auto-generate: gob
type LibraryInfo struct {
- BuildStubs bool
+ BuildStubs bool
+ AllStubsVersions []string
}
+// @auto-generate: gob
type InstallerInfo struct {
StubDecoratorInfo *StubDecoratorInfo
}
+// @auto-generate: gob
type LocalOrGlobalFlagsInfo struct {
CommonFlags []string // Flags that apply to C, C++, and assembly source files
CFlags []string // Flags that apply to C and C++ source files
@@ -141,21 +173,47 @@ type LocalOrGlobalFlagsInfo struct {
CppFlags []string // Flags that apply to C++ source files
}
+// @auto-generate: gob
+type SanitizeInfo struct {
+ IsUnsanitizedVariant bool
+ Sanitize SanitizeUserProps
+}
+
+// @auto-generate: gob
+type StlInfo struct {
+ Stl *string
+}
+
// Common info about the cc module.
+// @auto-generate: gob
type CcInfo struct {
IsPrebuilt bool
CmakeSnapshotSupported bool
HasLlndkStubs bool
DataPaths []android.DataPath
- CompilerInfo *CompilerInfo
- LinkerInfo *LinkerInfo
- SnapshotInfo *SnapshotInfo
- LibraryInfo *LibraryInfo
- InstallerInfo *InstallerInfo
+ VendorAvailable bool
+ OdmAvailable bool
+ ProductAvailable bool
+ IsVendorPublicLibrary bool
+ DoubleLoadable bool
+ // Allowable SdkMemberTypes of this module type.
+ SdkMemberTypes []android.SdkMemberType
+ LocalFlags LocalOrGlobalFlagsInfo
+ GlobalFlags LocalOrGlobalFlagsInfo
+ SystemIncludeFlags []string
+ NoOverrideFlags []string
+ CompilerInfo *CompilerInfo
+ LinkerInfo *LinkerInfo
+ SnapshotInfo *SnapshotInfo
+ LibraryInfo *LibraryInfo
+ InstallerInfo *InstallerInfo
+ StlInfo *StlInfo
+ SanitizeInfo *SanitizeInfo
}
var CcInfoProvider = blueprint.NewProvider[*CcInfo]()
+// @auto-generate: gob
type LinkableInfo struct {
// StaticExecutable returns true if this is a binary module with "static_executable: true".
StaticExecutable bool
@@ -170,6 +228,7 @@ type LinkableInfo struct {
CoverageFiles android.Paths
// CoverageOutputFile returns the output archive of gcno coverage information files.
CoverageOutputFile android.OptionalPath
+ LinkCoverage bool
SAbiDumpFiles android.Paths
// Partition returns the partition string for this module.
Partition string
@@ -209,13 +268,21 @@ type LinkableInfo struct {
APIListCoverageXMLPath android.ModuleOutPath
// FuzzSharedLibraries returns the shared library dependencies for this module.
// Expects that IsFuzzModule returns true.
- FuzzSharedLibraries android.RuleBuilderInstalls
+ FuzzSharedLibraries InstallPairs
IsVndkPrebuiltLibrary bool
HasLLNDKStubs bool
IsLLNDKMovedToApex bool
ImplementationModuleName string
}
+// @auto-generate: gob
+type InstallPair struct {
+ Src android.Path
+ Dst android.InstallPath
+}
+
+type InstallPairs []InstallPair
+
var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]()
func init() {
@@ -255,7 +322,6 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
ctx.Transition("lto", &ltoTransitionMutator{})
ctx.BottomUp("check_linktype", checkLinkTypeMutator)
- ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries)
})
ctx.PostApexMutators(func(ctx android.RegisterMutatorsContext) {
@@ -699,7 +765,6 @@ type ModuleContextIntf interface {
isCfi() bool
isFuzzer() bool
isNDKStubLibrary() bool
- useClangLld(actx ModuleContext) bool
apexVariationName() string
bootstrap() bool
nativeCoverage() bool
@@ -779,7 +844,6 @@ type linker interface {
linkerFlags(ctx ModuleContext, flags Flags) Flags
linkerProps() []interface{}
baseLinkerProps() BaseLinkerProperties
- useClangLld(actx ModuleContext) bool
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
appendLdflags([]string)
@@ -797,8 +861,6 @@ type linker interface {
defaultDistFiles() []android.Path
moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
-
- testSuiteInfo(ctx ModuleContext)
}
// specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker.
@@ -966,6 +1028,46 @@ type installDependencyTag struct {
name string
}
+type SymbolInfo struct {
+ Name string
+ ModuleDir string
+ Uninstallable bool
+ UnstrippedBinaryPath android.Path
+ InstalledStem string
+ Stem string
+ Suffix string
+}
+
+func (s *SymbolInfo) equals(other *SymbolInfo) bool {
+ return s.Name == other.Name &&
+ s.ModuleDir == other.ModuleDir &&
+ s.Uninstallable == other.Uninstallable &&
+ s.UnstrippedBinaryPath == other.UnstrippedBinaryPath &&
+ s.InstalledStem == other.InstalledStem &&
+ s.Suffix == other.Suffix
+}
+
+type SymbolInfos struct {
+ Symbols []*SymbolInfo
+}
+
+func (si *SymbolInfos) containsSymbolInfo(other *SymbolInfo) bool {
+ for _, info := range si.Symbols {
+ if info.equals(other) {
+ return true
+ }
+ }
+ return false
+}
+
+func (si *SymbolInfos) AppendSymbols(infos ...*SymbolInfo) {
+ for _, info := range infos {
+ if info.UnstrippedBinaryPath != nil && !si.containsSymbolInfo(info) {
+ si.Symbols = append(si.Symbols, infos...)
+ }
+ }
+}
+
var (
genSourceDepTag = dependencyTag{name: "gen source"}
genHeaderDepTag = dependencyTag{name: "gen header"}
@@ -1109,47 +1211,6 @@ func (c *Module) IncrementalSupported() bool {
var _ blueprint.Incremental = (*Module)(nil)
-func (c *Module) AddJSONData(d *map[string]interface{}) {
- c.AndroidModuleBase().AddJSONData(d)
- (*d)["Cc"] = map[string]interface{}{
- "SdkVersion": c.SdkVersion(),
- "MinSdkVersion": c.MinSdkVersion(),
- "VndkVersion": c.VndkVersion(),
- "ProductSpecific": c.ProductSpecific(),
- "SocSpecific": c.SocSpecific(),
- "DeviceSpecific": c.DeviceSpecific(),
- "InProduct": c.InProduct(),
- "InVendor": c.InVendor(),
- "InRamdisk": c.InRamdisk(),
- "InVendorRamdisk": c.InVendorRamdisk(),
- "InRecovery": c.InRecovery(),
- "VendorAvailable": c.VendorAvailable(),
- "ProductAvailable": c.ProductAvailable(),
- "RamdiskAvailable": c.RamdiskAvailable(),
- "VendorRamdiskAvailable": c.VendorRamdiskAvailable(),
- "RecoveryAvailable": c.RecoveryAvailable(),
- "OdmAvailable": c.OdmAvailable(),
- "InstallInData": c.InstallInData(),
- "InstallInRamdisk": c.InstallInRamdisk(),
- "InstallInSanitizerDir": c.InstallInSanitizerDir(),
- "InstallInVendorRamdisk": c.InstallInVendorRamdisk(),
- "InstallInRecovery": c.InstallInRecovery(),
- "InstallInRoot": c.InstallInRoot(),
- "IsLlndk": c.IsLlndk(),
- "IsVendorPublicLibrary": c.IsVendorPublicLibrary(),
- "ApexSdkVersion": c.apexSdkVersion,
- "AidlSrcs": c.hasAidl,
- "LexSrcs": c.hasLex,
- "ProtoSrcs": c.hasProto,
- "RenderscriptSrcs": c.hasRenderscript,
- "SyspropSrcs": c.hasSysprop,
- "WinMsgSrcs": c.hasWinMsg,
- "YaccSrsc": c.hasYacc,
- "OnlyCSrcs": !(c.hasAidl || c.hasLex || c.hasProto || c.hasRenderscript || c.hasSysprop || c.hasWinMsg || c.hasYacc),
- "OptimizeForSize": c.OptimizeForSize(),
- }
-}
-
func (c *Module) SetPreventInstall() {
c.Properties.PreventInstall = true
}
@@ -1319,7 +1380,7 @@ func (c *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", c.BaseModuleName()))
}
-func (c *Module) FuzzSharedLibraries() android.RuleBuilderInstalls {
+func (c *Module) FuzzSharedLibraries() InstallPairs {
if fuzzer, ok := c.compiler.(*fuzzBinary); ok {
return fuzzer.sharedLibraries
}
@@ -1413,6 +1474,10 @@ func (c *Module) CoverageOutputFile() android.OptionalPath {
return android.OptionalPath{}
}
+func (c *Module) LinkCoverage() bool {
+ return c.coverage != nil && c.coverage.linkCoverage
+}
+
func (c *Module) RelativeInstallPath() string {
if c.installer != nil {
return c.installer.relativeInstallPath()
@@ -1863,10 +1928,6 @@ func (ctx *moduleContextImpl) selectedStl() string {
return ""
}
-func (ctx *moduleContextImpl) useClangLld(actx ModuleContext) bool {
- return ctx.mod.linker.useClangLld(actx)
-}
-
func (ctx *moduleContextImpl) baseModuleName() string {
return ctx.mod.BaseModuleName()
}
@@ -2083,6 +2144,164 @@ var (
}
)
+func (c *Module) getSymbolInfo(ctx android.ModuleContext, t any, info *SymbolInfo) *SymbolInfo {
+ switch tt := t.(type) {
+ case *baseInstaller:
+ if tt.path != (android.InstallPath{}) {
+ path, file := filepath.Split(tt.path.String())
+ stem, suffix, _ := android.SplitFileExt(file)
+ info.ModuleDir = path
+ info.Stem = stem
+ info.Suffix = suffix
+ }
+ case *binaryDecorator:
+ c.getSymbolInfo(ctx, tt.baseInstaller, info)
+ info.UnstrippedBinaryPath = tt.unstrippedOutputFile
+ case *benchmarkDecorator:
+ c.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ case *testBinary:
+ c.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ c.getSymbolInfo(ctx, tt.testDecorator, info)
+ case *fuzzBinary:
+ c.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ case *testLibrary:
+ c.getSymbolInfo(ctx, tt.libraryDecorator, info)
+ c.getSymbolInfo(ctx, tt.testDecorator, info)
+ case *stubDecorator:
+ info.Uninstallable = true
+ case *libraryDecorator:
+ if tt.shared() && !tt.BuildStubs() {
+ if tt.unstrippedOutputFile != nil {
+ info.UnstrippedBinaryPath = tt.unstrippedOutputFile
+ }
+ c.getSymbolInfo(ctx, tt.baseInstaller, info)
+ } else {
+ info.Uninstallable = true
+ }
+ case *prebuiltLibraryLinker:
+ c.getSymbolInfo(ctx, tt.libraryDecorator, info)
+ if tt.shared() {
+ c.getSymbolInfo(ctx, &tt.prebuiltLinker, info)
+ }
+ case *prebuiltBinaryLinker:
+ c.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ c.getSymbolInfo(ctx, &tt.prebuiltLinker, info)
+ case *vndkPrebuiltLibraryDecorator:
+ info.Uninstallable = true
+ case *kernelHeadersDecorator:
+ c.getSymbolInfo(ctx, tt.libraryDecorator, info)
+ }
+ return info
+}
+
+func (c *Module) baseSymbolInfo(ctx android.ModuleContext) *SymbolInfo {
+ return &SymbolInfo{
+ Name: c.BaseModuleName() + c.SubName(),
+ ModuleDir: ctx.ModuleDir(),
+ Uninstallable: c.IsSkipInstall() || !proptools.BoolDefault(c.Properties.Installable, true) || c.NoFullInstall(),
+ }
+}
+
+func targetOutUnstripped(ctx android.ModuleContext) android.InstallPath {
+ return android.PathForModuleInPartitionInstall(ctx, "symbols")
+}
+
+func elfSymbolMappingDir(ctx android.ModuleContext) android.InstallPath {
+ return android.PathForModuleInPartitionInstall(ctx, "obj", "PACKAGING", "elf_symbol_mapping_intermediates")
+}
+
+// Generates the information to copy the symbols file to $PRODUCT_OUT/symbols directory based on
+// the symbols info. The actual copying is done in [CopySymbolsAndSetSymbolsInfoProvider].
+func getSymbolicOutputInfos(ctx android.ModuleContext, info *SymbolInfo) *android.SymbolicOutputInfo {
+
+ if info.Uninstallable || info.UnstrippedBinaryPath == nil {
+ return nil
+ }
+
+ mySymbolPath := info.ModuleDir
+
+ myUnstrippedPath := targetOutUnstripped(ctx).Join(ctx, strings.TrimPrefix(mySymbolPath, android.PathForModuleInPartitionInstall(ctx, "").String()+"/"))
+
+ myInstalledModuleStem := info.InstalledStem
+ if len(myInstalledModuleStem) == 0 {
+ myModuleStem := info.Stem
+ if len(myModuleStem) == 0 {
+ myModuleStem = info.Name
+ }
+ myInstalledModuleStem = myModuleStem + info.Suffix
+ }
+
+ symbolicOutput := myUnstrippedPath.Join(ctx, myInstalledModuleStem)
+
+ return &android.SymbolicOutputInfo{
+ UnstrippedOutputFile: info.UnstrippedBinaryPath,
+ SymbolicOutputPath: symbolicOutput,
+ }
+}
+
+func CopySymbolsAndSetSymbolsInfoProvider(ctx android.ModuleContext, symbolInfos *SymbolInfos) {
+ if android.ShouldSkipAndroidMkProcessing(ctx, ctx.Module()) {
+ return
+ }
+ var symbolicOutputInfos android.SymbolicOutputInfos
+ for _, info := range symbolInfos.Symbols {
+ if so := getSymbolicOutputInfos(ctx, info); so != nil {
+ symbolicOutputInfos = append(symbolicOutputInfos, so)
+ }
+ }
+
+ // Remove duplicates
+ symbolicOutputInfos = android.FirstUniqueFunc(symbolicOutputInfos, func(a, b *android.SymbolicOutputInfo) bool {
+ return a.UnstrippedOutputFile.String() == b.UnstrippedOutputFile.String() &&
+ a.SymbolicOutputPath.String() == b.SymbolicOutputPath.String()
+ })
+
+ // Copy the symbols files to $PRODUCT_OUT/symbols directory
+ for _, info := range symbolicOutputInfos {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpNoPreserveSymlink,
+ Input: info.UnstrippedOutputFile,
+ Output: info.SymbolicOutputPath,
+ })
+ }
+
+ // Generate the elf mapping textproto file from the copied symbols file
+ for _, info := range symbolicOutputInfos {
+ symbolPath := info.SymbolicOutputPath
+ symbolSubDir := strings.TrimPrefix(filepath.Dir(symbolPath.String()), targetOutUnstripped(ctx).String()+"/")
+ protoBase := filepath.Base(symbolPath.String()) + ".textproto"
+ info.ElfMappingProtoPath = elfSymbolMappingDir(ctx).Join(ctx, symbolSubDir, protoBase)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: elfSymbolsToProto,
+ Input: symbolPath,
+ Output: info.ElfMappingProtoPath,
+ })
+ }
+
+ android.SetProvider(ctx, android.SymbolInfosProvider, symbolicOutputInfos)
+
+ ctx.CheckbuildFile(symbolicOutputInfos.SortedUniqueSymbolicOutputPaths()...)
+ ctx.CheckbuildFile(symbolicOutputInfos.SortedUniqueElfMappingProtoPaths()...)
+}
+
+func (c *Module) collectSymbolsInfo(ctx android.ModuleContext) {
+ if !c.hideApexVariantFromMake && !c.Properties.HideFromMake {
+ infos := &SymbolInfos{}
+ for _, feature := range c.features {
+ infos.AppendSymbols(c.getSymbolInfo(ctx, feature, c.baseSymbolInfo(ctx)))
+ }
+ infos.AppendSymbols(c.getSymbolInfo(ctx, c.compiler, c.baseSymbolInfo(ctx)))
+ infos.AppendSymbols(c.getSymbolInfo(ctx, c.linker, c.baseSymbolInfo(ctx)))
+ if c.sanitize != nil {
+ infos.AppendSymbols(c.getSymbolInfo(ctx, c.sanitize, c.baseSymbolInfo(ctx)))
+ }
+ infos.AppendSymbols(c.getSymbolInfo(ctx, c.installer, c.baseSymbolInfo(ctx)))
+
+ CopySymbolsAndSetSymbolsInfoProvider(ctx, infos)
+ }
+}
+
// Returns true if a stub library could be installed in multiple apexes
func (c *Module) stubLibraryMultipleApexViolation(ctx android.ModuleContext) bool {
// If this is not an apex variant, no check necessary
@@ -2304,6 +2523,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
buildComplianceMetadataInfo(ctx, c, deps)
+ c.checkDoubleLoadableLibraries(ctx)
+
if b, ok := c.compiler.(*baseCompiler); ok {
c.hasAidl = b.hasSrcExt(ctx, ".aidl")
c.hasLex = b.hasSrcExt(ctx, ".l") || b.hasSrcExt(ctx, ".ll")
@@ -2344,6 +2565,26 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
CmakeSnapshotSupported: proptools.Bool(c.Properties.Cmake_snapshot_supported),
HasLlndkStubs: c.HasLlndkStubs(),
DataPaths: c.DataPaths(),
+ VendorAvailable: c.VendorAvailable(),
+ OdmAvailable: c.OdmAvailable(),
+ ProductAvailable: c.ProductAvailable(),
+ SdkMemberTypes: c.sdkMemberTypes,
+ IsVendorPublicLibrary: c.IsVendorPublicLibrary(),
+ DoubleLoadable: Bool(c.VendorProperties.Double_loadable),
+ LocalFlags: LocalOrGlobalFlagsInfo{
+ CommonFlags: c.flags.Local.CommonFlags,
+ CFlags: c.flags.Local.CFlags,
+ ConlyFlags: c.flags.Local.ConlyFlags,
+ CppFlags: c.flags.Local.CppFlags,
+ },
+ GlobalFlags: LocalOrGlobalFlagsInfo{
+ CommonFlags: c.flags.Global.CommonFlags,
+ CFlags: c.flags.Global.CFlags,
+ ConlyFlags: c.flags.Global.ConlyFlags,
+ CppFlags: c.flags.Global.CppFlags,
+ },
+ SystemIncludeFlags: c.flags.SystemIncludeFlags,
+ NoOverrideFlags: c.flags.NoOverrideFlags,
}
if c.compiler != nil {
cflags := c.compiler.baseCompilerProps().Cflags
@@ -2367,21 +2608,34 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if c.linker != nil {
baseLinkerProps := c.linker.baseLinkerProps()
ccInfo.LinkerInfo = &LinkerInfo{
- WholeStaticLibs: baseLinkerProps.Whole_static_libs.GetOrDefault(ctx, nil),
- StaticLibs: baseLinkerProps.Static_libs.GetOrDefault(ctx, nil),
- SharedLibs: baseLinkerProps.Shared_libs.GetOrDefault(ctx, nil),
- HeaderLibs: baseLinkerProps.Header_libs.GetOrDefault(ctx, nil),
+ WholeStaticLibs: baseLinkerProps.Whole_static_libs.GetOrDefault(ctx, nil),
+ StaticLibs: baseLinkerProps.Static_libs.GetOrDefault(ctx, nil),
+ SharedLibs: baseLinkerProps.Shared_libs.GetOrDefault(ctx, nil),
+ HeaderLibs: baseLinkerProps.Header_libs.GetOrDefault(ctx, nil),
+ SystemSharedLibs: baseLinkerProps.System_shared_libs,
}
switch decorator := c.linker.(type) {
case *binaryDecorator:
- ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{}
+ ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{
+ StaticExecutable: decorator.static(),
+ Nocrt: Bool(decorator.baseLinker.Properties.Nocrt),
+ }
case *libraryDecorator:
- lk := c.linker.(*libraryDecorator)
ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{
- InjectBsslHash: Bool(lk.Properties.Inject_bssl_hash),
- NdkSysrootPath: lk.ndkSysrootPath,
- VndkFileName: lk.getLibNameHelper(c.BaseModuleName(), true, false) + ".so",
+ InjectBsslHash: Bool(decorator.Properties.Inject_bssl_hash),
+ NdkSysrootPath: decorator.ndkSysrootPath,
+ VndkFileName: decorator.getLibNameHelper(c.BaseModuleName(), true, false) + ".so",
+ UniqueHostSoname: decorator.Properties.Unique_host_soname,
+ StubsSymbolFilePath: decorator.stubsSymbolFilePath,
}
+ var properties StaticOrSharedProperties
+ if decorator.static() {
+ properties = decorator.StaticProperties.Static
+ } else if decorator.shared() {
+ properties = decorator.SharedProperties.Shared
+ }
+ ccInfo.LinkerInfo.LibraryDecoratorInfo.SharedLibs = properties.Shared_libs.GetOrDefault(ctx, nil)
+ ccInfo.LinkerInfo.LibraryDecoratorInfo.SystemSharedLibs = properties.System_shared_libs
case *testBinary:
ccInfo.LinkerInfo.TestBinaryInfo = &TestBinaryInfo{
Gtest: decorator.testDecorator.gtest(),
@@ -2390,7 +2644,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
ccInfo.LinkerInfo.BenchmarkDecoratorInfo = &BenchmarkDecoratorInfo{}
case *objectLinker:
ccInfo.LinkerInfo.ObjectLinkerInfo = &ObjectLinkerInfo{
- NdkSysrootPath: c.linker.(*objectLinker).ndkSysrootPath,
+ NdkSysrootPath: c.linker.(*objectLinker).ndkSysrootPath,
+ SharedLibs: decorator.Properties.Shared_libs.GetOrDefault(ctx, nil),
+ SystemSharedLibs: decorator.Properties.System_shared_libs,
}
case *stubDecorator:
ccInfo.LinkerInfo.StubDecoratorInfo = &StubDecoratorInfo{}
@@ -2410,12 +2666,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
name := v.ImplementationModuleName(ctx.OtherModuleName(c))
ccInfo.LinkerInfo.ImplementationModuleName = &name
}
-
- c.linker.testSuiteInfo(ctx)
}
if c.library != nil {
ccInfo.LibraryInfo = &LibraryInfo{
- BuildStubs: c.library.BuildStubs(),
+ BuildStubs: c.library.BuildStubs(),
+ AllStubsVersions: c.library.AllStubsVersions(),
}
}
if c.installer != nil {
@@ -2429,13 +2684,66 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
}
}
}
+ if c.stl != nil {
+ ccInfo.StlInfo = &StlInfo{
+ Stl: c.stl.Properties.Stl,
+ }
+ }
+ if c.sanitize != nil {
+ ccInfo.SanitizeInfo = &SanitizeInfo{
+ IsUnsanitizedVariant: c.sanitize.isUnsanitizedVariant(),
+ Sanitize: c.sanitize.Properties.Sanitize,
+ }
+ }
android.SetProvider(ctx, CcInfoProvider, &ccInfo)
+ android.SetProvider(ctx, android.TestSuiteSharedLibsInfoProvider, android.TestSuiteSharedLibsInfo{
+ MakeNames: c.Properties.AndroidMkSharedLibs,
+ })
+
+ // TODO: Refactor MakeLibName so we don't have to fake CommonModuleInfo like this
+ myCommonInfo := android.CommonModuleInfo{
+ BaseModuleName: c.BaseModuleName(),
+ Target: ctx.Target(),
+ }
+ android.SetProvider(ctx, android.MakeNameInfoProvider, android.MakeNameInfo{
+ Name: MakeLibName(&ccInfo, linkableInfo, &myCommonInfo, ctx.ModuleName()),
+ })
+
c.setOutputFiles(ctx)
if c.makeVarsInfo != nil {
android.SetProvider(ctx, CcMakeVarsInfoProvider, c.makeVarsInfo)
}
+
+ if !c.hideApexVariantFromMake && !c.Properties.HideFromMake {
+ c.collectSymbolsInfo(ctx)
+ }
+
+ ctx.FreeModuleAfterGenerateBuildActions()
+}
+
+func (c *Module) CleanupAfterBuildActions() {
+ // Clear as much of Module as possible to reduce memory usage.
+ c.generators = nil
+ c.installer = nil
+ c.features = nil
+ c.coverage = nil
+ c.fuzzer = nil
+ c.sabi = nil
+ c.lto = nil
+ c.afdo = nil
+ c.orderfile = nil
+
+ // TODO: these can be cleared after nativeBinaryInfoProperties and nativeLibInfoProperties are switched to
+ // using providers.
+ // c.linker = nil
+ // c.stl = nil
+ // c.sanitize = nil
+ // c.library = nil
+
+ // TODO: this can be cleared after ccdeps.go is switched to using providers.
+ // c.compiler = nil
}
func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo {
@@ -2445,6 +2753,7 @@ func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableIn
OutputFile: mod.OutputFile(),
UnstrippedOutputFile: mod.UnstrippedOutputFile(),
CoverageOutputFile: mod.CoverageOutputFile(),
+ LinkCoverage: mod.LinkCoverage(),
Partition: mod.Partition(),
IsStubs: mod.IsStubs(),
CcLibrary: mod.CcLibrary(),
@@ -2481,6 +2790,7 @@ func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableIn
info.HasLLNDKStubs = vi.HasLLNDKStubs()
info.IsLLNDKMovedToApex = vi.IsLLNDKMovedToApex()
info.ImplementationModuleName = vi.ImplementationModuleName(mod.BaseModuleName())
+ vi.AllStubsVersions()
}
if !mod.PreventInstall() && fuzz.IsValid(ctx, mod.FuzzModuleStruct()) && mod.IsFuzzModule() {
@@ -3269,14 +3579,15 @@ func checkLinkTypeMutator(ctx android.BottomUpMutatorContext) {
// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
// or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
-func checkDoubleLoadableLibraries(ctx android.BottomUpMutatorContext) {
- check := func(child, parent android.Module) bool {
- to, ok := child.(*Module)
+func (c *Module) checkDoubleLoadableLibraries(ctx android.ModuleContext) {
+ check := func(child, parent android.ModuleProxy) bool {
+ ccInfo, ok := android.OtherModuleProvider(ctx, child, CcInfoProvider)
if !ok {
return false
}
- if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
+ linkableInfo, ok := android.OtherModuleProvider(ctx, child, LinkableInfoProvider)
+ if !ok || !linkableInfo.Shared {
return false
}
@@ -3299,30 +3610,28 @@ func checkDoubleLoadableLibraries(ctx android.BottomUpMutatorContext) {
// Even if target lib has no vendor variant, keep checking dependency
// graph in case it depends on vendor_available or product_available
// but not double_loadable transtively.
- if !to.HasNonSystemVariants() {
+ if !linkableInfo.HasNonSystemVariants {
return true
}
// The happy path. Keep tracking dependencies until we hit a non double-loadable
// one.
- if Bool(to.VendorProperties.Double_loadable) {
+ if ccInfo.DoubleLoadable {
return true
}
- if to.IsLlndk() {
+ if linkableInfo.IsLlndk {
return false
}
ctx.ModuleErrorf("links a library %q which is not LL-NDK, "+
"VNDK-SP, or explicitly marked as 'double_loadable:true'. "+
- "Dependency list: %s", ctx.OtherModuleName(to), ctx.GetPathString(false))
+ "Dependency list: %s", ctx.OtherModuleName(child), ctx.GetPathString(false))
return false
}
- if module, ok := ctx.Module().(*Module); ok {
- if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
- if lib.HasLLNDKStubs() {
- ctx.WalkDeps(check)
- }
+ if lib, ok := c.linker.(*libraryDecorator); ok && lib.shared() {
+ if lib.HasLLNDKStubs() {
+ ctx.WalkDepsProxy(check)
}
}
}
@@ -3444,7 +3753,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
if commonInfo.Target.Os != ctx.Os() {
- ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)", ctx.ModuleName(), ctx.Os().Name, depName, dep.Target().Os.Name)
+ ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)", ctx.ModuleName(), ctx.Os().Name, depName,
+ commonInfo.Target.Os.Name)
return
}
if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
@@ -3749,6 +4059,10 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.GeneratedDeps = android.FirstUniquePaths(depPaths.GeneratedDeps)
depPaths.RustRlibDeps = android.FirstUniqueFunc(depPaths.RustRlibDeps, EqRustRlibDeps)
+ depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Dedup()
+ depPaths.WholeStaticLibsFromPrebuilts = android.FirstUniquePaths(depPaths.WholeStaticLibsFromPrebuilts)
+ depPaths.Objs = depPaths.Objs.Dedup()
+
depPaths.ReexportedDirs = android.FirstUniquePaths(depPaths.ReexportedDirs)
depPaths.ReexportedSystemDirs = android.FirstUniquePaths(depPaths.ReexportedSystemDirs)
depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
@@ -3764,11 +4078,11 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
return depPaths
}
-func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep android.ModuleProxy) bool {
+func ShouldUseStubForApex(ctx android.ModuleContext, parent android.ModuleOrProxy, dep android.ModuleProxy) bool {
inVendorOrProduct := false
bootstrap := false
if android.EqualModules(ctx.Module(), parent) {
- if linkable, ok := parent.(LinkableInterface); !ok {
+ if linkable, ok := ctx.Module().(LinkableInterface); !ok {
ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
} else {
inVendorOrProduct = linkable.InVendorOrProduct()
@@ -4151,14 +4465,6 @@ func installable(c LinkableInterface, apexInfo android.ApexInfo) bool {
return false
}
-func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); ok {
- library.androidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- }
- }
-}
-
var _ android.ApexModule = (*Module)(nil)
// Implements android.ApexModule
diff --git a/cc/cc_gob_enc.go b/cc/cc_gob_enc.go
new file mode 100644
index 000000000..35c003d81
--- /dev/null
+++ b/cc/cc_gob_enc.go
@@ -0,0 +1,2290 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package cc
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ CcMakeVarsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CcMakeVarsInfo) })
+ CcObjectInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CcObjectInfo) })
+ AidlInterfaceInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(AidlInterfaceInfo) })
+ CompilerInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CompilerInfo) })
+ LinkerInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LinkerInfo) })
+ BinaryDecoratorInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(BinaryDecoratorInfo) })
+ LibraryDecoratorInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LibraryDecoratorInfo) })
+ SnapshotInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SnapshotInfo) })
+ TestBinaryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(TestBinaryInfo) })
+ BenchmarkDecoratorInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(BenchmarkDecoratorInfo) })
+ StubDecoratorInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(StubDecoratorInfo) })
+ ObjectLinkerInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ObjectLinkerInfo) })
+ PrebuiltLibraryLinkerInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(PrebuiltLibraryLinkerInfo) })
+ LibraryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LibraryInfo) })
+ InstallerInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(InstallerInfo) })
+ LocalOrGlobalFlagsInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LocalOrGlobalFlagsInfo) })
+ SanitizeInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SanitizeInfo) })
+ StlInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(StlInfo) })
+ CcInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(CcInfo) })
+ LinkableInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LinkableInfo) })
+ InstallPairGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(InstallPair) })
+}
+
+func (r CcMakeVarsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.WarningsAllowed); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.UsingWnoError); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.MissingProfile); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *CcMakeVarsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.WarningsAllowed)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.UsingWnoError)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.MissingProfile)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var CcMakeVarsInfoGobRegId int16
+
+func (r CcMakeVarsInfo) GetTypeId() int16 {
+ return CcMakeVarsInfoGobRegId
+}
+
+func (r CcObjectInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ObjFiles))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.ObjFiles); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.ObjFiles[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.TidyFiles))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.TidyFiles); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.TidyFiles[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.KytheFiles))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.KytheFiles); val3++ {
+ if err = gobtools.EncodeInterface(buf, r.KytheFiles[val3]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *CcObjectInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.ObjFiles = make([]android.Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.ObjFiles[val4] = nil
+ } else {
+ r.ObjFiles[val4] = val6.(android.Path)
+ }
+ }
+ }
+
+ var val9 int32
+ err = gobtools.DecodeSimple[int32](buf, &val9)
+ if err != nil {
+ return err
+ }
+ if val9 > 0 {
+ r.TidyFiles = make([]android.Path, val9)
+ for val10 := 0; val10 < int(val9); val10++ {
+ if val12, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val12 == nil {
+ r.TidyFiles[val10] = nil
+ } else {
+ r.TidyFiles[val10] = val12.(android.Path)
+ }
+ }
+ }
+
+ var val15 int32
+ err = gobtools.DecodeSimple[int32](buf, &val15)
+ if err != nil {
+ return err
+ }
+ if val15 > 0 {
+ r.KytheFiles = make([]android.Path, val15)
+ for val16 := 0; val16 < int(val15); val16++ {
+ if val18, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val18 == nil {
+ r.KytheFiles[val16] = nil
+ } else {
+ r.KytheFiles[val16] = val18.(android.Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var CcObjectInfoGobRegId int16
+
+func (r CcObjectInfo) GetTypeId() int16 {
+ return CcObjectInfoGobRegId
+}
+
+func (r AidlInterfaceInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Sources))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Sources); val1++ {
+ if err = gobtools.EncodeString(buf, r.Sources[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.AidlRoot); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Lang); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Flags))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Flags); val2++ {
+ if err = gobtools.EncodeString(buf, r.Flags[val2]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *AidlInterfaceInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.Sources = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.Sources[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeString(buf, &r.AidlRoot)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Lang)
+ if err != nil {
+ return err
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.Flags = make([]string, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ err = gobtools.DecodeString(buf, &r.Flags[val9])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var AidlInterfaceInfoGobRegId int16
+
+func (r AidlInterfaceInfo) GetTypeId() int16 {
+ return AidlInterfaceInfoGobRegId
+}
+
+func (r CompilerInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Srcs))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.Srcs); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.Srcs[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Cflags))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Cflags); val2++ {
+ if err = gobtools.EncodeString(buf, r.Cflags[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.AidlInterfaceInfo.Encode(buf); err != nil {
+ return err
+ }
+
+ val3 := r.LibraryDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val3); err != nil {
+ return err
+ }
+ if !val3 {
+ if err = (*r.LibraryDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *CompilerInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.Srcs = make([]android.Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.Srcs[val4] = nil
+ } else {
+ r.Srcs[val4] = val6.(android.Path)
+ }
+ }
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.Cflags = make([]string, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ err = gobtools.DecodeString(buf, &r.Cflags[val9])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = r.AidlInterfaceInfo.Decode(buf); err != nil {
+ return err
+ }
+
+ var val13 bool
+ if err = gobtools.DecodeSimple(buf, &val13); err != nil {
+ return err
+ }
+ if !val13 {
+ var val12 LibraryDecoratorInfo
+ if err = val12.Decode(buf); err != nil {
+ return err
+ }
+ r.LibraryDecoratorInfo = &val12
+ }
+
+ return err
+}
+
+var CompilerInfoGobRegId int16
+
+func (r CompilerInfo) GetTypeId() int16 {
+ return CompilerInfoGobRegId
+}
+
+func (r LinkerInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.WholeStaticLibs))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.WholeStaticLibs); val1++ {
+ if err = gobtools.EncodeString(buf, r.WholeStaticLibs[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.StaticLibs))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.StaticLibs); val2++ {
+ if err = gobtools.EncodeString(buf, r.StaticLibs[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SharedLibs))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.SharedLibs); val3++ {
+ if err = gobtools.EncodeString(buf, r.SharedLibs[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.HeaderLibs))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.HeaderLibs); val4++ {
+ if err = gobtools.EncodeString(buf, r.HeaderLibs[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SystemSharedLibs))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.SystemSharedLibs); val5++ {
+ if err = gobtools.EncodeString(buf, r.SystemSharedLibs[val5]); err != nil {
+ return err
+ }
+ }
+
+ val6 := r.ImplementationModuleName == nil
+ if err = gobtools.EncodeSimple(buf, val6); err != nil {
+ return err
+ }
+ if !val6 {
+ if err = gobtools.EncodeString(buf, (*r.ImplementationModuleName)); err != nil {
+ return err
+ }
+ }
+
+ val7 := r.BinaryDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val7); err != nil {
+ return err
+ }
+ if !val7 {
+ if err = (*r.BinaryDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val8 := r.LibraryDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val8); err != nil {
+ return err
+ }
+ if !val8 {
+ if err = (*r.LibraryDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val9 := r.TestBinaryInfo == nil
+ if err = gobtools.EncodeSimple(buf, val9); err != nil {
+ return err
+ }
+ if !val9 {
+ if err = (*r.TestBinaryInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val10 := r.BenchmarkDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val10); err != nil {
+ return err
+ }
+ if !val10 {
+ if err = (*r.BenchmarkDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val11 := r.ObjectLinkerInfo == nil
+ if err = gobtools.EncodeSimple(buf, val11); err != nil {
+ return err
+ }
+ if !val11 {
+ if err = (*r.ObjectLinkerInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val12 := r.StubDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val12); err != nil {
+ return err
+ }
+ if !val12 {
+ if err = (*r.StubDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val13 := r.PrebuiltLibraryLinkerInfo == nil
+ if err = gobtools.EncodeSimple(buf, val13); err != nil {
+ return err
+ }
+ if !val13 {
+ if err = (*r.PrebuiltLibraryLinkerInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *LinkerInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.WholeStaticLibs = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.WholeStaticLibs[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ r.StaticLibs = make([]string, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ err = gobtools.DecodeString(buf, &r.StaticLibs[val7])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val10 int32
+ err = gobtools.DecodeSimple[int32](buf, &val10)
+ if err != nil {
+ return err
+ }
+ if val10 > 0 {
+ r.SharedLibs = make([]string, val10)
+ for val11 := 0; val11 < int(val10); val11++ {
+ err = gobtools.DecodeString(buf, &r.SharedLibs[val11])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val14 int32
+ err = gobtools.DecodeSimple[int32](buf, &val14)
+ if err != nil {
+ return err
+ }
+ if val14 > 0 {
+ r.HeaderLibs = make([]string, val14)
+ for val15 := 0; val15 < int(val14); val15++ {
+ err = gobtools.DecodeString(buf, &r.HeaderLibs[val15])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val18 int32
+ err = gobtools.DecodeSimple[int32](buf, &val18)
+ if err != nil {
+ return err
+ }
+ if val18 > 0 {
+ r.SystemSharedLibs = make([]string, val18)
+ for val19 := 0; val19 < int(val18); val19++ {
+ err = gobtools.DecodeString(buf, &r.SystemSharedLibs[val19])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val22 bool
+ if err = gobtools.DecodeSimple(buf, &val22); err != nil {
+ return err
+ }
+ if !val22 {
+ var val21 string
+ err = gobtools.DecodeString(buf, &val21)
+ if err != nil {
+ return err
+ }
+ r.ImplementationModuleName = &val21
+ }
+
+ var val25 bool
+ if err = gobtools.DecodeSimple(buf, &val25); err != nil {
+ return err
+ }
+ if !val25 {
+ var val24 BinaryDecoratorInfo
+ if err = val24.Decode(buf); err != nil {
+ return err
+ }
+ r.BinaryDecoratorInfo = &val24
+ }
+
+ var val28 bool
+ if err = gobtools.DecodeSimple(buf, &val28); err != nil {
+ return err
+ }
+ if !val28 {
+ var val27 LibraryDecoratorInfo
+ if err = val27.Decode(buf); err != nil {
+ return err
+ }
+ r.LibraryDecoratorInfo = &val27
+ }
+
+ var val31 bool
+ if err = gobtools.DecodeSimple(buf, &val31); err != nil {
+ return err
+ }
+ if !val31 {
+ var val30 TestBinaryInfo
+ if err = val30.Decode(buf); err != nil {
+ return err
+ }
+ r.TestBinaryInfo = &val30
+ }
+
+ var val34 bool
+ if err = gobtools.DecodeSimple(buf, &val34); err != nil {
+ return err
+ }
+ if !val34 {
+ var val33 BenchmarkDecoratorInfo
+ if err = val33.Decode(buf); err != nil {
+ return err
+ }
+ r.BenchmarkDecoratorInfo = &val33
+ }
+
+ var val37 bool
+ if err = gobtools.DecodeSimple(buf, &val37); err != nil {
+ return err
+ }
+ if !val37 {
+ var val36 ObjectLinkerInfo
+ if err = val36.Decode(buf); err != nil {
+ return err
+ }
+ r.ObjectLinkerInfo = &val36
+ }
+
+ var val40 bool
+ if err = gobtools.DecodeSimple(buf, &val40); err != nil {
+ return err
+ }
+ if !val40 {
+ var val39 StubDecoratorInfo
+ if err = val39.Decode(buf); err != nil {
+ return err
+ }
+ r.StubDecoratorInfo = &val39
+ }
+
+ var val43 bool
+ if err = gobtools.DecodeSimple(buf, &val43); err != nil {
+ return err
+ }
+ if !val43 {
+ var val42 PrebuiltLibraryLinkerInfo
+ if err = val42.Decode(buf); err != nil {
+ return err
+ }
+ r.PrebuiltLibraryLinkerInfo = &val42
+ }
+
+ return err
+}
+
+var LinkerInfoGobRegId int16
+
+func (r LinkerInfo) GetTypeId() int16 {
+ return LinkerInfoGobRegId
+}
+
+func (r BinaryDecoratorInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.StaticExecutable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Nocrt); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *BinaryDecoratorInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.StaticExecutable)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Nocrt)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var BinaryDecoratorInfoGobRegId int16
+
+func (r BinaryDecoratorInfo) GetTypeId() int16 {
+ return BinaryDecoratorInfoGobRegId
+}
+
+func (r LibraryDecoratorInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExportIncludeDirs))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.ExportIncludeDirs); val1++ {
+ if err = gobtools.EncodeString(buf, r.ExportIncludeDirs[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InjectBsslHash); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.NdkSysrootPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.VndkFileName); err != nil {
+ return err
+ }
+
+ val2 := r.UniqueHostSoname == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = gobtools.EncodeSimple(buf, (*r.UniqueHostSoname)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SharedLibs))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.SharedLibs); val3++ {
+ if err = gobtools.EncodeString(buf, r.SharedLibs[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SystemSharedLibs))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.SystemSharedLibs); val4++ {
+ if err = gobtools.EncodeString(buf, r.SystemSharedLibs[val4]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.StubsSymbolFilePath); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *LibraryDecoratorInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.ExportIncludeDirs = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.ExportIncludeDirs[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InjectBsslHash)
+ if err != nil {
+ return err
+ }
+
+ if val7, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val7 == nil {
+ r.NdkSysrootPath = nil
+ } else {
+ r.NdkSysrootPath = val7.(android.Path)
+ }
+
+ err = gobtools.DecodeString(buf, &r.VndkFileName)
+ if err != nil {
+ return err
+ }
+
+ var val10 bool
+ if err = gobtools.DecodeSimple(buf, &val10); err != nil {
+ return err
+ }
+ if !val10 {
+ var val9 bool
+ err = gobtools.DecodeSimple[bool](buf, &val9)
+ if err != nil {
+ return err
+ }
+ r.UniqueHostSoname = &val9
+ }
+
+ var val13 int32
+ err = gobtools.DecodeSimple[int32](buf, &val13)
+ if err != nil {
+ return err
+ }
+ if val13 > 0 {
+ r.SharedLibs = make([]string, val13)
+ for val14 := 0; val14 < int(val13); val14++ {
+ err = gobtools.DecodeString(buf, &r.SharedLibs[val14])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val17 int32
+ err = gobtools.DecodeSimple[int32](buf, &val17)
+ if err != nil {
+ return err
+ }
+ if val17 > 0 {
+ r.SystemSharedLibs = make([]string, val17)
+ for val18 := 0; val18 < int(val17); val18++ {
+ err = gobtools.DecodeString(buf, &r.SystemSharedLibs[val18])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if val21, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val21 == nil {
+ r.StubsSymbolFilePath = nil
+ } else {
+ r.StubsSymbolFilePath = val21.(android.Path)
+ }
+
+ return err
+}
+
+var LibraryDecoratorInfoGobRegId int16
+
+func (r LibraryDecoratorInfo) GetTypeId() int16 {
+ return LibraryDecoratorInfoGobRegId
+}
+
+func (r SnapshotInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.SnapshotAndroidMkSuffix); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *SnapshotInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.SnapshotAndroidMkSuffix)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var SnapshotInfoGobRegId int16
+
+func (r SnapshotInfo) GetTypeId() int16 {
+ return SnapshotInfoGobRegId
+}
+
+func (r TestBinaryInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.Gtest); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *TestBinaryInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Gtest)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var TestBinaryInfoGobRegId int16
+
+func (r TestBinaryInfo) GetTypeId() int16 {
+ return TestBinaryInfoGobRegId
+}
+
+func (r BenchmarkDecoratorInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+ return err
+}
+
+func (r *BenchmarkDecoratorInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ return err
+}
+
+var BenchmarkDecoratorInfoGobRegId int16
+
+func (r BenchmarkDecoratorInfo) GetTypeId() int16 {
+ return BenchmarkDecoratorInfoGobRegId
+}
+
+func (r StubDecoratorInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.AbiDumpPath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HasAbiDump); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.AbiDiffPaths))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.AbiDiffPaths); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.AbiDiffPaths[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.InstallPath); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *StubDecoratorInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.AbiDumpPath.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HasAbiDump)
+ if err != nil {
+ return err
+ }
+
+ var val5 int32
+ err = gobtools.DecodeSimple[int32](buf, &val5)
+ if err != nil {
+ return err
+ }
+ if val5 > 0 {
+ r.AbiDiffPaths = make([]android.Path, val5)
+ for val6 := 0; val6 < int(val5); val6++ {
+ if val8, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val8 == nil {
+ r.AbiDiffPaths[val6] = nil
+ } else {
+ r.AbiDiffPaths[val6] = val8.(android.Path)
+ }
+ }
+ }
+
+ if val10, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val10 == nil {
+ r.InstallPath = nil
+ } else {
+ r.InstallPath = val10.(android.Path)
+ }
+
+ return err
+}
+
+var StubDecoratorInfoGobRegId int16
+
+func (r StubDecoratorInfo) GetTypeId() int16 {
+ return StubDecoratorInfoGobRegId
+}
+
+func (r ObjectLinkerInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.NdkSysrootPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SharedLibs))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.SharedLibs); val1++ {
+ if err = gobtools.EncodeString(buf, r.SharedLibs[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SystemSharedLibs))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.SystemSharedLibs); val2++ {
+ if err = gobtools.EncodeString(buf, r.SystemSharedLibs[val2]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *ObjectLinkerInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.NdkSysrootPath = nil
+ } else {
+ r.NdkSysrootPath = val2.(android.Path)
+ }
+
+ var val4 int32
+ err = gobtools.DecodeSimple[int32](buf, &val4)
+ if err != nil {
+ return err
+ }
+ if val4 > 0 {
+ r.SharedLibs = make([]string, val4)
+ for val5 := 0; val5 < int(val4); val5++ {
+ err = gobtools.DecodeString(buf, &r.SharedLibs[val5])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.SystemSharedLibs = make([]string, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ err = gobtools.DecodeString(buf, &r.SystemSharedLibs[val9])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var ObjectLinkerInfoGobRegId int16
+
+func (r ObjectLinkerInfo) GetTypeId() int16 {
+ return ObjectLinkerInfoGobRegId
+}
+
+func (r PrebuiltLibraryLinkerInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, r.VndkFileName); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *PrebuiltLibraryLinkerInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeString(buf, &r.VndkFileName)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var PrebuiltLibraryLinkerInfoGobRegId int16
+
+func (r PrebuiltLibraryLinkerInfo) GetTypeId() int16 {
+ return PrebuiltLibraryLinkerInfoGobRegId
+}
+
+func (r LibraryInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.BuildStubs); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.AllStubsVersions))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.AllStubsVersions); val1++ {
+ if err = gobtools.EncodeString(buf, r.AllStubsVersions[val1]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *LibraryInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.BuildStubs)
+ if err != nil {
+ return err
+ }
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.AllStubsVersions = make([]string, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ err = gobtools.DecodeString(buf, &r.AllStubsVersions[val4])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var LibraryInfoGobRegId int16
+
+func (r LibraryInfo) GetTypeId() int16 {
+ return LibraryInfoGobRegId
+}
+
+func (r InstallerInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ val1 := r.StubDecoratorInfo == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = (*r.StubDecoratorInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *InstallerInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 bool
+ if err = gobtools.DecodeSimple(buf, &val2); err != nil {
+ return err
+ }
+ if !val2 {
+ var val1 StubDecoratorInfo
+ if err = val1.Decode(buf); err != nil {
+ return err
+ }
+ r.StubDecoratorInfo = &val1
+ }
+
+ return err
+}
+
+var InstallerInfoGobRegId int16
+
+func (r InstallerInfo) GetTypeId() int16 {
+ return InstallerInfoGobRegId
+}
+
+func (r LocalOrGlobalFlagsInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CommonFlags))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.CommonFlags); val1++ {
+ if err = gobtools.EncodeString(buf, r.CommonFlags[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CFlags))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.CFlags); val2++ {
+ if err = gobtools.EncodeString(buf, r.CFlags[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ConlyFlags))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.ConlyFlags); val3++ {
+ if err = gobtools.EncodeString(buf, r.ConlyFlags[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CppFlags))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.CppFlags); val4++ {
+ if err = gobtools.EncodeString(buf, r.CppFlags[val4]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *LocalOrGlobalFlagsInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 int32
+ err = gobtools.DecodeSimple[int32](buf, &val2)
+ if err != nil {
+ return err
+ }
+ if val2 > 0 {
+ r.CommonFlags = make([]string, val2)
+ for val3 := 0; val3 < int(val2); val3++ {
+ err = gobtools.DecodeString(buf, &r.CommonFlags[val3])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val6 int32
+ err = gobtools.DecodeSimple[int32](buf, &val6)
+ if err != nil {
+ return err
+ }
+ if val6 > 0 {
+ r.CFlags = make([]string, val6)
+ for val7 := 0; val7 < int(val6); val7++ {
+ err = gobtools.DecodeString(buf, &r.CFlags[val7])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val10 int32
+ err = gobtools.DecodeSimple[int32](buf, &val10)
+ if err != nil {
+ return err
+ }
+ if val10 > 0 {
+ r.ConlyFlags = make([]string, val10)
+ for val11 := 0; val11 < int(val10); val11++ {
+ err = gobtools.DecodeString(buf, &r.ConlyFlags[val11])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val14 int32
+ err = gobtools.DecodeSimple[int32](buf, &val14)
+ if err != nil {
+ return err
+ }
+ if val14 > 0 {
+ r.CppFlags = make([]string, val14)
+ for val15 := 0; val15 < int(val14); val15++ {
+ err = gobtools.DecodeString(buf, &r.CppFlags[val15])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var LocalOrGlobalFlagsInfoGobRegId int16
+
+func (r LocalOrGlobalFlagsInfo) GetTypeId() int16 {
+ return LocalOrGlobalFlagsInfoGobRegId
+}
+
+func (r SanitizeInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.IsUnsanitizedVariant); err != nil {
+ return err
+ }
+
+ if err = r.Sanitize.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *SanitizeInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsUnsanitizedVariant)
+ if err != nil {
+ return err
+ }
+
+ if err = r.Sanitize.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var SanitizeInfoGobRegId int16
+
+func (r SanitizeInfo) GetTypeId() int16 {
+ return SanitizeInfoGobRegId
+}
+
+func (r StlInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ val1 := r.Stl == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = gobtools.EncodeString(buf, (*r.Stl)); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *StlInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 bool
+ if err = gobtools.DecodeSimple(buf, &val2); err != nil {
+ return err
+ }
+ if !val2 {
+ var val1 string
+ err = gobtools.DecodeString(buf, &val1)
+ if err != nil {
+ return err
+ }
+ r.Stl = &val1
+ }
+
+ return err
+}
+
+var StlInfoGobRegId int16
+
+func (r StlInfo) GetTypeId() int16 {
+ return StlInfoGobRegId
+}
+
+func (r CcInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.IsPrebuilt); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.CmakeSnapshotSupported); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HasLlndkStubs); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.DataPaths))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.DataPaths); val1++ {
+ if err = r.DataPaths[val1].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.VendorAvailable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.OdmAvailable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.ProductAvailable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsVendorPublicLibrary); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.DoubleLoadable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SdkMemberTypes))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.SdkMemberTypes); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.SdkMemberTypes[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.LocalFlags.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.GlobalFlags.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SystemIncludeFlags))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.SystemIncludeFlags); val3++ {
+ if err = gobtools.EncodeString(buf, r.SystemIncludeFlags[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.NoOverrideFlags))); err != nil {
+ return err
+ }
+ for val4 := 0; val4 < len(r.NoOverrideFlags); val4++ {
+ if err = gobtools.EncodeString(buf, r.NoOverrideFlags[val4]); err != nil {
+ return err
+ }
+ }
+
+ val5 := r.CompilerInfo == nil
+ if err = gobtools.EncodeSimple(buf, val5); err != nil {
+ return err
+ }
+ if !val5 {
+ if err = (*r.CompilerInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val6 := r.LinkerInfo == nil
+ if err = gobtools.EncodeSimple(buf, val6); err != nil {
+ return err
+ }
+ if !val6 {
+ if err = (*r.LinkerInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val7 := r.SnapshotInfo == nil
+ if err = gobtools.EncodeSimple(buf, val7); err != nil {
+ return err
+ }
+ if !val7 {
+ if err = (*r.SnapshotInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val8 := r.LibraryInfo == nil
+ if err = gobtools.EncodeSimple(buf, val8); err != nil {
+ return err
+ }
+ if !val8 {
+ if err = (*r.LibraryInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val9 := r.InstallerInfo == nil
+ if err = gobtools.EncodeSimple(buf, val9); err != nil {
+ return err
+ }
+ if !val9 {
+ if err = (*r.InstallerInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val10 := r.StlInfo == nil
+ if err = gobtools.EncodeSimple(buf, val10); err != nil {
+ return err
+ }
+ if !val10 {
+ if err = (*r.StlInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ val11 := r.SanitizeInfo == nil
+ if err = gobtools.EncodeSimple(buf, val11); err != nil {
+ return err
+ }
+ if !val11 {
+ if err = (*r.SanitizeInfo).Encode(buf); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *CcInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsPrebuilt)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.CmakeSnapshotSupported)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HasLlndkStubs)
+ if err != nil {
+ return err
+ }
+
+ var val5 int32
+ err = gobtools.DecodeSimple[int32](buf, &val5)
+ if err != nil {
+ return err
+ }
+ if val5 > 0 {
+ r.DataPaths = make([]android.DataPath, val5)
+ for val6 := 0; val6 < int(val5); val6++ {
+ if err = r.DataPaths[val6].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.VendorAvailable)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.OdmAvailable)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.ProductAvailable)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsVendorPublicLibrary)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.DoubleLoadable)
+ if err != nil {
+ return err
+ }
+
+ var val14 int32
+ err = gobtools.DecodeSimple[int32](buf, &val14)
+ if err != nil {
+ return err
+ }
+ if val14 > 0 {
+ r.SdkMemberTypes = make([]android.SdkMemberType, val14)
+ for val15 := 0; val15 < int(val14); val15++ {
+ if val17, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val17 == nil {
+ r.SdkMemberTypes[val15] = nil
+ } else {
+ r.SdkMemberTypes[val15] = val17.(android.SdkMemberType)
+ }
+ }
+ }
+
+ if err = r.LocalFlags.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.GlobalFlags.Decode(buf); err != nil {
+ return err
+ }
+
+ var val21 int32
+ err = gobtools.DecodeSimple[int32](buf, &val21)
+ if err != nil {
+ return err
+ }
+ if val21 > 0 {
+ r.SystemIncludeFlags = make([]string, val21)
+ for val22 := 0; val22 < int(val21); val22++ {
+ err = gobtools.DecodeString(buf, &r.SystemIncludeFlags[val22])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val25 int32
+ err = gobtools.DecodeSimple[int32](buf, &val25)
+ if err != nil {
+ return err
+ }
+ if val25 > 0 {
+ r.NoOverrideFlags = make([]string, val25)
+ for val26 := 0; val26 < int(val25); val26++ {
+ err = gobtools.DecodeString(buf, &r.NoOverrideFlags[val26])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val29 bool
+ if err = gobtools.DecodeSimple(buf, &val29); err != nil {
+ return err
+ }
+ if !val29 {
+ var val28 CompilerInfo
+ if err = val28.Decode(buf); err != nil {
+ return err
+ }
+ r.CompilerInfo = &val28
+ }
+
+ var val32 bool
+ if err = gobtools.DecodeSimple(buf, &val32); err != nil {
+ return err
+ }
+ if !val32 {
+ var val31 LinkerInfo
+ if err = val31.Decode(buf); err != nil {
+ return err
+ }
+ r.LinkerInfo = &val31
+ }
+
+ var val35 bool
+ if err = gobtools.DecodeSimple(buf, &val35); err != nil {
+ return err
+ }
+ if !val35 {
+ var val34 SnapshotInfo
+ if err = val34.Decode(buf); err != nil {
+ return err
+ }
+ r.SnapshotInfo = &val34
+ }
+
+ var val38 bool
+ if err = gobtools.DecodeSimple(buf, &val38); err != nil {
+ return err
+ }
+ if !val38 {
+ var val37 LibraryInfo
+ if err = val37.Decode(buf); err != nil {
+ return err
+ }
+ r.LibraryInfo = &val37
+ }
+
+ var val41 bool
+ if err = gobtools.DecodeSimple(buf, &val41); err != nil {
+ return err
+ }
+ if !val41 {
+ var val40 InstallerInfo
+ if err = val40.Decode(buf); err != nil {
+ return err
+ }
+ r.InstallerInfo = &val40
+ }
+
+ var val44 bool
+ if err = gobtools.DecodeSimple(buf, &val44); err != nil {
+ return err
+ }
+ if !val44 {
+ var val43 StlInfo
+ if err = val43.Decode(buf); err != nil {
+ return err
+ }
+ r.StlInfo = &val43
+ }
+
+ var val47 bool
+ if err = gobtools.DecodeSimple(buf, &val47); err != nil {
+ return err
+ }
+ if !val47 {
+ var val46 SanitizeInfo
+ if err = val46.Decode(buf); err != nil {
+ return err
+ }
+ r.SanitizeInfo = &val46
+ }
+
+ return err
+}
+
+var CcInfoGobRegId int16
+
+func (r CcInfo) GetTypeId() int16 {
+ return CcInfoGobRegId
+}
+
+func (r LinkableInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.StaticExecutable); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Static); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Shared); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Header); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HasStubsVariants); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.StubsVersion); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsStubs); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.UnstrippedOutputFile); err != nil {
+ return err
+ }
+
+ if err = r.OutputFile.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.CoverageFiles))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.CoverageFiles); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.CoverageFiles[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.CoverageOutputFile.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.LinkCoverage); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.SAbiDumpFiles))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.SAbiDumpFiles); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.SAbiDumpFiles[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.Partition); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.CcLibrary); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.CcLibraryInterface); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.RustLibraryInterface); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.CrateName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.ExportedCrateLinkDirs))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.ExportedCrateLinkDirs); val3++ {
+ if err = gobtools.EncodeString(buf, r.ExportedCrateLinkDirs[val3]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HasNonSystemVariants); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsLlndk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsNdk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InVendorOrProduct); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.SubName); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InRamdisk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.OnlyInRamdisk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InVendorRamdisk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.OnlyInVendorRamdisk); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InRecovery); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.OnlyInRecovery); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.InVendor); err != nil {
+ return err
+ }
+
+ val4 := r.Installable == nil
+ if err = gobtools.EncodeSimple(buf, val4); err != nil {
+ return err
+ }
+ if !val4 {
+ if err = gobtools.EncodeSimple(buf, (*r.Installable)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeString(buf, r.RelativeInstallPath); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.RustApexExclude); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Bootstrap); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.Multilib); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.ImplementationModuleNameForMake); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsStubsImplementationRequired); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Symlinks))); err != nil {
+ return err
+ }
+ for val5 := 0; val5 < len(r.Symlinks); val5++ {
+ if err = gobtools.EncodeString(buf, r.Symlinks[val5]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.APIListCoverageXMLPath.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.FuzzSharedLibraries))); err != nil {
+ return err
+ }
+ for val6 := 0; val6 < len(r.FuzzSharedLibraries); val6++ {
+ if err = r.FuzzSharedLibraries[val6].Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsVndkPrebuiltLibrary); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.HasLLNDKStubs); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsLLNDKMovedToApex); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, r.ImplementationModuleName); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *LinkableInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.StaticExecutable)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Static)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Shared)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Header)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HasStubsVariants)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.StubsVersion)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsStubs)
+ if err != nil {
+ return err
+ }
+
+ if val9, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val9 == nil {
+ r.UnstrippedOutputFile = nil
+ } else {
+ r.UnstrippedOutputFile = val9.(android.Path)
+ }
+
+ if err = r.OutputFile.Decode(buf); err != nil {
+ return err
+ }
+
+ var val13 int32
+ err = gobtools.DecodeSimple[int32](buf, &val13)
+ if err != nil {
+ return err
+ }
+ if val13 > 0 {
+ r.CoverageFiles = make([]android.Path, val13)
+ for val14 := 0; val14 < int(val13); val14++ {
+ if val16, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val16 == nil {
+ r.CoverageFiles[val14] = nil
+ } else {
+ r.CoverageFiles[val14] = val16.(android.Path)
+ }
+ }
+ }
+
+ if err = r.CoverageOutputFile.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.LinkCoverage)
+ if err != nil {
+ return err
+ }
+
+ var val21 int32
+ err = gobtools.DecodeSimple[int32](buf, &val21)
+ if err != nil {
+ return err
+ }
+ if val21 > 0 {
+ r.SAbiDumpFiles = make([]android.Path, val21)
+ for val22 := 0; val22 < int(val21); val22++ {
+ if val24, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val24 == nil {
+ r.SAbiDumpFiles[val22] = nil
+ } else {
+ r.SAbiDumpFiles[val22] = val24.(android.Path)
+ }
+ }
+ }
+
+ err = gobtools.DecodeString(buf, &r.Partition)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.CcLibrary)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.CcLibraryInterface)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.RustLibraryInterface)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.CrateName)
+ if err != nil {
+ return err
+ }
+
+ var val31 int32
+ err = gobtools.DecodeSimple[int32](buf, &val31)
+ if err != nil {
+ return err
+ }
+ if val31 > 0 {
+ r.ExportedCrateLinkDirs = make([]string, val31)
+ for val32 := 0; val32 < int(val31); val32++ {
+ err = gobtools.DecodeString(buf, &r.ExportedCrateLinkDirs[val32])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HasNonSystemVariants)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsLlndk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsNdk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InVendorOrProduct)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.SubName)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InRamdisk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.OnlyInRamdisk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InVendorRamdisk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.OnlyInVendorRamdisk)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InRecovery)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.OnlyInRecovery)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.InVendor)
+ if err != nil {
+ return err
+ }
+
+ var val47 bool
+ if err = gobtools.DecodeSimple(buf, &val47); err != nil {
+ return err
+ }
+ if !val47 {
+ var val46 bool
+ err = gobtools.DecodeSimple[bool](buf, &val46)
+ if err != nil {
+ return err
+ }
+ r.Installable = &val46
+ }
+
+ err = gobtools.DecodeString(buf, &r.RelativeInstallPath)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.RustApexExclude)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Bootstrap)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.Multilib)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.ImplementationModuleNameForMake)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsStubsImplementationRequired)
+ if err != nil {
+ return err
+ }
+
+ var val56 int32
+ err = gobtools.DecodeSimple[int32](buf, &val56)
+ if err != nil {
+ return err
+ }
+ if val56 > 0 {
+ r.Symlinks = make([]string, val56)
+ for val57 := 0; val57 < int(val56); val57++ {
+ err = gobtools.DecodeString(buf, &r.Symlinks[val57])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if err = r.APIListCoverageXMLPath.Decode(buf); err != nil {
+ return err
+ }
+
+ var val62 int32
+ err = gobtools.DecodeSimple[int32](buf, &val62)
+ if err != nil {
+ return err
+ }
+ if val62 > 0 {
+ r.FuzzSharedLibraries = make([]InstallPair, val62)
+ for val63 := 0; val63 < int(val62); val63++ {
+ if err = r.FuzzSharedLibraries[val63].Decode(buf); err != nil {
+ return err
+ }
+ }
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsVndkPrebuiltLibrary)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.HasLLNDKStubs)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsLLNDKMovedToApex)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeString(buf, &r.ImplementationModuleName)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var LinkableInfoGobRegId int16
+
+func (r LinkableInfo) GetTypeId() int16 {
+ return LinkableInfoGobRegId
+}
+
+func (r InstallPair) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.Src); err != nil {
+ return err
+ }
+
+ if err = r.Dst.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *InstallPair) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.Src = nil
+ } else {
+ r.Src = val2.(android.Path)
+ }
+
+ if err = r.Dst.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var InstallPairGobRegId int16
+
+func (r InstallPair) GetTypeId() int16 {
+ return InstallPairGobRegId
+}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7240ea587..e9d2474ac 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -26,8 +26,6 @@ import (
"android/soong/aidl_library"
"android/soong/android"
-
- "github.com/google/blueprint"
)
func init() {
@@ -3124,17 +3122,6 @@ func TestImageVariants(t *testing.T) {
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- hasDep := func(m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
testDepWithVariant := func(imageVariant string) {
imageVariantStr := ""
if imageVariant != "core" {
@@ -3142,7 +3129,8 @@ func TestImageVariants(t *testing.T) {
}
binFooModule := ctx.ModuleForTests(t, "binfoo", "android"+imageVariantStr+"_arm64_armv8-a").Module()
libBarModule := ctx.ModuleForTests(t, "libbar", "android"+imageVariantStr+"_arm64_armv8-a_shared").Module()
- android.AssertBoolEquals(t, "binfoo should have dependency on libbar with image variant "+imageVariant, true, hasDep(binFooModule, libBarModule))
+ android.AssertBoolEquals(t, "binfoo should have dependency on libbar with image variant "+imageVariant, true,
+ android.HasDirectDep(ctx, binFooModule, libBarModule))
}
testDepWithVariant("core")
diff --git a/cc/cc_test_only_property_test.go b/cc/cc_test_only_property_test.go
index a178cad68..fe4fb56a2 100644
--- a/cc/cc_test_only_property_test.go
+++ b/cc/cc_test_only_property_test.go
@@ -15,13 +15,13 @@
package cc
import (
- "android/soong/android"
- "android/soong/android/team_proto"
"log"
"strings"
"testing"
- "github.com/google/blueprint"
+ "android/soong/android"
+ "android/soong/android/team_proto"
+
"google.golang.org/protobuf/proto"
)
@@ -56,7 +56,7 @@ func TestTestOnlyProvider(t *testing.T) {
// marked as test-only are marked as test-only.
actualTestOnly := []string{}
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m android.Module) {
if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
if provider.TestOnly {
actualTestOnly = append(actualTestOnly, m.Name())
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
index 4247778e8..fefd57f91 100644
--- a/cc/ccdeps.go
+++ b/cc/ccdeps.go
@@ -90,10 +90,10 @@ func (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon
moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang)
moduleDeps.Cpp_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cppClang)
- ctx.VisitAllModules(func(module android.Module) {
- if ccModule, ok := module.(*Module); ok {
- if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
- generateCLionProjectData(ctx, compiledModule, ccModule, bestVariantFound, moduleInfos)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if ccModule, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if ccModule.CompilerInfo != nil {
+ generateCLionProjectData(ctx, module, ccModule, bestVariantFound, moduleInfos)
}
}
})
@@ -169,11 +169,12 @@ func parseCompilerCCParameters(ctx android.SingletonContext, params []string) cc
return compilerParams
}
-func generateCLionProjectData(ctx android.SingletonContext, compiledModule CompiledInterface,
- ccModule *Module, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) {
- moduleName := ccModule.ModuleBase.Name()
- srcs := compiledModule.Srcs()
-
+func generateCLionProjectData(ctx android.SingletonContext, module android.ModuleProxy,
+ ccModule *CcInfo, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) {
+ commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ moduleName := commonInfo.BaseModuleName
+ srcs := ccModule.CompilerInfo.Srcs
+ target := commonInfo.Target
// Skip if best variant has already been found.
if bestVariantFound[moduleName] {
return
@@ -185,7 +186,7 @@ func generateCLionProjectData(ctx android.SingletonContext, compiledModule Compi
}
// Check if device arch matches, in which case this is the best variant and takes precedence.
- if ccModule.Device() && ccModule.ModuleBase.Arch().ArchType.Name == ctx.DeviceConfig().DeviceArch() {
+ if target.Os.Class == android.Device && target.Arch.ArchType.Name == ctx.DeviceConfig().DeviceArch() {
bestVariantFound[moduleName] = true
} else if _, ok := moduleInfos[moduleName]; ok {
// Skip because this isn't the best variant and a previous one has already been added.
@@ -195,20 +196,20 @@ func generateCLionProjectData(ctx android.SingletonContext, compiledModule Compi
dpInfo := ccIdeInfo{}
- dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(ccModule)))
+ dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(module)))
dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...)
dpInfo.Path = android.FirstUniqueStrings(dpInfo.Path)
dpInfo.Srcs = android.FirstUniqueStrings(dpInfo.Srcs)
- dpInfo.Global_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CommonFlags)
- dpInfo.Local_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CommonFlags)
- dpInfo.Global_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CFlags)
- dpInfo.Local_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CFlags)
- dpInfo.Global_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.ConlyFlags)
- dpInfo.Local_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.ConlyFlags)
- dpInfo.Global_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CppFlags)
- dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CppFlags)
- dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.flags.SystemIncludeFlags)
+ dpInfo.Global_Common_Flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CommonFlags)
+ dpInfo.Local_Common_Flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CommonFlags)
+ dpInfo.Global_C_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CFlags)
+ dpInfo.Local_C_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CFlags)
+ dpInfo.Global_C_only_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.ConlyFlags)
+ dpInfo.Local_C_only_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.ConlyFlags)
+ dpInfo.Global_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CppFlags)
+ dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CppFlags)
+ dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.SystemIncludeFlags)
dpInfo.Module_name = moduleName
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
index 3f6a01d1b..c51fa10dd 100644
--- a/cc/cmake_snapshot.go
+++ b/cc/cmake_snapshot.go
@@ -503,6 +503,10 @@ func (m *CmakeSnapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
zipRule.Build(m.zipPath.String(), "archiving "+ctx.ModuleName())
ctx.SetOutputFiles(android.Paths{m.zipPath}, "")
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"DATA"}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (m *CmakeSnapshot) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index 0f3f02da5..c2bd17ad9 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -16,12 +16,12 @@ package cc
import (
"fmt"
-
- "android/soong/android"
"os"
"path"
"path/filepath"
"strings"
+
+ "android/soong/android"
)
// This singleton generates CMakeLists.txt files. It does so for each blueprint Android.bp resulting in a cc.Module
@@ -65,10 +65,10 @@ func (c *cmakelistsGeneratorSingleton) GenerateBuildActions(ctx android.Singleto
// variant for each project.
seenProjects := map[string]bool{}
- ctx.VisitAllModules(func(module android.Module) {
- if ccModule, ok := module.(*Module); ok {
- if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
- generateCLionProject(compiledModule, ctx, ccModule, seenProjects)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if ccModule, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if ccModule.CompilerInfo != nil {
+ generateCLionProject(ctx, module, ccModule, seenProjects)
}
}
})
@@ -117,15 +117,15 @@ func linkAggregateCMakeListsFiles(path string, info os.FileInfo, err error) erro
return nil
}
-func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module,
+func generateCLionProject(ctx android.SingletonContext, module android.ModuleProxy, ccModule *CcInfo,
seenProjects map[string]bool) {
- srcs := compiledModule.Srcs()
+ srcs := ccModule.CompilerInfo.Srcs
if len(srcs) == 0 {
return
}
// Only write CMakeLists.txt for the first variant of each architecture of each module
- clionprojectLocation := getCMakeListsForModule(ccModule, ctx)
+ clionprojectLocation := getCMakeListsForModule(ctx, module)
if seenProjects[clionprojectLocation] {
return
}
@@ -146,7 +146,7 @@ func generateCLionProject(compiledModule CompiledInterface, ctx android.Singleto
f.WriteString("# To improve project view in Clion :\n")
f.WriteString("# Tools > CMake > Change Project Root \n\n")
f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported))
- f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
+ f.WriteString(fmt.Sprintf("project(%s)\n", module.Name()))
f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", android.AbsSrcDirForExistingUseCases()))
pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
@@ -163,44 +163,44 @@ func generateCLionProject(compiledModule CompiledInterface, ctx android.Singleto
// Add all header search path and compiler parameters (-D, -W, -f, -XXXX)
f.WriteString("\n# GLOBAL ALL FLAGS:\n")
- globalAllParameters := parseCompilerParameters(ccModule.flags.Global.CommonFlags, ctx, f)
+ globalAllParameters := parseCompilerParameters(ccModule.GlobalFlags.CommonFlags, ctx, f)
translateToCMake(globalAllParameters, f, true, true)
f.WriteString("\n# LOCAL ALL FLAGS:\n")
- localAllParameters := parseCompilerParameters(ccModule.flags.Local.CommonFlags, ctx, f)
+ localAllParameters := parseCompilerParameters(ccModule.LocalFlags.CommonFlags, ctx, f)
translateToCMake(localAllParameters, f, true, true)
f.WriteString("\n# GLOBAL CFLAGS:\n")
- globalCParameters := parseCompilerParameters(ccModule.flags.Global.CFlags, ctx, f)
+ globalCParameters := parseCompilerParameters(ccModule.GlobalFlags.CFlags, ctx, f)
translateToCMake(globalCParameters, f, true, true)
f.WriteString("\n# LOCAL CFLAGS:\n")
- localCParameters := parseCompilerParameters(ccModule.flags.Local.CFlags, ctx, f)
+ localCParameters := parseCompilerParameters(ccModule.LocalFlags.CFlags, ctx, f)
translateToCMake(localCParameters, f, true, true)
f.WriteString("\n# GLOBAL C ONLY FLAGS:\n")
- globalConlyParameters := parseCompilerParameters(ccModule.flags.Global.ConlyFlags, ctx, f)
+ globalConlyParameters := parseCompilerParameters(ccModule.GlobalFlags.ConlyFlags, ctx, f)
translateToCMake(globalConlyParameters, f, true, false)
f.WriteString("\n# LOCAL C ONLY FLAGS:\n")
- localConlyParameters := parseCompilerParameters(ccModule.flags.Local.ConlyFlags, ctx, f)
+ localConlyParameters := parseCompilerParameters(ccModule.LocalFlags.ConlyFlags, ctx, f)
translateToCMake(localConlyParameters, f, true, false)
f.WriteString("\n# GLOBAL CPP FLAGS:\n")
- globalCppParameters := parseCompilerParameters(ccModule.flags.Global.CppFlags, ctx, f)
+ globalCppParameters := parseCompilerParameters(ccModule.GlobalFlags.CppFlags, ctx, f)
translateToCMake(globalCppParameters, f, false, true)
f.WriteString("\n# LOCAL CPP FLAGS:\n")
- localCppParameters := parseCompilerParameters(ccModule.flags.Local.CppFlags, ctx, f)
+ localCppParameters := parseCompilerParameters(ccModule.LocalFlags.CppFlags, ctx, f)
translateToCMake(localCppParameters, f, false, true)
f.WriteString("\n# GLOBAL SYSTEM INCLUDE FLAGS:\n")
- globalIncludeParameters := parseCompilerParameters(ccModule.flags.SystemIncludeFlags, ctx, f)
+ globalIncludeParameters := parseCompilerParameters(ccModule.SystemIncludeFlags, ctx, f)
translateToCMake(globalIncludeParameters, f, true, true)
// Add project executable.
f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n",
- cleanExecutableName(ccModule.ModuleBase.Name())))
+ cleanExecutableName(module.Name())))
}
func cleanExecutableName(s string) string {
@@ -467,12 +467,13 @@ func evalVariable(ctx android.SingletonContext, str string) (string, error) {
return "", err
}
-func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string {
+func getCMakeListsForModule(ctx android.SingletonContext, module android.ModuleProxy) string {
+ commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
return filepath.Join(android.AbsSrcDirForExistingUseCases(),
cLionOutputProjectsDirectory,
path.Dir(ctx.BlueprintFile(module)),
- module.ModuleBase.Name()+"-"+
- module.ModuleBase.Arch().ArchType.Name+"-"+
- module.ModuleBase.Os().Name,
+ module.Name()+"-"+
+ commonInfo.Target.Arch.ArchType.Name+"-"+
+ commonInfo.Target.Os.Name,
cMakeListsFilename)
}
diff --git a/cc/compdb.go b/cc/compdb.go
index 3818e9c46..4f61e5793 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -69,10 +69,10 @@ func (c *compdbGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon
// We only want one entry per file. We don't care what module/isa it's from
m := make(map[string]compDbEntry)
- ctx.VisitAllModules(func(module android.Module) {
- if ccModule, ok := module.(*Module); ok {
- if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
- generateCompdbProject(compiledModule, ctx, ccModule, m)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if ccModule, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if ccModule.CompilerInfo != nil {
+ generateCompdbProject(ctx, module, ccModule, m)
}
}
})
@@ -127,7 +127,7 @@ func expandAllVars(ctx android.SingletonContext, args []string) []string {
return out
}
-func getArguments(src android.Path, ctx android.SingletonContext, ccModule *Module, ccPath string, cxxPath string) []string {
+func getArguments(ctx android.SingletonContext, src android.Path, ccModule *CcInfo, ccPath string, cxxPath string) []string {
var args []string
isCpp := false
isAsm := false
@@ -155,25 +155,25 @@ func getArguments(src android.Path, ctx android.SingletonContext, ccModule *Modu
clangPath = ccPath
}
args = append(args, clangPath)
- args = append(args, expandAllVars(ctx, ccModule.flags.Global.CommonFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.Local.CommonFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.Global.CFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.Local.CFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.GlobalFlags.CommonFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.LocalFlags.CommonFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.GlobalFlags.CFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.LocalFlags.CFlags)...)
if isCpp {
- args = append(args, expandAllVars(ctx, ccModule.flags.Global.CppFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.Local.CppFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.GlobalFlags.CppFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.LocalFlags.CppFlags)...)
} else if !isAsm {
- args = append(args, expandAllVars(ctx, ccModule.flags.Global.ConlyFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.Local.ConlyFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.GlobalFlags.ConlyFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.LocalFlags.ConlyFlags)...)
}
- args = append(args, expandAllVars(ctx, ccModule.flags.SystemIncludeFlags)...)
- args = append(args, expandAllVars(ctx, ccModule.flags.NoOverrideFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.SystemIncludeFlags)...)
+ args = append(args, expandAllVars(ctx, ccModule.NoOverrideFlags)...)
args = append(args, src.String())
return args
}
-func generateCompdbProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module, builds map[string]compDbEntry) {
- srcs := compiledModule.Srcs()
+func generateCompdbProject(ctx android.SingletonContext, module android.ModuleProxy, ccModule *CcInfo, builds map[string]compDbEntry) {
+ srcs := ccModule.CompilerInfo.Srcs
if len(srcs) == 0 {
return
}
@@ -187,7 +187,7 @@ func generateCompdbProject(compiledModule CompiledInterface, ctx android.Singlet
}
for _, src := range srcs {
if _, ok := builds[src.String()]; !ok {
- args := getArguments(src, ctx, ccModule, ccPath, cxxPath)
+ args := getArguments(ctx, src, ccModule, ccPath, cxxPath)
if args == nil {
continue
}
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 25edb798d..332c138c7 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -28,38 +28,21 @@ var (
}
arm64ArchVariantCflags = map[string][]string{
- "armv8-a": []string{
- "-march=armv8-a",
- },
- "armv8-a-branchprot": []string{
- "-march=armv8-a",
- "-mbranch-protection=standard",
- },
- "armv8-2a": []string{
- "-march=armv8.2-a",
- },
- "armv8-2a-dotprod": []string{
- "-march=armv8.2-a+dotprod",
- },
- // On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory,
- // so -fstack-protector is unnecessary.
- "armv9-a": []string{
- "-march=armv9-a",
- "-mbranch-protection=standard",
- "-fno-stack-protector",
- },
- "armv9-2a": []string{
- "-march=armv9.2-a",
- "-mbranch-protection=standard",
- "-fno-stack-protector",
- },
- "armv9-3a": []string{
- "-march=armv9.3-a",
- "-mbranch-protection=standard",
- "-fno-stack-protector",
- },
- "armv9-4a": []string{
- "-march=armv9.4-a",
+ "armv8-a": {"-march=armv8-a"},
+ "armv8-a-branchprot": {"-march=armv8-a"},
+ "armv8-2a": {"-march=armv8.2-a"},
+ "armv8-2a-dotprod": {"-march=armv8.2-a+dotprod"},
+ "armv8-5a": {"-march=armv8.5-a"},
+ "armv8-7a": {"-march=armv8.7-a"},
+ "armv9-a": {"-march=armv9-a"},
+ "armv9-2a": {"-march=armv9.2-a"},
+ "armv9-3a": {"-march=armv9.3-a"},
+ "armv9-4a": {"-march=armv9.4-a"},
+ }
+
+ arm64ArchFeatureCflags = map[string][]string{
+ // When Pointer Authentication Codes (PAC) are available, -fstack-protector is unnecessary.
+ "branchprot": {
"-mbranch-protection=standard",
"-fno-stack-protector",
},
@@ -70,8 +53,6 @@ var (
"-Wl,-z,separate-loadable-segments",
}
- arm64Lldflags = arm64Ldflags
-
arm64Cppflags = []string{}
arm64CpuVariantCflags = map[string][]string{
@@ -108,11 +89,9 @@ var (
)
func init() {
- pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
-
- pctx.VariableFunc("Arm64Lldflags", func(ctx android.PackageVarContext) string {
+ pctx.VariableFunc("Arm64Ldflags", func(ctx android.PackageVarContext) string {
maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
- flags := append(arm64Lldflags, maxPageSizeFlag)
+ flags := append(arm64Ldflags, maxPageSizeFlag)
return strings.Join(flags, " ")
})
@@ -170,7 +149,6 @@ type toolchainArm64 struct {
toolchain64Bit
ldflags string
- lldflags string
toolchainCflags string
}
@@ -198,10 +176,6 @@ func (t *toolchainArm64) Ldflags() string {
return t.ldflags
}
-func (t *toolchainArm64) Lldflags() string {
- return t.lldflags
-}
-
func (t *toolchainArm64) ToolchainCflags() string {
return t.toolchainCflags
}
@@ -219,6 +193,9 @@ func arm64ToolchainFactory(arch android.Arch) Toolchain {
toolchainCflags := []string{"${config.Arm64" + arch.ArchVariant + "VariantCflags}"}
toolchainCflags = append(toolchainCflags,
variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant))
+ for _, feature := range arch.ArchFeatures {
+ toolchainCflags = append(toolchainCflags, arm64ArchFeatureCflags[feature]...)
+ }
extraLdflags := variantOrDefault(arm64CpuVariantLdflags, arch.CpuVariant)
return &toolchainArm64{
@@ -226,10 +203,6 @@ func arm64ToolchainFactory(arch android.Arch) Toolchain {
"${config.Arm64Ldflags}",
extraLdflags,
}, " "),
- lldflags: strings.Join([]string{
- "${config.Arm64Lldflags}",
- extraLdflags,
- }, " "),
toolchainCflags: strings.Join(toolchainCflags, " "),
}
}
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index a19b0ed92..32cf722c5 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -43,11 +43,8 @@ var (
"-Wl,--build-id=md5",
"-Wl,--fatal-warnings",
"-Wl,--no-undefined-version",
- }
-
- linuxCrossLldflags = append(linuxCrossLdflags,
"-Wl,--compress-debug-sections=zstd",
- )
+ }
// Embed the linker into host bionic binaries. This is needed to support host bionic,
// as the linux kernel requires that the ELF interpreter referenced by PT_INTERP be
@@ -63,7 +60,6 @@ var (
func init() {
pctx.StaticVariable("LinuxBionicArm64Cflags", strings.Join(linuxCrossCflags, " "))
pctx.StaticVariable("LinuxBionicArm64Ldflags", strings.Join(linuxCrossLdflags, " "))
- pctx.StaticVariable("LinuxBionicArm64Lldflags", strings.Join(linuxCrossLldflags, " "))
}
// toolchain config for ARM64 Linux CrossHost. Almost everything is the same as the ARM64 Android
@@ -102,11 +98,6 @@ func linuxBionicArm64ToolchainFactory(arch android.Arch) Toolchain {
"${config.LinuxBionicArm64Ldflags}",
extraLdflags,
}, " ")
- ret.toolchainArm64.lldflags = strings.Join([]string{
- "${config.Arm64Lldflags}",
- "${config.LinuxBionicArm64Ldflags}",
- extraLdflags,
- }, " ")
ret.toolchainArm64.toolchainCflags = strings.Join(toolchainCflags, " ")
return &ret
}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 3cb190966..de9c749b0 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -15,7 +15,6 @@
package config
import (
- "fmt"
"strings"
"android/soong/android"
@@ -43,8 +42,6 @@ var (
"-Wl,-mllvm", "-Wl,-enable-shrink-wrap=false",
}
- armLldflags = armLdflags
-
armFixCortexA8LdFlags = []string{"-Wl,--fix-cortex-a8"}
armNoFixCortexA8LdFlags = []string{"-Wl,--no-fix-cortex-a8"}
@@ -186,7 +183,6 @@ const (
func init() {
pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
- pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
pctx.StaticVariable("ArmFixCortexA8LdFlags", strings.Join(armFixCortexA8LdFlags, " "))
pctx.StaticVariable("ArmNoFixCortexA8LdFlags", strings.Join(armNoFixCortexA8LdFlags, " "))
@@ -252,7 +248,6 @@ type toolchainArm struct {
toolchainBionic
toolchain32Bit
ldflags string
- lldflags string
toolchainCflags string
}
@@ -287,11 +282,7 @@ func (t *toolchainArm) Cppflags() string {
}
func (t *toolchainArm) Ldflags() string {
- return t.ldflags
-}
-
-func (t *toolchainArm) Lldflags() string {
- return t.lldflags // TODO: handle V8 cases
+ return t.ldflags // TODO: handle V8 cases
}
func (t *toolchainArm) InstructionSetFlags(isa string) (string, error) {
@@ -310,7 +301,6 @@ func (toolchainArm) LibclangRuntimeLibraryArch() string {
}
func armToolchainFactory(arch android.Arch) Toolchain {
- var fixCortexA8 string
toolchainCflags := make([]string, 2, 3)
toolchainCflags[0] = "${config.ArmToolchainCflags}"
@@ -319,29 +309,8 @@ func armToolchainFactory(arch android.Arch) Toolchain {
toolchainCflags = append(toolchainCflags,
variantOrDefault(armCpuVariantCflagsVar, arch.CpuVariant))
- switch arch.ArchVariant {
- case "armv7-a-neon":
- switch arch.CpuVariant {
- case "cortex-a8", "":
- // Generic ARM might be a Cortex A8 -- better safe than sorry
- fixCortexA8 = "${config.ArmFixCortexA8LdFlags}"
- default:
- fixCortexA8 = "${config.ArmNoFixCortexA8LdFlags}"
- }
- case "armv7-a":
- fixCortexA8 = "${config.ArmFixCortexA8LdFlags}"
- case "armv8-a", "armv8-2a":
- // Nothing extra for armv8-a/armv8-2a
- default:
- panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
- }
-
return &toolchainArm{
- ldflags: strings.Join([]string{
- "${config.ArmLdflags}",
- fixCortexA8,
- }, " "),
- lldflags: "${config.ArmLldflags}",
+ ldflags: "${config.ArmLdflags}",
toolchainCflags: strings.Join(toolchainCflags, " "),
}
}
diff --git a/cc/config/arm_linux_host.go b/cc/config/arm_linux_host.go
index e7c7bc466..ebac56f8a 100644
--- a/cc/config/arm_linux_host.go
+++ b/cc/config/arm_linux_host.go
@@ -15,8 +15,9 @@
package config
import (
- "android/soong/android"
"strings"
+
+ "android/soong/android"
)
var (
@@ -28,26 +29,19 @@ var (
linuxArmLdflags = []string{
"-march=armv7a",
- }
-
- linuxArmLldflags = append(linuxArmLdflags,
"-Wl,--compress-debug-sections=zstd",
- )
-
- linuxArm64Ldflags = []string{}
+ }
- linuxArm64Lldflags = append(linuxArm64Ldflags,
+ linuxArm64Ldflags = []string{
"-Wl,--compress-debug-sections=zstd",
- )
+ }
)
func init() {
pctx.StaticVariable("LinuxArmCflags", strings.Join(linuxArmCflags, " "))
pctx.StaticVariable("LinuxArm64Cflags", strings.Join(linuxArm64Cflags, " "))
pctx.StaticVariable("LinuxArmLdflags", strings.Join(linuxArmLdflags, " "))
- pctx.StaticVariable("LinuxArmLldflags", strings.Join(linuxArmLldflags, " "))
pctx.StaticVariable("LinuxArm64Ldflags", strings.Join(linuxArm64Ldflags, " "))
- pctx.StaticVariable("LinuxArm64Lldflags", strings.Join(linuxArm64Lldflags, " "))
pctx.StaticVariable("LinuxArmYasmFlags", "-f elf32 -m arm")
pctx.StaticVariable("LinuxArm64YasmFlags", "-f elf64 -m aarch64")
@@ -93,18 +87,10 @@ func (t *toolchainLinuxArm) Ldflags() string {
return "${config.LinuxLdflags} ${config.LinuxArmLdflags}"
}
-func (t *toolchainLinuxArm) Lldflags() string {
- return "${config.LinuxLldflags} ${config.LinuxArmLldflags}"
-}
-
func (t *toolchainLinuxArm64) Ldflags() string {
return "${config.LinuxLdflags} ${config.LinuxArm64Ldflags}"
}
-func (t *toolchainLinuxArm64) Lldflags() string {
- return "${config.LinuxLldflags} ${config.LinuxArm64Lldflags}"
-}
-
func (t *toolchainLinuxArm) YasmFlags() string {
return "${config.LinuxArmYasmFlags}"
}
@@ -148,10 +134,6 @@ func (t *toolchainLinuxMuslArm) Ldflags() string {
return t.toolchainLinuxArm.Ldflags() + " " + t.toolchainMusl.Ldflags()
}
-func (t *toolchainLinuxMuslArm) Lldflags() string {
- return t.toolchainLinuxArm.Lldflags() + " " + t.toolchainMusl.Lldflags()
-}
-
func (t *toolchainLinuxMuslArm64) ClangTriple() string {
return "aarch64-linux-musl"
}
@@ -164,10 +146,6 @@ func (t *toolchainLinuxMuslArm64) Ldflags() string {
return t.toolchainLinuxArm64.Ldflags() + " " + t.toolchainMusl.Ldflags()
}
-func (t *toolchainLinuxMuslArm64) Lldflags() string {
- return t.toolchainLinuxArm64.Lldflags() + " " + t.toolchainMusl.Lldflags()
-}
-
var toolchainLinuxMuslArmSingleton Toolchain = &toolchainLinuxMuslArm{}
var toolchainLinuxMuslArm64Singleton Toolchain = &toolchainLinuxMuslArm64{}
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 716965a3a..03eefc096 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -99,7 +99,6 @@ func init() {
pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
- pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64")
}
@@ -212,10 +211,6 @@ func (t *toolchainDarwin) Ldflags() string {
return "${config.DarwinLdflags}"
}
-func (t *toolchainDarwin) Lldflags() string {
- return "${config.DarwinLldflags}"
-}
-
func (t *toolchainDarwin) YasmFlags() string {
return "${config.DarwinYasmFlags}"
}
diff --git a/cc/config/global.go b/cc/config/global.go
index e81ac0d47..b08ac6f7e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -177,7 +177,7 @@ var (
"-Werror=format-security",
}
- commonGlobalLldflags = []string{
+ commonGlobalLdflags = []string{
"-fuse-ld=lld",
"-Wl,--icf=safe",
"-Wl,--no-demangle",
@@ -188,7 +188,7 @@ var (
}
// Linking flags for device code; not applied to host binaries.
- deviceGlobalLdflags = []string{
+ deviceGlobalLdflags = slices.Concat([]string{
"-Wl,-z,noexecstack",
"-Wl,-z,relro",
"-Wl,-z,now",
@@ -201,19 +201,14 @@ var (
"-Wl,--exclude-libs,libgcc_stripped.a",
"-Wl,--exclude-libs,libunwind_llvm.a",
"-Wl,--exclude-libs,libunwind.a",
- }
-
- deviceGlobalLldflags = append(append(deviceGlobalLdflags, commonGlobalLldflags...),
"-Wl,--compress-debug-sections=zstd",
- )
+ }, commonGlobalLdflags)
hostGlobalCflags = []string{}
hostGlobalCppflags = []string{}
- hostGlobalLdflags = []string{}
-
- hostGlobalLldflags = commonGlobalLldflags
+ hostGlobalLdflags = commonGlobalLdflags
commonGlobalCppflags = []string{
// -Wimplicit-fallthrough is not enabled by -Wall.
@@ -376,11 +371,13 @@ var (
"-pedantic",
"-pedantic-errors",
"-Werror=pedantic",
+ "-Wno-all",
+ "-Wno-everything",
}
CStdVersion = "gnu23"
CppStdVersion = "gnu++20"
- ExperimentalCStdVersion = "gnu2x"
+ ExperimentalCStdVersion = "gnu2y"
ExperimentalCppStdVersion = "gnu++2b"
// prebuilts/clang default settings.
@@ -409,10 +406,8 @@ func init() {
pctx.StaticVariable("CommonGlobalAsflags", strings.Join(commonGlobalAsflags, " "))
pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " "))
pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " "))
- pctx.StaticVariable("DeviceGlobalLldflags", strings.Join(deviceGlobalLldflags, " "))
pctx.StaticVariable("HostGlobalCppflags", strings.Join(hostGlobalCppflags, " "))
pctx.StaticVariable("HostGlobalLdflags", strings.Join(hostGlobalLdflags, " "))
- pctx.StaticVariable("HostGlobalLldflags", strings.Join(hostGlobalLldflags, " "))
pctx.VariableFunc("CommonGlobalCflags", func(ctx android.PackageVarContext) string {
flags := slices.Clone(commonGlobalCflags)
@@ -493,15 +488,12 @@ func init() {
}
pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I", commonGlobalIncludes)
- pctx.StaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
- pctx.StaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
-
pctx.StaticVariableWithEnvOverride("ClangBase", "LLVM_PREBUILTS_BASE", ClangDefaultBase)
pctx.StaticVariableWithEnvOverride("ClangVersion", "LLVM_PREBUILTS_VERSION", ClangDefaultVersion)
+ pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion)
+
pctx.StaticVariable("ClangPath", "${ClangBase}/${HostPrebuiltTag}/${ClangVersion}")
pctx.StaticVariable("ClangBin", "${ClangPath}/bin")
-
- pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion)
pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib/clang/${ClangShortVersion}/lib/linux")
pctx.StaticVariable("WarningAllowedProjects", strings.Join(WarningAllowedProjects, " "))
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 6a5293f4c..4bbf9fcef 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -41,13 +41,8 @@ var (
// This is already the driver's Android default, but duplicated here (and
// above) for ease of experimentation with additional extensions.
"-march=rv64gcv_zba_zbb_zbs",
- // TODO: remove when clang default changed (https://github.com/google/android-riscv64/issues/124)
- "-Wl,-mllvm -Wl,-jump-is-expensive=false",
- }
-
- riscv64Lldflags = append(riscv64Ldflags,
"-Wl,-z,max-page-size=4096",
- )
+ }
riscv64Cppflags = []string{}
@@ -59,7 +54,6 @@ const ()
func init() {
pctx.StaticVariable("Riscv64Ldflags", strings.Join(riscv64Ldflags, " "))
- pctx.StaticVariable("Riscv64Lldflags", strings.Join(riscv64Lldflags, " "))
pctx.StaticVariable("Riscv64Cflags", strings.Join(riscv64Cflags, " "))
pctx.StaticVariable("Riscv64Cppflags", strings.Join(riscv64Cppflags, " "))
@@ -78,7 +72,6 @@ type toolchainRiscv64 struct {
toolchain64Bit
ldflags string
- lldflags string
toolchainCflags string
}
@@ -106,10 +99,6 @@ func (t *toolchainRiscv64) Ldflags() string {
return t.ldflags
}
-func (t *toolchainRiscv64) Lldflags() string {
- return t.lldflags
-}
-
func (t *toolchainRiscv64) ToolchainCflags() string {
return t.toolchainCflags
}
@@ -135,10 +124,6 @@ func riscv64ToolchainFactory(arch android.Arch) Toolchain {
"${config.Riscv64Ldflags}",
extraLdflags,
}, " "),
- lldflags: strings.Join([]string{
- "${config.Riscv64Lldflags}",
- extraLdflags,
- }, " "),
toolchainCflags: strings.Join(toolchainCflags, " "),
}
}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 5d8c351ab..7adb07beb 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -79,7 +79,6 @@ type Toolchain interface {
Cflags() string
Cppflags() string
Ldflags() string
- Lldflags() string
InstructionSetFlags(string) (string, error)
ndkTriple() string
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index e7ac03863..2ee425db0 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -33,8 +33,6 @@ var (
"-Wl,-z,separate-loadable-segments",
}
- X86_64Lldflags = x86_64Ldflags
-
x86_64ArchVariantCflags = map[string][]string{
"": []string{
"-march=x86-64",
@@ -103,10 +101,9 @@ func init() {
pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
- pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
- pctx.VariableFunc("X86_64Lldflags", func(ctx android.PackageVarContext) string {
+ pctx.VariableFunc("X86_64Ldflags", func(ctx android.PackageVarContext) string {
maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
- flags := append(X86_64Lldflags, maxPageSizeFlag)
+ flags := append(x86_64Ldflags, maxPageSizeFlag)
return strings.Join(flags, " ")
})
@@ -170,10 +167,6 @@ func (t *toolchainX86_64) Ldflags() string {
return "${config.X86_64Ldflags}"
}
-func (t *toolchainX86_64) Lldflags() string {
- return "${config.X86_64Lldflags}"
-}
-
func (t *toolchainX86_64) YasmFlags() string {
return "${config.X86_64YasmFlags}"
}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index a92881d91..bd8d9d6de 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -108,7 +108,6 @@ func init() {
pctx.StaticVariable("X86ToolchainLdflags", "-m32")
pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
- pctx.StaticVariable("X86Lldflags", strings.Join(x86Ldflags, " "))
// Clang cflags
pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
@@ -161,10 +160,6 @@ func (t *toolchainX86) Ldflags() string {
return "${config.X86Ldflags}"
}
-func (t *toolchainX86) Lldflags() string {
- return "${config.X86Lldflags}"
-}
-
func (t *toolchainX86) YasmFlags() string {
return "${config.X86YasmFlags}"
}
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index d2f88ef34..6d3512920 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -15,8 +15,9 @@
package config
import (
- "android/soong/android"
"strings"
+
+ "android/soong/android"
)
var (
@@ -53,11 +54,9 @@ var (
// Use the device gcc toolchain
"--gcc-toolchain=${LinuxBionicGccRoot}",
- }
- linuxBionicLldflags = append(linuxBionicLdflags,
"-Wl,--compress-debug-sections=zstd",
- )
+ }
// Embed the linker into host bionic binaries. This is needed to support host bionic,
// as the linux kernel requires that the ELF interpreter referenced by PT_INTERP be
@@ -77,7 +76,6 @@ const (
func init() {
pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
- pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLldflags, " "))
// Use the device gcc toolchain for now
pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
@@ -115,10 +113,6 @@ func (t *toolchainLinuxBionic) Ldflags() string {
return "${config.LinuxBionicLdflags}"
}
-func (t *toolchainLinuxBionic) Lldflags() string {
- return "${config.LinuxBionicLldflags}"
-}
-
func (t *toolchainLinuxBionic) ToolchainCflags() string {
return "-m64 -march=x86-64" +
// TODO: We're not really android, but we don't have a triple yet b/31393676
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index c3f25aa21..0601b2f7e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -53,11 +53,9 @@ var (
"-Wl,--no-undefined-version",
"--gcc-toolchain=${LinuxGccRoot}",
- }
- linuxLldflags = append(linuxLdflags,
"-Wl,--compress-debug-sections=zstd",
- )
+ }
linuxGlibcLdflags = []string{
"--sysroot ${LinuxGccRoot}/sysroot",
@@ -138,20 +136,15 @@ func init() {
pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
- pctx.StaticVariable("LinuxLldflags", strings.Join(linuxLldflags, " "))
pctx.StaticVariable("LinuxGlibcCflags", strings.Join(linuxGlibcCflags, " "))
pctx.StaticVariable("LinuxGlibcLdflags", strings.Join(linuxGlibcLdflags, " "))
- pctx.StaticVariable("LinuxGlibcLldflags", strings.Join(linuxGlibcLdflags, " "))
pctx.StaticVariable("LinuxMuslCflags", strings.Join(linuxMuslCflags, " "))
pctx.StaticVariable("LinuxMuslLdflags", strings.Join(linuxMuslLdflags, " "))
- pctx.StaticVariable("LinuxMuslLldflags", strings.Join(linuxMuslLdflags, " "))
pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
- pctx.StaticVariable("LinuxX86Lldflags", strings.Join(linuxX86Ldflags, " "))
pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
- pctx.StaticVariable("LinuxX8664Lldflags", strings.Join(linuxX8664Ldflags, " "))
// Yasm flags
pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86")
pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64")
@@ -204,18 +197,10 @@ func (t *toolchainLinuxX86) Ldflags() string {
return "${config.LinuxLdflags} ${config.LinuxX86Ldflags}"
}
-func (t *toolchainLinuxX86) Lldflags() string {
- return "${config.LinuxLldflags} ${config.LinuxX86Lldflags}"
-}
-
func (t *toolchainLinuxX8664) Ldflags() string {
return "${config.LinuxLdflags} ${config.LinuxX8664Ldflags}"
}
-func (t *toolchainLinuxX8664) Lldflags() string {
- return "${config.LinuxLldflags} ${config.LinuxX8664Lldflags}"
-}
-
func (t *toolchainLinuxX86) YasmFlags() string {
return "${config.LinuxX86YasmFlags}"
}
@@ -260,10 +245,6 @@ func (toolchainGlibc) Ldflags() string {
return "${config.LinuxGlibcLdflags}"
}
-func (toolchainGlibc) Lldflags() string {
- return "${config.LinuxGlibcLldflags}"
-}
-
type toolchainLinuxGlibcX86 struct {
toolchainLinuxX86
toolchainGlibc
@@ -286,10 +267,6 @@ func (t *toolchainLinuxGlibcX86) Ldflags() string {
return t.toolchainLinuxX86.Ldflags() + " " + t.toolchainGlibc.Ldflags()
}
-func (t *toolchainLinuxGlibcX86) Lldflags() string {
- return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainGlibc.Lldflags()
-}
-
func (t *toolchainLinuxGlibcX8664) ClangTriple() string {
return "x86_64-linux-gnu"
}
@@ -302,10 +279,6 @@ func (t *toolchainLinuxGlibcX8664) Ldflags() string {
return t.toolchainLinuxX8664.Ldflags() + " " + t.toolchainGlibc.Ldflags()
}
-func (t *toolchainLinuxGlibcX8664) Lldflags() string {
- return t.toolchainLinuxX8664.Lldflags() + " " + t.toolchainGlibc.Lldflags()
-}
-
var toolchainLinuxGlibcX86Singleton Toolchain = &toolchainLinuxGlibcX86{}
var toolchainLinuxGlibcX8664Singleton Toolchain = &toolchainLinuxGlibcX8664{}
@@ -342,10 +315,6 @@ func (toolchainMusl) Ldflags() string {
return "${config.LinuxMuslLdflags}"
}
-func (toolchainMusl) Lldflags() string {
- return "${config.LinuxMuslLldflags}"
-}
-
type toolchainLinuxMuslX86 struct {
toolchainLinuxX86
toolchainMusl
@@ -368,10 +337,6 @@ func (t *toolchainLinuxMuslX86) Ldflags() string {
return t.toolchainLinuxX86.Ldflags() + " " + t.toolchainMusl.Ldflags()
}
-func (t *toolchainLinuxMuslX86) Lldflags() string {
- return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainMusl.Lldflags()
-}
-
func (t *toolchainLinuxMuslX8664) ClangTriple() string {
return "x86_64-linux-musl"
}
@@ -384,10 +349,6 @@ func (t *toolchainLinuxMuslX8664) Ldflags() string {
return t.toolchainLinuxX8664.Ldflags() + " " + t.toolchainMusl.Ldflags()
}
-func (t *toolchainLinuxMuslX8664) Lldflags() string {
- return t.toolchainLinuxX8664.Lldflags() + " " + t.toolchainMusl.Lldflags()
-}
-
var toolchainLinuxMuslX86Singleton Toolchain = &toolchainLinuxMuslX86{}
var toolchainLinuxMuslX8664Singleton Toolchain = &toolchainLinuxMuslX8664{}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 505ddfab4..2f1048812 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -33,7 +33,8 @@ var (
// Use C99-compliant printf functions (%zd).
"-D__USE_MINGW_ANSI_STDIO=1",
- // Admit to using >= Windows 7. Both are needed because of <_mingw.h>.
+ // Admit to using >= Windows 7.
+ // Both #defines are needed: https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt
"-D_WIN32_WINNT=0x0601",
"-DWINVER=0x0601",
// Get 64-bit off_t and related functions.
@@ -68,10 +69,15 @@ var (
windowsLdflags = []string{
"-Wl,--dynamicbase",
"-Wl,--nxcompat",
- }
- windowsLldflags = append(windowsLdflags, []string{
+
"-Wl,--Xlink=-Brepro", // Enable deterministic build
- }...)
+
+ // Additional libraries required for generated static rustlibs
+ "-lssp",
+ "-lgcc_s",
+ "-ladvapi32",
+ "-lntdll",
+ }
windowsX86Cflags = []string{
"-m32",
@@ -141,15 +147,12 @@ func init() {
pctx.StaticVariable("WindowsCflags", strings.Join(windowsCflags, " "))
pctx.StaticVariable("WindowsLdflags", strings.Join(windowsLdflags, " "))
- pctx.StaticVariable("WindowsLldflags", strings.Join(windowsLldflags, " "))
pctx.StaticVariable("WindowsCppflags", strings.Join(windowsCppflags, " "))
pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " "))
pctx.StaticVariable("WindowsX8664Cflags", strings.Join(windowsX8664Cflags, " "))
pctx.StaticVariable("WindowsX86Ldflags", strings.Join(windowsX86Ldflags, " "))
- pctx.StaticVariable("WindowsX86Lldflags", strings.Join(windowsX86Ldflags, " "))
pctx.StaticVariable("WindowsX8664Ldflags", strings.Join(windowsX8664Ldflags, " "))
- pctx.StaticVariable("WindowsX8664Lldflags", strings.Join(windowsX8664Ldflags, " "))
pctx.StaticVariable("WindowsX86Cppflags", strings.Join(windowsX86Cppflags, " "))
pctx.StaticVariable("WindowsX8664Cppflags", strings.Join(windowsX8664Cppflags, " "))
@@ -223,18 +226,10 @@ func (t *toolchainWindowsX86) Ldflags() string {
return "${config.WindowsLdflags} ${config.WindowsX86Ldflags}"
}
-func (t *toolchainWindowsX86) Lldflags() string {
- return "${config.WindowsLldflags} ${config.WindowsX86Lldflags}"
-}
-
func (t *toolchainWindowsX8664) Ldflags() string {
return "${config.WindowsLdflags} ${config.WindowsX8664Ldflags}"
}
-func (t *toolchainWindowsX8664) Lldflags() string {
- return "${config.WindowsLldflags} ${config.WindowsX8664Lldflags}"
-}
-
func (t *toolchainWindowsX86) YasmFlags() string {
return "${config.WindowsX86YasmFlags}"
}
diff --git a/cc/coverage.go b/cc/coverage.go
index 757641cba..15eace601 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -38,6 +38,14 @@ var (
"-fcoverage-mapping",
"-Wno-pass-failed",
"-D__ANDROID_CLANG_COVERAGE__",
+
+ // Bug: http://b/408093589, http://b/396515430: LLVM change 4089763883 to
+ // global merge regressed code coverage, marking previously covered lines
+ // as uncovered. Disable global merge until the regression is fixed.
+ // -Wunused-command-line-argument needs to be disabled because
+ // -mno-global-merge is reported as unused in LTO mode.
+ "-mno-global-merge",
+ "-Wno-unused-command-line-argument",
}
clangCoverageHWASanFlags = []string{
"-mllvm",
@@ -149,11 +157,11 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
// For static libraries, the only thing that changes our object files
// are included whole static libraries, so check to see if any of
// those have coverage enabled.
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
if depTag.static() && depTag.wholeStatic {
- if cc, ok := m.(*Module); ok && cc.coverage != nil {
- if cc.coverage.linkCoverage {
+ if info, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider); ok {
+ if info.LinkCoverage {
cov.linkCoverage = true
}
}
@@ -163,18 +171,13 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
} else {
// For executables and shared libraries, we need to check all of
// our static dependencies.
- ctx.VisitDirectDeps(func(m android.Module) {
- cc, ok := m.(*Module)
- if !ok || cc.coverage == nil {
- return
- }
-
- if static, ok := cc.linker.(libraryInterface); !ok || !static.static() {
- return
- }
-
- if cc.coverage.linkCoverage {
- cov.linkCoverage = true
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
+ if _, ok := android.OtherModuleProvider(ctx, m, StaticLibraryInfoProvider); ok {
+ if info, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider); ok {
+ if info.LinkCoverage {
+ cov.linkCoverage = true
+ }
+ }
}
})
}
@@ -185,8 +188,8 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
flags.Local.LdFlags = append(flags.Local.LdFlags, "--coverage")
if ctx.Device() {
- coverage := ctx.GetDirectDepWithTag(getGcovProfileLibraryName(ctx), CoverageDepTag).(*Module)
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path())
+ coverage := ctx.GetDirectDepProxyWithTag(getGcovProfileLibraryName(ctx), CoverageDepTag)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, android.OutputFileForModule(ctx, coverage, ""))
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv")
}
} else if clangCoverage {
@@ -196,8 +199,8 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
}
if ctx.Device() {
- coverage := ctx.GetDirectDepWithTag(getClangProfileLibraryName(ctx), CoverageDepTag).(*Module)
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path())
+ coverage := ctx.GetDirectDepProxyWithTag(getClangProfileLibraryName(ctx), CoverageDepTag)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, android.OutputFileForModule(ctx, coverage, ""))
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,open")
}
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 79874fc80..5798860b5 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -16,7 +16,6 @@ package cc
import (
"path/filepath"
- "sort"
"strings"
"github.com/google/blueprint/proptools"
@@ -141,10 +140,9 @@ func LibFuzzFactory() android.Module {
type fuzzBinary struct {
*binaryDecorator
*baseCompiler
- fuzzPackagedModule fuzz.FuzzPackagedModule
- installedSharedDeps []string
- sharedLibraries android.RuleBuilderInstalls
- data []android.DataPath
+ fuzzPackagedModule fuzz.FuzzPackagedModule
+ sharedLibraries InstallPairs
+ data []android.DataPath
}
func (fuzz *fuzzBinary) fuzzBinary() bool {
@@ -257,37 +255,15 @@ func isValidSharedDependency(ctx android.ModuleContext, dependency android.Modul
// If the same library is present both as source and a prebuilt we must pick
// only one to avoid a conflict. Always prefer the source since the prebuilt
// probably won't be built with sanitizers enabled.
- if prebuilt, ok := android.OtherModuleProvider(ctx, dependency, android.PrebuiltModuleInfoProvider); ok && prebuilt.SourceExists {
- return false
+ if info, ok := android.OtherModuleProvider(ctx, dependency, android.PrebuiltInfoProvider); ok {
+ if info.IsPrebuilt && info.PrebuiltSourceExists {
+ return false
+ }
}
return true
}
-func SharedLibraryInstallLocation(
- libraryBase string, isHost bool, isVendor bool, fuzzDir string, archString string) string {
- installLocation := "$(PRODUCT_OUT)/data"
- if isHost {
- installLocation = "$(HOST_OUT)"
- }
- subdir := "lib"
- if isVendor {
- subdir = "lib/vendor"
- }
- installLocation = filepath.Join(
- installLocation, fuzzDir, archString, subdir, libraryBase)
- return installLocation
-}
-
-// Get the device-only shared library symbols install directory.
-func SharedLibrarySymbolsInstallLocation(libraryBase string, isVendor bool, fuzzDir string, archString string) string {
- subdir := "lib"
- if isVendor {
- subdir = "lib/vendor"
- }
- return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, subdir, libraryBase)
-}
-
func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule)
@@ -295,31 +271,12 @@ func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
// Grab the list of required shared libraries.
fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
-
- // TODO: does not mirror Android linkernamespaces
- // the logic here has special cases for vendor, but it would need more work to
- // work in arbitrary partitions, so just surface errors early for a few cases
- //
- // Even without these, there are certain situations across linkernamespaces
- // that this won't support. For instance, you might have:
- //
- // my_fuzzer (vendor) -> libbinder_ndk (core) -> libbinder (vendor)
- //
- // This dependency chain wouldn't be possible to express in the current
- // logic because all the deps currently match the variant of the source
- // module.
-
- for _, ruleBuilderInstall := range fuzzBin.sharedLibraries {
- install := ruleBuilderInstall.To
- fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- SharedLibraryInstallLocation(
- install, ctx.Host(), ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
-
- // Also add the dependency on the shared library symbols dir.
- if !ctx.Host() {
- fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- SharedLibrarySymbolsInstallLocation(install, ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
- }
+ // Add the shared libraries to install deps.
+ for _, sharedLib := range fuzzBin.sharedLibraries {
+ fuzzBin.binaryDecorator.baseInstaller.installDeps = append(
+ fuzzBin.binaryDecorator.baseInstaller.installDeps,
+ sharedLib.Dst,
+ )
}
for _, d := range fuzzBin.fuzzPackagedModule.Corpus {
@@ -428,19 +385,15 @@ func NewFuzzer(hod android.HostOrDeviceSupported) *Module {
// their architecture & target/host specific zip file.
type ccRustFuzzPackager struct {
fuzz.FuzzPackager
- fuzzPackagingArchModules string
- fuzzTargetSharedDepsInstallPairs string
- allFuzzTargetsName string
- onlyIncludePresubmits bool
+ onlyIncludePresubmits bool
+ phonyName string
}
func fuzzPackagingFactory() android.Singleton {
fuzzPackager := &ccRustFuzzPackager{
- fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
- fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
- allFuzzTargetsName: "ALL_FUZZ_TARGETS",
- onlyIncludePresubmits: false,
+ onlyIncludePresubmits: false,
+ phonyName: "haiku",
}
return fuzzPackager
}
@@ -448,10 +401,8 @@ func fuzzPackagingFactory() android.Singleton {
func fuzzPackagingFactoryPresubmit() android.Singleton {
fuzzPackager := &ccRustFuzzPackager{
- fuzzPackagingArchModules: "SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES",
- fuzzTargetSharedDepsInstallPairs: "PRESUBMIT_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
- allFuzzTargetsName: "ALL_PRESUBMIT_FUZZ_TARGETS",
- onlyIncludePresubmits: true,
+ onlyIncludePresubmits: true,
+ phonyName: "haiku-presubmit",
}
return fuzzPackager
}
@@ -468,7 +419,7 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
// multiple fuzzers that depend on the same shared library.
- sharedLibraryInstalled := make(map[string]bool)
+ sharedLibraryInstalled := make(map[string]InstallPair)
ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
ccModule, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider)
@@ -511,9 +462,14 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder)
// Package shared libraries
- files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries, isHost, ccModule.InVendor, &s.FuzzPackager,
- archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
-
+ files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries, sharedLibsInstallDirPrefix)...)
+ if !s.onlyIncludePresubmits { // Create the copy rules from the `fuzzPackagingFactory` singleton and not `fuzzPackagingFactoryPresubmit` singleton.
+ for _, sharedLib := range ccModule.FuzzSharedLibraries {
+ if _, exists := sharedLibraryInstalled[sharedLib.Dst.String()]; !exists {
+ sharedLibraryInstalled[sharedLib.Dst.String()] = sharedLib
+ }
+ }
+ }
// The executable.
files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, module, "unstripped")})
@@ -531,71 +487,39 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
}
})
- s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
-}
-
-func (s *ccRustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
- packages := s.Packages.Strings()
- sort.Strings(packages)
- sort.Strings(s.FuzzPackager.SharedLibInstallStrings)
- // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
- // ready to handle phony targets created in Soong. In the meantime, this
- // exports the phony 'fuzz' target and dependencies on packages to
- // core/main.mk so that we can use dist-for-goals.
-
- ctx.Strict(s.fuzzPackagingArchModules, strings.Join(packages, " "))
+ for _, k := range android.SortedKeys(sharedLibraryInstalled) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: sharedLibraryInstalled[k].Src,
+ Output: sharedLibraryInstalled[k].Dst,
+ })
+ }
- ctx.Strict(s.fuzzTargetSharedDepsInstallPairs,
- strings.Join(s.FuzzPackager.SharedLibInstallStrings, " "))
+ s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
- // Preallocate the slice of fuzz targets to minimise memory allocations.
- s.PreallocateSlice(ctx, s.allFuzzTargetsName)
+ // Create the phony and dist rules
+ ctx.Phony(s.phonyName, s.Packages...)
+ ctx.DistForGoals([]string{s.phonyName}, s.Packages...)
+ for _, target := range android.SortedKeys(s.FuzzTargets) {
+ ctx.Phony(s.phonyName, android.PathForPhony(ctx, target))
+ }
}
// GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for
// packaging.
-func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, isHost bool, inVendor bool, s *fuzz.FuzzPackager,
- archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
+func GetSharedLibsToZip(sharedLibraries InstallPairs, destinationPathPrefix string) []fuzz.FileToZip {
var files []fuzz.FileToZip
- fuzzDir := "fuzz"
-
- for _, ruleBuilderInstall := range sharedLibraries {
- library := ruleBuilderInstall.From
- install := ruleBuilderInstall.To
+ for _, installPair := range sharedLibraries {
+ if strings.Contains(installPair.Dst.String(), "symbols/data/fuzz") {
+ // The unstripped so files would be copied from the main data/fuzz direcgtory.
+ continue
+ }
files = append(files, fuzz.FileToZip{
- SourceFilePath: library,
+ SourceFilePath: installPair.Src,
DestinationPathPrefix: destinationPathPrefix,
- DestinationPath: install,
+ DestinationPath: installPair.Dst.Base(),
})
-
- // For each architecture-specific shared library dependency, we need to
- // install it to the output directory. Setup the install destination here,
- // which will be used by $(copy-many-files) in the Make backend.
- installDestination := SharedLibraryInstallLocation(
- install, isHost, inVendor, fuzzDir, archString)
- if (*sharedLibraryInstalled)[installDestination] {
- continue
- }
- (*sharedLibraryInstalled)[installDestination] = true
-
- // Escape all the variables, as the install destination here will be called
- // via. $(eval) in Make.
- installDestination = strings.ReplaceAll(
- installDestination, "$", "$$")
- s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
- library.String()+":"+installDestination)
-
- // Ensure that on device, the library is also reinstalled to the /symbols/
- // dir. Symbolized DSO's are always installed to the device when fuzzing, but
- // we want symbolization tools (like `stack`) to be able to find the symbols
- // in $ANDROID_PRODUCT_OUT/symbols automagically.
- if !isHost {
- symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, inVendor, fuzzDir, archString)
- symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
- s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
- library.String()+":"+symbolsInstallDestination)
- }
}
return files
}
@@ -605,12 +529,35 @@ func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, isHost bool
// VisitDirectDeps is used first to avoid incorrectly using the core libraries (sanitizer
// runtimes, libc, libdl, etc.) from a dependency. This may cause issues when dependencies
// have explicit sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
-func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilderInstalls, []android.ModuleProxy) {
+func CollectAllSharedDependencies(ctx android.ModuleContext) (InstallPairs, []android.ModuleProxy) {
+ sharedLibInstallPaths := func(src android.Path) InstallPairs {
+ var ret InstallPairs
+ // Install in data/fuzz
+ hostOrDevicePrefix := "data"
+ if ctx.Host() {
+ hostOrDevicePrefix = ""
+ }
+ installPath := android.PathForModuleInPartitionInstall(ctx, hostOrDevicePrefix, "fuzz", ctx.Target().Arch.ArchType.String(), "lib")
+ if ctx.InstallInVendor() {
+ installPath = installPath.Join(ctx, "vendor")
+ }
+ ret = append(ret, InstallPair{src, installPath.Join(ctx, src.Base())})
+ // Install in symbols/data/fuzz
+ if !ctx.Host() {
+ installPath := android.PathForModuleInPartitionInstall(ctx, "symbols", "data", "fuzz", ctx.Target().Arch.ArchType.String(), "lib")
+ if ctx.InstallInVendor() {
+ installPath = installPath.Join(ctx, "vendor")
+ }
+ ret = append(ret, InstallPair{src, installPath.Join(ctx, src.Base())})
+ }
+ return ret
+ }
+
seen := make(map[string]bool)
recursed := make(map[string]bool)
deps := []android.ModuleProxy{}
- var sharedLibraries android.RuleBuilderInstalls
+ var sharedLibraries InstallPairs
// Enumerate the first level of dependencies, as we discard all non-library
// modules in the BFS loop below.
@@ -618,7 +565,7 @@ func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilde
if !isValidSharedDependency(ctx, dep) {
return
}
- sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider)
+ _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider)
if !hasSharedLibraryInfo {
return
}
@@ -628,9 +575,8 @@ func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilde
seen[ctx.OtherModuleName(dep)] = true
deps = append(deps, dep)
- installDestination := sharedLibraryInfo.SharedLibrary.Base()
- ruleBuilderInstall := android.RuleBuilderInstall{android.OutputFileForModule(ctx, dep, "unstripped"), installDestination}
- sharedLibraries = append(sharedLibraries, ruleBuilderInstall)
+ src := android.OutputFileForModule(ctx, dep, "unstripped")
+ sharedLibraries = append(sharedLibraries, sharedLibInstallPaths(src)...)
})
ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool {
@@ -650,7 +596,7 @@ func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilde
if !isValidSharedDependency(ctx, child) {
return false
}
- sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, child, SharedLibraryInfoProvider)
+ _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, child, SharedLibraryInfoProvider)
if !hasSharedLibraryInfo {
return false
}
@@ -658,9 +604,8 @@ func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilde
seen[ctx.OtherModuleName(child)] = true
deps = append(deps, child)
- installDestination := sharedLibraryInfo.SharedLibrary.Base()
- ruleBuilderInstall := android.RuleBuilderInstall{android.OutputFileForModule(ctx, child, "unstripped"), installDestination}
- sharedLibraries = append(sharedLibraries, ruleBuilderInstall)
+ src := android.OutputFileForModule(ctx, child, "unstripped")
+ sharedLibraries = append(sharedLibraries, sharedLibInstallPaths(src)...)
}
if recursed[ctx.OtherModuleName(child)] {
diff --git a/cc/installer.go b/cc/installer.go
index d7d8c6d22..99e220faa 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -108,7 +108,7 @@ func (installer *baseInstaller) installTestData(ctx ModuleContext, data []androi
}
func (installer *baseInstaller) installStandaloneTestDep(ctx ModuleContext, standaloneTestDep android.PackagingSpec) {
- installer.installTestData(ctx, []android.DataPath{{SrcPath: standaloneTestDep.ToGob().SrcPath, RelativeInstallPath: "standalone-libs"}})
+ installer.installTestData(ctx, []android.DataPath{{SrcPath: standaloneTestDep.SrcPath(), RelativeInstallPath: "standalone-libs"}})
}
func (installer *baseInstaller) everInstallable() bool {
diff --git a/cc/library.go b/cc/library.go
index 7b854864f..ac93f6634 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -16,7 +16,6 @@ package cc
import (
"fmt"
- "io"
"path/filepath"
"regexp"
"slices"
@@ -805,9 +804,6 @@ type libraryInterface interface {
// Gets the ABI properties for vendor, product, or platform variant
getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties
- // Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
- androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
-
apexAvailable() []string
setAPIListCoverageXMLPath(out android.ModuleOutPath)
@@ -1085,10 +1081,6 @@ func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSO
library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
}
-func (library *libraryDecorator) testSuiteInfo(ctx ModuleContext) {
- // not a test
-}
-
func (library *libraryDecorator) linkStatic(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
@@ -1296,17 +1288,20 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
}
}
+ objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...)
+ objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
+ library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile)
+
+ validations := slices.Concat(objs.tidyDepFiles, library.sAbiDiff)
+
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin,
- deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
+ deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, validations)
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
- objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...)
- objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
library.coverageOutputFile = transformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
- library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile)
var transitiveStaticLibrariesForOrdering depset.DepSet[android.Path]
if static := ctx.GetDirectDepsProxyWithTag(staticVariantTag); len(static) > 0 {
@@ -1563,7 +1558,10 @@ func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext,
// Most opt-in libraries do not have dumps for all default architectures.
if ctx.Config().HasDeviceProduct() {
- errorMessage += " --product " + ctx.Config().DeviceProduct()
+ // Instead of showing the product name directly, use an env variable to
+ // the error message to avoid changing build rules just because of lunch
+ // target change.
+ errorMessage += " --product $$TARGET_PRODUCT"
}
library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
@@ -1919,7 +1917,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
CtxIsForPlatform(ctx) && !ctx.isPreventInstall() {
installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
- ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Description: "install " + installPath.Base(),
Output: installPath,
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
index 88ccd4303..73e599672 100644
--- a/cc/library_headers_test.go
+++ b/cc/library_headers_test.go
@@ -19,8 +19,6 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
func TestLibraryHeaders(t *testing.T) {
@@ -85,7 +83,7 @@ func TestPrebuiltLibraryHeadersPreferred(t *testing.T) {
prebuiltDep := ctx.ModuleForTests(t, "prebuilt_headers", "android_arm64_armv8-a")
hasSourceDep := false
hasPrebuiltDep := false
- ctx.VisitDirectDeps(lib.Module(), func(dep blueprint.Module) {
+ ctx.VisitDirectDeps(lib.Module(), func(dep android.Module) {
if dep == sourceDep.Module() {
hasSourceDep = true
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 46290300c..847436c2a 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -15,6 +15,7 @@
package cc
import (
+ "fmt"
"path/filepath"
"android/soong/android"
@@ -186,11 +187,11 @@ func (mt *librarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext
}
}
-func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
+func (mt *librarySdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
// Check the module to see if it can be used with this module type.
- if m, ok := module.(*Module); ok {
- for _, allowableMemberType := range m.sdkMemberTypes {
- if allowableMemberType == mt {
+ if m, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ for _, allowableMemberType := range m.SdkMemberTypes {
+ if allowableMemberType.SdkPropertyName() == mt.SdkPropertyName() {
return true
}
}
@@ -202,7 +203,11 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, mt.prebuiltModuleType)
- ccModule := member.Variants()[0].(*Module)
+ ccModule := member.Variants()[0]
+ info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, CcInfoProvider)
+ if !ok {
+ panic(fmt.Errorf("not a cc module: %s", member.Variants()[0]))
+ }
if ctx.RequiresTrait(nativeBridgeSdkTrait) {
pbm.AddProperty("native_bridge_supported", true)
@@ -216,30 +221,30 @@ func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext,
pbm.AddProperty("recovery_available", true)
}
- if proptools.Bool(ccModule.VendorProperties.Vendor_available) {
+ if info.VendorAvailable {
pbm.AddProperty("vendor_available", true)
}
- if proptools.Bool(ccModule.VendorProperties.Odm_available) {
+ if info.OdmAvailable {
pbm.AddProperty("odm_available", true)
}
- if proptools.Bool(ccModule.VendorProperties.Product_available) {
+ if info.ProductAvailable {
pbm.AddProperty("product_available", true)
}
- sdkVersion := ccModule.SdkVersion()
+ sdkVersion := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(),
+ ccModule, android.CommonModuleInfoProvider).SdkVersion
if sdkVersion != "" {
pbm.AddProperty("sdk_version", sdkVersion)
}
- stl := ccModule.stl.Properties.Stl
- if stl != nil {
- pbm.AddProperty("stl", proptools.String(stl))
+ if info.StlInfo != nil && info.StlInfo.Stl != nil {
+ pbm.AddProperty("stl", proptools.String(info.StlInfo.Stl))
}
- if lib, ok := ccModule.linker.(*libraryDecorator); ok {
- uhs := lib.Properties.Unique_host_soname
+ if info.LinkerInfo != nil && info.LinkerInfo.LibraryDecoratorInfo != nil {
+ uhs := info.LinkerInfo.LibraryDecoratorInfo.UniqueHostSoname
if uhs != nil {
pbm.AddProperty("unique_host_soname", proptools.Bool(uhs))
}
@@ -496,21 +501,21 @@ type nativeLibInfoProperties struct {
outputFile android.Path
}
-func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
+func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
addOutputFile := true
- ccModule := variant.(*Module)
+ ccInfo := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, CcInfoProvider)
- if s := ccModule.sanitize; s != nil {
+ if s := ccInfo.SanitizeInfo; s != nil {
// We currently do not capture sanitizer flags for libs with sanitizers
// enabled, because they may vary among variants that cannot be represented
// in the input blueprint files. In particular, sanitizerDepsMutator enables
// various sanitizers on dependencies, but in many cases only on static
// ones, and we cannot specify sanitizer flags at the link type level (i.e.
// in StaticOrSharedProperties).
- if s.isUnsanitizedVariant() {
+ if s.IsUnsanitizedVariant {
// This still captures explicitly disabled sanitizers, which may be
// necessary to avoid cyclic dependencies.
- p.Sanitize = s.Properties.Sanitize
+ p.Sanitize = s.Sanitize
} else {
// Do not add the output file to the snapshot if we don't represent it
// properly.
@@ -525,7 +530,7 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
- target := ccModule.Target()
+ target := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider).Target
p.archSubDir = target.Arch.ArchType.String()
if target.NativeBridge == android.NativeBridgeEnabled {
p.archSubDir += "_native_bridge"
@@ -541,12 +546,13 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs)
p.ExportedFlags = exportedInfo.Flags
- if ccModule.linker != nil {
+ if linker := ccInfo.LinkerInfo; linker != nil {
specifiedDeps := specifiedDeps{}
- specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx.SdkModuleContext(), ccModule, specifiedDeps)
+ setLinkerSpecifiedDeps(linker, &specifiedDeps)
- if lib := ccModule.library; lib != nil {
- if !lib.HasStubsVariants() {
+ if lib := ccInfo.LibraryInfo; lib != nil {
+ linkableInfo := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, LinkableInfoProvider)
+ if !linkableInfo.HasStubsVariants {
// Propagate dynamic dependencies for implementation libs, but not stubs.
p.SharedLibs = specifiedDeps.sharedLibs
} else {
@@ -554,11 +560,11 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
// ccModule.StubsVersion()) if the module is versioned. 2. Ensure that all
// the versioned stub libs are retained in the prebuilt tree; currently only
// the stub corresponding to ccModule.StubsVersion() is.
- p.StubsVersions = lib.AllStubsVersions()
- if lib.BuildStubs() && ccModule.stubsSymbolFilePath() == nil {
+ p.StubsVersions = lib.AllStubsVersions
+ if lib.BuildStubs && linker.LibraryDecoratorInfo.StubsSymbolFilePath == nil {
ctx.ModuleErrorf("Could not determine symbol_file")
} else {
- p.StubsSymbolFilePath = ccModule.stubsSymbolFilePath()
+ p.StubsSymbolFilePath = linker.LibraryDecoratorInfo.StubsSymbolFilePath
}
}
}
@@ -567,16 +573,16 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
if !p.memberType.noOutputFiles && addOutputFile {
- p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
+ p.outputFile = getRequiredMemberOutputFile(ctx, variant)
}
}
-func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path {
+func getRequiredMemberOutputFile(ctx android.SdkMemberContext, module android.ModuleOrProxy) android.Path {
var path android.Path
- if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, LinkableInfoProvider); ok && info.OutputFile.Valid() {
+ if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), module, LinkableInfoProvider); ok && info.OutputFile.Valid() {
path = info.OutputFile.Path()
} else {
- ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule)
+ ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", module)
}
return path
}
diff --git a/cc/linkable.go b/cc/linkable.go
index f3aff1523..1877dc637 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -8,6 +8,8 @@ import (
"github.com/google/blueprint/depset"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// PlatformSanitizeable is an interface for sanitizing platform modules.
type PlatformSanitizeable interface {
LinkableInterface
@@ -117,6 +119,8 @@ type LinkableInterface interface {
// CoverageOutputFile returns the output archive of gcno coverage information files.
CoverageOutputFile() android.OptionalPath
+ LinkCoverage() bool
+
NonCcVariants() bool
SelectedStl() string
@@ -138,7 +142,7 @@ type LinkableInterface interface {
// FuzzSharedLibraries returns the shared library dependencies for this module.
// Expects that IsFuzzModule returns true.
- FuzzSharedLibraries() android.RuleBuilderInstalls
+ FuzzSharedLibraries() InstallPairs
Device() bool
Host() bool
@@ -333,6 +337,7 @@ func HeaderDepTag() blueprint.DependencyTag {
}
// SharedLibraryInfo is a provider to propagate information about a shared C++ library.
+// @auto-generate: gob
type SharedLibraryInfo struct {
SharedLibrary android.Path
Target android.Target
@@ -371,6 +376,7 @@ type SharedLibraryStubsInfo struct {
var SharedLibraryStubsProvider = blueprint.NewProvider[SharedLibraryStubsInfo]()
// StaticLibraryInfo is a provider to propagate information about a static C++ library.
+// @auto-generate: gob
type StaticLibraryInfo struct {
StaticLibrary android.Path
Objects Objects
@@ -411,6 +417,7 @@ var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
var ImplementationDepInfoProvider = blueprint.NewProvider[*ImplementationDepInfo]()
+// @auto-generate: gob
type ImplementationDepInfo struct {
ImplementationDeps depset.DepSet[android.Path]
}
diff --git a/cc/linkable_gob_enc.go b/cc/linkable_gob_enc.go
new file mode 100644
index 000000000..06205771e
--- /dev/null
+++ b/cc/linkable_gob_enc.go
@@ -0,0 +1,190 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package cc
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ SharedLibraryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SharedLibraryInfo) })
+ StaticLibraryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(StaticLibraryInfo) })
+ ImplementationDepInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ImplementationDepInfo) })
+}
+
+func (r SharedLibraryInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.SharedLibrary); err != nil {
+ return err
+ }
+
+ if err = r.Target.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.TableOfContents.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.IsStubs); err != nil {
+ return err
+ }
+
+ if err = r.ImplementationDeps.EncodeString(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveStaticLibrariesForOrdering.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *SharedLibraryInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.SharedLibrary = nil
+ } else {
+ r.SharedLibrary = val2.(android.Path)
+ }
+
+ if err = r.Target.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.TableOfContents.Decode(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.IsStubs)
+ if err != nil {
+ return err
+ }
+
+ if err = r.ImplementationDeps.DecodeString(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveStaticLibrariesForOrdering.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var SharedLibraryInfoGobRegId int16
+
+func (r SharedLibraryInfo) GetTypeId() int16 {
+ return SharedLibraryInfoGobRegId
+}
+
+func (r StaticLibraryInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.StaticLibrary); err != nil {
+ return err
+ }
+
+ if err = r.Objects.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ReuseObjects.Encode(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.WholeStaticLibsFromPrebuilts))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.WholeStaticLibsFromPrebuilts); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.WholeStaticLibsFromPrebuilts[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.TransitiveStaticLibrariesForOrdering.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *StaticLibraryInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.StaticLibrary = nil
+ } else {
+ r.StaticLibrary = val2.(android.Path)
+ }
+
+ if err = r.Objects.Decode(buf); err != nil {
+ return err
+ }
+
+ if err = r.ReuseObjects.Decode(buf); err != nil {
+ return err
+ }
+
+ var val7 int32
+ err = gobtools.DecodeSimple[int32](buf, &val7)
+ if err != nil {
+ return err
+ }
+ if val7 > 0 {
+ r.WholeStaticLibsFromPrebuilts = make([]android.Path, val7)
+ for val8 := 0; val8 < int(val7); val8++ {
+ if val10, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val10 == nil {
+ r.WholeStaticLibsFromPrebuilts[val8] = nil
+ } else {
+ r.WholeStaticLibsFromPrebuilts[val8] = val10.(android.Path)
+ }
+ }
+ }
+
+ if err = r.TransitiveStaticLibrariesForOrdering.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var StaticLibraryInfoGobRegId int16
+
+func (r StaticLibraryInfo) GetTypeId() int16 {
+ return StaticLibraryInfoGobRegId
+}
+
+func (r ImplementationDepInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.ImplementationDeps.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ImplementationDepInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.ImplementationDeps.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ImplementationDepInfoGobRegId int16
+
+func (r ImplementationDepInfo) GetTypeId() int16 {
+ return ImplementationDepInfoGobRegId
+}
diff --git a/cc/linker.go b/cc/linker.go
index f85493726..e138203a4 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -69,9 +69,6 @@ type BaseLinkerProperties struct {
// don't link in libclang_rt.builtins-*.a
No_libcrt *bool `android:"arch_variant"`
- // Use clang lld instead of gnu ld.
- Use_clang_lld *bool `android:"arch_variant"`
-
// -l arguments to pass to linker for host-provided shared libraries
Host_ldlibs []string `android:"arch_variant"`
@@ -445,13 +442,6 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
return deps
}
-func (linker *baseLinker) useClangLld(ctx ModuleContext) bool {
- if linker.Properties.Use_clang_lld != nil {
- return Bool(linker.Properties.Use_clang_lld)
- }
- return true
-}
-
// Check whether the SDK version is not older than the specific one
func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion android.ApiLevel) bool {
if ctx.minSdkVersion() == "current" {
@@ -471,8 +461,7 @@ func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion android.ApiLevel) bool
// ModuleContext extends BaseModuleContext
// BaseModuleContext should know if LLD is used?
-func CommonLinkerFlags(ctx android.ModuleContext, flags Flags, useClangLld bool,
- toolchain config.Toolchain, allow_undefined_symbols bool) Flags {
+func CommonLinkerFlags(ctx android.ModuleContext, flags Flags, toolchain config.Toolchain, allow_undefined_symbols bool) Flags {
hod := "Host"
if ctx.Os().Class == android.Device {
hod = "Device"
@@ -483,11 +472,7 @@ func CommonLinkerFlags(ctx android.ModuleContext, flags Flags, useClangLld bool,
ctx.ModuleErrorf("trying to add CommonLinkerFlags to non-LinkableInterface module.")
return flags
}
- if useClangLld {
- flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
- } else {
- flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
- }
+ flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
if allow_undefined_symbols {
if ctx.Darwin() {
@@ -498,11 +483,7 @@ func CommonLinkerFlags(ctx android.ModuleContext, flags Flags, useClangLld bool,
flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--no-undefined")
}
- if useClangLld {
- flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Lldflags())
- } else {
- flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Ldflags())
- }
+ flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Ldflags())
if !toolchain.Bionic() && ctx.Os() != android.LinuxMusl {
if !ctx.Windows() {
@@ -531,8 +512,7 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
toolchain := ctx.toolchain()
allow_undefined_symbols := Bool(linker.Properties.Allow_undefined_symbols)
- flags = CommonLinkerFlags(ctx, flags, linker.useClangLld(ctx), toolchain,
- allow_undefined_symbols)
+ flags = CommonLinkerFlags(ctx, flags, toolchain, allow_undefined_symbols)
if !toolchain.Bionic() && ctx.Os() != android.LinuxMusl {
CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
@@ -541,23 +521,21 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
- if linker.useClangLld(ctx) {
- if !BoolDefault(linker.Properties.Pack_relocations, packRelocationsDefault) {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=none")
- } else if ctx.Device() {
- // SHT_RELR relocations are only supported at API level >= 30.
- // ANDROID_RELR relocations were supported at API level >= 28.
- // Relocation packer was supported at API level >= 23.
- // Do the best we can...
- if (!ctx.useSdk() && ctx.minSdkVersion() == "") || CheckSdkVersionAtLeast(ctx, android.FirstShtRelrVersion) {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
- } else if CheckSdkVersionAtLeast(ctx, android.FirstAndroidRelrVersion) {
- flags.Global.LdFlags = append(flags.Global.LdFlags,
- "-Wl,--pack-dyn-relocs=android+relr",
- "-Wl,--use-android-relr-tags")
- } else if CheckSdkVersionAtLeast(ctx, android.FirstPackedRelocationsVersion) {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android")
- }
+ if !BoolDefault(linker.Properties.Pack_relocations, packRelocationsDefault) {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=none")
+ } else if ctx.Device() {
+ // SHT_RELR relocations are only supported at API level >= 30.
+ // ANDROID_RELR relocations were supported at API level >= 28.
+ // Relocation packer was supported at API level >= 23.
+ // Do the best we can...
+ if (!ctx.useSdk() && ctx.minSdkVersion() == "") || CheckSdkVersionAtLeast(ctx, android.FirstShtRelrVersion) {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
+ } else if CheckSdkVersionAtLeast(ctx, android.FirstAndroidRelrVersion) {
+ flags.Global.LdFlags = append(flags.Global.LdFlags,
+ "-Wl,--pack-dyn-relocs=android+relr",
+ "-Wl,--use-android-relr-tags")
+ } else if CheckSdkVersionAtLeast(ctx, android.FirstPackedRelocationsVersion) {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android")
}
}
diff --git a/cc/llvm_coverage_tools_zip.go b/cc/llvm_coverage_tools_zip.go
new file mode 100644
index 000000000..0b0b0b649
--- /dev/null
+++ b/cc/llvm_coverage_tools_zip.go
@@ -0,0 +1,55 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "android/soong/cc/config"
+)
+
+func init() {
+ android.RegisterParallelSingletonType("llvm_coverage_tools_zip", llvmCoverageToolsZipFactory)
+}
+
+func llvmCoverageToolsZipFactory() android.Singleton {
+ return &llvmCoverageToolsZipSingleton{}
+}
+
+type llvmCoverageToolsZipSingleton struct{}
+
+// GenerateBuildActions implements android.Singleton.
+func (l *llvmCoverageToolsZipSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !ctx.DeviceConfig().ClangCoverageEnabled() {
+ return
+ }
+
+ clangBase := config.ClangPath(ctx, "")
+ llvmProfdata := config.ClangPath(ctx, "bin/llvm-profdata")
+ llvmCov := config.ClangPath(ctx, "bin/llvm-cov")
+ libCxx := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so")
+ llvmCoverageToolsZip := android.PathForOutput(ctx, "llvm-profdata.zip")
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().BuiltTool("soong_zip").
+ Flag("-d").
+ FlagWithOutput("-o ", llvmCoverageToolsZip).
+ FlagWithArg("-C ", clangBase.String()).
+ FlagWithInput("-f ", llvmProfdata).
+ FlagWithInput("-f ", libCxx).
+ FlagWithInput("-f ", llvmCov)
+ builder.Build("llvm_coverage_tools_zip", "llvm coverage tools zip")
+
+ ctx.DistForGoals([]string{"droidcore-unbundled", "apps_only"}, llvmCoverageToolsZip)
+}
diff --git a/cc/lto_test.go b/cc/lto_test.go
index 3fb1f3c06..7cfbba9e1 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -19,24 +19,12 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
var LTOPreparer = android.GroupFixturePreparers(
prepareForCcTest,
)
-func hasDep(result *android.TestResult, m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
-}
-
func TestThinLtoDeps(t *testing.T) {
t.Parallel()
bp := `
@@ -73,22 +61,22 @@ func TestThinLtoDeps(t *testing.T) {
libLto := result.ModuleForTests(t, "lto_enabled", "android_arm64_armv8-a_shared").Module()
libFoo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static").Module()
- if !hasDep(result, libLto, libFoo) {
+ if !android.HasDirectDep(result, libLto, libFoo) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'")
}
libBaz := result.ModuleForTests(t, "baz", "android_arm64_armv8-a_static").Module()
- if !hasDep(result, libFoo, libBaz) {
+ if !android.HasDirectDep(result, libFoo, libBaz) {
t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
libNeverLto := result.ModuleForTests(t, "lib_never_lto", "android_arm64_armv8-a_static").Module()
- if !hasDep(result, libLto, libNeverLto) {
+ if !android.HasDirectDep(result, libLto, libNeverLto) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'")
}
libBar := result.ModuleForTests(t, "bar", "android_arm64_armv8-a_shared").Module()
- if !hasDep(result, libLto, libBar) {
+ if !android.HasDirectDep(result, libLto, libBar) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'")
}
@@ -142,12 +130,12 @@ func TestThinLtoOnlyOnStaticDep(t *testing.T) {
libRootLtoNever := result.ModuleForTests(t, "root_no_lto", "android_arm64_armv8-a_shared").Module()
libFoo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static")
- if !hasDep(result, libRoot, libFoo.Module()) {
+ if !android.HasDirectDep(result, libRoot, libFoo.Module()) {
t.Errorf("'root' missing dependency on the default variant of 'foo'")
}
libFooNoLto := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static_lto-none")
- if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) {
+ if !android.HasDirectDep(result, libRootLtoNever, libFooNoLto.Module()) {
t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'")
}
@@ -157,7 +145,7 @@ func TestThinLtoOnlyOnStaticDep(t *testing.T) {
}
libBaz := result.ModuleForTests(t, "baz", "android_arm64_armv8-a_static")
- if !hasDep(result, libFoo.Module(), libBaz.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBaz.Module()) {
t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
diff --git a/cc/makevars.go b/cc/makevars.go
index 9358755cc..624f7482f 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -100,11 +100,11 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
// Filter vendor_public_library that are exported to make
var exportedVendorPublicLibraries []string
- ctx.VisitAllModules(func(module android.Module) {
- if ccModule, ok := module.(*Module); ok {
- baseName := ccModule.BaseModuleName()
- if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() {
- exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ if ccInfo.IsVendorPublicLibrary && commonInfo.ExportedToMake {
+ exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, commonInfo.BaseModuleName)
}
}
})
@@ -247,12 +247,6 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
toolchain.ToolchainLdflags(),
productExtraLdflags,
}, " "))
- ctx.Strict(clangPrefix+"GLOBAL_LLDFLAGS", strings.Join([]string{
- fmt.Sprintf("${config.%sGlobalLldflags}", hod),
- toolchain.Lldflags(),
- toolchain.ToolchainLdflags(),
- productExtraLdflags,
- }, " "))
if target.Os.Class == android.Device {
for variable, value := range sanitizerVariables {
diff --git a/cc/misc_disted_files.go b/cc/misc_disted_files.go
index 4bdffaa03..ef0b4eb45 100644
--- a/cc/misc_disted_files.go
+++ b/cc/misc_disted_files.go
@@ -15,8 +15,9 @@
package cc
import (
- "android/soong/android"
"strings"
+
+ "android/soong/android"
)
func init() {
@@ -36,7 +37,7 @@ func (s *ccMiscDistedFilesSingleton) GenerateBuildActions(ctx android.SingletonC
var warningsAllowed []string
var usingWnoErrors []string
var missingProfiles []string
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
if v, ok := android.OtherModuleProvider(ctx, module, CcMakeVarsInfoProvider); ok {
warningsAllowed = android.AppendIfNotZero(warningsAllowed, v.WarningsAllowed)
usingWnoErrors = android.AppendIfNotZero(usingWnoErrors, v.UsingWnoError)
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index c21fe564b..69092b79c 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -298,17 +298,17 @@ func CompileStubLibrary(ctx android.ModuleContext, flags Flags, src android.Path
func (this *stubDecorator) findImplementationLibrary(ctx ModuleContext) android.Path {
dep := ctx.GetDirectDepProxyWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
stubImplementation)
- if dep == nil {
+ if dep.IsNil() {
ctx.ModuleErrorf("Could not find implementation for stub: ")
return nil
}
- if _, ok := android.OtherModuleProvider(ctx, *dep, CcInfoProvider); !ok {
+ if _, ok := android.OtherModuleProvider(ctx, dep, CcInfoProvider); !ok {
ctx.ModuleErrorf("Implementation for stub is not correct module type")
return nil
}
- output := android.OtherModuleProviderOrDefault(ctx, *dep, LinkableInfoProvider).UnstrippedOutputFile
+ output := android.OtherModuleProviderOrDefault(ctx, dep, LinkableInfoProvider).UnstrippedOutputFile
if output == nil {
- ctx.ModuleErrorf("implementation module (%s) has no output", *dep)
+ ctx.ModuleErrorf("implementation module (%s) has no output", dep)
return nil
}
diff --git a/cc/ndk_test.go b/cc/ndk_test.go
index 8574bf148..e9804024c 100644
--- a/cc/ndk_test.go
+++ b/cc/ndk_test.go
@@ -17,15 +17,13 @@ package cc
import (
"testing"
- "github.com/google/blueprint"
-
"android/soong/android"
)
func TestNdkHeaderDependency(t *testing.T) {
isDep := func(ctx *android.TestResult, from, toExpected android.Module) bool {
foundDep := false
- ctx.VisitDirectDeps(from, func(toActual blueprint.Module) {
+ ctx.VisitDirectDeps(from, func(toActual android.Module) {
if toExpected.Name() == toActual.Name() {
foundDep = true
}
diff --git a/cc/ndk_translation_package.go b/cc/ndk_translation_package.go
new file mode 100644
index 000000000..7d18576b4
--- /dev/null
+++ b/cc/ndk_translation_package.go
@@ -0,0 +1,270 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "fmt"
+
+ "android/soong/android"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ android.RegisterModuleType("ndk_translation_package", NdkTranslationPackageFactory)
+}
+
+func NdkTranslationPackageFactory() android.Module {
+ module := &ndkTranslationPackage{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type ndkTranslationPackage struct {
+ android.ModuleBase
+ properties ndkTranslationPackageProperties
+
+ output android.Path
+}
+
+type ndkTranslationPackageProperties struct {
+ // Dependencies with native bridge variants that should be packaged.
+ // (e.g. arm and arm64 on an x86_64 device)
+ Native_bridge_deps proptools.Configurable[[]string]
+ // Non-native bridge variants that should be packaged.
+ // (e.g. x86 and x86_64 on an x86_64 device)
+ Device_both_deps []string
+ // Non-native bridge variants with lib64 that should be packaged.
+ // (e.g. x86_64 on an x86_64 device)
+ Device_64_deps []string
+ // Non-native bridge variants with lib32 that should be packaged.
+ // (e.g. x86 on an x86_64 device)
+ Device_32_deps []string
+ // Non-native bridge variants whose first variant should be packaged.
+ Device_first_deps []string
+ // Non-native bridge variants whose first variant should be packaged,
+ // but always into lib/, bin/ directories.
+ Device_first_to_32_deps []string
+ // Non-native bridge variants that should _not_ be packaged, but
+ // used as inputs to generate Android.mk and product.mk
+ Device_both_extra_allowed_deps []string
+ Device_32_extra_allowed_deps []string
+
+ // Version to use in generating the new sysprops
+ Version *string
+
+ // Path to Android.bp generator
+ Android_bp_gen_path *string
+
+ // Path to product.mk generator
+ Product_mk_gen_path *string
+
+ // Whether generate build files for the ndk_translation_packages, default is true.
+ Generate_build_files *bool
+}
+
+type ndkTranslationPackageDepTag struct {
+ blueprint.DependencyTag
+ name string
+}
+
+func (_ ndkTranslationPackageDepTag) ExcludeFromVisibilityEnforcement() {}
+
+// Some dependencies do not support native bridge variants for riscv
+func (_ ndkTranslationPackageDepTag) AllowDisabledModuleDependency(target android.Module) bool {
+ return target.Target().NativeBridge == android.NativeBridgeEnabled &&
+ target.Target().Arch.ArchType == android.Riscv64
+}
+
+func (_ ndkTranslationPackageDepTag) AllowDisabledModuleDependencyProxy(ctx android.OtherModuleProviderContext, mod android.ModuleProxy) bool {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, mod, android.CommonModuleInfoProvider)
+ return commonInfo.Target.NativeBridge == android.NativeBridgeEnabled &&
+ commonInfo.Target.Arch.ArchType == android.Riscv64
+
+}
+
+var (
+ ndkTranslationPackageTag = ndkTranslationPackageDepTag{name: "dep"}
+ ndkTranslationPackageFirstTo32SrcsTag = ndkTranslationPackageDepTag{name: "first_to_32"}
+ ndkTranslationExtraAllowedDepsTag = ndkTranslationPackageDepTag{name: "extra_allowed_deps"}
+)
+
+func (n *ndkTranslationPackage) DepsMutator(ctx android.BottomUpMutatorContext) {
+ for index, t := range ctx.MultiTargets() {
+ if t.NativeBridge == android.NativeBridgeEnabled {
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Native_bridge_deps.GetOrDefault(ctx, nil)...)
+ } else if t.Arch.ArchType == android.X86_64 {
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Device_64_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Device_both_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationExtraAllowedDepsTag, n.properties.Device_both_extra_allowed_deps...)
+ } else if t.Arch.ArchType == android.X86 {
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Device_32_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Device_both_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationExtraAllowedDepsTag, n.properties.Device_both_extra_allowed_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationExtraAllowedDepsTag, n.properties.Device_32_extra_allowed_deps...)
+ }
+ if index == 0 { // Primary arch
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageTag, n.properties.Device_first_deps...)
+ ctx.AddFarVariationDependencies(t.Variations(), ndkTranslationPackageFirstTo32SrcsTag, n.properties.Device_first_to_32_deps...)
+ }
+ }
+}
+
+func (n *ndkTranslationPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var files []android.PackagingSpec // both arches
+ var files64 []android.PackagingSpec // 64 only
+ var extraFiles []android.PackagingSpec
+ var extraFiles64 []android.PackagingSpec
+
+ ctx.VisitDirectDepsProxy(func(child android.ModuleProxy) {
+ tag := ctx.OtherModuleDependencyTag(child)
+ info := android.OtherModuleProviderOrDefault(ctx, child, android.InstallFilesProvider)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider)
+ if tag == ndkTranslationExtraAllowedDepsTag {
+ extraFiles = append(extraFiles, info.PackagingSpecs...)
+ if commonInfo.Target.Arch.ArchType == android.X86_64 || commonInfo.Target.Arch.ArchType == android.Arm64 {
+ extraFiles64 = append(extraFiles64, info.PackagingSpecs...)
+ }
+ return
+ }
+ files = append(files, info.PackagingSpecs...)
+ if (commonInfo.Target.Arch.ArchType == android.X86_64 || commonInfo.Target.Arch.ArchType == android.Arm64) && tag != ndkTranslationPackageFirstTo32SrcsTag {
+ files64 = append(files64, info.PackagingSpecs...)
+ }
+ })
+
+ outZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command().
+ BuiltTool("soong_zip").
+ FlagWithOutput("-o ", outZip)
+
+ if proptools.BoolDefault(n.properties.Generate_build_files, true) {
+ outBp := n.genAndroidBp(ctx, files)
+ outArm64ArmMk, outArm64Mk := n.genProductMk(ctx, files, files64, extraFiles, extraFiles64)
+ for _, buildFile := range []android.Path{outBp, outArm64ArmMk, outArm64Mk} {
+ cmd.
+ FlagWithArg("-C ", filepath.Dir(buildFile.String())).
+ FlagWithInput("-f ", buildFile)
+ }
+ }
+
+ for _, file := range files {
+ // Copy to relative path inside the zip
+ cmd.
+ FlagWithArg("-e ", "system/"+file.RelPathInPackage()).
+ FlagWithInput("-f ", file.SrcPath())
+ }
+
+ builder.Build("ndk_translation_package.zip", fmt.Sprintf("Build ndk_translation_package for %s", ctx.ModuleName()))
+
+ ctx.CheckbuildFile(outZip)
+ n.output = outZip
+
+ ctx.DistForGoal(ctx.ModuleName(), outZip)
+}
+
+// Creates a build rule to generate Android.bp and returns path of the generated file.
+func (n *ndkTranslationPackage) genAndroidBp(ctx android.ModuleContext, files []android.PackagingSpec) android.Path {
+ genDir := android.PathForModuleOut(ctx, "android_bp_dir")
+ generator := android.PathForModuleSrc(ctx, proptools.String(n.properties.Android_bp_gen_path))
+ builder := android.NewRuleBuilder(pctx, ctx).Sbox(
+ genDir,
+ android.PathForModuleOut(ctx, "Android.bp.sbox.textproto"),
+ )
+ outBp := genDir.Join(ctx, "Android.bp")
+ builder.Command().
+ Input(generator).
+ Implicits(specsToSrcPaths(files)).
+ Flag(strings.Join(filesRelativeToInstallDir(ctx, files), " ")).
+ FlagWithOutput("> ", outBp)
+ builder.Build("ndk_translation_package.Android.bp", "Build ndk_translation_package Android.bp")
+
+ return outBp
+}
+
+// Creates a build rule to generate product.mk and returns path of the generated files
+func (n *ndkTranslationPackage) genProductMk(ctx android.ModuleContext, files, files64, extraFiles, extraFiles64 []android.PackagingSpec) (android.Path, android.Path) {
+ genDir := android.PathForModuleOut(ctx, "product_arm64_arm_dir")
+ generator := android.PathForModuleSrc(ctx, proptools.String(n.properties.Product_mk_gen_path))
+ // Both arches
+ builder := android.NewRuleBuilder(pctx, ctx).Sbox(
+ genDir,
+ android.PathForModuleOut(ctx, "product_arm64_arm.mk.textproto"),
+ )
+ outArm64ArmMk := genDir.Join(ctx, "product_arm64_arm.mk")
+ builder.Command().
+ Input(generator).
+ Implicits(specsToSrcPaths(files)).
+ FlagWithArg("--version=", proptools.String(n.properties.Version)).
+ Flag("--arm64 --arm").
+ FlagForEachArg("--extra_allowed_artifact ", filesRelativeToInstallDir(ctx, extraFiles)).
+ Flag(strings.Join(filesRelativeToInstallDir(ctx, files), " ")).
+ FlagWithOutput("> ", outArm64ArmMk)
+ builder.Build("ndk_translation_package.product_arm64_arm.mk", "Build ndk_translation_package product_arm64_arm.mk")
+
+ // Arm64 only
+ genDir = android.PathForModuleOut(ctx, "product_arm64_dir")
+ builder = android.NewRuleBuilder(pctx, ctx).Sbox(
+ genDir,
+ android.PathForModuleOut(ctx, "product_arm64.mk.textproto"),
+ )
+ outArm64Mk := genDir.Join(ctx, "product_arm64.mk")
+ builder.Command().
+ Input(generator).
+ Implicits(specsToSrcPaths(files64)).
+ FlagWithArg("--version=", proptools.String(n.properties.Version)).
+ Flag("--arm64").
+ FlagForEachArg("--extra_allowed_artifact ", filesRelativeToInstallDir(ctx, extraFiles64)).
+ Flag(strings.Join(filesRelativeToInstallDir(ctx, files64), " ")).
+ FlagWithOutput("> ", outArm64Mk)
+ builder.Build("ndk_translation_package.product_arm_64.mk", "Build ndk_translation_package product_arm64.mk")
+
+ return outArm64ArmMk, outArm64Mk
+}
+
+func filesRelativeToInstallDir(ctx android.ModuleContext, files []android.PackagingSpec) []string {
+ var ret []string
+ for _, file := range files {
+ ret = append(ret, "system/"+file.RelPathInPackage())
+ }
+ return ret
+}
+
+func specsToSrcPaths(specs []android.PackagingSpec) android.Paths {
+ var ret android.Paths
+ for _, spec := range specs {
+ ret = append(ret, spec.SrcPath())
+ }
+ return ret
+}
+
+// The only purpose of this method is to make sure we can build the module directly without dist.
+func (n *ndkTranslationPackage) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{
+ android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(n.output),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ }},
+ },
+ }
+}
diff --git a/cc/object.go b/cc/object.go
index ea3ed6151..95a8beb52 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -250,7 +250,3 @@ func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *an
object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
}
-
-func (object *objectLinker) testSuiteInfo(ctx ModuleContext) {
- // not a test
-}
diff --git a/cc/orderfile_test.go b/cc/orderfile_test.go
index 41253adc6..b5709ae0a 100644
--- a/cc/orderfile_test.go
+++ b/cc/orderfile_test.go
@@ -207,11 +207,11 @@ func TestOrderfileProfilePropagateStaticDeps(t *testing.T) {
}
// Check dependency edge from orderfile-enabled module to orderfile variant static libraries
- if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) {
t.Errorf("libTest missing dependency on orderfile variant of libFoo")
}
- if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) {
+ if !android.HasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) {
t.Errorf("libTest missing dependency on orderfile variant of libBar")
}
@@ -230,11 +230,11 @@ func TestOrderfileProfilePropagateStaticDeps(t *testing.T) {
}
// Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries
- if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest has dependency on non-orderfile variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libTest has dependency on non-orderfile variant of libBar")
}
}
@@ -285,11 +285,11 @@ func TestOrderfileLoadPropagateStaticDeps(t *testing.T) {
libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
- if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
}
@@ -365,11 +365,11 @@ func TestOrderfileProfilePropagateSharedDeps(t *testing.T) {
}
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
- if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
}
@@ -445,11 +445,11 @@ func TestOrderfileProfileStaticLibrary(t *testing.T) {
}
// Check dependency edge from orderfile-enabled module to non-orderfile variant libraries
- if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ if !android.HasDirectDep(result, libTest.Module(), libFoo.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !android.HasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index af68ca6bf..cade677ee 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -20,7 +20,6 @@ import (
"testing"
"android/soong/android"
- "github.com/google/blueprint"
)
var prepareForPrebuiltTest = android.GroupFixturePreparers(
@@ -132,42 +131,31 @@ func TestPrebuilt(t *testing.T) {
prebuiltLibfShared := ctx.ModuleForTests(t, "prebuilt_libf", "android_arm64_armv8-a_shared").Module()
prebuiltCrtx := ctx.ModuleForTests(t, "prebuilt_crtx", "android_arm64_armv8-a").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
- if !hasDep(liba, prebuiltLiba) {
+ if !android.HasDirectDep(ctx, liba, prebuiltLiba) {
t.Errorf("liba missing dependency on prebuilt_liba")
}
- if !hasDep(libb, prebuiltLibb) {
+ if !android.HasDirectDep(ctx, libb, prebuiltLibb) {
t.Errorf("libb missing dependency on prebuilt_libb")
}
- if !hasDep(libd, prebuiltLibd) {
+ if !android.HasDirectDep(ctx, libd, prebuiltLibd) {
t.Errorf("libd missing dependency on prebuilt_libd")
}
- if !hasDep(libe, prebuiltLibe) {
+ if !android.HasDirectDep(ctx, libe, prebuiltLibe) {
t.Errorf("libe missing dependency on prebuilt_libe")
}
- if !hasDep(libfStatic, prebuiltLibfStatic) {
+ if !android.HasDirectDep(ctx, libfStatic, prebuiltLibfStatic) {
t.Errorf("libf static missing dependency on prebuilt_libf")
}
- if !hasDep(libfShared, prebuiltLibfShared) {
+ if !android.HasDirectDep(ctx, libfShared, prebuiltLibfShared) {
t.Errorf("libf shared missing dependency on prebuilt_libf")
}
- if !hasDep(crtx, prebuiltCrtx) {
+ if !android.HasDirectDep(ctx, crtx, prebuiltCrtx) {
t.Errorf("crtx missing dependency on prebuilt_crtx")
}
@@ -440,17 +428,6 @@ func TestMultiplePrebuilts(t *testing.T) {
}
all_apex_contributions {name: "all_apex_contributions"}
`
- hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
testCases := []struct {
desc string
selectedDependencyName string
@@ -486,7 +463,7 @@ func TestMultiplePrebuilts(t *testing.T) {
}, preparer)
libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
- android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, android.HasDirectDep(ctx, libfoo, expectedDependency))
// check that LOCAL_SHARED_LIBRARIES contains libbar and not libbar.v<N>
entries := android.AndroidMkInfoForTest(t, ctx, libfoo).PrimaryInfo
android.AssertStringListContains(t, "Version should not be present in LOCAL_SHARED_LIBRARIES", entries.EntryMap["LOCAL_SHARED_LIBRARIES"], "libbar")
@@ -539,16 +516,6 @@ func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
}
all_apex_contributions {name: "all_apex_contributions"}
`
- hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
testCases := []struct {
desc string
@@ -587,7 +554,8 @@ func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
}
libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
- android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName),
+ true, android.HasDirectDep(ctx, libfoo, expectedDependency))
}
}
@@ -617,16 +585,6 @@ func TestMissingVariantInModuleSdk(t *testing.T) {
}
all_apex_contributions {name: "all_apex_contributions"}
`
- hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
preparer := android.GroupFixturePreparers(
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
@@ -642,5 +600,6 @@ func TestMissingVariantInModuleSdk(t *testing.T) {
sourceLibBar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_static").Module()
// Even though the prebuilt is listed in apex_contributions, the prebuilt does not have a static variant.
// Therefore source of libbar should be used.
- android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true, hasDep(ctx, libfoo, sourceLibBar))
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true,
+ android.HasDirectDep(ctx, libfoo, sourceLibBar))
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f0b0308ae..1678bc482 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -28,6 +28,8 @@ import (
"android/soong/etc"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
// Any C flags added by sanitizer which libTooling tools may not
// understand also need to be added to ClangLibToolingUnknownCflags in
@@ -231,6 +233,7 @@ func (t SanitizerType) incompatibleWithCfi() bool {
return t == Asan || t == Fuzzer || t == Hwasan
}
+// @auto-generate: gob
type SanitizeUserProps struct {
// Prevent use of any sanitizers on this module
Never *bool `android:"arch_variant"`
@@ -1856,30 +1859,34 @@ func (txt *sanitizerLibrariesTxtModule) DepsMutator(actx android.BottomUpMutator
func (txt *sanitizerLibrariesTxtModule) getSanitizerLibs(ctx android.ModuleContext) string {
var sanitizerLibStems []string
- ctx.VisitDirectDepsIf(func(m android.Module) bool {
- if !m.Enabled(ctx) {
- return false
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
+ info := android.OtherModuleProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ if !info.Enabled {
+ return
}
- ccModule, _ := m.(*Module)
- if ccModule == nil || ccModule.library == nil || !ccModule.library.shared() {
- return false
+ if _, ok := android.OtherModuleProvider(ctx, m, SharedLibraryInfoProvider); !ok {
+ return
}
targets := ctx.Config().Targets[android.Android]
+ var targetMatches bool
for _, target := range targets {
- if m.Target().Os == target.Os && m.Target().Arch.ArchType == target.Arch.ArchType {
- return true
+ if info.Target.Os == target.Os && info.Target.Arch.ArchType == target.Arch.ArchType {
+ targetMatches = true
}
}
- return false
- }, func(m android.Module) {
- ccModule, _ := m.(*Module)
- outputFile := ccModule.outputFile
- if outputFile.Valid() {
- sanitizerLibStems = append(sanitizerLibStems, outputFile.Path().Base())
+ if !targetMatches {
+ return
+ }
+
+ outputFiles := android.OutputFilesForModule(ctx, m, "")
+ if len(outputFiles) == 1 {
+ sanitizerLibStems = append(sanitizerLibStems, outputFiles[0].Base())
+ } else if len(outputFiles) > 1 {
+ panic(fmt.Errorf("multiple output files for %s: %s", m, outputFiles.Strings()))
}
})
diff --git a/cc/sanitize_gob_enc.go b/cc/sanitize_gob_enc.go
new file mode 100644
index 000000000..a2b68a3e0
--- /dev/null
+++ b/cc/sanitize_gob_enc.go
@@ -0,0 +1,631 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package cc
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ SanitizeUserPropsGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SanitizeUserProps) })
+}
+
+func (r SanitizeUserProps) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ val1 := r.Never == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = gobtools.EncodeSimple(buf, (*r.Never)); err != nil {
+ return err
+ }
+ }
+
+ val2 := r.Address == nil
+ if err = gobtools.EncodeSimple(buf, val2); err != nil {
+ return err
+ }
+ if !val2 {
+ if err = gobtools.EncodeSimple(buf, (*r.Address)); err != nil {
+ return err
+ }
+ }
+
+ val3 := r.Thread == nil
+ if err = gobtools.EncodeSimple(buf, val3); err != nil {
+ return err
+ }
+ if !val3 {
+ if err = gobtools.EncodeSimple(buf, (*r.Thread)); err != nil {
+ return err
+ }
+ }
+
+ val4 := r.Hwaddress == nil
+ if err = gobtools.EncodeSimple(buf, val4); err != nil {
+ return err
+ }
+ if !val4 {
+ if err = gobtools.EncodeSimple(buf, (*r.Hwaddress)); err != nil {
+ return err
+ }
+ }
+
+ val5 := r.All_undefined == nil
+ if err = gobtools.EncodeSimple(buf, val5); err != nil {
+ return err
+ }
+ if !val5 {
+ if err = gobtools.EncodeSimple(buf, (*r.All_undefined)); err != nil {
+ return err
+ }
+ }
+
+ val6 := r.Undefined == nil
+ if err = gobtools.EncodeSimple(buf, val6); err != nil {
+ return err
+ }
+ if !val6 {
+ if err = gobtools.EncodeSimple(buf, (*r.Undefined)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Misc_undefined))); err != nil {
+ return err
+ }
+ for val7 := 0; val7 < len(r.Misc_undefined); val7++ {
+ if err = gobtools.EncodeString(buf, r.Misc_undefined[val7]); err != nil {
+ return err
+ }
+ }
+
+ val8 := r.Fuzzer == nil
+ if err = gobtools.EncodeSimple(buf, val8); err != nil {
+ return err
+ }
+ if !val8 {
+ if err = gobtools.EncodeSimple(buf, (*r.Fuzzer)); err != nil {
+ return err
+ }
+ }
+
+ val9 := r.Safestack == nil
+ if err = gobtools.EncodeSimple(buf, val9); err != nil {
+ return err
+ }
+ if !val9 {
+ if err = gobtools.EncodeSimple(buf, (*r.Safestack)); err != nil {
+ return err
+ }
+ }
+
+ val10 := r.Cfi == nil
+ if err = gobtools.EncodeSimple(buf, val10); err != nil {
+ return err
+ }
+ if !val10 {
+ if err = gobtools.EncodeSimple(buf, (*r.Cfi)); err != nil {
+ return err
+ }
+ }
+
+ val11 := r.Integer_overflow == nil
+ if err = gobtools.EncodeSimple(buf, val11); err != nil {
+ return err
+ }
+ if !val11 {
+ if err = gobtools.EncodeSimple(buf, (*r.Integer_overflow)); err != nil {
+ return err
+ }
+ }
+
+ val12 := r.Scudo == nil
+ if err = gobtools.EncodeSimple(buf, val12); err != nil {
+ return err
+ }
+ if !val12 {
+ if err = gobtools.EncodeSimple(buf, (*r.Scudo)); err != nil {
+ return err
+ }
+ }
+
+ val13 := r.Scs == nil
+ if err = gobtools.EncodeSimple(buf, val13); err != nil {
+ return err
+ }
+ if !val13 {
+ if err = gobtools.EncodeSimple(buf, (*r.Scs)); err != nil {
+ return err
+ }
+ }
+
+ val14 := r.Memtag_heap == nil
+ if err = gobtools.EncodeSimple(buf, val14); err != nil {
+ return err
+ }
+ if !val14 {
+ if err = gobtools.EncodeSimple(buf, (*r.Memtag_heap)); err != nil {
+ return err
+ }
+ }
+
+ val15 := r.Memtag_stack == nil
+ if err = gobtools.EncodeSimple(buf, val15); err != nil {
+ return err
+ }
+ if !val15 {
+ if err = gobtools.EncodeSimple(buf, (*r.Memtag_stack)); err != nil {
+ return err
+ }
+ }
+
+ val16 := r.Memtag_globals == nil
+ if err = gobtools.EncodeSimple(buf, val16); err != nil {
+ return err
+ }
+ if !val16 {
+ if err = gobtools.EncodeSimple(buf, (*r.Memtag_globals)); err != nil {
+ return err
+ }
+ }
+
+ val17 := r.Writeonly == nil
+ if err = gobtools.EncodeSimple(buf, val17); err != nil {
+ return err
+ }
+ if !val17 {
+ if err = gobtools.EncodeSimple(buf, (*r.Writeonly)); err != nil {
+ return err
+ }
+ }
+
+ val18 := r.Diag.Undefined == nil
+ if err = gobtools.EncodeSimple(buf, val18); err != nil {
+ return err
+ }
+ if !val18 {
+ if err = gobtools.EncodeSimple(buf, (*r.Diag.Undefined)); err != nil {
+ return err
+ }
+ }
+
+ val19 := r.Diag.Cfi == nil
+ if err = gobtools.EncodeSimple(buf, val19); err != nil {
+ return err
+ }
+ if !val19 {
+ if err = gobtools.EncodeSimple(buf, (*r.Diag.Cfi)); err != nil {
+ return err
+ }
+ }
+
+ val20 := r.Diag.Integer_overflow == nil
+ if err = gobtools.EncodeSimple(buf, val20); err != nil {
+ return err
+ }
+ if !val20 {
+ if err = gobtools.EncodeSimple(buf, (*r.Diag.Integer_overflow)); err != nil {
+ return err
+ }
+ }
+
+ val21 := r.Diag.Memtag_heap == nil
+ if err = gobtools.EncodeSimple(buf, val21); err != nil {
+ return err
+ }
+ if !val21 {
+ if err = gobtools.EncodeSimple(buf, (*r.Diag.Memtag_heap)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Diag.Misc_undefined))); err != nil {
+ return err
+ }
+ for val22 := 0; val22 < len(r.Diag.Misc_undefined); val22++ {
+ if err = gobtools.EncodeString(buf, r.Diag.Misc_undefined[val22]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Diag.No_recover))); err != nil {
+ return err
+ }
+ for val23 := 0; val23 < len(r.Diag.No_recover); val23++ {
+ if err = gobtools.EncodeString(buf, r.Diag.No_recover[val23]); err != nil {
+ return err
+ }
+ }
+
+ val24 := r.Config.Cfi_assembly_support == nil
+ if err = gobtools.EncodeSimple(buf, val24); err != nil {
+ return err
+ }
+ if !val24 {
+ if err = gobtools.EncodeSimple(buf, (*r.Config.Cfi_assembly_support)); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Recover))); err != nil {
+ return err
+ }
+ for val25 := 0; val25 < len(r.Recover); val25++ {
+ if err = gobtools.EncodeString(buf, r.Recover[val25]); err != nil {
+ return err
+ }
+ }
+
+ val26 := r.Blocklist == nil
+ if err = gobtools.EncodeSimple(buf, val26); err != nil {
+ return err
+ }
+ if !val26 {
+ if err = gobtools.EncodeString(buf, (*r.Blocklist)); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *SanitizeUserProps) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 bool
+ if err = gobtools.DecodeSimple(buf, &val2); err != nil {
+ return err
+ }
+ if !val2 {
+ var val1 bool
+ err = gobtools.DecodeSimple[bool](buf, &val1)
+ if err != nil {
+ return err
+ }
+ r.Never = &val1
+ }
+
+ var val5 bool
+ if err = gobtools.DecodeSimple(buf, &val5); err != nil {
+ return err
+ }
+ if !val5 {
+ var val4 bool
+ err = gobtools.DecodeSimple[bool](buf, &val4)
+ if err != nil {
+ return err
+ }
+ r.Address = &val4
+ }
+
+ var val8 bool
+ if err = gobtools.DecodeSimple(buf, &val8); err != nil {
+ return err
+ }
+ if !val8 {
+ var val7 bool
+ err = gobtools.DecodeSimple[bool](buf, &val7)
+ if err != nil {
+ return err
+ }
+ r.Thread = &val7
+ }
+
+ var val11 bool
+ if err = gobtools.DecodeSimple(buf, &val11); err != nil {
+ return err
+ }
+ if !val11 {
+ var val10 bool
+ err = gobtools.DecodeSimple[bool](buf, &val10)
+ if err != nil {
+ return err
+ }
+ r.Hwaddress = &val10
+ }
+
+ var val14 bool
+ if err = gobtools.DecodeSimple(buf, &val14); err != nil {
+ return err
+ }
+ if !val14 {
+ var val13 bool
+ err = gobtools.DecodeSimple[bool](buf, &val13)
+ if err != nil {
+ return err
+ }
+ r.All_undefined = &val13
+ }
+
+ var val17 bool
+ if err = gobtools.DecodeSimple(buf, &val17); err != nil {
+ return err
+ }
+ if !val17 {
+ var val16 bool
+ err = gobtools.DecodeSimple[bool](buf, &val16)
+ if err != nil {
+ return err
+ }
+ r.Undefined = &val16
+ }
+
+ var val20 int32
+ err = gobtools.DecodeSimple[int32](buf, &val20)
+ if err != nil {
+ return err
+ }
+ if val20 > 0 {
+ r.Misc_undefined = make([]string, val20)
+ for val21 := 0; val21 < int(val20); val21++ {
+ err = gobtools.DecodeString(buf, &r.Misc_undefined[val21])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val24 bool
+ if err = gobtools.DecodeSimple(buf, &val24); err != nil {
+ return err
+ }
+ if !val24 {
+ var val23 bool
+ err = gobtools.DecodeSimple[bool](buf, &val23)
+ if err != nil {
+ return err
+ }
+ r.Fuzzer = &val23
+ }
+
+ var val27 bool
+ if err = gobtools.DecodeSimple(buf, &val27); err != nil {
+ return err
+ }
+ if !val27 {
+ var val26 bool
+ err = gobtools.DecodeSimple[bool](buf, &val26)
+ if err != nil {
+ return err
+ }
+ r.Safestack = &val26
+ }
+
+ var val30 bool
+ if err = gobtools.DecodeSimple(buf, &val30); err != nil {
+ return err
+ }
+ if !val30 {
+ var val29 bool
+ err = gobtools.DecodeSimple[bool](buf, &val29)
+ if err != nil {
+ return err
+ }
+ r.Cfi = &val29
+ }
+
+ var val33 bool
+ if err = gobtools.DecodeSimple(buf, &val33); err != nil {
+ return err
+ }
+ if !val33 {
+ var val32 bool
+ err = gobtools.DecodeSimple[bool](buf, &val32)
+ if err != nil {
+ return err
+ }
+ r.Integer_overflow = &val32
+ }
+
+ var val36 bool
+ if err = gobtools.DecodeSimple(buf, &val36); err != nil {
+ return err
+ }
+ if !val36 {
+ var val35 bool
+ err = gobtools.DecodeSimple[bool](buf, &val35)
+ if err != nil {
+ return err
+ }
+ r.Scudo = &val35
+ }
+
+ var val39 bool
+ if err = gobtools.DecodeSimple(buf, &val39); err != nil {
+ return err
+ }
+ if !val39 {
+ var val38 bool
+ err = gobtools.DecodeSimple[bool](buf, &val38)
+ if err != nil {
+ return err
+ }
+ r.Scs = &val38
+ }
+
+ var val42 bool
+ if err = gobtools.DecodeSimple(buf, &val42); err != nil {
+ return err
+ }
+ if !val42 {
+ var val41 bool
+ err = gobtools.DecodeSimple[bool](buf, &val41)
+ if err != nil {
+ return err
+ }
+ r.Memtag_heap = &val41
+ }
+
+ var val45 bool
+ if err = gobtools.DecodeSimple(buf, &val45); err != nil {
+ return err
+ }
+ if !val45 {
+ var val44 bool
+ err = gobtools.DecodeSimple[bool](buf, &val44)
+ if err != nil {
+ return err
+ }
+ r.Memtag_stack = &val44
+ }
+
+ var val48 bool
+ if err = gobtools.DecodeSimple(buf, &val48); err != nil {
+ return err
+ }
+ if !val48 {
+ var val47 bool
+ err = gobtools.DecodeSimple[bool](buf, &val47)
+ if err != nil {
+ return err
+ }
+ r.Memtag_globals = &val47
+ }
+
+ var val51 bool
+ if err = gobtools.DecodeSimple(buf, &val51); err != nil {
+ return err
+ }
+ if !val51 {
+ var val50 bool
+ err = gobtools.DecodeSimple[bool](buf, &val50)
+ if err != nil {
+ return err
+ }
+ r.Writeonly = &val50
+ }
+
+ var val55 bool
+ if err = gobtools.DecodeSimple(buf, &val55); err != nil {
+ return err
+ }
+ if !val55 {
+ var val54 bool
+ err = gobtools.DecodeSimple[bool](buf, &val54)
+ if err != nil {
+ return err
+ }
+ r.Diag.Undefined = &val54
+ }
+
+ var val58 bool
+ if err = gobtools.DecodeSimple(buf, &val58); err != nil {
+ return err
+ }
+ if !val58 {
+ var val57 bool
+ err = gobtools.DecodeSimple[bool](buf, &val57)
+ if err != nil {
+ return err
+ }
+ r.Diag.Cfi = &val57
+ }
+
+ var val61 bool
+ if err = gobtools.DecodeSimple(buf, &val61); err != nil {
+ return err
+ }
+ if !val61 {
+ var val60 bool
+ err = gobtools.DecodeSimple[bool](buf, &val60)
+ if err != nil {
+ return err
+ }
+ r.Diag.Integer_overflow = &val60
+ }
+
+ var val64 bool
+ if err = gobtools.DecodeSimple(buf, &val64); err != nil {
+ return err
+ }
+ if !val64 {
+ var val63 bool
+ err = gobtools.DecodeSimple[bool](buf, &val63)
+ if err != nil {
+ return err
+ }
+ r.Diag.Memtag_heap = &val63
+ }
+
+ var val67 int32
+ err = gobtools.DecodeSimple[int32](buf, &val67)
+ if err != nil {
+ return err
+ }
+ if val67 > 0 {
+ r.Diag.Misc_undefined = make([]string, val67)
+ for val68 := 0; val68 < int(val67); val68++ {
+ err = gobtools.DecodeString(buf, &r.Diag.Misc_undefined[val68])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val71 int32
+ err = gobtools.DecodeSimple[int32](buf, &val71)
+ if err != nil {
+ return err
+ }
+ if val71 > 0 {
+ r.Diag.No_recover = make([]string, val71)
+ for val72 := 0; val72 < int(val71); val72++ {
+ err = gobtools.DecodeString(buf, &r.Diag.No_recover[val72])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val76 bool
+ if err = gobtools.DecodeSimple(buf, &val76); err != nil {
+ return err
+ }
+ if !val76 {
+ var val75 bool
+ err = gobtools.DecodeSimple[bool](buf, &val75)
+ if err != nil {
+ return err
+ }
+ r.Config.Cfi_assembly_support = &val75
+ }
+
+ var val79 int32
+ err = gobtools.DecodeSimple[int32](buf, &val79)
+ if err != nil {
+ return err
+ }
+ if val79 > 0 {
+ r.Recover = make([]string, val79)
+ for val80 := 0; val80 < int(val79); val80++ {
+ err = gobtools.DecodeString(buf, &r.Recover[val80])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var val83 bool
+ if err = gobtools.DecodeSimple(buf, &val83); err != nil {
+ return err
+ }
+ if !val83 {
+ var val82 string
+ err = gobtools.DecodeString(buf, &val82)
+ if err != nil {
+ return err
+ }
+ r.Blocklist = &val82
+ }
+
+ return err
+}
+
+var SanitizeUserPropsGobRegId int16
+
+func (r SanitizeUserProps) GetTypeId() int16 {
+ return SanitizeUserPropsGobRegId
+}
diff --git a/cc/sdk.go b/cc/sdk.go
index 5dd44d8b8..f375ce828 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -57,6 +57,9 @@ func (sdkTransitionMutator) Split(ctx android.BaseModuleContext) []string {
}
func (sdkTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if _, ok := ctx.DepTag().(android.UsesUnbundledVariantDepTag); ok {
+ return "sdk"
+ }
return sourceVariation
}
@@ -78,8 +81,15 @@ func (sdkTransitionMutator) IncomingTransition(ctx android.IncomingTransitionCon
}
}
}
-
- if ctx.IsAddingDependency() {
+ _, usesUnbundledVariantDepTag := ctx.DepTag().(android.UsesUnbundledVariantDepTag)
+ // If we've reached this point, the module doesn't have an sdk variant. If we're adding
+ // a dependency, we want to pass the sdk variant through to cause a missing dependency error,
+ // so that sdk modules can't depend on non-sdk modules and smuggle the use of private apis.
+ // However, when the unbundled_builder depends on modules, it wants to prefer the sdk variant
+ // but fall back to non-sdk if it doesn't exist. It's ok in this case because the
+ // unbundled_builder is just a module for disting other modules, it doesn't have any code of its
+ // own.
+ if ctx.IsAddingDependency() && !usesUnbundledVariantDepTag {
return incomingVariation
} else {
return ""
@@ -114,7 +124,7 @@ func (sdkTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation
ccModule.Properties.PreventInstall = true
}
- if ctx.Config().UnbundledBuildApps() {
+ if ctx.Config().HasUnbundledBuildApps() {
if variation == "" {
// For an unbundled apps build, hide the platform variant from Make
// so that other Make modules don't link against it, but against the
diff --git a/cc/test.go b/cc/test.go
index 9c276b81a..a20592892 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -274,12 +274,6 @@ func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJ
}
}
-func (test *testDecorator) testSuiteInfo(ctx ModuleContext) {
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: test.InstallerProperties.Test_suites,
- })
-}
-
func NewTestInstaller() *baseInstaller {
return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
}
@@ -348,10 +342,6 @@ func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *androi
}
-func (test *testBinary) testSuiteInfo(ctx ModuleContext) {
- test.testDecorator.testSuiteInfo(ctx)
-}
-
func (test *testBinary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -422,44 +412,36 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
- if !ctx.Config().KatiEnabled() { // TODO(spandandas): Remove the special case for kati
- // Install the test config in testcases/ directory for atest.
- c, ok := ctx.Module().(*Module)
- if !ok {
- ctx.ModuleErrorf("Not a cc_test module")
- }
- // Install configs in the root of $PRODUCT_OUT/testcases/$module
- testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName()+c.SubName())
- if ctx.PrimaryArch() {
- if test.testConfig != nil {
- ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
- }
- dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
- if dynamicConfig.Valid() {
- ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
- }
- for _, extraTestConfig := range test.extraTestConfigs {
- ctx.InstallFile(testCases, extraTestConfig.Base(), extraTestConfig)
- }
- }
- // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
- testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
- ctx.InstallTestData(testCases, test.data)
- ctx.InstallFile(testCases, file.Base(), file)
+ // Install the test config in testcases/ directory for atest.
+ c, ok := ctx.Module().(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Not a cc_test module")
}
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ NameSuffix: c.SubName(),
+ TestSuites: test.InstallerProperties.Test_suites,
+ MainFile: file,
+ MainFileStem: file.Base(),
+ ConfigFile: test.testConfig,
+ ExtraConfigs: test.extraTestConfigs,
+ Data: test.data,
+ NeedsArchFolder: true,
+ PerTestcaseDirectory: Bool(test.Properties.Per_testcase_directory),
+ })
+
test.binaryDecorator.baseInstaller.installTestData(ctx, test.data)
test.binaryDecorator.baseInstaller.install(ctx, file)
if Bool(test.Properties.Standalone_test) {
packagingSpecsBuilder := depset.NewBuilder[android.PackagingSpec](depset.TOPOLOGICAL)
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
deps := android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider)
packagingSpecsBuilder.Transitive(deps.TransitivePackagingSpecs)
})
for _, standaloneTestDep := range packagingSpecsBuilder.Build().ToList() {
- if standaloneTestDep.ToGob().SrcPath == nil {
+ if standaloneTestDep.SrcPath() == nil {
continue
}
if standaloneTestDep.SkipInstall() {
@@ -588,8 +570,24 @@ func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *andro
test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
}
-func (test *testLibrary) testSuiteInfo(ctx ModuleContext) {
- test.testDecorator.testSuiteInfo(ctx)
+func (test *testLibrary) install(ctx ModuleContext, file android.Path) {
+ test.libraryDecorator.install(ctx, file)
+
+ c, ok := ctx.Module().(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Expected a cc module")
+ }
+ // host tests are not installed to testcases/ as per:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/base_rules.mk;l=251;drc=45efec6797cbf812df34dac9d05e43a9fe7217e0
+ if test.shared() {
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ NameSuffix: c.SubName(),
+ TestSuites: test.InstallerProperties.Test_suites,
+ NeedsArchFolder: true,
+ MainFile: file,
+ MainFileStem: file.Base(),
+ })
+ }
}
func (test *testLibrary) installerProps() []interface{} {
@@ -684,6 +682,21 @@ func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Pat
benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
benchmark.binaryDecorator.baseInstaller.installTestData(ctx, benchmark.data)
benchmark.binaryDecorator.baseInstaller.install(ctx, file)
+
+ c, ok := ctx.Module().(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Not a cc module")
+ }
+
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ NameSuffix: c.SubName(),
+ TestSuites: benchmark.Properties.Test_suites,
+ MainFile: file,
+ MainFileStem: file.Base(),
+ ConfigFile: benchmark.testConfig,
+ Data: benchmark.data,
+ NeedsArchFolder: true,
+ })
}
func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
@@ -709,12 +722,6 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf
}
}
-func (benchmark *benchmarkDecorator) testSuiteInfo(ctx ModuleContext) {
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: benchmark.Properties.Test_suites,
- })
-}
-
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
module, binary := newBinary(hod)
module.multilib = android.MultilibBoth
diff --git a/cc/testing.go b/cc/testing.go
index 69ae11dfd..7cfcac8c5 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -104,6 +104,7 @@ func commonDefaultModules() string {
name: "libclang_rt.hwasan",
defaults: ["toolchain_libs_defaults"],
srcs: [""],
+ double_loadable: true,
}
cc_prebuilt_library_static {
@@ -130,6 +131,7 @@ func commonDefaultModules() string {
cc_prebuilt_library_shared {
name: "libclang_rt.ubsan_standalone",
defaults: ["toolchain_libs_defaults"],
+ double_loadable: true,
srcs: [""],
}
diff --git a/ci_tests/Android.bp b/ci_tests/Android.bp
index 181ded46d..27edc585c 100644
--- a/ci_tests/Android.bp
+++ b/ci_tests/Android.bp
@@ -10,6 +10,7 @@ bootstrap_go_package {
"blueprint-proptools",
"soong",
"soong-android",
+ "soong-cc",
],
srcs: [
"ci_test_package_zip.go",
diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go
index 4cadffddc..5838c0d3b 100644
--- a/ci_tests/ci_test_package_zip.go
+++ b/ci_tests/ci_test_package_zip.go
@@ -15,11 +15,14 @@
package ci_tests
import (
+ "cmp"
"fmt"
"path/filepath"
+ "slices"
"strings"
"android/soong/android"
+ "android/soong/cc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -56,6 +59,10 @@ type CITestPackageProperties struct {
Tests_if_exist_common proptools.Configurable[[]string] `android:"arch_variant"`
// git-main only test modules. Will only be added as dependencies based on both 32bit and 64bit arch variant and the device os variant if exists.
Tests_if_exist_device_both proptools.Configurable[[]string] `android:"arch_variant"`
+ // git-main only test modules. Will only be added as dependencies based on the first supported arch variant and the device os variant if exists.
+ Tests_if_exist_device_first proptools.Configurable[[]string] `android:"arch_variant"`
+ // git-main only test modules. Will only be added as dependencies based on host if exists.
+ Tests_if_exist_host proptools.Configurable[[]string] `android:"arch_variant"`
}
type testPackageZipDepTagType struct {
@@ -67,8 +74,13 @@ var testPackageZipDepTag testPackageZipDepTagType
var (
pctx = android.NewPackageContext("android/soong/ci_tests")
// test_package module type should only be used for the following modules.
- // TODO: remove "_soong" from the module names inside when eliminating the corresponding make modules
- moduleNamesAllowed = []string{"continuous_instrumentation_tests_soong", "continuous_instrumentation_metric_tests_soong", "continuous_native_tests_soong", "continuous_native_metric_tests_soong", "platform_tests"}
+ moduleNamesAllowed = []string{
+ "continuous_instrumentation_tests",
+ "continuous_instrumentation_metric_tests",
+ "continuous_native_tests",
+ "continuous_native_metric_tests",
+ "platform_tests",
+ }
)
func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -89,6 +101,12 @@ func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, t := range p.properties.Host_tests.GetOrDefault(ctx, nil) {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), testPackageZipDepTag, t)
}
+ // adding Tests_if_exist_host property deps
+ for _, t := range p.properties.Tests_if_exist_host.GetOrDefault(ctx, nil) {
+ if ctx.OtherModuleExists(t) {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), testPackageZipDepTag, t)
+ }
+ }
// adding Tests_if_exist_* property deps
for _, t := range p.properties.Tests_if_exist_common.GetOrDefault(ctx, nil) {
@@ -96,6 +114,11 @@ func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), testPackageZipDepTag, t)
}
}
+ for _, t := range p.properties.Tests_if_exist_device_first.GetOrDefault(ctx, nil) {
+ if ctx.OtherModuleExists(t) {
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), testPackageZipDepTag, t)
+ }
+ }
p.addDeviceBothDeps(ctx, true)
}
@@ -139,12 +162,21 @@ func TestPackageZipFactory() android.Module {
return module
}
+// We need to implement IsNativeCoverageNeeded so that in coverage builds we depend on the coverage
+// variants of the tests. The non-coverage variants will have PreventInstall called on them,
+// so they won't be able to be packaged into this test zip.
+func (p *testPackageZip) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
+ return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
+var _ cc.UseCoverage = (*testPackageZip)(nil)
+
func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Never install this test package, it's for disting only
p.SkipInstall()
if !android.InList(ctx.ModuleName(), moduleNamesAllowed) {
- ctx.ModuleErrorf("%s is not allowed to use module type test_package")
+ ctx.ModuleErrorf("%s is not allowed to use module type test_package", ctx.ModuleName())
}
p.output = createOutput(ctx, pctx)
@@ -152,33 +184,49 @@ func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.SetOutputFiles(android.Paths{p.output}, "")
}
-func createOutput(ctx android.ModuleContext, pctx android.PackageContext) android.ModuleOutPath {
- productOut := filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName())
- stagingDir := android.PathForModuleOut(ctx, "STAGING")
- productVariables := ctx.Config().ProductVariables()
- arch := proptools.String(productVariables.DeviceArch)
- secondArch := proptools.String(productVariables.DeviceSecondaryArch)
-
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().Text("rm").Flag("-rf").Text(stagingDir.String())
- builder.Command().Text("mkdir").Flag("-p").Output(stagingDir)
- builder.Temporary(stagingDir)
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if !child.Enabled(ctx) {
+func getAllTestModules(ctx android.ModuleContext) []android.ModuleOrProxy {
+ var ret []android.ModuleOrProxy
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ if info, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); !ok || !info.Enabled {
return false
}
if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == testPackageZipDepTag {
// handle direct deps
- extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch)
+ ret = append(ret, child)
return true
} else if !android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == android.RequiredDepTag {
// handle the "required" from deps
- extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch)
+ ret = append(ret, child)
return true
} else {
return false
}
})
+ ret = android.FirstUniqueInPlace(ret)
+ slices.SortFunc(ret, func(a, b android.ModuleOrProxy) int {
+ return cmp.Compare(a.String(), b.String())
+ })
+ return ret
+}
+
+func createOutput(ctx android.ModuleContext, pctx android.PackageContext) android.ModuleOutPath {
+ productOut := android.PathForModuleInPartitionInstall(ctx, "").String()
+ stagingDir := android.PathForModuleOut(ctx, "STAGING")
+ productVariables := ctx.Config().ProductVariables()
+ arch := proptools.String(productVariables.DeviceArch)
+ secondArch := proptools.String(productVariables.DeviceSecondaryArch)
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("rm").Flag("-rf").Text(stagingDir.String())
+ builder.Command().Text("mkdir").Flag("-p").Output(stagingDir)
+ builder.Temporary(stagingDir)
+
+ allTestModules := getAllTestModules(ctx)
+ for _, dep := range allTestModules {
+ extendBuilderCommand(ctx, dep, builder, stagingDir, productOut, arch, secondArch)
+ }
+
+ createSymbolsZip(ctx, allTestModules)
output := android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
builder.Command().
@@ -191,16 +239,25 @@ func createOutput(ctx android.ModuleContext, pctx android.PackageContext) androi
return output
}
-func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder *android.RuleBuilder, stagingDir android.ModuleOutPath, productOut, arch, secondArch string) {
+func createSymbolsZip(ctx android.ModuleContext, allModules []android.ModuleOrProxy) {
+ symbolsZipFile := android.PathForModuleOut(ctx, "symbols.zip")
+ symbolsMappingFile := android.PathForModuleOut(ctx, "symbols-mapping.textproto")
+ android.BuildSymbolsZip(ctx, allModules, symbolsZipFile, symbolsMappingFile)
+
+ ctx.SetOutputFiles(android.Paths{symbolsZipFile}, ".symbols")
+ ctx.SetOutputFiles(android.Paths{symbolsMappingFile}, ".elf_mapping")
+}
+
+func extendBuilderCommand(ctx android.ModuleContext, m android.ModuleOrProxy, builder *android.RuleBuilder, stagingDir android.ModuleOutPath, productOut, arch, secondArch string) {
info, ok := android.OtherModuleProvider(ctx, m, android.ModuleInfoJSONProvider)
if !ok {
ctx.OtherModuleErrorf(m, "doesn't set ModuleInfoJSON provider")
- } else if len(info) != 1 {
+ } else if len(info.Data) != 1 {
ctx.OtherModuleErrorf(m, "doesn't provide exactly one ModuleInfoJSON")
}
- classes := info[0].GetClass()
- if len(info[0].Class) != 1 {
+ classes := info.Data[0].GetClass()
+ if len(info.Data[0].Class) != 1 {
ctx.OtherModuleErrorf(m, "doesn't have exactly one class in its ModuleInfoJSON")
}
class := strings.ToLower(classes[0])
@@ -234,8 +291,11 @@ func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder *
}
name := removeFileExtension(installedFile.Base())
// some apks have other apk as installed files, these additional files shouldn't be included
+ // But due to for override_android_test or override_android_app it will have OtherModuleName deps for the module
+ // it wants to override, to prevent it being ignored only skip this deps if it not the direct dependency of the
+ // test_packages.
isAppOrFramework := class == "app" || class == "framework"
- if isAppOrFramework && name != ctx.OtherModuleName(m) {
+ if ctx.OtherModuleDependencyTag(m) != testPackageZipDepTag && isAppOrFramework && name != ctx.OtherModuleName(m) {
continue
}
diff --git a/android/init.go b/cmd/dir_to_depfile/Android.bp
index af50323d3..a70216e22 100644
--- a/android/init.go
+++ b/cmd/dir_to_depfile/Android.bp
@@ -1,4 +1,4 @@
-// Copyright 2024 Google Inc. All rights reserved.
+// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,19 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package android
-
-import "encoding/gob"
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
-func init() {
- gob.Register(applicableLicensesPropertyImpl{})
- gob.Register(extraFilesZip{})
- gob.Register(InstallPath{})
- gob.Register(ModuleGenPath{})
- gob.Register(ModuleObjPath{})
- gob.Register(ModuleOutPath{})
- gob.Register(OutputPath{})
- gob.Register(PhonyPath{})
- gob.Register(SourcePath{})
- gob.Register(unstableInfo{})
+blueprint_go_binary {
+ name: "dir_to_depfile",
+ deps: ["soong-makedeps"],
+ srcs: ["dir_to_depfile.go"],
}
diff --git a/cmd/dir_to_depfile/dir_to_depfile.go b/cmd/dir_to_depfile/dir_to_depfile.go
new file mode 100644
index 000000000..afc3d027c
--- /dev/null
+++ b/cmd/dir_to_depfile/dir_to_depfile.go
@@ -0,0 +1,80 @@
+// Copyright 2025[ Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This tool finds all subdirectories and files in a list of directories and
+// produces a dependency file for use by ninja.
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/fs"
+ "log"
+ "os"
+ "path/filepath"
+
+ "android/soong/makedeps"
+)
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, "Usage: %s -o <output> -t <target> <dir> [<dir>...]", os.Args[0])
+ flag.PrintDefaults()
+ }
+ output := flag.String("o", "", "Output file")
+ target := flag.String("t", "", "Target name to write into depfile")
+
+ flag.Parse()
+
+ if flag.NArg() < 1 {
+ log.Fatal("Expected at least one directory as an argument")
+ }
+
+ if *output == "" {
+ log.Fatal("Expected -o argument")
+ }
+
+ if *target == "" {
+ log.Fatal("Expected -t argument")
+ }
+
+ depsFile := makedeps.Deps{
+ Output: *target,
+ }
+
+ for _, arg := range flag.Args() {
+ deps, err := collectDirectoryDeps(arg)
+ if err != nil {
+ log.Fatalf("Error collecting deps from %q: %v", arg, err)
+ }
+
+ depsFile.Inputs = append(depsFile.Inputs, deps...)
+ }
+
+ err := os.WriteFile(*output, depsFile.Print(), 0666)
+ if err != nil {
+ log.Fatalf("Failed to write output file %q: %v", *output, err)
+ }
+}
+
+func collectDirectoryDeps(dir string) (deps []string, err error) {
+ err = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ deps = append(deps, path)
+ return nil
+ })
+ return deps, err
+}
diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go
index 65ef88145..cbdcdae9d 100644
--- a/cmd/find_input_delta/find_input_delta/main.go
+++ b/cmd/find_input_delta/find_input_delta/main.go
@@ -70,31 +70,11 @@ func main() {
inputs = append(inputs, fileSepRegex.FindAllString(string(data), -1)...)
}
- // Read the prior state
- prior_state, err := fid_lib.LoadState(prior_state_file, fid_lib.OsFs)
+ file_list, err := fid_lib.GenerateFileList(target, prior_state_file, new_state_file, inputs, inspect, fid_lib.OsFs)
if err != nil {
panic(err)
}
- // Create the new state
- new_state, err := fid_lib.CreateState(inputs, inspect, fid_lib.OsFs)
- if err != nil {
- panic(err)
- }
- if err = fid_lib.WriteState(new_state, new_state_file); err != nil {
- panic(err)
- }
-
- file_list := fid_lib.CompareInternalState(prior_state, new_state, target)
-
if err = file_list.Format(os.Stdout, template); err != nil {
panic(err)
}
-
- metrics_dir := os.Getenv("SOONG_METRICS_AGGREGATION_DIR")
- out_dir := os.Getenv("OUT_DIR")
- if metrics_dir != "" {
- if err = file_list.WriteMetrics(metrics_dir, out_dir); err != nil {
- panic(err)
- }
- }
}
diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
index 0f88159be..cc7e17499 100644
--- a/cmd/find_input_delta/find_input_delta_lib/internal_state.go
+++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
@@ -18,6 +18,7 @@ import (
"errors"
"fmt"
"io/fs"
+ "os"
"regexp"
"slices"
@@ -29,7 +30,7 @@ import (
// Load the internal state from a file.
// If the file does not exist, an empty state is returned.
-func LoadState(filename string, fsys fs.ReadFileFS) (*fid_proto.PartialCompileInputs, error) {
+func loadState(filename string, fsys fs.ReadFileFS) (*fid_proto.PartialCompileInputs, error) {
var message = &fid_proto.PartialCompileInputs{}
data, err := fsys.ReadFile(filename)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
@@ -45,7 +46,7 @@ type StatReadFileFS interface {
}
// Create the internal state by examining the inputs.
-func CreateState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (*fid_proto.PartialCompileInputs, error) {
+func createState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (*fid_proto.PartialCompileInputs, error) {
ret := &fid_proto.PartialCompileInputs{}
slices.Sort(inputs)
for _, input := range inputs {
@@ -63,7 +64,7 @@ func CreateState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (*
}
if inspect_contents {
// NOTE: When we find it useful, we can parallelize the file inspection for speed.
- contents, err := InspectFileContents(input)
+ contents, err := inspectFileContents(input)
if err != nil {
return ret, err
}
@@ -81,7 +82,7 @@ var InspectExtsZipRegexp = regexp.MustCompile("\\.(jar|apex|apk)[0-9]*$")
// Inspect the file and extract the state of the elements in the archive.
// If this is not an archive of some sort, nil is returned.
-func InspectFileContents(name string) ([]*fid_proto.PartialCompileInput, error) {
+func inspectFileContents(name string) ([]*fid_proto.PartialCompileInput, error) {
if InspectExtsZipRegexp.Match([]byte(name)) {
return inspectZipFileContents(name)
}
@@ -111,7 +112,7 @@ func inspectZipFileContents(name string) ([]*fid_proto.PartialCompileInput, erro
return ret, nil
}
-func WriteState(s *fid_proto.PartialCompileInputs, path string) error {
+func writeState(s *fid_proto.PartialCompileInputs, path string) error {
data, err := proto.Marshal(s)
if err != nil {
return err
@@ -119,11 +120,11 @@ func WriteState(s *fid_proto.PartialCompileInputs, path string) error {
return pathtools.WriteFileIfChanged(path, data, 0644)
}
-func CompareInternalState(prior, other *fid_proto.PartialCompileInputs, target string) *FileList {
- return CompareInputFiles(prior.GetInputFiles(), other.GetInputFiles(), target)
+func compareInternalState(prior, other *fid_proto.PartialCompileInputs, target string) *FileList {
+ return compareInputFiles(prior.GetInputFiles(), other.GetInputFiles(), target)
}
-func CompareInputFiles(prior, other []*fid_proto.PartialCompileInput, name string) *FileList {
+func compareInputFiles(prior, other []*fid_proto.PartialCompileInput, name string) *FileList {
fl := FileListFactory(name)
PriorMap := make(map[string]*fid_proto.PartialCompileInput, len(prior))
// We know that the lists are properly sorted, so we can simply compare them.
@@ -139,7 +140,7 @@ func CompareInputFiles(prior, other []*fid_proto.PartialCompileInput, name strin
fl.addFile(name)
} else if !proto.Equal(PriorMap[name], v) {
// Changed file
- fl.changeFile(name, CompareInputFiles(PriorMap[name].GetContents(), v.GetContents(), name))
+ fl.changeFile(name, compareInputFiles(PriorMap[name].GetContents(), v.GetContents(), name))
}
}
for _, v := range prior {
@@ -151,3 +152,30 @@ func CompareInputFiles(prior, other []*fid_proto.PartialCompileInput, name strin
}
return fl
}
+
+func GenerateFileList(target, prior_state_file, new_state_file string, inputs []string, inspect bool, fsys StatReadFileFS) (file_list *FileList, err error) {
+ // Read the prior state
+ prior_state, err := loadState(prior_state_file, fsys)
+ if err != nil {
+ return
+ }
+ // Create the new state
+ new_state, err := createState(inputs, inspect, fsys)
+ if err != nil {
+ return
+ }
+ if err = writeState(new_state, new_state_file); err != nil {
+ return
+ }
+
+ file_list = compareInternalState(prior_state, new_state, target)
+
+ metrics_dir := os.Getenv("SOONG_METRICS_AGGREGATION_DIR")
+ out_dir := os.Getenv("OUT_DIR")
+ if metrics_dir != "" {
+ if err = file_list.WriteMetrics(metrics_dir, out_dir); err != nil {
+ return
+ }
+ }
+ return
+}
diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go
index c168d5a6b..a729193aa 100644
--- a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go
+++ b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go
@@ -116,7 +116,7 @@ func TestLoadState(t *testing.T) {
},
}
for _, tc := range testCases {
- actual, err := LoadState(tc.Filename, tc.Mapfs)
+ actual, err := loadState(tc.Filename, tc.Mapfs)
if tc.Err == nil {
android.AssertSame(t, tc.Name, tc.Err, err)
} else if err == nil {
@@ -164,7 +164,7 @@ func TestCreateState(t *testing.T) {
},
}
for _, tc := range testCases {
- actual, err := CreateState(tc.Inputs, tc.Inspect, tc.Mapfs)
+ actual, err := createState(tc.Inputs, tc.Inspect, tc.Mapfs)
if tc.Err == nil {
android.AssertSame(t, tc.Name, tc.Err, err)
} else if err == nil {
@@ -253,7 +253,7 @@ func TestCompareInternalState(t *testing.T) {
},
}
for _, tc := range testCases {
- actual := CompareInternalState(tc.Prior, tc.New, tc.Target)
+ actual := compareInternalState(tc.Prior, tc.New, tc.Target)
if !tc.Expected.Equal(actual) {
t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual)
}
diff --git a/cmd/incremental_dex_input/Android.bp b/cmd/incremental_dex_input/Android.bp
new file mode 100644
index 000000000..b68a4e69b
--- /dev/null
+++ b/cmd/incremental_dex_input/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "incremental_dex_input",
+ srcs: [
+ "main.go",
+ ],
+ deps: [
+ "soong-cmd-incremental_dex_input-lib",
+ ],
+}
diff --git a/cmd/incremental_dex_input/README.md b/cmd/incremental_dex_input/README.md
new file mode 100644
index 000000000..436a1e0be
--- /dev/null
+++ b/cmd/incremental_dex_input/README.md
@@ -0,0 +1,43 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+# Incremental Dex Input
+
+[incremental_dex_input] command line tool. This tool can be used to find the correct subset
+of java packages to be passed for incremental dexing
+
+# Getting Started
+
+## Inputs
+* class jar, jar file containing java class files to be dexed.
+* deps file, containing the dependencies for dex.
+* dexTarget path to the output of ninja rule that triggers dex
+* outputDir, path to a output dir where dex outputs are placed
+
+## Output
+* [dexTarget].rsp file, representing list of all java packages
+* [dexTarget].inc.rsp file, representing list of java packages to be incrementally dexed
+* [dexTarget].input.pc_state.new temp state file, representing the current state of all dex sources (java class files)
+* [dexTarget].deps.pc_state.new temp state file, representing the current state of dex dependencies.
+
+## Usage
+```
+incremental_dex_input --classesJar [classJar] --dexTarget [dexTargetPath] --deps [depsRspFile] --outputDir [outputDirPath]
+```
+
+## Notes
+* This tool internally references the core logic of [find_input_delta] tool.
+* All outputs are relative to the dexTarget path
+* Same class jar, deps, when used for different targets will output *different* results.
+* Once dex succeeds, the temp state files should be saved as current state files, to prepare for next iteration.
diff --git a/cmd/incremental_dex_input/incremental_dex_input_lib/Android.bp b/cmd/incremental_dex_input/incremental_dex_input_lib/Android.bp
new file mode 100644
index 000000000..b5ebfe63b
--- /dev/null
+++ b/cmd/incremental_dex_input/incremental_dex_input_lib/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-cmd-incremental_dex_input-lib",
+ pkgPath: "android/soong/cmd/incremental_dex_input/incremental_dex_input_lib",
+ deps: [
+ "blueprint-pathtools",
+ "soong-cmd-find_input_delta-lib",
+ ],
+ srcs: [
+ "generate_incremental_input.go",
+ ],
+}
diff --git a/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input.go b/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input.go
new file mode 100644
index 000000000..20d918730
--- /dev/null
+++ b/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input.go
@@ -0,0 +1,194 @@
+package incremental_dex_input_lib
+
+import (
+ "archive/zip"
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "sort"
+ "strings"
+
+ fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
+)
+
+var fileSepRegex = regexp.MustCompile("[^[:space:]]+")
+
+func GenerateIncrementalInput(jarFilePath, outputDir, packageOutputDir, dexTarget, deps string) {
+ inputPcState := dexTarget + ".input.pc_state"
+ depsPcState := dexTarget + ".deps.pc_state"
+
+ packagePaths := getAllPackages(jarFilePath)
+ var chPackagePaths []string
+ includeAllPackages := false
+
+ addF, delF, chF := findInputDelta([]string{jarFilePath}, inputPcState, dexTarget, true)
+
+ depsList := readRspFile(deps)
+ addD, delD, chD := findInputDelta(depsList, depsPcState, dexTarget, false)
+
+ // If we are not doing a partial compile, we can just return all packages in the incremental list.
+ if !usePartialCompile() {
+ includeAllPackages = true
+ chPackagePaths = packagePaths
+ }
+
+ // Changing the dependencies warrants including all packages.
+ if !includeAllPackages && len(addD)+len(delD)+len(chD) > 0 {
+ includeAllPackages = true
+ chPackagePaths = packagePaths
+ }
+
+ if !includeAllPackages {
+ chPackageSet := make(map[string]bool)
+ chPackagePaths = nil
+ // We only want to include all packages when there is a modification to the number of packages present.
+ // We loosely simulate that by including all packages when there is change in number of classes in the jar.
+ if len(addF) > 0 || len(delF) > 0 {
+ includeAllPackages = true
+ chPackagePaths = packagePaths
+ } else {
+ for _, ch := range chF {
+ // Filter out the files that do not end with ".class"
+ if normalizedPath := getPackagePath(ch); normalizedPath != "" {
+ chPackageSet[normalizedPath] = true
+ }
+ }
+
+ for path := range chPackageSet {
+ chPackagePaths = append(chPackagePaths, path)
+ }
+ sort.Strings(chPackagePaths)
+ }
+ }
+
+ preparePackagePaths(packageOutputDir, packagePaths)
+
+ writePackagePathsToRspFile(dexTarget+".rsp", packagePaths)
+ writePackagePathsToRspFile(dexTarget+".inc.rsp", chPackagePaths)
+}
+
+// Reads a rsp file and returns the content
+func readRspFile(rspFile string) (list []string) {
+ data, err := os.ReadFile(rspFile)
+ if err != nil {
+ panic(err)
+ }
+ list = append(list, fileSepRegex.FindAllString(string(data), -1)...)
+ return list
+}
+
+// Checks if Full Compile is enabled or not
+func usePartialCompile() bool {
+ usePartialCompileVar := os.Getenv("SOONG_USE_PARTIAL_COMPILE")
+ if usePartialCompileVar == "true" {
+ return true
+ }
+ return false
+}
+
+// Re-creates the package paths.
+func preparePackagePaths(packageOutputDir string, packagePaths []string) {
+ // Create package directories relative to packageOutputDir
+ for _, pkgPath := range packagePaths {
+ targetPath := filepath.Join(packageOutputDir, pkgPath)
+ if err := os.MkdirAll(targetPath, 0755); err != nil {
+ fmt.Println("err: ", err)
+ panic(err)
+ }
+ }
+}
+
+// Returns the list of java packages derived from .class files in a jar.
+func getAllPackages(jarFilePath string) []string {
+ // Open the JAR file for reading.
+ r, err := zip.OpenReader(jarFilePath)
+ if err != nil {
+ panic(err)
+ }
+ defer r.Close()
+
+ packageSet := make(map[string]bool)
+
+ // Iterate over each file in the JAR archive.
+ for _, file := range r.File {
+ if file.FileInfo().IsDir() {
+ continue
+ }
+ if packagePath := getPackagePath(file.Name); packagePath != "" {
+ packageSet[packagePath] = true
+ }
+ }
+
+ packagePaths := make([]string, 0, len(packageSet))
+ for path := range packageSet {
+ packagePaths = append(packagePaths, path)
+ }
+ sort.Strings(packagePaths)
+
+ return packagePaths
+}
+
+// Returns package path, for files ending with .class
+func getPackagePath(file string) string {
+ if strings.HasSuffix(file, ".class") {
+ dirPath := filepath.Dir(file)
+ if dirPath != "." {
+ return filepath.ToSlash(dirPath)
+ }
+ // Return `.` if the class does not have a package, i.e. present at the root
+ // of the jar.
+ return "."
+ }
+ return ""
+}
+
+// writePathsToRspFile writes a slice of strings to a file, one string per line.
+func writePackagePathsToRspFile(filePath string, packagePaths []string) {
+ // Join the paths with newline characters.
+ // Add a final newline for standard text file format.
+ content := strings.Join(packagePaths, "\n") + "\n"
+
+ // Write the content to the file.
+ err := os.WriteFile(filePath, []byte(content), 0644) // 0644: rw-r--r--
+ if err != nil {
+ fmt.Println("failed to write rsp file ", filePath, err)
+ panic(err)
+ }
+}
+
+// Computes the diff of the inputs provided, saving the temp state in the
+// priorStateFile.
+func findInputDelta(inputs []string, priorStateFile, target string, inspect bool) ([]string, []string, []string) {
+ newStateFile := priorStateFile + ".new"
+ fileList, err := fid_lib.GenerateFileList(target, priorStateFile, newStateFile, inputs, inspect, fid_lib.OsFs)
+ if err != nil {
+ panic(err)
+ }
+ return flattenChanges(fileList)
+}
+
+// Recursively flattens the output of find_input_delta.
+func flattenChanges(root *fid_lib.FileList) ([]string, []string, []string) {
+ var allAdditions []string
+ var allDeletions []string
+ var allChangedFiles []string
+
+ for _, addition := range root.Additions {
+ allAdditions = append(allAdditions, addition)
+ }
+
+ for _, del := range root.Deletions {
+ allDeletions = append(allDeletions, del)
+ }
+
+ for _, ch := range root.Changes {
+ allChangedFiles = append(allChangedFiles, ch.Name)
+ recAdd, recDel, recCh := flattenChanges(&ch)
+ allAdditions = append(allAdditions, recAdd...)
+ allDeletions = append(allDeletions, recDel...)
+ allChangedFiles = append(allChangedFiles, recCh...)
+ }
+
+ return allAdditions, allDeletions, allChangedFiles
+}
diff --git a/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input_test.go b/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input_test.go
new file mode 100644
index 000000000..a6af57a05
--- /dev/null
+++ b/cmd/incremental_dex_input/incremental_dex_input_lib/generate_incremental_input_test.go
@@ -0,0 +1,493 @@
+package incremental_dex_input_lib
+
+import (
+ "archive/zip"
+ "fmt"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+
+ soong_zip "android/soong/zip"
+
+ fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
+)
+
+// --- Tests for `readRspFile` ---
+
+func TestReadRspFile(t *testing.T) {
+ tmpDir := t.TempDir()
+
+ testCases := []struct {
+ name string
+ content string
+ expected []string
+ }{
+ {"Empty", "", nil},
+ {"SingleLine", "external/kotlinx.serialization/rules/r8.pro", []string{"external/kotlinx.serialization/rules/r8.pro"}},
+ {"MultipleLines", "external/kotlinx.serialization/rules/r8.pro\nfoo/bar/baz/guava.jar\nfoo/bar/baz1/guava1.jar", []string{"external/kotlinx.serialization/rules/r8.pro", "foo/bar/baz/guava.jar", "foo/bar/baz1/guava1.jar"}},
+ {"WithSpaces", " foo/bar/baz/guava.jar \n foo/bar/baz1/guava1.jar ", []string{"foo/bar/baz/guava.jar", "foo/bar/baz1/guava1.jar"}}, //Should be trimmed.
+ {"WithEmptyLines", "foo/bar/baz/guava.jar\n\nfoo/bar/baz1/guava1.jar", []string{"foo/bar/baz/guava.jar", "foo/bar/baz1/guava1.jar"}},
+ {"WithCarriageReturn", "foo/bar/baz/guava.jar\r\nfoo/bar/baz1/guava1.jar", []string{"foo/bar/baz/guava.jar", "foo/bar/baz1/guava1.jar"}},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ rspFile := filepath.Join(tmpDir, "test.rsp")
+ writeFile(t, rspFile, tc.content)
+
+ actual := readRspFile(rspFile)
+ if !reflect.DeepEqual(actual, tc.expected) {
+ t.Errorf("readRspFile(); expected %v, got %v", tc.expected, actual)
+ }
+ })
+ }
+
+ //Test for panic
+ t.Run("Panic on non-existent file", func(t *testing.T) {
+ defer func() {
+ if r := recover(); r == nil { //should have panicked
+ t.Errorf("readRspFile() did not panic on non-existent file")
+ }
+ }()
+ _ = readRspFile("nonexistent_file.rsp")
+ })
+}
+
+// --- Tests for `flattenChanges` ---
+
+func TestFlattenChanges(t *testing.T) {
+ fileList := &fid_lib.FileList{
+ Changes: []fid_lib.FileList{
+ {
+ Name: "out/soong/dummy/my/fav/code-target.jar",
+ Additions: []string{"foo/bar/added.class", "foo/bar/added$1.class"},
+ Deletions: []string{"foo/bar/deleted.class"},
+ Changes: []fid_lib.FileList{
+ {Name: "foo/bar/changed.class"},
+ {Name: "foo/bar/changed$1.class"},
+ },
+ },
+ },
+ }
+
+ expectedAdditions := []string{"foo/bar/added.class", "foo/bar/added$1.class"}
+ expectedDeletions := []string{"foo/bar/deleted.class"}
+ expectedChanges := []string{"out/soong/dummy/my/fav/code-target.jar", "foo/bar/changed.class", "foo/bar/changed$1.class"}
+
+ actualAdditions, actualDeletions, actualChanges := flattenChanges(fileList)
+
+ // Sort for consistent comparison
+ sort.Strings(expectedAdditions)
+ sort.Strings(actualAdditions)
+ sort.Strings(expectedDeletions)
+ sort.Strings(actualDeletions)
+ sort.Strings(expectedChanges)
+ sort.Strings(actualChanges)
+
+ if !reflect.DeepEqual(actualAdditions, expectedAdditions) {
+ t.Errorf("flattenChanges() additions; expected %v, got %v", expectedAdditions, actualAdditions)
+ }
+ if !reflect.DeepEqual(actualDeletions, expectedDeletions) {
+ t.Errorf("flattenChanges() deletions; expected %v, got %v", expectedDeletions, actualDeletions)
+ }
+ if !reflect.DeepEqual(actualChanges, expectedChanges) {
+ t.Errorf("flattenChanges() changes; expected %v, got %v", expectedChanges, actualChanges)
+ }
+}
+
+// --- Tests for `getAllPackages` ---
+func TestGetAllPackages(t *testing.T) {
+ testCases := []struct {
+ name string
+ entries map[string][]byte
+ expectedPackages []string // Must be sorted
+ }{
+ {
+ name: "Basic Functionality",
+ entries: map[string][]byte{
+ "com/example/Main.class": nil,
+ "org/gradle/Utils.class": nil,
+ "com/example/data/Model.class": nil,
+ "META-INF/MANIFEST.MF": []byte("Manifest-Version: 1.0"),
+ "config.properties": []byte("key=value"),
+ "com/example/another/One.class": nil,
+ },
+ expectedPackages: []string{"com/example", "com/example/another", "com/example/data", "org/gradle"},
+ },
+ {
+ name: "Empty JAR",
+ entries: map[string][]byte{},
+ expectedPackages: []string{},
+ },
+ {
+ name: "No Class Files",
+ entries: map[string][]byte{
+ "META-INF/MANIFEST.MF": []byte("Manifest-Version: 1.0"),
+ "resource.txt": []byte("some data"),
+ "some/dir/config.xml": nil,
+ },
+ expectedPackages: []string{},
+ },
+ {
+ name: "Root Class Files",
+ entries: map[string][]byte{
+ "RootClass.class": nil,
+ "AnotherRoot.class": nil,
+ "com/example/App.class": nil,
+ "org/myapp/Start.class": nil,
+ },
+ expectedPackages: []string{".", "com/example", "org/myapp"},
+ },
+ {
+ name: "Duplicate Packages",
+ entries: map[string][]byte{
+ "com/example/ClassA.class": nil,
+ "com/example/ClassB.class": nil,
+ "org/utils/Helper1.class": nil,
+ "org/utils/Helper2.class": nil,
+ "com/example/ClassC.class": nil,
+ },
+ expectedPackages: []string{"com/example", "org/utils"},
+ },
+ {
+ name: "Nested Packages",
+ entries: map[string][]byte{
+ "com/example/util/io/Reader.class": nil,
+ "com/example/util/net/Client.class": nil,
+ "com/example/App.class": nil,
+ },
+ expectedPackages: []string{"com/example", "com/example/util/io", "com/example/util/net"},
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc // Capture range variable
+ t.Run(tc.name, func(t *testing.T) {
+ jarFileName := strings.ReplaceAll(strings.ToLower(tc.name), " ", "_") + ".jar"
+ jarPath := createTestJar(t, jarFileName, tc.entries)
+
+ actualPackages := getAllPackages(jarPath)
+
+ // --- Assertion using standard testing package ---
+ if !reflect.DeepEqual(tc.expectedPackages, actualPackages) {
+ t.Errorf("Test case '%s' failed:\nExpected: %v\nActual: %v",
+ tc.name, tc.expectedPackages, actualPackages)
+ }
+ if len(tc.expectedPackages) != len(actualPackages) {
+ t.Errorf("Test case '%s' failed: Expected length %d, got %d",
+ tc.name, len(tc.expectedPackages), len(actualPackages))
+ }
+ })
+ }
+}
+
+// --- Test Fixture Setup ---
+// Struct to hold common test file paths
+type testFixture struct {
+ t *testing.T
+ tmpDir string
+ DexOutputDir string
+ PackageOutputDir string
+ ClassJar string
+ DepsRspFile string
+ DexTargetJar string
+ ClassFile1 string
+ ClassFile2 string
+ ClassFile3 string
+ DepJar string
+}
+
+// newTestFixture creates the temporary directory and necessary files
+func newTestFixture(t *testing.T) *testFixture {
+ tmpDir := t.TempDir() // Use t.TempDir for automatic cleanup
+
+ // Create dummy files needed for the tests
+ fixture := &testFixture{
+ t: t,
+ tmpDir: tmpDir,
+ DexOutputDir: filepath.Join(tmpDir, "dex"),
+ PackageOutputDir: filepath.Join(tmpDir, "dex", "packages"),
+ ClassJar: filepath.Join(tmpDir, "javac/classes.jar"),
+ DepsRspFile: filepath.Join(tmpDir, "dex/deps.rsp"),
+ DexTargetJar: filepath.Join(tmpDir, "dex/dex.jar"),
+ ClassFile1: filepath.Join(tmpDir, "javac/classes/com/example/ClassA.class"),
+ ClassFile2: filepath.Join(tmpDir, "javac/classes/com/example/ClassC.class"),
+ ClassFile3: filepath.Join(tmpDir, "javac/classes/org/another/ClassD.class"),
+ DepJar: filepath.Join(tmpDir, "dex/deps.jar"),
+ }
+
+ // Create directories and initial file contents
+ createDir(t, filepath.Dir(fixture.ClassFile1))
+ createDir(t, filepath.Dir(fixture.ClassFile3))
+ createDir(t, fixture.DexOutputDir)
+
+ writeFile(t, fixture.ClassFile1, "package com.example; class File1 {}")
+ writeFile(t, fixture.ClassFile2, "package com.example; class File2 {}")
+ writeFile(t, fixture.ClassFile3, "package org.another; class ClassD {}")
+
+ writeFile(t, fixture.DepJar, "Dep jar")
+
+ writeFile(t, fixture.DepsRspFile, fmt.Sprintf("%s", fixture.DepJar))
+ writeFile(t, fixture.DexTargetJar, "Dex Jar")
+
+ return fixture
+}
+
+// --- Tests for `generateIncrementalInput` ---
+
+func TestGenerateIncrementalInput(t *testing.T) {
+ // Set the environment variable to enable inc-compilation
+ t.Setenv("SOONG_USE_PARTIAL_COMPILE", "true")
+
+ // Shared setup for all subtests
+ tf := newTestFixture(t)
+
+ // --- Subtest: Initial Full Compile ---
+ t.Run("InitialFullCompile", func(t *testing.T) {
+ // Arrange
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", "com/example", "org/another"), // All files included initially
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One Class File Modified ---
+ t.Run("Incremental_OneFileModified", func(t *testing.T) {
+ // Arrange: Modify one file (ensure timestamp changes)
+ modifyFile(t, tf.ClassFile1, "Incremental_OneFileModified")
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s", "com/example"),
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - Dependency Change ---
+ t.Run("Incremental_DependencyChanged", func(t *testing.T) {
+ // Arrange: Modify the DepJar
+ modifyFile(t, tf.DepJar, "Incremental_DependencyChanged")
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: All source files should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", "com/example", "org/another"),
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One Class File Added ---
+ t.Run("Incremental_FileAdded", func(t *testing.T) {
+ // Arrange: Add one class file
+ writeFile(t, filepath.Join(tf.tmpDir, "javac/classes/org/another/ClassE.class"), "package org.another; class File4 {}")
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: Check usages of deleted file in inc.rsp, and class files
+ // corresponding to deleted files in rem.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", "com/example", "org/another"),
+ )
+ tf.savePriorState() // Save state if needed for subsequent tests
+ })
+}
+
+// --- Tests for `generateIncrementalInputPartialCompileOff` ---
+func TestGenerateIncrementalInputPartialCompileOff(t *testing.T) {
+ // Set the environment variable to enable inc-compilation
+ t.Setenv("SOONG_USE_PARTIAL_COMPILE", "")
+
+ // Shared setup for all subtests
+ tf := newTestFixture(t)
+
+ // --- Subtest: Initial Full Compile ---
+ t.Run("InitialFullCompile", func(t *testing.T) {
+ // Arrange
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", "com/example", "org/another"), // All files included initially
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One Class File Modified ---
+ t.Run("Incremental_OneFileModified", func(t *testing.T) {
+ // Arrange: Modify one file (ensure timestamp changes)
+ modifyFile(t, tf.ClassFile1, "Incremental_OneFileModified")
+ createQualifiedTestJar(t, tf.ClassJar, filepath.Join(tf.tmpDir, "javac", "classes"))
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", "com/example", "org/another"),
+ )
+ tf.savePriorState()
+ })
+}
+
+// createQualifiedTestJar creates a jar using soong_zip, mimicking javac
+func createQualifiedTestJar(t *testing.T, outputPath, inputDir string) {
+ err := soong_zip.Zip(soong_zip.ZipArgs{
+ EmulateJar: true,
+ OutputFilePath: outputPath,
+ FileArgs: soong_zip.NewFileArgsBuilder().SourcePrefixToStrip(inputDir).Dir(inputDir).FileArgs(),
+ })
+ if err != nil {
+ t.Fatalf("Error creating jar %s: %v", outputPath, err)
+ }
+}
+
+// runGenerator calls GenerateIncrementalInput for the testFixture
+func (tf *testFixture) runGenerator() {
+ // Small delay often needed for filesystem timestamp granularity
+ time.Sleep(15 * time.Millisecond)
+ GenerateIncrementalInput(tf.ClassJar, tf.DexOutputDir, tf.PackageOutputDir, tf.DexTargetJar, tf.DepsRspFile)
+}
+
+// returns incOutputPath for testFixture
+func (tf *testFixture) incOutputPath() string {
+ return tf.DexTargetJar + ".inc.rsp"
+}
+
+// Helper to save prior state
+func (tf *testFixture) savePriorState() {
+ tf.t.Helper()
+ // Implement your logic to save the necessary state files
+ // e.g., copy *.pc_state.new to *.pc_state
+ inputStateNew := tf.DexTargetJar + ".input.pc_state.new"
+ inputState := tf.DexTargetJar + ".input.pc_state"
+ depsStateNew := tf.DexTargetJar + ".deps.pc_state.new"
+ depsState := tf.DexTargetJar + ".deps.pc_state"
+
+ os.Rename(inputStateNew, inputState)
+ os.Rename(depsStateNew, depsState)
+}
+
+// Verifies the test output against expected output
+func checkOutput(t *testing.T, incOutputPath, expectedIncContent string) {
+ contentBytes, err := os.ReadFile(incOutputPath)
+ if err != nil {
+ t.Fatalf("Failed to read output file %q: %v", incOutputPath, err)
+ }
+ actualContent := strings.TrimSpace(string(contentBytes))
+
+ actualLines := strings.Split(actualContent, "\n")
+ expectedLines := strings.Split(expectedIncContent, "\n")
+ sort.Strings(actualLines)
+ sort.Strings(expectedLines)
+ actualContent = strings.Join(actualLines, "\n")
+ expectedIncContent = strings.Join(expectedLines, "\n")
+
+ if actualContent != expectedIncContent {
+ t.Errorf("Unexpected content in %q.\nGot:\n%s\nWant:\n%s", incOutputPath, actualContent, expectedIncContent)
+ }
+}
+
+// createTestJar creates a temporary JAR file for testing purposes.
+// entries is a map where key is the entry name (path inside JAR) and value is content.
+func createTestJar(t *testing.T, filename string, entries map[string][]byte) string {
+ t.Helper() // Mark this as a test helper
+
+ tempDir := t.TempDir() // Automatically cleaned up
+ fullPath := filepath.Join(tempDir, filename)
+
+ jarFile, err := os.Create(fullPath)
+ if err != nil {
+ t.Fatalf("Failed to create test JAR file %s: %v", fullPath, err)
+ }
+ defer jarFile.Close() // Ensure file is closed
+
+ zipWriter := zip.NewWriter(jarFile)
+ defer zipWriter.Close() // Ensure writer is closed
+
+ for name, content := range entries {
+ name = filepath.ToSlash(name)
+ writer, err := zipWriter.Create(name)
+ if err != nil {
+ t.Fatalf("Failed to create entry %s in test JAR %s: %v", name, filename, err)
+ }
+ if content != nil {
+ _, err = writer.Write(content)
+ if err != nil {
+ t.Fatalf("Failed to write content for entry %s in test JAR %s: %v", name, filename, err)
+ }
+ }
+ }
+
+ err = zipWriter.Close()
+ if err != nil {
+ t.Fatalf("Failed to close zip writer for JAR %s: %v", filename, err)
+ }
+ err = jarFile.Close()
+ if err != nil {
+ t.Fatalf("Failed to close JAR file %s: %v", filename, err)
+ }
+
+ return fullPath
+}
+
+// --- File Create/Mod/Delete helpers ---
+func createDir(t *testing.T, dirPath string) {
+ t.Helper()
+ err := os.MkdirAll(dirPath, 0755)
+ if err != nil {
+ t.Fatalf("Failed to create directory %q: %v", dirPath, err)
+ }
+}
+
+func writeFile(t *testing.T, filePath, content string) {
+ t.Helper()
+ err := os.WriteFile(filePath, []byte(content), 0644)
+ if err != nil {
+ t.Fatalf("Failed to write file %q: %v", filePath, err)
+ }
+}
+
+func modifyFile(t *testing.T, filePath, newContentSuffix string) {
+ t.Helper()
+ // Append suffix to ensure modification time changes reliably
+ contentBytes, err := os.ReadFile(filePath)
+ if err != nil && !os.IsNotExist(err) { // Allow modification even if file was deleted before
+ t.Fatalf("Failed to read file for modification %q: %v", filePath, err)
+ }
+ newContent := string(contentBytes) + "// " + newContentSuffix
+ writeFile(t, filePath, newContent)
+}
diff --git a/cmd/incremental_dex_input/main.go b/cmd/incremental_dex_input/main.go
new file mode 100644
index 000000000..5be86c40c
--- /dev/null
+++ b/cmd/incremental_dex_input/main.go
@@ -0,0 +1,55 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "flag"
+
+ idi_lib "android/soong/cmd/incremental_dex_input/incremental_dex_input_lib"
+)
+
+func main() {
+ var classesJar, deps, outputDir, packageOutputDir, dexTarget string
+
+ flag.StringVar(&classesJar, "classesJar", "", "jar file containing compiled java classes")
+ flag.StringVar(&deps, "deps", "", "rsp file enlisting all module deps")
+ flag.StringVar(&dexTarget, "dexTarget", "", "dex output")
+ flag.StringVar(&outputDir, "outputDir", "", "root directory for creating dex entries")
+ flag.StringVar(&packageOutputDir, "packageOutputDir", "", "root directory for creating package based dex entries")
+
+ flag.Parse()
+
+ if classesJar == "" {
+ panic("must specify --classesJar")
+ }
+
+ if deps == "" {
+ panic("must specify --deps")
+ }
+
+ if dexTarget == "" {
+ panic("must specify --dexTarget")
+ }
+
+ if outputDir == "" {
+ panic("must specify --outputDir")
+ }
+
+ if packageOutputDir == "" {
+ panic("must specify --packageOutputDir")
+ }
+
+ idi_lib.GenerateIncrementalInput(classesJar, outputDir, packageOutputDir, dexTarget, deps)
+}
diff --git a/cmd/incremental_javac_input/Android.bp b/cmd/incremental_javac_input/Android.bp
new file mode 100644
index 000000000..9d3f076ed
--- /dev/null
+++ b/cmd/incremental_javac_input/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "incremental_javac_input",
+ srcs: [
+ "main.go",
+ ],
+ deps: [
+ "soong-cmd-incremental_javac_input-lib",
+ ],
+}
diff --git a/cmd/incremental_javac_input/README.md b/cmd/incremental_javac_input/README.md
new file mode 100644
index 000000000..6ad000e9f
--- /dev/null
+++ b/cmd/incremental_javac_input/README.md
@@ -0,0 +1,45 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+# Incremental Javac Input
+
+[incremental_javac_input] command line tool. This tool can be used to find the correct subset
+of java files to be passed for incremental javac compilation.
+
+# Getting Started
+
+## Inputs
+* rsp file, containing list of java source files separated by whitespace.
+* deps file, containing the cross-module dependencies for javac.
+* javacTarget path to the output jar of javac
+* srcDepsProto, path to a proto file representing dependencies across java source files.
+* localHeaderJars *(optional)* rsp file containing space separated header jar path(s) for java sources.
+
+## Output
+* [javacTarget].inc.rsp file, representing list of java source files for incremental compilation.
+* [javacTarget].rem.rsp file, representing the list of .class files whose sources were removed and hence should be cleaned.
+* [javacTarget].input.pc_state.new temp state file, representing the current state of all java sources.
+* [javacTarget].deps.pc_state.new temp state file, representing the current state of cross-module dependencies.
+* [javacTarget].headers.pc_state.new temp state file, representing the current state of java source headers.
+
+## Usage
+```
+incremental_javac_input --srcs [srcRspFile] --deps [depsRspFile] --javacTarget [javacTargetPath] --srcDepsProto [srcDepsProtoPath] --localHeaderJars [localHeaderJarsRspFile]
+```
+
+## Notes
+* This tool internally references the core logic of [find_input_delta] tool.
+* All outputs are relative to the javacTarget path
+* Same sources, deps, headers when used for different targets will output different results.
+* Once javac succeeds, the temp state files should be saved as current state files, to prepare for next iteration. \ No newline at end of file
diff --git a/cmd/incremental_javac_input/incremental_javac_input_lib/Android.bp b/cmd/incremental_javac_input/incremental_javac_input_lib/Android.bp
new file mode 100644
index 000000000..42219a222
--- /dev/null
+++ b/cmd/incremental_javac_input/incremental_javac_input_lib/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-cmd-incremental_javac_input-lib",
+ pkgPath: "android/soong/cmd/incremental_javac_input/incremental_javac_input_lib",
+ deps: [
+ "blueprint-pathtools",
+ "soong-cmd-find_input_delta-lib",
+ "golang-dependency-mapper-protoimpl",
+ ],
+ srcs: [
+ "generate_incremental_input.go",
+ ],
+}
diff --git a/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input.go b/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input.go
new file mode 100644
index 000000000..fdc7c9466
--- /dev/null
+++ b/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input.go
@@ -0,0 +1,290 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package incremental_javac_input_lib
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+
+ fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
+ "github.com/google/blueprint/pathtools"
+ dependency_proto "go.dependencymapper/protoimpl"
+ "google.golang.org/protobuf/proto"
+)
+
+var fileSepRegex = regexp.MustCompile("[^[:space:]]+")
+
+type UsageMap struct {
+ FilePath string
+
+ Usages []string
+
+ IsDependencyToAll bool
+
+ GeneratedClasses []string
+}
+
+func GenerateIncrementalInput(classDir, srcs, deps, javacTarget, srcDeps, localHeaderJars string) (err error) {
+ incInputPath := javacTarget + ".inc.rsp"
+ removedClassesPath := javacTarget + ".rem.rsp"
+ inputPcState := javacTarget + ".input.pc_state"
+ depsPcState := javacTarget + ".deps.pc_state"
+ headersPcState := javacTarget + ".headers.pc_state"
+
+ var classesForRemoval []string
+ var incAllSources bool
+
+ // Read the srcRspFile contents
+ srcList := readRspFile(srcs)
+ // run find_input_delta, save [add + ch] as a []string, and [del] as another []string
+ addF, delF, chF := findInputDelta(srcList, inputPcState, javacTarget)
+ var incInputList []string
+ incInputList = append(incInputList, addF...)
+ incInputList = append(incInputList, chF...)
+
+ // check if deps have changed
+ depsList := readRspFile(deps)
+ if addD, delD, chD := findInputDelta(depsList, depsPcState, javacTarget); len(addD)+len(delD)+len(chD) > 0 {
+ incAllSources = true
+ }
+
+ // If we are not doing a partial compile, we can just return the full list.
+ // We can do this earlier as well, but allowing findInputDelta to run outputs
+ // the changed sources to build metrics as well as maintains the state of
+ // inputs we require if the partialCompile is switched on again.
+ if !usePartialCompile() {
+ // Remove the output class directory to prevent any stale files
+ os.RemoveAll(classDir)
+ return writeOutput(incInputPath, removedClassesPath, srcList, classesForRemoval)
+ }
+
+ // if the output directory of javac which will contain .class files is not present, include all sources
+ if !dirExists(classDir) {
+ incAllSources = true
+ }
+
+ // if javacTarget does not exist, we can include all sources
+ if incAllSources || !fileExists(javacTarget) {
+ incAllSources = true
+ }
+
+ // if incInputList has the same size as srcList (all files touched), we can
+ // just include all sources
+ if incAllSources || len(incInputList) == len(srcList) {
+ incAllSources = true
+ }
+
+ // if dependencyMap does not exist, we can include all sources
+ if incAllSources || !fileExists(srcDeps) {
+ incAllSources = true
+ }
+
+ headersChanged := false
+ // if headers do not change, we can just keep the incInputList as is.
+ // Read the srcRspFile contents
+ headersList := readRspFile(localHeaderJars)
+ if addH, delH, chH := findInputDelta(headersList, headersPcState, javacTarget); len(addH)+len(delH)+len(chH) > 0 {
+ headersChanged = true
+ }
+
+ // use revDepsMap to find all usages, add them to output, alongside [add + ch] files
+ if fileExists(srcDeps) {
+ usageMap, _ := generateUsageMap(srcDeps)
+ // if including all sources, no need to check the usageMap
+ if headersChanged && !incAllSources {
+ incInputList, incAllSources = getUsages(usageMap, incInputList, delF, headersChanged)
+ }
+ // use usageMap to add all classes that were generated from removed files.
+ classesForRemoval = generateRemovalList(usageMap, delF, classDir)
+ }
+
+ if incAllSources {
+ incInputList = srcList
+ }
+
+ // write the output to output path(s)
+ return writeOutput(incInputPath, removedClassesPath, incInputList, classesForRemoval)
+}
+
+// Checks if Full Compile is enabled or not
+func usePartialCompile() bool {
+ usePartialCompileVar := os.Getenv("SOONG_USE_PARTIAL_COMPILE")
+ if usePartialCompileVar == "true" {
+ return true
+ }
+ return false
+}
+
+// Returns the list of files that use added, modified or deleted files.
+// Returns whether to include all src Files in incremental src set
+func getUsages(usageMap map[string]UsageMap, modifiedFiles, deletedFiles []string, headersChanged bool) ([]string, bool) {
+ usagesSet := make(map[string]bool)
+
+ // First add all the modified files in the output
+ for _, incInput := range modifiedFiles {
+ usagesSet[incInput] = true
+ }
+ // Add all the usages of modified + deleted files
+ for _, modFile := range append(modifiedFiles, deletedFiles...) {
+ if um, exists := usageMap[modFile]; exists {
+ if um.IsDependencyToAll {
+ return nil, true
+ }
+ if headersChanged {
+ for _, usage := range um.Usages {
+ usagesSet[usage] = true
+ }
+ }
+ }
+ }
+
+ var usages []string
+ for usage := range usagesSet {
+ usages = append(usages, usage)
+ }
+ return usages, false
+}
+
+// Returns the list of class files to be removed, as a result of deleting a source file.
+func generateRemovalList(usageMap map[string]UsageMap, delFiles []string, classesDir string) []string {
+ var classesForRemoval []string
+ for _, delFile := range delFiles {
+ if _, exists := usageMap[delFile]; exists {
+ for _, generatedClass := range usageMap[delFile].GeneratedClasses {
+ classesForRemoval = append(classesForRemoval, filepath.Join(classesDir, generatedClass))
+ }
+ }
+ }
+ return classesForRemoval
+}
+
+// Generates the usage map, by reading the supplied dependency map as a proto
+// Throws error if the map is unparsable.
+func generateUsageMap(srcDeps string) (map[string]UsageMap, error) {
+ var message = &dependency_proto.FileDependencyList{}
+
+ usageMapSet := make(map[string]UsageMap)
+
+ data, err := os.ReadFile(srcDeps)
+ if err != nil && errors.Is(err, fs.ErrNotExist) {
+ fmt.Println("err: ", err)
+ panic(err)
+ }
+ err = proto.Unmarshal(data, message)
+ if err != nil {
+ fmt.Println("err: ", err)
+ panic(err)
+ }
+ for _, dep := range message.FileDependency {
+ addUsageMapIfNotPresent(usageMapSet, *dep.FilePath)
+ for _, depV := range dep.FileDependencies {
+ addUsageMapIfNotPresent(usageMapSet, depV)
+ updatedUsageMap := usageMapSet[depV]
+ updatedUsageMap.Usages = append(updatedUsageMap.Usages, *dep.FilePath)
+ usageMapSet[depV] = updatedUsageMap
+ }
+ updatedUsageMap := usageMapSet[*dep.FilePath]
+ updatedUsageMap.IsDependencyToAll = *dep.IsDependencyToAll
+ updatedUsageMap.GeneratedClasses = dep.GeneratedClasses
+ usageMapSet[*dep.FilePath] = updatedUsageMap
+ }
+ return usageMapSet, nil
+}
+
+func addUsageMapIfNotPresent(usageMapSet map[string]UsageMap, key string) {
+ if _, exists := usageMapSet[key]; !exists {
+ usageMap := UsageMap{
+ FilePath: key,
+ Usages: []string{},
+ IsDependencyToAll: false,
+ GeneratedClasses: []string{},
+ }
+ usageMapSet[key] = usageMap
+ }
+}
+
+func fileExists(filePath string) bool {
+ if file, err := os.Open(filePath); err != nil {
+ if os.IsNotExist(err) {
+ return false
+ }
+ panic(err)
+ } else {
+ file.Close()
+ }
+ return true
+}
+
+func dirExists(dirPath string) bool {
+ if _, err := os.Stat(dirPath); err == nil || !os.IsNotExist(err) {
+ return true
+ }
+ return false
+}
+
+func readRspFile(rspFile string) (list []string) {
+ data, err := os.ReadFile(rspFile)
+ if err != nil {
+ panic(err)
+ }
+ list = append(list, fileSepRegex.FindAllString(string(data), -1)...)
+ return list
+}
+
+// Writes incInput and classesForRemoval to output paths
+func writeOutput(incInputPath, removedClassesPath string, incInputList, classesForRemoval []string) (err error) {
+ err = pathtools.WriteFileIfChanged(incInputPath, []byte(strings.Join(incInputList, "\n")), 0644)
+ if err != nil {
+ return err
+ }
+ return pathtools.WriteFileIfChanged(removedClassesPath, []byte(strings.Join(classesForRemoval, "\n")), 0644)
+}
+
+// Computes the diff of the inputs provided, saving the temp state in the
+// priorStateFile.
+func findInputDelta(inputs []string, priorStateFile, target string) ([]string, []string, []string) {
+ newStateFile := priorStateFile + ".new"
+ fileList, err := fid_lib.GenerateFileList(target, priorStateFile, newStateFile, inputs, false, fid_lib.OsFs)
+ if err != nil {
+ panic(err)
+ }
+ return flattenChanges(fileList)
+}
+
+// Flattens the output of find_input_delta for javac's consumption.
+func flattenChanges(root *fid_lib.FileList) ([]string, []string, []string) {
+ var allAdditions []string
+ var allDeletions []string
+ var allChangedFiles []string
+
+ for _, addition := range root.Additions {
+ allAdditions = append(allAdditions, addition)
+ }
+
+ for _, del := range root.Deletions {
+ allDeletions = append(allDeletions, del)
+ }
+
+ for _, ch := range root.Changes {
+ allChangedFiles = append(allChangedFiles, ch.Name)
+ }
+
+ return allAdditions, allDeletions, allChangedFiles
+}
diff --git a/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input_test.go b/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input_test.go
new file mode 100644
index 000000000..99ea804fd
--- /dev/null
+++ b/cmd/incremental_javac_input/incremental_javac_input_lib/generate_incremental_input_test.go
@@ -0,0 +1,699 @@
+package incremental_javac_input_lib
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+
+ fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
+ dependency_proto "go.dependencymapper/protoimpl"
+ "google.golang.org/protobuf/proto"
+)
+
+// --- Tests for `getUsages` ---
+func TestGetUsages(t *testing.T) {
+ usageMap := map[string]UsageMap{
+ "file1.java": {Usages: []string{"file3.java", "file4.java"}},
+ "file2.java": {Usages: []string{"file3.java"}},
+ "file3.java": {Usages: []string{}},
+ "fileAll.java": {Usages: []string{}, IsDependencyToAll: true},
+ }
+
+ testCases := []struct {
+ name string
+ modifiedFiles []string
+ deletedFiles []string
+ expected []string
+ expectedAll bool
+ }{
+ {
+ name: "Basic",
+ modifiedFiles: []string{"file1.java"},
+ deletedFiles: []string{"file2.java"},
+ expected: []string{"file1.java", "file3.java", "file4.java"}, // file3 is used by both
+ expectedAll: false,
+ },
+ {
+ name: "Empty",
+ modifiedFiles: []string{},
+ deletedFiles: []string{},
+ expected: nil,
+ expectedAll: false,
+ },
+ {
+ name: "NonExistentFile",
+ modifiedFiles: []string{"nonexistent.java"},
+ deletedFiles: []string{},
+ expected: []string{"nonexistent.java"},
+ expectedAll: false,
+ },
+ {
+ name: "DependencyToAll",
+ modifiedFiles: []string{"file1.java"},
+ deletedFiles: []string{"fileAll.java"},
+ expected: nil,
+ expectedAll: true,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ actual, all := getUsages(usageMap, tc.modifiedFiles, tc.deletedFiles, true)
+ if all != tc.expectedAll {
+ t.Errorf("getUsages() all sources; expected %v, got %v", tc.expectedAll, all)
+ }
+
+ // Sort for consistent comparison, as map iteration order isn't guaranteed
+ sort.Strings(actual)
+ sort.Strings(tc.expected)
+ if !reflect.DeepEqual(actual, tc.expected) {
+ t.Errorf("getUsages(); expected %v, got %v", tc.expected, actual)
+ }
+ })
+ }
+}
+
+// --- Tests for `generateRemovalList` ---
+func TestGenerateRemovalList(t *testing.T) {
+ usageMap := map[string]UsageMap{
+ "file1.java": {GeneratedClasses: []string{"Class1", "Class2"}},
+ "file2.java": {GeneratedClasses: []string{"Class3"}},
+ "file3.java": {},
+ }
+
+ testCases := []struct {
+ name string
+ classDir string
+ delFiles []string
+ expected []string
+ }{
+ {"Basic", "out/classes", []string{"file1.java", "file2.java"}, []string{"out/classes/Class1", "out/classes/Class2", "out/classes/Class3"}},
+ {"Empty", "out/classes", []string{}, nil},
+ {"NonExistent", "out/classes", []string{"nonexistent.java"}, nil},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ actual := generateRemovalList(usageMap, tc.delFiles, tc.classDir)
+ sort.Strings(actual)
+ sort.Strings(tc.expected)
+ if !reflect.DeepEqual(actual, tc.expected) {
+ t.Errorf("generateRemovalList(); expected %v, got %v", tc.expected, actual)
+ }
+ })
+ }
+}
+
+// --- Tests for `generateUsageMap` ---
+func TestGenerateUsageMap(t *testing.T) {
+ tmpDir := t.TempDir()
+
+ // 1. Test with a valid proto file.
+ protoFile := filepath.Join(tmpDir, "deps.pb")
+ createProtoFile(t, protoFile)
+
+ usageMap, err := generateUsageMap(protoFile)
+ if err != nil {
+ t.Fatalf("generateUsageMap() returned an error: %v", err)
+ }
+
+ expectedUsageMap := map[string]UsageMap{
+ "file1.java": {FilePath: "file1.java", Usages: []string{}, IsDependencyToAll: false, GeneratedClasses: []string{"ClassA", "ClassB"}},
+ "file2.java": {FilePath: "file2.java", Usages: []string{"file1.java"}, IsDependencyToAll: true, GeneratedClasses: []string{"ClassC"}},
+ "file3.java": {FilePath: "file3.java", Usages: []string{"file1.java"}, IsDependencyToAll: false, GeneratedClasses: []string{"ClassD"}},
+ }
+
+ if !reflect.DeepEqual(usageMap, expectedUsageMap) {
+ t.Errorf("generateUsageMap() returned unexpected map.\nGot: %+v\nWant:%+v", usageMap, expectedUsageMap)
+ }
+
+ // 2. Test with a non-existent file (should panic)
+ t.Run("Panic on non-existent proto", func(t *testing.T) {
+ defer func() {
+ if r := recover(); r == nil { //should have panicked
+ t.Errorf("generateUsageMap() did not panic on non-existent proto")
+ }
+ }()
+ _, _ = generateUsageMap("nonexistent.pb")
+ })
+
+ // 3. Test with an invalid proto file (should panic)
+ invalidProtoFile := filepath.Join(tmpDir, "invalid.pb")
+ writeFile(t, invalidProtoFile, "This is not a valid proto file") // Create invalid file
+ t.Run("Panic on invalid proto file", func(t *testing.T) {
+ defer func() {
+ if r := recover(); r == nil { //should have panicked
+ t.Errorf("generateUsageMap() did not panic on invalid proto")
+ }
+ }()
+ _, _ = generateUsageMap(invalidProtoFile)
+ })
+}
+
+// --- Tests for `readRspFile` ---
+func TestReadRspFile(t *testing.T) {
+ tmpDir := t.TempDir()
+
+ testCases := []struct {
+ name string
+ content string
+ expected []string
+ }{
+ {"Empty", "", nil},
+ {"SingleLine", "file1.java", []string{"file1.java"}},
+ {"MultipleLines", "file1.java\nfile2.java\nfile3.java", []string{"file1.java", "file2.java", "file3.java"}},
+ {"WithSpaces", " file1.java \n file2.java ", []string{"file1.java", "file2.java"}}, //Should be trimmed.
+ {"WithEmptyLines", "file1.java\n\nfile2.java", []string{"file1.java", "file2.java"}},
+ {"WithCarriageReturn", "file1.java\r\nfile2.java", []string{"file1.java", "file2.java"}},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ rspFile := filepath.Join(tmpDir, "test.rsp")
+ writeFile(t, rspFile, tc.content)
+
+ actual := readRspFile(rspFile)
+ if !reflect.DeepEqual(actual, tc.expected) {
+ t.Errorf("readRspFile(); expected %v, got %v", tc.expected, actual)
+ }
+ })
+ }
+
+ //Test for panic
+ t.Run("Panic on non-existent file", func(t *testing.T) {
+ defer func() {
+ if r := recover(); r == nil { //should have panicked
+ t.Errorf("readRspFile() did not panic on non-existent file")
+ }
+ }()
+ _ = readRspFile("nonexistent_file.rsp")
+ })
+}
+
+// --- Tests for `flattenChanges` ---
+
+func TestFlattenChanges(t *testing.T) {
+ fileList := &fid_lib.FileList{
+ Additions: []string{"add1.java", "add2.java"},
+ Deletions: []string{"del1.java"},
+ Changes: []fid_lib.FileList{
+ {Name: "change1.java"},
+ {Name: "change2.java"},
+ },
+ }
+
+ expectedAdditions := []string{"add1.java", "add2.java"}
+ expectedDeletions := []string{"del1.java"}
+ expectedChanges := []string{"change1.java", "change2.java"}
+
+ actualAdditions, actualDeletions, actualChanges := flattenChanges(fileList)
+
+ // Sort for consistent comparison
+ sort.Strings(expectedAdditions)
+ sort.Strings(actualAdditions)
+ sort.Strings(expectedDeletions)
+ sort.Strings(actualDeletions)
+ sort.Strings(expectedChanges)
+ sort.Strings(actualChanges)
+
+ if !reflect.DeepEqual(actualAdditions, expectedAdditions) {
+ t.Errorf("flattenChanges() additions; expected %v, got %v", expectedAdditions, actualAdditions)
+ }
+ if !reflect.DeepEqual(actualDeletions, expectedDeletions) {
+ t.Errorf("flattenChanges() deletions; expected %v, got %v", expectedDeletions, actualDeletions)
+ }
+ if !reflect.DeepEqual(actualChanges, expectedChanges) {
+ t.Errorf("flattenChanges() changes; expected %v, got %v", expectedChanges, actualChanges)
+ }
+}
+
+// --- Tests for `GenerateIncrementalInput` ---
+
+func TestGenerateIncrementalInput(t *testing.T) {
+ // Set the environment variable to enable inc-compilation
+ t.Setenv("SOONG_USE_PARTIAL_COMPILE", "true")
+
+ // Shared setup for all subtests
+ tf := newTestFixture(t)
+ // No need for top-level defer os.RemoveAll(tmpDir) because t.TempDir() handles it
+
+ // --- Subtest: Initial Full Compile ---
+ t.Run("InitialFullCompile", func(t *testing.T) {
+ // Arrange (already done by newTestFixture)
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s\n%s", tf.JavaFile1, tf.JavaFile2, tf.JavaFile3), // All files included initially
+ tf.remOutputPath(),
+ "", // No removals initially
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One File Modified ---
+ t.Run("Incremental_OneFileModified", func(t *testing.T) {
+ // Arrange: Modify one file (ensure timestamp changes)
+ modifyFile(t, tf.JavaFile3, "Incremental_OneFileModified")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: Only the modified file should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s", tf.JavaFile3),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One File and Header Modified ---
+ t.Run("Incremental_FileAndHeaderModified", func(t *testing.T) {
+ // Arrange: Modify a different file and the header jar
+ modifyFile(t, tf.JavaFile3, "Incremental_FileAndHeaderModified")
+ modifyFile(t, tf.HeaderJar, "Incremental_FileAndHeaderModified")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: All source files and their usages should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s", tf.JavaFile1, tf.JavaFile3),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - Dependency Change ---
+ t.Run("Incremental_DependencyChanged", func(t *testing.T) {
+ // Arrange: Modify the DepJar
+ modifyFile(t, tf.DepJar, "Incremental_DependencyChanged")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: All source files should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s\n%s", tf.JavaFile1, tf.JavaFile2, tf.JavaFile3),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - File which is dependency to all files is Changed ---
+ t.Run("Incremental_DependencyToAllChanged", func(t *testing.T) {
+ // Arrange: Modify the DepsRspFile or JavaSrcDeps proto
+ modifyFile(t, tf.JavaFile2, "Incremental_DependencyToAllChanged")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: All source files should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s", tf.JavaFile2),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - File which is dependency to all files is changed along with headers---
+ t.Run("Incremental_DependencyToAllChangedWithHeaders", func(t *testing.T) {
+ // Arrange: Modify the DepsRspFile or JavaSrcDeps proto
+ modifyFile(t, tf.JavaFile2, "Incremental_DependencyToAllChangedWithHeader")
+ modifyFile(t, tf.HeaderJar, "Incremental_DependencyToAllChangedWithHeader")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: All source files should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s\n%s", tf.JavaFile1, tf.JavaFile2, tf.JavaFile3),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One File Deleted, Header Modified ---
+ t.Run("Incremental_FileDeletedHeaderModified", func(t *testing.T) {
+ // Arrange: Delete one file and modify header
+ deleteFile(t, tf.JavaFile3, tf.SrcRspFile)
+ // Modify Headers
+ modifyFile(t, tf.HeaderJar, "Incremental_FileDeletedHeaderModified")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: Check usages of deleted file in inc.rsp, and class files
+ // corresponding to deleted files in rem.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s", tf.JavaFile1), // usages of deleted file
+ tf.remOutputPath(),
+ filepath.Join(tf.ClassDir, "org.another.ClassD"), // class name corresponding to the deleted file path
+ )
+ tf.savePriorState() // Save state if needed for subsequent tests
+ })
+}
+
+func TestGenerateIncrementalInputPartialCompileOff(t *testing.T) {
+ // Set the environment variable to disable inc-compilation
+ t.Setenv("SOONG_USE_PARTIAL_COMPILE", "")
+
+ // Shared setup for all subtests
+ tf := newTestFixture(t)
+ // No need for top-level defer os.RemoveAll(tmpDir) because t.TempDir() handles it
+
+ // --- Subtest: Initial Full Compile ---
+ t.Run("InitialFullCompile", func(t *testing.T) {
+ // Arrange (already done by newTestFixture)
+
+ // Act
+ tf.runGenerator()
+
+ // Assert
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s\n%s", tf.JavaFile1, tf.JavaFile2, tf.JavaFile3), // All files included initially
+ tf.remOutputPath(),
+ "", // No removals initially
+ )
+ tf.savePriorState()
+ })
+
+ // --- Subtest: Incremental - One File Modified, should add all files ---
+ t.Run("Incremental_OneFileModified_AddsAllFiles", func(t *testing.T) {
+ // Arrange: Modify one file (ensure timestamp changes)
+ modifyFile(t, tf.JavaFile3, "Incremental_OneFileModified")
+
+ // Act
+ tf.runGenerator()
+
+ // Assert: Only the modified file should be in inc.rsp
+ checkOutput(
+ t,
+ tf.incOutputPath(),
+ fmt.Sprintf("%s\n%s\n%s", tf.JavaFile1, tf.JavaFile2, tf.JavaFile3),
+ tf.remOutputPath(),
+ "", // No removals
+ )
+ tf.savePriorState()
+ })
+}
+
+// --- Test Fixture Setup ---
+// Struct to hold common test file paths
+type testFixture struct {
+ t *testing.T
+ tmpDir string
+ ClassDir string
+ SrcRspFile string
+ DepsRspFile string
+ JavacTargetJar string
+ JavaSrcDeps string
+ HeadersRspFile string
+ JavaFile1 string
+ JavaFile2 string
+ JavaFile3 string
+ DepJar string
+ HeaderJar string
+}
+
+// newTestFixture creates the temporary directory and necessary files
+func newTestFixture(t *testing.T) *testFixture {
+ tmpDir := t.TempDir() // Use t.TempDir for automatic cleanup
+
+ // Create dummy files needed for the tests
+ fixture := &testFixture{
+ t: t,
+ tmpDir: tmpDir,
+ ClassDir: filepath.Join(tmpDir, "classes"),
+ SrcRspFile: filepath.Join(tmpDir, "sources.rsp"),
+ DepsRspFile: filepath.Join(tmpDir, "deps.rsp"),
+ JavacTargetJar: filepath.Join(tmpDir, "output.jar"),
+ JavaSrcDeps: filepath.Join(tmpDir, "srcdeps.pb"), // Example proto file path
+ HeadersRspFile: filepath.Join(tmpDir, "localHeaders.rsp"),
+ JavaFile1: filepath.Join(tmpDir, "src/com/example/ClassA.java"),
+ JavaFile2: filepath.Join(tmpDir, "src/com/example/ClassC.java"),
+ JavaFile3: filepath.Join(tmpDir, "src/org/another/ClassD.java"), // Example different package
+ DepJar: filepath.Join(tmpDir, "deps.jar"),
+ HeaderJar: filepath.Join(tmpDir, "headers.jar"),
+ }
+
+ // Create directories and initial file contents
+ createDir(t, filepath.Dir(fixture.JavaFile1))
+ createDir(t, filepath.Dir(fixture.JavaFile3))
+ createDir(t, fixture.ClassDir)
+
+ writeFile(t, fixture.JavaFile1, "package com.example; class File1 {}")
+ writeFile(t, fixture.JavaFile2, "package com.example; class File2 {}")
+ writeFile(t, fixture.JavaFile3, "package org.another; class ClassD {}")
+
+ writeFile(t, fixture.DepJar, "Dep jar")
+ writeFile(t, fixture.HeaderJar, "Header jar")
+
+ writeFile(t, fixture.SrcRspFile, fmt.Sprintf("%s\n%s\n%s", fixture.JavaFile1, fixture.JavaFile2, fixture.JavaFile3))
+ writeFile(t, fixture.DepsRspFile, fmt.Sprintf("%s", fixture.DepJar))
+ writeFile(t, fixture.HeadersRspFile, fmt.Sprintf("%s", fixture.HeaderJar))
+ writeFile(t, fixture.JavacTargetJar, "Javac Jar")
+ writeFile(t, fixture.JavaSrcDeps, "")
+ createProtoFileWithActualPaths(t, fixture.JavaSrcDeps, fixture.JavaFile1, fixture.JavaFile2, fixture.JavaFile3)
+
+ return fixture
+}
+
+// runGenerator calls GenerateIncrementalInput for the testFixture
+func (tf *testFixture) runGenerator() {
+ // Small delay often needed for filesystem timestamp granularity
+ time.Sleep(15 * time.Millisecond)
+ err := GenerateIncrementalInput(tf.ClassDir, tf.SrcRspFile, tf.DepsRspFile, tf.JavacTargetJar, tf.JavaSrcDeps, tf.HeadersRspFile)
+ if err != nil {
+ tf.t.Fatalf("GenerateIncrementalInput() returned an error: %v", err)
+ }
+}
+
+// returns incOutputPath for testFixture
+func (tf *testFixture) incOutputPath() string {
+ return tf.JavacTargetJar + ".inc.rsp"
+}
+
+// returns remOutputPath for testFixture
+func (tf *testFixture) remOutputPath() string {
+ return tf.JavacTargetJar + ".rem.rsp"
+}
+
+// Verifies the test output against expected output
+func checkOutput(t *testing.T, incOutputPath, expectedIncContent, remOutputPath, expectedRemContent string) {
+ checkFileContent(t, incOutputPath, expectedIncContent)
+ checkFileContent(t, remOutputPath, expectedRemContent)
+}
+
+// Helper to check if the content of a file matches the expected content (order insensitive)
+func checkFileContent(t *testing.T, filePath, expectedContent string) {
+ contentBytes, err := os.ReadFile(filePath)
+ if err != nil {
+ t.Fatalf("Failed to read output file %q: %v", filePath, err)
+ }
+ actualContent := strings.TrimSpace(string(contentBytes))
+
+ actualLines := strings.Split(actualContent, "\n")
+ expectedLines := strings.Split(expectedContent, "\n")
+ sort.Strings(actualLines)
+ sort.Strings(expectedLines)
+ actualContent = strings.Join(actualLines, "\n")
+ expectedContent = strings.Join(expectedLines, "\n")
+
+ if actualContent != expectedContent {
+ t.Errorf("Unexpected content in %q.\nGot:\n%s\nWant:\n%s", filePath, actualContent, expectedContent)
+ }
+}
+
+// Helper to save prior state
+func (tf *testFixture) savePriorState() {
+ tf.t.Helper()
+ // Implement your logic to save the necessary state files
+ // e.g., copy *.pc_state.new to *.pc_state
+ inputStateNew := tf.JavacTargetJar + ".input.pc_state.new"
+ inputState := tf.JavacTargetJar + ".input.pc_state"
+ depsStateNew := tf.JavacTargetJar + ".deps.pc_state.new"
+ depsState := tf.JavacTargetJar + ".deps.pc_state"
+ headerStateNew := tf.JavacTargetJar + ".headers.pc_state.new"
+ headerState := tf.JavacTargetJar + ".headers.pc_state"
+
+ os.Rename(inputStateNew, inputState)
+ os.Rename(depsStateNew, depsState)
+ os.Rename(headerStateNew, headerState)
+}
+
+// --- File Create/Mod/Delete helpers ---
+
+func createDir(t *testing.T, dirPath string) {
+ t.Helper()
+ err := os.MkdirAll(dirPath, 0755)
+ if err != nil {
+ t.Fatalf("Failed to create directory %q: %v", dirPath, err)
+ }
+}
+
+func writeFile(t *testing.T, filePath, content string) {
+ t.Helper()
+ err := os.WriteFile(filePath, []byte(content), 0644)
+ if err != nil {
+ t.Fatalf("Failed to write file %q: %v", filePath, err)
+ }
+}
+
+func modifyFile(t *testing.T, filePath, newContentSuffix string) {
+ t.Helper()
+ // Append suffix to ensure modification time changes reliably
+ contentBytes, err := os.ReadFile(filePath)
+ if err != nil && !os.IsNotExist(err) { // Allow modification even if file was deleted before
+ t.Fatalf("Failed to read file for modification %q: %v", filePath, err)
+ }
+ newContent := string(contentBytes) + "// " + newContentSuffix
+ writeFile(t, filePath, newContent)
+}
+
+func deleteFile(t *testing.T, filePath, srcRspFilePath string) {
+ t.Helper()
+ err := os.Remove(filePath)
+ if err != nil && !os.IsNotExist(err) { // Ignore error if already deleted
+ t.Fatalf("Failed to delete file %q: %v", filePath, err)
+ }
+ // Also update the source rsp file!
+ updateSrcRsp(t, srcRspFilePath, filePath, true)
+}
+
+func updateSrcRsp(t *testing.T, rspPath, filePath string, remove bool) {
+ t.Helper()
+ contentBytes, err := os.ReadFile(rspPath)
+ if err != nil {
+ t.Fatalf("Failed to read source rsp file %q: %v", rspPath, err)
+ }
+ lines := strings.Split(string(contentBytes), "\n")
+ var newLines []string
+ found := false
+ for _, line := range lines {
+ trimmedLine := strings.TrimSpace(line)
+ if trimmedLine == "" {
+ continue
+ }
+ if trimmedLine == filePath {
+ found = true
+ if !remove { // Keep it if not removing
+ newLines = append(newLines, trimmedLine)
+ }
+ } else {
+ newLines = append(newLines, trimmedLine)
+ }
+ }
+ // Add back if it wasn't found and we are not removing (e.g., restoring)
+ if !found && !remove {
+ newLines = append(newLines, filePath)
+ }
+
+ writeFile(t, rspPath, strings.Join(newLines, "\n"))
+}
+
+// --- ProtoFile Creation helpers ---
+
+func createProtoFile(t *testing.T, filePath string) string {
+ t.Helper()
+
+ dep1 := &dependency_proto.FileDependency{
+ FilePath: proto.String("file1.java"),
+ FileDependencies: []string{"file2.java", "file3.java"},
+ IsDependencyToAll: proto.Bool(false),
+ GeneratedClasses: []string{"ClassA", "ClassB"},
+ }
+ dep2 := &dependency_proto.FileDependency{
+ FilePath: proto.String("file2.java"),
+ FileDependencies: []string{},
+ IsDependencyToAll: proto.Bool(true),
+ GeneratedClasses: []string{"ClassC"},
+ }
+ dep3 := &dependency_proto.FileDependency{
+ FilePath: proto.String("file3.java"),
+ FileDependencies: []string{},
+ IsDependencyToAll: proto.Bool(false),
+ GeneratedClasses: []string{"ClassD"},
+ }
+
+ message := &dependency_proto.FileDependencyList{
+ FileDependency: []*dependency_proto.FileDependency{dep1, dep2, dep3},
+ }
+
+ data, err := proto.Marshal(message)
+ if err != nil {
+ t.Fatalf("Failed to marshal proto message: %v", err)
+ }
+
+ if err := os.WriteFile(filePath, data, 0644); err != nil {
+ t.Fatalf("Failed to write proto file: %v", err)
+ }
+
+ return filePath
+}
+
+func createProtoFileWithActualPaths(t *testing.T, protoFilePath, javaFile1, javaFile2, javaFile3 string) string {
+ t.Helper()
+
+ dep1 := &dependency_proto.FileDependency{
+ FilePath: proto.String(javaFile1),
+ FileDependencies: []string{javaFile2, javaFile3},
+ IsDependencyToAll: proto.Bool(false),
+ GeneratedClasses: []string{"src/com/example/ClassA", "src/com/example/ClassB"},
+ }
+ dep2 := &dependency_proto.FileDependency{
+ FilePath: proto.String(javaFile2),
+ FileDependencies: []string{},
+ IsDependencyToAll: proto.Bool(true),
+ GeneratedClasses: []string{"src/com/example/ClassC"},
+ }
+ dep3 := &dependency_proto.FileDependency{
+ FilePath: proto.String(javaFile3),
+ FileDependencies: []string{},
+ IsDependencyToAll: proto.Bool(false),
+ GeneratedClasses: []string{"org.another.ClassD"},
+ }
+
+ message := &dependency_proto.FileDependencyList{
+ FileDependency: []*dependency_proto.FileDependency{dep1, dep2, dep3},
+ }
+
+ data, err := proto.Marshal(message)
+ if err != nil {
+ t.Fatalf("Failed to marshal proto message: %v", err)
+ }
+
+ if err := os.WriteFile(protoFilePath, data, 0644); err != nil {
+ t.Fatalf("Failed to write proto file: %v", err)
+ }
+
+ return protoFilePath
+}
diff --git a/cmd/incremental_javac_input/main.go b/cmd/incremental_javac_input/main.go
new file mode 100644
index 000000000..a3c8d9717
--- /dev/null
+++ b/cmd/incremental_javac_input/main.go
@@ -0,0 +1,68 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+
+ iji_lib "android/soong/cmd/incremental_javac_input/incremental_javac_input_lib"
+)
+
+func main() {
+ var classDir, srcs, deps, javacTarget, srcDepsProto, localHeaderJars string
+
+ flag.StringVar(&classDir, "classDir", "", "dir which will contain compiled java classes")
+ flag.StringVar(&srcs, "srcs", "", "rsp file containing java source paths")
+ flag.StringVar(&deps, "deps", "", "rsp file enlisting all module deps")
+ flag.StringVar(&javacTarget, "javacTarget", "", "javac output")
+ flag.StringVar(&srcDepsProto, "srcDepsProto", "", "dependency map between src files in a proto")
+ flag.StringVar(&localHeaderJars, "localHeaderJars", "", "rsp file enlisting all local header jars")
+
+ flag.Parse()
+
+ if classDir == "" {
+ panic("must specify --classDir")
+ }
+
+ if deps == "" {
+ panic("must specify --deps")
+ }
+
+ if javacTarget == "" {
+ panic("must specify --javacTarget")
+ }
+
+ if localHeaderJars == "" {
+ panic("must specify --localHeaderJars")
+ }
+
+ if srcDepsProto == "" {
+ panic("must specify --depsProto")
+ }
+
+ if srcs == "" {
+ panic("must specify --srcs")
+ }
+
+ if srcs != "" {
+ err := iji_lib.GenerateIncrementalInput(classDir, srcs, deps, javacTarget, srcDepsProto, localHeaderJars)
+ if err != nil {
+ panic("errored")
+ }
+ } else {
+ fmt.Println("No source files provided via --srcs flag.")
+ }
+}
diff --git a/cmd/kotlinc_incremental/Android.bp b/cmd/kotlinc_incremental/Android.bp
index 7816553ee..5c1456fc0 100644
--- a/cmd/kotlinc_incremental/Android.bp
+++ b/cmd/kotlinc_incremental/Android.bp
@@ -34,9 +34,13 @@ java_library_host {
"src/com/**/*.kt",
],
static_libs: [
+ "kotlin-build-tools-api",
+ "kotlin-build-tools-impl",
"kotlin-compiler-embeddable",
"kotlin-compiler-runner",
"kotlin-daemon-client",
+ "kotlinx_coroutines",
+ "kotlinc-trove4j",
],
plugins: [],
@@ -44,12 +48,31 @@ java_library_host {
kotlincflags: [
"-Werror",
],
+ kotlin_incremental: false,
}
java_binary_host {
name: "kotlin-incremental-client",
manifest: "kotlin-incremental-client.mf",
static_libs: ["kotlin-incremental-client-lib"],
+ libs: ["kotlin-build-tools-impl"],
+ required: [
+ "kotlin-build-tools-impl",
+ "kotlin-compose-compiler-embeddable",
+ ],
+ kotlin_incremental: false,
+}
+
+java_binary_host {
+ name: "kotlin-jar-snapshotter",
+ manifest: "kotlin-jar-snapshotter.mf",
+ static_libs: ["kotlin-incremental-client-lib"],
+ libs: ["kotlin-build-tools-impl"],
+ required: [
+ "kotlin-build-tools-impl",
+ "kotlin-compose-compiler-embeddable",
+ ],
+ kotlin_incremental: false,
}
java_test_host {
@@ -57,6 +80,9 @@ java_test_host {
srcs: [
"tests/src/com/**/*.kt",
],
+ data: [
+ "tests/resources/test_build.xml",
+ ],
static_libs: [
"kotlin-incremental-client-lib",
"junit",
diff --git a/cmd/kotlinc_incremental/kotlin-jar-snapshotter.mf b/cmd/kotlinc_incremental/kotlin-jar-snapshotter.mf
new file mode 100644
index 000000000..af6b752be
--- /dev/null
+++ b/cmd/kotlinc_incremental/kotlin-jar-snapshotter.mf
@@ -0,0 +1 @@
+Main-Class: com.android.kotlin.compiler.snapshotter.MainKt
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Argument.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Argument.kt
new file mode 100644
index 000000000..e46074751
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Argument.kt
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.cli
+
+import java.io.File
+import java.io.PrintStream
+
+fun <O : Options> parseArgs(
+ args: Array<String>,
+ opts: O,
+ argumentParsers: List<Argument<out Any, O>>,
+ stdoutPrinter: PrintStream,
+ stderrPrinter: PrintStream,
+ additionalHelp: String? = null,
+): Boolean {
+ var matched: Boolean
+ var hasError = false
+ var showHelp = args.isEmpty()
+ val iter = args.iterator()
+ while (iter.hasNext()) {
+ val arg = iter.next()
+ matched = false
+ for (parser in argumentParsers) {
+ if (parser.matches(arg)) {
+ matched = true
+ if (parser is HelpArgument) {
+ showHelp = true
+ }
+ parser.parse(arg, iter, opts)
+ if (parser.error != null) {
+ hasError = true
+ stderrPrinter.println(parser.error)
+ stderrPrinter.println()
+ }
+ break
+ }
+ }
+ if (!matched) {
+ opts.passThroughArgs.add(arg.substring(0))
+ }
+ }
+
+ if (showHelp) {
+ showArgumentHelp(argumentParsers, stdoutPrinter, additionalHelp)
+ }
+
+ return !hasError
+}
+
+fun <O : Options> showArgumentHelp(
+ argumentParsers: List<Argument<out Any, O>>,
+ printer: PrintStream,
+ additionalHelp: String?,
+) {
+ var longest = -1
+ val padding = 5
+
+ printer.println(
+ "Usage: kotlin-incremental-client <-root-dir> <dir> [options] [kotlinc options] [-- <source files>]"
+ )
+ printer.println()
+ for (parser in argumentParsers) {
+ if (parser.argumentName.length > longest) {
+ longest = parser.argumentName.length
+ }
+ }
+
+ val indent = " ".repeat(longest + padding)
+ for (parser in argumentParsers) {
+ print(("-" + parser.argumentName).padEnd(longest + padding))
+ var first = true
+ parser.helpText.lines().forEach {
+ if (first) {
+ printer.println(it)
+ first = false
+ } else {
+ printer.println(indent + it)
+ }
+ }
+ if (parser.default != null) {
+ printer.print(indent + "[Default: ")
+ if (parser.default is String) {
+ printer.println("\"${parser.default}\"]")
+ } else {
+ printer.println("${parser.default}]")
+ }
+ }
+ }
+
+ if (additionalHelp != null) {
+ println()
+ println(additionalHelp)
+ }
+}
+
+abstract class Argument<T, O : Options> {
+ abstract val argumentName: String
+ abstract val helpText: String
+ abstract val default: T?
+
+ var error: String? = null
+ protected set
+
+ abstract fun matches(arg: String): Boolean
+
+ abstract fun parse(arg: String, position: Iterator<String>, opts: O)
+
+ abstract fun setOption(option: T, opts: O)
+
+ fun setupDefault(opts: O) {
+ if (default != null) {
+ setOption(default!!, opts)
+ }
+ }
+}
+
+abstract class NoArgument<O : Options> : Argument<Boolean, O>() {
+ override val default = null
+
+ override fun matches(arg: String) = arg == "-$argumentName"
+
+ override fun parse(arg: String, position: Iterator<String>, opts: O) {
+ setOption(true, opts)
+ }
+}
+
+abstract class SingleArgument<T, O : Options> : Argument<T, O>() {
+
+ override fun matches(arg: String) = arg.startsWith("-$argumentName=")
+
+ override fun parse(arg: String, position: Iterator<String>, opts: O) {
+ val splits = arg.split("=", limit = 2)
+ if (splits.size != 2 || splits[1].isEmpty()) {
+ error = "Required argument not supplied for $argumentName"
+ return
+ }
+ val value = stringToType(splits[1])
+ setOption(value, opts)
+ }
+
+ abstract fun stringToType(arg: String): T
+}
+
+abstract class StringArgument<O : Options> : SingleArgument<String, O>() {
+ override fun stringToType(arg: String): String {
+ return arg
+ }
+}
+
+abstract class WritableDirectoryArgument<O : Options> : StringArgument<O>() {
+ override fun setOption(option: String, opts: O) {
+ val e = isValidDirectoryForWriting(option)
+ if (e != null) {
+ error = "Invalid $argumentName option specified: $e"
+ } else {
+ setDirectory(File(option), opts)
+ }
+ }
+
+ abstract fun setDirectory(dir: File, opts: O)
+}
+
+class HelpArgument<O : Options> : NoArgument<O>() {
+ override val argumentName = "h"
+
+ override val helpText = """
+ Outputs this help text.
+ """.trimIndent()
+
+ override fun setOption(option: Boolean, opts: O) {}
+}
+
+abstract class SubdirectoryArgument<O : Options> : StringArgument<O>() {
+ override fun setOption(option: String, opts: O) {
+ if (option.isBlank()) {
+ error = "Invalid $argumentName option specified: Must be non-empty string."
+ } else if (option.contains("..")) {
+ error = "Invalid $argumentName option specified: No path traversal allowed."
+ } else {
+ setSubDirectory(option, opts)
+ }
+ }
+
+ abstract fun setSubDirectory(dir: String, opts: O)
+}
+
+fun isValidDirectoryForWriting(filePath: String): String? {
+ try {
+ val file = File(filePath)
+ if (file.exists()) {
+ if (!file.isDirectory) {
+ return "Path exists but is not a directory"
+ }
+ if (!file.canWrite()) {
+ return "Directory exists but is not writable"
+ }
+ } else if (!file.mkdirs()) {
+ return "Unable to create directory"
+ }
+
+ return null // All checks passed!
+ } catch (e: Exception) {
+ // Handle exceptions like invalid path characters, no permissions, etc.
+ return e.message
+ }
+}
+
+fun isValidFilePathForWriting(filePath: String): String? {
+ if (filePath.isBlank()) {
+ return "Empty log-file path"
+ }
+
+ try {
+ val file = File(filePath)
+ val parentDir = file.parentFile ?: return "Invalid parent directory"
+
+ if (!parentDir.exists()) {
+ if (!parentDir.mkdirs()) {
+ return "Unable to create parent directory"
+ }
+ } else if (!parentDir.isDirectory) {
+ return "Parent directory is not a directory"
+ } else if (!parentDir.canWrite()) {
+ return "Parent directory is not writable"
+ }
+
+ if (file.exists()) {
+ if (file.isDirectory) {
+ return "File is a directory"
+ } else if (!file.canWrite()) {
+ return "File exists but is not writable"
+ }
+ }
+
+ return null // All checks passed!
+ } catch (e: Exception) {
+ // Handle exceptions like invalid path characters, no permissions, etc.
+ return e.message
+ }
+}
diff --git a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Options.kt
index 3354aa49c..3e5344ec7 100644
--- a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/cli/Options.kt
@@ -14,14 +14,8 @@
* limitations under the License.
*/
-package com.android.kotlin.compiler.client
+package com.android.kotlin.compiler.cli
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-class MainTest {
- @Test
- fun testMain() {
- assertThat(true).isTrue()
- }
-} \ No newline at end of file
+interface Options {
+ val passThroughArgs: MutableList<String>
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Argument.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Argument.kt
new file mode 100644
index 000000000..cd6223bcc
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Argument.kt
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import com.android.kotlin.compiler.cli.Argument
+import com.android.kotlin.compiler.cli.NoArgument
+import com.android.kotlin.compiler.cli.StringArgument
+import com.android.kotlin.compiler.cli.SubdirectoryArgument
+import com.android.kotlin.compiler.cli.WritableDirectoryArgument
+import java.io.File
+import javax.xml.parsers.SAXParserFactory
+
+class Verbose : NoArgument<ClientOptions>() {
+ override val argumentName = "verbose"
+ override val helpText =
+ """
+ Outputs additional information during compilation. Quite noisy.
+ """
+ .trimIndent()
+
+ override fun setOption(option: Boolean, opts: ClientOptions) {
+ opts.verbose = option
+ }
+}
+
+class Debug : NoArgument<ClientOptions>() {
+ override val argumentName = "debug"
+ override val helpText =
+ """
+ Outputs additional information during compilation.
+ """.trimIndent()
+
+ override fun setOption(option: Boolean, opts: ClientOptions) {
+ opts.debug = option
+ }
+}
+
+class SourcesArgument : Argument<String, ClientOptions>() {
+ override val default = null
+ override val argumentName = "-"
+ override val helpText =
+ """
+ Everything after this is treated as a source file.
+ """.trimIndent()
+
+ override fun matches(arg: String) = arg == "--"
+
+ override fun parse(arg: String, position: Iterator<String>, opts: ClientOptions) {
+ position.forEachRemaining { setOption(it, opts) }
+ }
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.addSource(option)
+ }
+}
+
+class BuildFileArgument : StringArgument<ClientOptions>() {
+ override val default = null
+
+ override val argumentName = "build-file"
+ override val helpText =
+ """
+ Build file containing sources and classpaths to be consumed by kotlinc. See
+ -Xbuild-file on kotlinc.
+ """
+ .trimIndent()
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.buildFileLocation = option
+ parseBuildFile(opts.buildFile!!, opts)
+ }
+
+ private fun parseBuildFile(buildFile: File, opts: ClientOptions) {
+ val parser = BuildFileParser()
+ val spf = SAXParserFactory.newInstance()
+ val saxParser = spf.newSAXParser()
+ val xmlReader = saxParser.xmlReader
+ xmlReader.contentHandler = parser
+ xmlReader.parse(buildFile.absolutePath)
+
+ opts.buildFileModuleName = parser.moduleName
+ opts.buildFileClassPaths = parser.classpaths
+ opts.buildFileSources = parser.sources
+ opts.buildFileJavaSources = parser.javaSources
+ if (parser.outputDirName != null) {
+ opts.outputDirName = parser.outputDirName!!
+ }
+ }
+}
+
+class XBuildFileArgument : StringArgument<ClientOptions>() {
+ override val default = null
+
+ override val argumentName = "Xbuild-file"
+ override val helpText = """
+ Deprecated: use -build-file
+ """.trimIndent()
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ error = "Can not parse -Xbuild-file. Please use -build-file."
+ }
+}
+
+class LogDirArgument : WritableDirectoryArgument<ClientOptions>() {
+ override val argumentName = "log-dir"
+ override val helpText = """
+ Directory to write log output to.
+ """.trimIndent()
+ override val default = null
+
+ override fun setDirectory(dir: File, opts: ClientOptions) {
+ opts.logDir = dir
+ }
+}
+
+class RunFilesArgument : WritableDirectoryArgument<ClientOptions>() {
+ override val argumentName = "run-files-path"
+ override val helpText =
+ """
+ Local directory to place lock files and other process-specific
+ metadata.
+ """
+ .trimIndent()
+ override val default = "/tmp"
+
+ override fun setDirectory(dir: File, opts: ClientOptions) {
+ opts.runFiles = dir
+ }
+}
+
+class RootDirArgument : WritableDirectoryArgument<ClientOptions>() {
+ override val argumentName = "root-dir"
+ override val helpText =
+ """
+ Base directory for the Kotlin daemon's artifacts.
+ Other directories - working-dir, output-dir, and build-dir - are all relative
+ to this directory.
+ This option is REQUIRED.
+ """
+ .trimIndent()
+ override val default = null
+
+ override fun setDirectory(dir: File, opts: ClientOptions) {
+ opts.rootDir = dir
+ }
+}
+
+class WorkingDirArgument : SubdirectoryArgument<ClientOptions>() {
+ override val argumentName = "working-dir"
+ override val helpText =
+ """
+ Stores intermediate steps used specifically for incremental compilation.
+ Must be maintained between compilation invocations to see
+ incremental speed benefits.
+ Relative to root-dir.
+ """
+ .trimIndent()
+ override val default = "work"
+
+ override fun setSubDirectory(dir: String, opts: ClientOptions) {
+ opts.workingDirName = dir
+ }
+}
+
+class OutputDirArgument : SubdirectoryArgument<ClientOptions>() {
+ override val argumentName = "output-dir"
+ override val helpText =
+ """
+ Where to output compiler results.
+ Relative to root-dir.
+ """
+ .trimIndent()
+ override val default = "output"
+
+ override fun setSubDirectory(dir: String, opts: ClientOptions) {
+ opts.outputDirName = dir
+ }
+}
+
+class BuildDirArgument : SubdirectoryArgument<ClientOptions>() {
+ override val argumentName = "build-dir"
+ override val helpText =
+ """
+ TODO: figure out what this is. Notes say:
+ "buildDir is the parent of destDir and workingDir"
+ """
+ .trimIndent()
+ override val default = "build"
+
+ override fun setSubDirectory(dir: String, opts: ClientOptions) {
+ opts.buildDirName = dir
+ }
+}
+
+class SourceDeltaArgument : StringArgument<ClientOptions>() {
+ override val argumentName = "source-delta-file"
+ override val helpText =
+ """
+ Input file containing a list of added, modified, and deleted source files since the last
+ run. Additions and modifications should be the file name preceded by a +. Deletions should
+ be the file name preceded by a -. Files should be separated by white space.
+ """
+ .trimIndent()
+
+ override val default = null
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.sourceDeltaFileName = option
+ }
+}
+
+class BuildHistoryFileArgument : StringArgument<ClientOptions>() {
+ override val argumentName = "build-history"
+ override val helpText =
+ """
+ Location of the build-history file used for incremental compilation.
+ """
+ .trimIndent()
+ override val default = "build-history"
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.buildHistoryFileName = option
+ }
+}
+
+class ClassPathArgument : StringArgument<ClientOptions>() {
+ override val argumentName = "classpath"
+ override val helpText =
+ """
+ List of directories and JAR/ZIP archives to search for user class files.
+ Colon separated: "foo.jar:bar.jar"
+ """
+ .trimIndent()
+ override val default = null
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ val paths = option.split(":").filter { !it.isBlank() }
+ // TODO: validate paths?
+ opts.classPath.addAll(paths)
+ }
+}
+
+/**
+ * Intercepts the -Xplugin argument of kotlinc such that we can prepend them to the front of the
+ * classpath.
+ *
+ * Without this, you can run into a bug where a passed in plugin can cause a plugin implementing the
+ * same package+classname to be loaded from a different part of the classpath than is intended.
+ */
+class PluginArgument : StringArgument<ClientOptions>() {
+ override val argumentName = "Xplugin"
+ override val helpText =
+ """
+ Compiler plugins passed to kotlin. See the `-Xplugin` argument of kotlinc.
+ """
+ .trimIndent()
+ override val default = null
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.classPath.addFirst(option)
+ opts.passThroughArgs.add("-Xplugin=$option")
+ }
+}
+
+class JvmArgument : Argument<String, ClientOptions>() {
+ override val argumentName = "-J<option>"
+ override val helpText = """
+ Options passed through to the JVM.
+ """.trimIndent()
+ override val default = null
+
+ override fun matches(arg: String) = arg.startsWith("-J")
+
+ override fun parse(arg: String, position: Iterator<String>, opts: ClientOptions) {
+ // Strip off "-J-" so that we're left with just "<option>"
+ setOption(arg.substring(3), opts)
+ }
+
+ override fun setOption(option: String, opts: ClientOptions) {
+ opts.jvmArgs.add(option)
+ }
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/BuildFileParser.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/BuildFileParser.kt
new file mode 100644
index 000000000..2e26e4373
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/BuildFileParser.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import org.xml.sax.Attributes
+import org.xml.sax.helpers.DefaultHandler
+
+class BuildFileParser : DefaultHandler() {
+ val classpaths: List<String>
+ get() = _classpaths
+
+ val sources: List<String>
+ get() = _sources
+
+ val javaSources: List<String>
+ get() = _javaSources
+
+ val moduleName: String?
+ get() = _moduleName
+
+ val outputDirName: String?
+ get() = _outputDirName
+
+ private val _classpaths = mutableListOf<String>()
+ private val _sources = mutableListOf<String>()
+ private val _javaSources = mutableListOf<String>()
+ private var _moduleName: String? = null
+ private var _outputDirName: String? = null
+
+ override fun startElement(
+ uri: String?,
+ localName: String?,
+ qName: String?,
+ attributes: Attributes?,
+ ) {
+ when (qName) {
+ "module" -> parseModule(attributes)
+ "classpath" -> parseClassPath(attributes)
+ "sources" -> parseSources(attributes)
+ "javaSourceRoots" -> parseJavaSourceRoots(attributes)
+ }
+ }
+
+ private fun parseClassPath(attributes: Attributes?) {
+ if (attributes == null) {
+ return
+ }
+
+ val cp = attributes.getValue("", "path")
+ if (cp == null) {
+ return
+ }
+ _classpaths.add(cp)
+ }
+
+ private fun parseSources(attributes: Attributes?) {
+ if (attributes == null) {
+ return
+ }
+
+ val path = attributes.getValue("", "path")
+ if (path == null) {
+ return
+ }
+
+ _sources.add(path)
+ }
+
+ private fun parseJavaSourceRoots(attributes: Attributes?) {
+ if (attributes == null) {
+ return
+ }
+
+ val path = attributes.getValue("", "path")
+ if (path == null) {
+ return
+ }
+
+ _javaSources.add(path)
+ }
+
+ private fun parseModule(attributes: Attributes?) {
+ if (attributes == null) {
+ return
+ }
+
+ _moduleName = attributes.getValue("", "name")
+ _outputDirName = attributes.getValue("", "outputDir")
+ }
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/ClientOptions.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/ClientOptions.kt
new file mode 100644
index 000000000..63febb932
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/ClientOptions.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import com.android.kotlin.compiler.cli.Options
+import java.io.File
+
+class ClientOptions : Options {
+ var verbose = false
+ var debug = false
+
+ val classPath = mutableListOf<String>()
+ override val passThroughArgs = mutableListOf<String>()
+ val jvmArgs = mutableListOf<String>()
+ val _sources = mutableListOf<String>()
+ val sources
+ get() = _sources
+
+ fun addSource(arg: String) {
+ _sources.add(arg)
+ }
+
+ private var _rootDir: File? = null
+ var rootDir: File
+ get() {
+ return _rootDir ?: throw IllegalStateException("Can not read rootDir before it is set")
+ }
+ set(value) {
+ _rootDir = value
+ }
+
+ var rootDirLocation: String
+ get() {
+ return _rootDir?.absolutePath
+ ?: throw IllegalStateException("Can not read rootDirLocation before it is set")
+ }
+ set(value) {
+ if (value == "") {
+ _rootDir = null
+ } else {
+ _rootDir = File(value)
+ }
+ }
+
+ var buildDirName: String = "build"
+ val buildDir: File
+ get() {
+ if (_rootDir == null) {
+ throw IllegalStateException("Can not read buildDir before rootDir is set")
+ }
+ if (buildDirName.isEmpty()) {
+ throw IllegalStateException("buildDirName may not be empty.")
+ }
+ return File(rootDir, buildDirName)
+ }
+
+ var outputDirName: String = "output"
+ val outputDir: File
+ get() {
+ if (_rootDir == null) {
+ throw IllegalStateException("Can not read outputDir before rootDir is set")
+ }
+ if (outputDirName.isEmpty()) {
+ throw IllegalStateException("outputDirName may not be empty.")
+ }
+ return File(rootDir, outputDirName)
+ }
+
+ var workingDirName: String = "work"
+ val workingDir: File
+ get() {
+ if (_rootDir == null) {
+ throw IllegalStateException("Can not read workingDir before rootDir is set")
+ }
+ if (workingDirName.isEmpty()) {
+ throw IllegalStateException("workingDirName may not be empty.")
+ }
+ return File(rootDir, workingDirName)
+ }
+
+ var sourceDeltaFileName: String? = null
+ val sourceDeltaFile: File?
+ get() = if (sourceDeltaFileName != null) File(sourceDeltaFileName!!) else null
+
+ var buildHistoryFileName: String = "build-history"
+ val buildHistory: File
+ get() {
+ if (_rootDir == null) {
+ throw IllegalStateException("Can not read buildHistory before rootDir is set")
+ }
+ if (buildHistoryFileName.isEmpty()) {
+ throw IllegalStateException("buildHistoryFileName may not be empty.")
+ }
+ return File(rootDir, buildHistoryFileName)
+ }
+
+ private var _logDir: File? = null
+ var logDir: File
+ get() {
+ return _logDir ?: throw IllegalStateException("Can not read logDir before it is set")
+ }
+ set(value) {
+ _logDir = value
+ }
+
+ var logDirLocation: String
+ get() {
+ return _logDir?.absolutePath
+ ?: throw IllegalStateException("Can not read logDirLocation before it is set")
+ }
+ set(value) {
+ if (value == "") {
+ _logDir = null
+ } else {
+ _logDir = File(value)
+ }
+ }
+
+ private var _runFiles: File? = null
+ var runFiles: File
+ get() {
+ return _runFiles
+ ?: throw IllegalStateException("Can not read runFiles before it is set")
+ }
+ set(value) {
+ _runFiles = value
+ }
+
+ var runFilesLocation: String
+ get() {
+ return _runFiles?.absolutePath
+ ?: throw IllegalStateException("Can not read runFilesLocation before it is set")
+ }
+ set(value) {
+ if (value == "") {
+ _runFiles = null
+ } else {
+ _runFiles = File(value)
+ }
+ }
+
+ private var _buildFile: File? = null
+ var buildFile: File?
+ get() = _buildFile
+ set(value) {
+ _buildFile = value
+ }
+
+ var buildFileLocation: String?
+ get() {
+ return _buildFile?.absolutePath
+ ?: throw IllegalStateException("Can not read buildFileLocation before it is set")
+ }
+ set(value) {
+ if (value == "" || value == null) {
+ _buildFile = null
+ } else {
+ _buildFile = File(value)
+ }
+ }
+
+ var buildFileModuleName: String? = null
+
+ var buildFileClassPaths: List<String> = emptyList()
+
+ var buildFileSources: List<String> = emptyList()
+
+ var buildFileJavaSources: List<String> = emptyList()
+
+ private var classpathSnapshotDir: String = "cpsnapshot"
+ val classpathSnapshot: File
+ get() {
+ if (_rootDir == null) {
+ throw IllegalStateException("Can not read classpathSnapshot before rootDir is set")
+ }
+ if (classpathSnapshotDir.isEmpty()) {
+ throw IllegalStateException("classpathSnapshotDir may not be empty.")
+ }
+ return File(rootDir, classpathSnapshotDir)
+ }
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Logger.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Logger.kt
new file mode 100644
index 000000000..80c7a977a
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Logger.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import org.jetbrains.kotlin.buildtools.api.KotlinLogger
+
+class Logger(private val verbose: Boolean, override val isDebugEnabled: Boolean) : KotlinLogger {
+ override fun debug(msg: String) {
+ if (isDebugEnabled) {
+ println("DEBUG: " + msg)
+ }
+ }
+
+ override fun error(msg: String, throwable: Throwable?) {
+ println("ERROR: " + msg)
+ if (throwable != null) {
+ println(throwable)
+ }
+ }
+
+ override fun info(msg: String) {
+ if (verbose) {
+ println("INFO: " + msg)
+ }
+ }
+
+ override fun lifecycle(msg: String) {
+ println("LIFECYCLE: " + msg)
+ }
+
+ override fun warn(msg: String, throwable: Throwable?) {
+ println("WARN: " + msg)
+ if (throwable != null) {
+ println(throwable)
+ }
+ }
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt
index 493864148..270225651 100644
--- a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt
@@ -16,6 +16,237 @@
package com.android.kotlin.compiler.client
+import com.android.kotlin.compiler.cli.HelpArgument
+import com.android.kotlin.compiler.cli.parseArgs
+import com.android.kotlin.compiler.snapshotter.fileToSnapshotFile
+import java.io.File
+import java.net.URLClassLoader
+import java.util.UUID
+import kotlin.system.exitProcess
+import org.jetbrains.kotlin.buildtools.api.CompilationResult
+import org.jetbrains.kotlin.buildtools.api.CompilationService
+import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
+import org.jetbrains.kotlin.buildtools.api.ProjectId
+import org.jetbrains.kotlin.buildtools.api.SourcesChanges
+import org.jetbrains.kotlin.buildtools.api.jvm.ClasspathSnapshotBasedIncrementalCompilationApproachParameters
+
+private val ARGUMENT_PARSERS =
+ listOf(
+ BuildDirArgument(),
+ BuildFileArgument(),
+ BuildHistoryFileArgument(),
+ ClassPathArgument(),
+ Debug(),
+ HelpArgument(),
+ JvmArgument(),
+ LogDirArgument(),
+ OutputDirArgument(),
+ PluginArgument(),
+ RunFilesArgument(),
+ RootDirArgument(),
+ SourceDeltaArgument(),
+ Verbose(),
+ WorkingDirArgument(),
+ XBuildFileArgument(),
+ SourcesArgument(), // must come last
+ )
+
+val ADDITIONAL_HELP =
+ """
+ EXAMPLES
+ ========
+
+ kotlin-incremental-client -root-dir=/tmp/helloworld -- HelloWorld.kt
+
+ kotlin-incremental-client -root-dir=/tmp/helloworld -build-file=HelloWorldBuild.xml
+
+ kotlin-incremental-client -root-dir=/tmp/helloworld -output-dir=out -- HelloWorld.kt
+"""
+ .trimIndent()
+
fun main(args: Array<String>) {
- println("compiling")
+ val opts = ClientOptions()
+ ARGUMENT_PARSERS.forEach { it.setupDefault(opts) }
+
+ if (!parseArgs(args, opts, ARGUMENT_PARSERS, System.out, System.err, ADDITIONAL_HELP)) {
+ exitProcess(-1)
+ }
+
+ if (opts.sources.isEmpty() && (opts.buildFile == null || opts.buildFileSources.isEmpty())) {
+ println("No sources or build file specified. Exiting.")
+ exitProcess(0)
+ }
+
+ val result = BTACompilation(opts)
+ when (result) {
+ CompilationResult.COMPILATION_SUCCESS -> {}
+ CompilationResult.COMPILATION_ERROR -> exitProcess(-1)
+ CompilationResult.COMPILATION_OOM_ERROR -> {
+ println("Out of Memory")
+ exitProcess(-2)
+ }
+
+ CompilationResult.COMPILER_INTERNAL_ERROR -> {
+ println("Internal compiler error. Please report to https://kotl.in/issue")
+ exitProcess(-3)
+ }
+ }
+}
+
+fun BTACompilation(opts: ClientOptions): CompilationResult {
+ val kotlincArgs = mutableListOf<String>()
+ if (opts.buildFile != null) {
+ if (opts.buildFileModuleName != null) {
+ kotlincArgs.add("-module-name")
+ kotlincArgs.add(opts.buildFileModuleName!!)
+ }
+ }
+ kotlincArgs.add("-d=${opts.outputDir.absolutePath}")
+ kotlincArgs.addAll(opts.passThroughArgs)
+ kotlincArgs.addAll(opts.sources)
+ kotlincArgs.addAll(opts.buildFileJavaSources)
+ return doBtaCompilation(
+ opts.sources + opts.buildFileSources,
+ opts.classPath + opts.buildFileClassPaths,
+ opts.workingDir,
+ opts.outputDir,
+ opts.sourceDeltaFile,
+ kotlincArgs,
+ opts.jvmArgs,
+ Logger(opts.verbose, opts.debug),
+ )
+}
+
+@OptIn(ExperimentalBuildToolsApi::class)
+fun doBtaCompilation(
+ sources: List<String>,
+ classPath: List<String>,
+ workingDirectory: File,
+ outputDirectory: File,
+ sourceDeltaFile: File?,
+ args: List<String>,
+ jvmArgs: List<String>,
+ logger: Logger,
+): CompilationResult {
+ var anyMissing = false
+ sources.forEach {
+ if (!File(it).exists()) {
+ logger.error("Missing source: $it")
+ anyMissing = true
+ }
+ }
+
+ if (anyMissing) {
+ return CompilationResult.COMPILATION_ERROR
+ }
+
+ val loader =
+ URLClassLoader(
+ classPath.map { File(it).toURI().toURL() }.toTypedArray() +
+ // Need to include this code's own jar in the classpath.
+ arrayOf(ClientOptions::class.java.protectionDomain?.codeSource?.location)
+ )
+
+ val service = CompilationService.loadImplementation(loader)
+ val executionConfig = service.makeCompilerExecutionStrategyConfiguration()
+ // TODO: investigate using the daemon.
+ // Right now, it hangs (https://youtrack.jetbrains.com/issue/KT-75142/)
+ // executionConfig.useDaemonStrategy(jvmArgs)
+ executionConfig.useInProcessStrategy()
+ val compilationConfig = service.makeJvmCompilationConfiguration()
+
+ val cpsnapshotParameters = getClasspathSnapshotParameters(workingDirectory, classPath)
+
+ val incJvmCompilationConfig =
+ compilationConfig.makeClasspathSnapshotBasedIncrementalCompilationConfiguration()
+ var sourceChanges: SourcesChanges = SourcesChanges.Unknown
+ if (sourceDeltaFile != null) {
+ sourceChanges = parseSourceChanges(sourceDeltaFile)
+ }
+ compilationConfig.useIncrementalCompilation(
+ workingDirectory,
+ sourceChanges,
+ cpsnapshotParameters,
+ incJvmCompilationConfig,
+ )
+ compilationConfig.useLogger(logger)
+
+ val pid = ProjectId.ProjectUUID(UUID.randomUUID())
+ val mArgs = args.toMutableList()
+ mArgs.add("-cp")
+ mArgs.add(classPath.joinToString(":"))
+ return service.compileJvm(
+ pid,
+ executionConfig,
+ compilationConfig,
+ sources.map { File(it) },
+ mArgs,
+ )
+}
+
+@OptIn(ExperimentalBuildToolsApi::class)
+fun getClasspathSnapshotParameters(
+ workingDirectory: File,
+ classPath: List<String>,
+): ClasspathSnapshotBasedIncrementalCompilationApproachParameters {
+ val cps = File(workingDirectory.parentFile, "shrunk-classpath-snapshot.bin")
+ val cpsFiles =
+ classPath.mapNotNull {
+ val cpFile = File(it)
+ if (!cpFile.exists()) {
+ throw RuntimeException("classpath entry does not exist: $it")
+ }
+
+ val snf = fileToSnapshotFile(cpFile)
+
+ if (!snf.exists()) {
+ null
+ } else {
+ snf
+ }
+ }
+
+ return ClasspathSnapshotBasedIncrementalCompilationApproachParameters(
+ newClasspathSnapshotFiles = cpsFiles,
+ shrunkClasspathSnapshot = cps,
+ )
+}
+
+fun parseSourceChanges(sourceDeltaFile: File): SourcesChanges.Known {
+ val modifiedList = mutableListOf<File>()
+ val removedList = mutableListOf<File>()
+ for (entry in sourceDeltaFile.readText().split(" ")) {
+ if (entry.length < 1) {
+ continue
+ }
+ val f = File(entry.substring(1))
+ when {
+ entry.startsWith("+") -> {
+ if (!f.exists()) {
+ throw RuntimeException(
+ "Supplied file diff contains modified file that does not exist: $entry"
+ )
+ }
+ modifiedList.add(f.absoluteFile)
+ }
+
+ entry.startsWith("-") -> {
+ /*
+ if (f.exists()) {
+ throw RuntimeException(
+ "Supplied file diff contains removed file that exist: $entry"
+ )
+ }
+ */
+ removedList.add(f.absoluteFile)
+ }
+
+ else -> {
+ throw RuntimeException(
+ "Supplied file diff contains entry that can not be parsed: $entry"
+ )
+ }
+ }
+ }
+ return SourcesChanges.Known(modifiedFiles = modifiedList, removedFiles = removedList)
}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Argument.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Argument.kt
new file mode 100644
index 000000000..e8406ab5b
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Argument.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.snapshotter
+
+import com.android.kotlin.compiler.cli.NoArgument
+import com.android.kotlin.compiler.cli.StringArgument
+
+class JarArgument : StringArgument<SnapshotterOptions>() {
+ override val argumentName = "jar"
+
+ override val helpText = """
+ The jar to generate a snapshot of.
+ """.trimIndent()
+
+ override val default: String? = null
+
+ override fun setOption(option: String, opts: SnapshotterOptions) {
+ opts.jarFileName = option
+ }
+}
+
+class HelpArgument : NoArgument<SnapshotterOptions>() {
+ override val argumentName = "h"
+
+ override val helpText = """
+ Outputs this help text.
+ """.trimIndent()
+
+ override fun setOption(option: Boolean, opts: SnapshotterOptions) {}
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Main.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Main.kt
new file mode 100644
index 000000000..2cae92423
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Main.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.snapshotter
+
+import com.android.kotlin.compiler.cli.parseArgs
+import java.io.File
+import java.net.URLClassLoader
+import kotlin.system.exitProcess
+import org.jetbrains.kotlin.buildtools.api.CompilationService
+import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
+import org.jetbrains.kotlin.buildtools.api.jvm.ClassSnapshotGranularity
+
+private val ARGUMENT_PARSERS = listOf(JarArgument(), HelpArgument())
+
+fun main(args: Array<String>) {
+ val opts = SnapshotterOptions()
+ ARGUMENT_PARSERS.forEach { it.setupDefault(opts) }
+
+ if (!parseArgs(args, opts, ARGUMENT_PARSERS, System.out, System.err)) {
+ exitProcess(-1)
+ }
+
+ if (opts.jarFile == null) {
+ println("No jar specified. Exiting.")
+ exitProcess(0)
+ }
+
+ snapshotJar(opts.jarFile!!)
+}
+
+@OptIn(ExperimentalBuildToolsApi::class)
+fun snapshotJar(jar: File) {
+ val snf = fileToSnapshotFile(jar)
+
+ val loader =
+ URLClassLoader(
+ // Need to include this code's own jar in the classpath.
+ arrayOf(SnapshotterOptions::class.java.protectionDomain?.codeSource?.location)
+ )
+
+ val service = CompilationService.loadImplementation(loader)
+ val sn = service.calculateClasspathSnapshot(jar, ClassSnapshotGranularity.CLASS_MEMBER_LEVEL)
+ sn.saveSnapshot(snf)
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/SnapshotterOptions.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/SnapshotterOptions.kt
new file mode 100644
index 000000000..656d15ea9
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/SnapshotterOptions.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.snapshotter
+
+import com.android.kotlin.compiler.cli.Options
+import java.io.File
+
+class SnapshotterOptions : Options {
+ override val passThroughArgs = mutableListOf<String>()
+
+ var jarFileName: String? = null
+ val jarFile: File?
+ get() = if (jarFileName != null) File(jarFileName!!) else null
+}
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Util.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Util.kt
new file mode 100644
index 000000000..f302cc2a5
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/snapshotter/Util.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.snapshotter
+
+import java.io.File
+
+fun fileToSnapshotFile(file: File): File {
+ val snName = file.name.replace(".", "_") + "-snapshot.bin"
+ return File(file.parentFile, snName)
+}
diff --git a/cmd/kotlinc_incremental/tests/resources/test_build.xml b/cmd/kotlinc_incremental/tests/resources/test_build.xml
new file mode 100644
index 000000000..ed443d49c
--- /dev/null
+++ b/cmd/kotlinc_incremental/tests/resources/test_build.xml
@@ -0,0 +1,10 @@
+<modules>
+ <module name="test_module" type="java-production" outputDir="output">
+ <classpath path="a.jar" />
+ <classpath path="b.jar" />
+ <javaSourceRoots path="c.java" />
+ <javaSourceRoots path="d.java" />
+ <sources path="e.kt" />
+ <sources path="f.kt" />
+ </module>
+</modules> \ No newline at end of file
diff --git a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/cli/ArgumentTest.kt b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/cli/ArgumentTest.kt
new file mode 100644
index 000000000..0e474f299
--- /dev/null
+++ b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/cli/ArgumentTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.cli
+
+import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayOutputStream
+import java.io.PrintStream
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+class ArgumentTest {
+
+ class TestOpts : Options {
+ override val passThroughArgs = mutableListOf<String>()
+ }
+
+ private val opts = TestOpts()
+ private val stdoutStreamCaptor = ByteArrayOutputStream()
+ private val stderrStreamCaptor = ByteArrayOutputStream()
+
+ @get:Rule val tFolder = TemporaryFolder()
+
+ @Before fun setup() {}
+
+ @Test
+ fun testParseArgs_NoError() {
+ val argParsers = listOf(HelpArgument<TestOpts>())
+ val args = arrayOf("-h", "foo", "bar", "baz")
+
+ val result =
+ parseArgs(
+ args,
+ opts,
+ argParsers,
+ PrintStream(stdoutStreamCaptor),
+ PrintStream(stderrStreamCaptor),
+ )
+
+ assertThat(result).isTrue()
+ assertThat(opts.passThroughArgs).isEqualTo(listOf("foo", "bar", "baz"))
+ assertThat(stdoutStreamCaptor.toString()).startsWith("Usage: ")
+ assertThat(stderrStreamCaptor.toString()).isEmpty()
+ }
+
+ @Test
+ fun testParseArgs_Error() {
+ class ErrorArg : NoArgument<TestOpts>() {
+ override val argumentName = "error"
+ override val helpText = "This argument forces an error"
+
+ override fun setOption(option: Boolean, opts: TestOpts) {
+ error = "A forced error"
+ }
+ }
+
+ val argParsers = listOf(ErrorArg())
+ val args = arrayOf("-error", "foo", "bar", "baz")
+
+ val result =
+ parseArgs(
+ args,
+ opts,
+ argParsers,
+ PrintStream(stdoutStreamCaptor),
+ PrintStream(stderrStreamCaptor),
+ )
+
+ assertThat(result).isFalse()
+ assertThat(stdoutStreamCaptor.toString()).isEmpty()
+ assertThat(stderrStreamCaptor.toString()).isEqualTo(argParsers.get(0).error + "\n\n")
+ }
+
+ @Test
+ fun testHelpArgument() {
+ val ha = HelpArgument<TestOpts>()
+ assertThat(ha.matches("-h")).isTrue()
+ val args = listOf("foo").iterator()
+ ha.parse("-h", args, opts)
+ assertThat(args.hasNext()).isTrue()
+ }
+}
diff --git a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/ArgumentTest.kt b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/ArgumentTest.kt
new file mode 100644
index 000000000..7c0b225b4
--- /dev/null
+++ b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/ArgumentTest.kt
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.nio.file.attribute.PosixFilePermission
+import kotlin.io.path.setPosixFilePermissions
+import org.junit.Assert.assertThrows
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+class ArgumentTest {
+
+ private val opts = ClientOptions()
+
+ @get:Rule val tFolder = TemporaryFolder()
+
+ @Before fun setup() {}
+
+ @Test
+ fun testSourcesArgument_NoAdditional() {
+ val dda = SourcesArgument()
+ assertThat(dda.matches("--")).isTrue()
+ dda.parse("--", emptyList<String>().iterator(), opts)
+ assertThat(opts.sources.size).isEqualTo(0)
+ }
+
+ @Test
+ fun testSourcesArgument_OneArgument() {
+ val dda = SourcesArgument()
+ val arg1 = "foo"
+ dda.parse("--", listOf(arg1).iterator(), opts)
+ assertThat(opts.sources.size).isEqualTo(1)
+ assertThat(opts.sources.get(0)).isEqualTo(arg1)
+ }
+
+ @Test
+ fun testSourcesArgument_MultiArgument() {
+ val dda = SourcesArgument()
+ // Test a variety of argument formats, even though we treat them all as source.
+ val args = listOf("foo", "bar", "-cp", "this:is:a:classpath", "-single", "-with-arg", "arg")
+ dda.parse("--", args.iterator(), opts)
+ assertThat(opts.sources.size).isEqualTo(args.size)
+ assertThat(opts.sources).isEqualTo(args)
+ }
+
+ @Test
+ fun testBuildFileArgument() {
+ val bfa = BuildFileArgument()
+ val buildFile = File("tests/resources/test_build.xml")
+ val arg = "-build-file=" + buildFile.absoluteFile
+ bfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(opts.buildFileLocation).isEqualTo(buildFile.absolutePath)
+ }
+
+ @Test
+ fun testBuildFileArgument_SetsOptions() {
+ val bfa = BuildFileArgument()
+ val buildFile = File("tests/resources/test_build.xml")
+ val arg = "-build-file=" + buildFile.absoluteFile
+ bfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(opts.buildFileLocation).isEqualTo(buildFile.absolutePath)
+ assertThat(opts.buildFileClassPaths).containsExactly("a.jar", "b.jar")
+ assertThat(opts.buildFileJavaSources).containsExactly("c.java", "d.java")
+ assertThat(opts.buildFileSources).containsExactly("e.kt", "f.kt")
+ assertThat(opts.buildFileModuleName).isEqualTo("test_module")
+ assertThat(opts.outputDirName).isEqualTo("output")
+ }
+
+ @Test
+ fun testBuildFileArgument_NoArgument() {
+ val bfa = BuildFileArgument()
+ val arg = "-build-file="
+ bfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThrows(IllegalStateException::class.java, { opts.buildFileLocation })
+ assertThat(bfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testLogDirArgument() {
+ val lfa = LogDirArgument()
+ val logDirLocation = tFolder.root.absolutePath
+ val arg = "-log-dir=$logDirLocation"
+ assertThat(lfa.matches(arg)).isTrue()
+ lfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.logDirLocation).isEqualTo(logDirLocation)
+ assertThat(lfa.error).isNull()
+ }
+
+ @Test
+ fun testLogDirArgument_NoArgument() {
+ val lfa = LogDirArgument()
+ val arg = "-log-dir="
+ lfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThrows(IllegalStateException::class.java, { opts.logDirLocation })
+ assertThat(lfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testLogDirArgument_NoWritePermissions() {
+ val lfa = LogDirArgument()
+ val readOnlyDirectory = tFolder.newFolder("read-only")
+ // Remove write permissions
+ readOnlyDirectory
+ .toPath()
+ .setPosixFilePermissions(
+ setOf(
+ PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ,
+ PosixFilePermission.GROUP_EXECUTE,
+ PosixFilePermission.OTHERS_READ,
+ PosixFilePermission.OTHERS_EXECUTE,
+ )
+ )
+
+ val logDirLocation = readOnlyDirectory.absolutePath
+ val arg = "-log-dir=$logDirLocation"
+ lfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThrows(IllegalStateException::class.java, { opts.logDirLocation })
+ assertThat(lfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testRunFilesArgument() {
+ val rfa = RunFilesArgument()
+ val runFilesLocation = tFolder.root.absolutePath
+ val arg = "-run-files-path=$runFilesLocation"
+ assertThat(rfa.matches(arg)).isTrue()
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.runFilesLocation).isEqualTo(runFilesLocation)
+ assertThat(rfa.error).isNull()
+ }
+
+ @Test
+ fun testRunFilesArgument_NoArgument() {
+ val rfa = RunFilesArgument()
+ val arg = "-run-files-path="
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThrows(IllegalStateException::class.java, { opts.runFilesLocation })
+ assertThat(rfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testRunFilesArgument_NoWritePermissions() {
+ val rfa = RunFilesArgument()
+ val readOnlyDirectory = tFolder.newFolder("read-only")
+ // Remove write permissions
+ readOnlyDirectory
+ .toPath()
+ .setPosixFilePermissions(
+ setOf(
+ PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ,
+ PosixFilePermission.GROUP_EXECUTE,
+ PosixFilePermission.OTHERS_READ,
+ PosixFilePermission.OTHERS_EXECUTE,
+ )
+ )
+
+ val runFilesLocation = readOnlyDirectory.absolutePath
+ val arg = "-run-files-path=$runFilesLocation"
+
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThrows(IllegalStateException::class.java, { opts.runFilesLocation })
+ assertThat(rfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testBuildHistoryFileArgument() {
+ val bfa = BuildHistoryFileArgument()
+ val tFile = tFolder.newFile("build")
+ val arg = "-build-history=" + tFile.absolutePath
+ bfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(opts.buildHistoryFileName).isEqualTo(tFile.absolutePath)
+ }
+
+ @Test
+ fun testBuildHistoryFileArgument_NoArgument() {
+ val bfa = BuildHistoryFileArgument()
+ val arg = "-build-history="
+ bfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(bfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testRootDirArgument() {
+ val rfa = RootDirArgument()
+ val rootDirLocation = tFolder.root.absolutePath
+ val arg = "-root-dir=$rootDirLocation"
+ assertThat(rfa.matches(arg)).isTrue()
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.rootDirLocation).isEqualTo(rootDirLocation)
+ assertThat(rfa.error).isNull()
+ }
+
+ @Test
+ fun testRootDirArgument_NoArgument() {
+ val rfa = RootDirArgument()
+ val arg = "-root-dir="
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+ assertThrows(IllegalStateException::class.java, { opts.rootDirLocation })
+ assertThat(rfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testRootDirArgument_NoWritePermissions() {
+ val rfa = RootDirArgument()
+ val readOnlyDirectory = tFolder.newFolder("read-only")
+ // Remove write permissions
+ readOnlyDirectory
+ .toPath()
+ .setPosixFilePermissions(
+ setOf(
+ PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ,
+ PosixFilePermission.GROUP_EXECUTE,
+ PosixFilePermission.OTHERS_READ,
+ PosixFilePermission.OTHERS_EXECUTE,
+ )
+ )
+
+ val rootDirLocation = readOnlyDirectory.absolutePath
+ val arg = "-root-dir=$rootDirLocation"
+
+ rfa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThrows(IllegalStateException::class.java, { opts.rootDirLocation })
+ assertThat(rfa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testWorkingDirArgument() {
+ val wda = WorkingDirArgument()
+ val arg = "-working-dir=FOOBAR"
+ assertThat(wda.matches(arg)).isTrue()
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.workingDirName).isEqualTo("FOOBAR")
+ assertThat(wda.error).isNull()
+ }
+
+ @Test
+ fun testWorkingDirArgument_NoArgument() {
+ val wda = WorkingDirArgument()
+ val arg = "-working-dir="
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testWorkingDirArgument_PathTraversal() {
+ val wda = WorkingDirArgument()
+ val arg = "-working-dir=../FOOBAR"
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testOutputDirArgument() {
+ val oda = OutputDirArgument()
+ val arg = "-output-dir=FOOBAR"
+ assertThat(oda.matches(arg)).isTrue()
+ oda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.outputDirName).isEqualTo("FOOBAR")
+ assertThat(oda.error).isNull()
+ }
+
+ @Test
+ fun testOutputDirArgument_NoArgument() {
+ val wda = OutputDirArgument()
+ val arg = "-output-dir="
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testOutputDirArgument_PathTraversal() {
+ val wda = OutputDirArgument()
+ val arg = "-output-dir=../FOOBAR"
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testBuildDirArgument() {
+ val oda = BuildDirArgument()
+ val arg = "-build-dir=FOOBAR"
+ assertThat(oda.matches(arg)).isTrue()
+ oda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.buildDirName).isEqualTo("FOOBAR")
+ assertThat(oda.error).isNull()
+ }
+
+ @Test
+ fun testBuildDirArgument_NoArgument() {
+ val wda = BuildDirArgument()
+ val arg = "-build-dir="
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testBuildDirArgument_PathTraversal() {
+ val wda = BuildDirArgument()
+ val arg = "-build-dir=../FOOBAR"
+ wda.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(wda.error).isNotEmpty()
+ }
+
+ @Test
+ fun testClassPathArgument() {
+ val cpa = ClassPathArgument()
+ val paths = listOf("foo", "bar", "baz")
+ val arg = "-classpath=" + paths.joinToString(":")
+ assertThat(cpa.matches(arg)).isTrue()
+ cpa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.classPath).isEqualTo(paths)
+ }
+
+ @Test
+ fun testClassPathArgument_NoArgument() {
+ val cpa = ClassPathArgument()
+ val arg = "-classpath="
+ cpa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.classPath).isEmpty()
+ assertThat(cpa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testPluginArgument() {
+ val pa = PluginArgument()
+ val arg = "-Xplugin=foo"
+ assertThat(pa.matches(arg)).isTrue()
+ pa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.classPath).contains("foo")
+ assertThat(opts.passThroughArgs).contains("-Xplugin=foo")
+ }
+
+ @Test
+ fun testPluginArgument_NoArgument() {
+ val pa = PluginArgument()
+ val arg = "-Xplugin="
+ pa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.classPath).isEmpty()
+ assertThat(opts.passThroughArgs).isEmpty()
+ assertThat(pa.error).isNotEmpty()
+ }
+
+ @Test
+ fun testPluginArgument_FirstInClassPath() {
+ val pa = PluginArgument()
+ val arg = "-Xplugin=foo"
+
+ opts.classPath.addAll(listOf("a", "b", "c"))
+ assertThat(opts.classPath.first()).isNotEqualTo("foo")
+
+ assertThat(pa.matches(arg)).isTrue()
+ pa.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.classPath.first()).isEqualTo("foo")
+ assertThat(opts.passThroughArgs).contains("-Xplugin=foo")
+ }
+
+ @Test
+ fun testJvmArgument() {
+ val jvma = JvmArgument()
+ val arg = "-J-option"
+ assertThat(jvma.matches(arg)).isTrue()
+ jvma.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.jvmArgs).contains("option")
+ }
+
+ @Test
+ fun testPluginArgument_WithEquals() {
+ val jvma = JvmArgument()
+ val arg = "-J-option=foo"
+ jvma.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.jvmArgs).contains("option=foo")
+ }
+
+ @Test
+ fun testPluginArgument_DoubleDash() {
+ val jvma = JvmArgument()
+ val arg = "-J--option=foo"
+ jvma.parse(arg, emptyList<String>().iterator(), opts)
+
+ assertThat(opts.jvmArgs).contains("-option=foo")
+ }
+}
diff --git a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/BuildFileParserTest.kt b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/BuildFileParserTest.kt
new file mode 100644
index 000000000..068bda361
--- /dev/null
+++ b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/BuildFileParserTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.kotlin.compiler.client
+
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import javax.xml.parsers.SAXParserFactory
+import org.junit.Before
+import org.junit.Test
+import org.xml.sax.XMLReader
+
+class BuildFileParserTest {
+ private lateinit var parser: BuildFileParser
+ private lateinit var xmlReader: XMLReader
+ val buildFile = File("tests/resources/test_build.xml")
+
+ @Before
+ fun setup() {
+ parser = BuildFileParser()
+ val spf = SAXParserFactory.newInstance()
+ val saxParser = spf.newSAXParser()
+ xmlReader = saxParser.xmlReader
+ xmlReader.contentHandler = parser
+
+ xmlReader.parse(buildFile.absolutePath)
+ }
+
+ @Test
+ fun testParseClasspaths() {
+ assertThat(parser.classpaths).containsExactly("a.jar", "b.jar")
+ }
+
+ @Test
+ fun testParseJavaSources() {
+ assertThat(parser.javaSources).containsExactly("c.java", "d.java")
+ }
+
+ @Test
+ fun testParseSources() {
+ assertThat(parser.sources).containsExactly("e.kt", "f.kt")
+ }
+
+ @Test
+ fun testParserModuleName() {
+ assertThat(parser.moduleName).isEqualTo("test_module")
+ }
+
+ @Test
+ fun testParserOutputDirName() {
+ assertThat(parser.outputDirName).isEqualTo("output")
+ }
+}
diff --git a/cmd/release_config/build_flag/Android.bp b/cmd/release_config/build_flag/Android.bp
index 0f10c91cb..10ec36cbb 100644
--- a/cmd/release_config/build_flag/Android.bp
+++ b/cmd/release_config/build_flag/Android.bp
@@ -3,7 +3,7 @@ package {
}
blueprint_go_binary {
- name: "build-flag",
+ name: "build-flag-internal",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go
index 5d103cc25..c63ff71ce 100644
--- a/cmd/release_config/build_flag/main.go
+++ b/cmd/release_config/build_flag/main.go
@@ -29,6 +29,10 @@ type Flags struct {
// `PRODUCT_RELEASE_CONFIG_MAPS` are used.
maps rc_lib.StringList
+ // File containing the list of maps to use, one file per line.
+ // Cannot be used with --map.
+ mapsFile string
+
// Output directory (relative to `top`).
outDir string
@@ -53,6 +57,10 @@ type Flags struct {
// If true, and we cannot find the named release config, values for
// `trunk_staging` will be used.
allowMissing bool
+
+ // Only load flag declarations, do not load values. The output
+ // will have only values provided in the declaration files.
+ declarationsOnly bool
}
type CommandFunc func(*rc_lib.ReleaseConfigs, Flags, string, []string) error
@@ -323,7 +331,7 @@ func SetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, a
}
// Reload the release configs.
- configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, commonFlags.targetReleases[0], commonFlags.useGetBuildVar, commonFlags.allowMissing)
+ configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, commonFlags.targetReleases[0], commonFlags.useGetBuildVar, commonFlags.allowMissing, commonFlags.declarationsOnly)
if err != nil {
return err
}
@@ -345,12 +353,14 @@ func main() {
flag.StringVar(&commonFlags.top, "top", topDir, "path to top of workspace")
flag.BoolVar(&commonFlags.quiet, "quiet", false, "disable warning messages")
flag.Var(&commonFlags.maps, "map", "path to a release_config_map.textproto. may be repeated")
+ flag.StringVar(&commonFlags.mapsFile, "maps-file", "", "path to a file containing a list of release_config_map.textproto paths, one per line")
flag.StringVar(&commonFlags.outDir, "out-dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
flag.Var(&commonFlags.targetReleases, "release", "TARGET_RELEASE for this build")
flag.BoolVar(&commonFlags.allowMissing, "allow-missing", false, "Use trunk_staging values if release not found")
flag.BoolVar(&commonFlags.allReleases, "all-releases", false, "operate on all releases. (Ignored for set command)")
flag.BoolVar(&commonFlags.useGetBuildVar, "use-get-build-var", true, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS to get needed maps")
flag.BoolVar(&commonFlags.debug, "debug", false, "turn on debugging output for errors")
+ flag.BoolVar(&commonFlags.declarationsOnly, "declarations-only", false, "only process flag declarations")
flag.Parse()
errorExit := func(err error) {
@@ -365,6 +375,22 @@ func main() {
rc_lib.DisableWarnings()
}
+ if commonFlags.mapsFile != "" {
+ if len(commonFlags.maps) > 0 {
+ errorExit(fmt.Errorf("Cannot use both --map and --maps-file"))
+ }
+ data, err := os.ReadFile(commonFlags.mapsFile)
+ if err != nil {
+ errorExit(err)
+ }
+ // Add the list of maps to `maps`.
+ for _, m := range strings.Split(string(data), "\n") {
+ if len(m) > 0 {
+ commonFlags.maps.Set(m)
+ }
+ }
+ }
+
if len(commonFlags.targetReleases) == 0 {
release, ok := os.LookupEnv("TARGET_RELEASE")
if ok {
@@ -383,7 +409,7 @@ func main() {
if relName == "--all" || relName == "-all" {
commonFlags.allReleases = true
}
- configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName, commonFlags.useGetBuildVar, commonFlags.allowMissing)
+ configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName, commonFlags.useGetBuildVar, commonFlags.allowMissing, commonFlags.declarationsOnly)
if err != nil {
errorExit(err)
}
diff --git a/cmd/release_config/build_flag_declarations/main.go b/cmd/release_config/build_flag_declarations/main.go
index cc286b6a9..f1716bb7e 100644
--- a/cmd/release_config/build_flag_declarations/main.go
+++ b/cmd/release_config/build_flag_declarations/main.go
@@ -69,7 +69,10 @@ func main() {
intermediates = append(intermediates, fda)
}
for _, decl := range flags.decls {
- fa := rc_lib.FlagArtifactFactory(decl)
+ fa, err := rc_lib.FlagArtifactFactory(decl)
+ if err != nil {
+ errorExit(err)
+ }
(*flagArtifacts)[*fa.FlagDeclaration.Name] = fa
}
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index 7013d6bd4..825b4676a 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -55,7 +55,7 @@ func main() {
flag.BoolVar(&allMake, "all_make", false, "write makefiles for all release configs")
flag.BoolVar(&inheritance, "inheritance", true, "write inheritance graph")
flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS")
- flag.BoolVar(&guard, "guard", true, "whether to guard with RELEASE_BUILD_FLAGS_IN_PROTOBUF")
+ flag.BoolVar(&guard, "guard", false, "obsolete")
flag.Parse()
@@ -66,7 +66,7 @@ func main() {
if err = os.Chdir(top); err != nil {
panic(err)
}
- configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease, useBuildVar, allowMissing)
+ configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease, useBuildVar, allowMissing, false)
if err != nil {
panic(err)
}
@@ -80,13 +80,6 @@ func main() {
}
makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.varmk", product, targetRelease))
- useProto, ok := config.FlagArtifacts["RELEASE_BUILD_FLAGS_IN_PROTOBUF"]
- if guard && (!ok || rc_lib.MarshalValue(useProto.Value) == "") {
- // We were told to guard operation and either we have no build flag, or it is False.
- // Write an empty file so that release_config.mk will use the old process.
- os.WriteFile(makefilePath, []byte{}, 0644)
- return
- }
// Write the makefile where release_config.mk is going to look for it.
err = config.WriteMakefile(makefilePath, targetRelease, configs)
if err != nil {
@@ -129,7 +122,7 @@ func main() {
panic(err)
}
}
- if err = config.WritePartitionBuildFlags(outputDir); err != nil {
+ if err = config.WritePartitionBuildFlags(product, outputDir); err != nil {
panic(err)
}
diff --git a/cmd/release_config/release_config_lib/Android.bp b/cmd/release_config/release_config_lib/Android.bp
index 17251bdba..f47ba3f0e 100644
--- a/cmd/release_config/release_config_lib/Android.bp
+++ b/cmd/release_config/release_config_lib/Android.bp
@@ -23,8 +23,9 @@ bootstrap_go_package {
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
- "soong-cmd-release_config-proto",
"blueprint-pathtools",
+ "soong-android",
+ "soong-cmd-release_config-proto",
],
srcs: [
"flag_artifact.go",
@@ -34,4 +35,8 @@ bootstrap_go_package {
"release_configs.go",
"util.go",
],
+ testSrcs: [
+ "flag_declaration_test.go",
+ "flag_value_test.go",
+ ],
}
diff --git a/cmd/release_config/release_config_lib/flag_artifact.go b/cmd/release_config/release_config_lib/flag_artifact.go
index f493e1e06..6e278eb95 100644
--- a/cmd/release_config/release_config_lib/flag_artifact.go
+++ b/cmd/release_config/release_config_lib/flag_artifact.go
@@ -47,19 +47,21 @@ type FlagArtifact struct {
// Key is flag name.
type FlagArtifacts map[string]*FlagArtifact
-func FlagArtifactFactory(declPath string) *FlagArtifact {
- fd := &rc_proto.FlagDeclaration{}
- fa := &FlagArtifact{
+func FlagArtifactFactory(declPath string) (fa *FlagArtifact, err error) {
+ fd, err := FlagDeclarationFactory(declPath)
+ if err != nil {
+ return nil, err
+ }
+ fa = &FlagArtifact{
FlagDeclaration: fd,
DeclarationIndex: -1,
Traces: []*rc_proto.Tracepoint{},
}
if declPath != "" {
- LoadMessage(declPath, fd)
fa.Value = fd.GetValue()
fa.Traces = append(fa.Traces, &rc_proto.Tracepoint{Source: proto.String(declPath), Value: fa.Value})
}
- return fa
+ return fa, nil
}
func FlagArtifactsFactory(artifactsPath string) *FlagArtifacts {
diff --git a/cmd/release_config/release_config_lib/flag_declaration.go b/cmd/release_config/release_config_lib/flag_declaration.go
index 22001bf09..e0756149f 100644
--- a/cmd/release_config/release_config_lib/flag_declaration.go
+++ b/cmd/release_config/release_config_lib/flag_declaration.go
@@ -15,6 +15,9 @@
package release_config_lib
import (
+ "fmt"
+ "path/filepath"
+
rc_proto "android/soong/cmd/release_config/release_config_proto"
)
@@ -25,14 +28,36 @@ var (
DuplicateDeclarationAllowlist = map[string]bool{}
)
-func FlagDeclarationFactory(protoPath string) (fd *rc_proto.FlagDeclaration) {
+func FlagDeclarationFactory(protoPath string) (fd *rc_proto.FlagDeclaration, err error) {
fd = &rc_proto.FlagDeclaration{}
- if protoPath != "" {
- LoadMessage(protoPath, fd)
+ if protoPath == "" {
+ return fd, nil
+ }
+ LoadMessage(protoPath, fd)
+
+ switch {
+ case fd.Name == nil:
+ return nil, fmt.Errorf("Flag declaration %s does not specify name", protoPath)
+ case *fd.Name == "RELEASE_ACONFIG_VALUE_SETS":
+ return nil, fmt.Errorf("%s: %s is a reserved build flag", protoPath, *fd.Name)
+ case fmt.Sprintf("%s.textproto", *fd.Name) != filepath.Base(protoPath):
+ return nil, fmt.Errorf("%s incorrectly declares flag %s", protoPath, *fd.Name)
+ case fd.Namespace == nil:
+ return nil, fmt.Errorf("Flag declaration %s has no namespace.", protoPath)
+ case fd.Workflow == nil:
+ return nil, fmt.Errorf("Flag declaration %s has no workflow.", protoPath)
+ case fd.Containers != nil:
+ for _, container := range fd.Containers {
+ if !validContainer(container) {
+ return nil, fmt.Errorf("Flag declaration %s has invalid container %s", protoPath, container)
+ }
+ }
}
+
// If the input didn't specify a value, create one (== UnspecifiedValue).
if fd.Value == nil {
fd.Value = &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}}
}
- return fd
+
+ return fd, nil
}
diff --git a/cmd/release_config/release_config_lib/flag_declaration_test.go b/cmd/release_config/release_config_lib/flag_declaration_test.go
new file mode 100644
index 000000000..058ae37e2
--- /dev/null
+++ b/cmd/release_config/release_config_lib/flag_declaration_test.go
@@ -0,0 +1,90 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package release_config_lib
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ rc_proto "android/soong/cmd/release_config/release_config_proto"
+ // For Assert*.
+ "android/soong/android"
+
+ "google.golang.org/protobuf/proto"
+)
+
+type testCaseFlagDeclarationFactory struct {
+ protoPath string
+ name string
+ data []byte
+ expected *rc_proto.FlagDeclaration
+ err error
+}
+
+func (tc testCaseFlagDeclarationFactory) assertProtoEqual(t *testing.T, expected, actual proto.Message) {
+ if !proto.Equal(expected, actual) {
+ t.Errorf("Expected %q found %q", expected, actual)
+ }
+}
+
+func TestFlagDeclarationFactory(t *testing.T) {
+ testCases := []testCaseFlagDeclarationFactory{
+ {
+ name: "boolVal",
+ protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto",
+ data: []byte(`name: "RELEASE_FOO" namespace: "soong_test" value {bool_value: false} workflow: LAUNCH containers: "product"`),
+ expected: &rc_proto.FlagDeclaration{
+ Name: proto.String("RELEASE_FOO"),
+ Namespace: proto.String("soong_test"),
+ Value: &rc_proto.Value{Val: &rc_proto.Value_BoolValue{false}},
+ Workflow: rc_proto.Workflow_LAUNCH.Enum(),
+ Containers: []string{"product"},
+ },
+ err: nil,
+ },
+ {
+ name: "missingWorkflow",
+ protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto",
+ data: []byte(`name: "RELEASE_FOO" namespace: "soong_test" value {bool_value: false} containers: "product"`),
+ expected: nil,
+ err: fmt.Errorf("has no workflow"),
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ var err error
+ tempdir := t.TempDir()
+ path := filepath.Join(tempdir, tc.protoPath)
+ if err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {
+ t.Fatal(err)
+ }
+ if err = os.WriteFile(path, tc.data, 0644); err != nil {
+ t.Fatal(err)
+ }
+ actual, err := FlagDeclarationFactory(path)
+ if tc.err == nil {
+ android.AssertSame(t, "Expected %v got %v", tc.err, err)
+ tc.assertProtoEqual(t, tc.expected, actual)
+ } else if err == nil {
+ t.Errorf("Expected error containing '%q' got nil", tc.err.Error())
+ } else if !strings.Contains(err.Error(), tc.err.Error()) {
+ t.Errorf("Error %v does not include %v", err.Error(), tc.err.Error())
+ }
+ })
+ }
+}
diff --git a/cmd/release_config/release_config_lib/flag_value.go b/cmd/release_config/release_config_lib/flag_value.go
index 76363cec4..f55fa3eda 100644
--- a/cmd/release_config/release_config_lib/flag_value.go
+++ b/cmd/release_config/release_config_lib/flag_value.go
@@ -15,6 +15,8 @@
package release_config_lib
import (
+ "fmt"
+ "path/filepath"
"strings"
rc_proto "android/soong/cmd/release_config/release_config_proto"
@@ -28,12 +30,24 @@ type FlagValue struct {
proto rc_proto.FlagValue
}
-func FlagValueFactory(protoPath string) (fv *FlagValue) {
+func FlagValueFactory(protoPath string) (fv *FlagValue, err error) {
fv = &FlagValue{path: protoPath}
- if protoPath != "" {
- LoadMessage(protoPath, &fv.proto)
+ if protoPath == "" {
+ return fv, nil
}
- return fv
+ LoadMessage(protoPath, &fv.proto)
+
+ if fv.proto.Name == nil {
+ return nil, fmt.Errorf("%s does not set name", protoPath)
+ }
+ name := *fv.proto.Name
+ switch {
+ case name == "RELEASE_ACONFIG_VALUE_SETS":
+ return nil, fmt.Errorf("%s: %s is a reserved build flag", protoPath, name)
+ case fmt.Sprintf("%s.textproto", name) != filepath.Base(protoPath):
+ return nil, fmt.Errorf("%s incorrectly sets value for flag %s", protoPath, name)
+ }
+ return fv, nil
}
func UnmarshalValue(str string) *rc_proto.Value {
diff --git a/cmd/release_config/release_config_lib/flag_value_test.go b/cmd/release_config/release_config_lib/flag_value_test.go
index 8a98baf6a..18f836538 100644
--- a/cmd/release_config/release_config_lib/flag_value_test.go
+++ b/cmd/release_config/release_config_lib/flag_value_test.go
@@ -15,11 +15,15 @@
package release_config_lib
import (
+ "fmt"
"os"
"path/filepath"
+ "strings"
"testing"
rc_proto "android/soong/cmd/release_config/release_config_proto"
+ // For Assert*.
+ "android/soong/android"
"google.golang.org/protobuf/proto"
)
@@ -50,6 +54,15 @@ func TestFlagValueFactory(t *testing.T) {
},
err: nil,
},
+ {
+ name: "missingName",
+ protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto",
+ data: []byte(`value {string_value: "BAR"}`),
+ expected: rc_proto.FlagValue{
+ Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{"BAR"}},
+ },
+ err: fmt.Errorf("does not set name"),
+ },
}
for _, tc := range testCases {
var err error
@@ -61,8 +74,15 @@ func TestFlagValueFactory(t *testing.T) {
if err = os.WriteFile(path, tc.data, 0644); err != nil {
t.Fatal(err)
}
- actual := FlagValueFactory(path)
- tc.assertProtoEqual(t, &tc.expected, &actual.proto)
+ actual, err := FlagValueFactory(path)
+ if tc.err == nil {
+ android.AssertSame(t, "Expected %v got %v", tc.err, err)
+ tc.assertProtoEqual(t, &tc.expected, &actual.proto)
+ } else if err == nil {
+ t.Errorf("Expected error containing '%q' got nil", tc.err.Error())
+ } else if !strings.Contains(err.Error(), tc.err.Error()) {
+ t.Errorf("Error %v does not include %v", err.Error(), tc.err.Error())
+ }
}
}
@@ -106,9 +126,11 @@ func TestMarshalValue(t *testing.T) {
},
}
for _, tc := range testCases {
- actual := MarshalValue(tc.value)
- if actual != tc.expected {
- t.Errorf("Expected %q found %q", tc.expected, actual)
- }
+ t.Run(tc.name, func(t *testing.T) {
+ actual := MarshalValue(tc.value)
+ if actual != tc.expected {
+ t.Errorf("Expected %q found %q", tc.expected, actual)
+ }
+ })
}
}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index 873f2fc28..7f792cc8a 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -141,6 +141,11 @@ func (config *ReleaseConfig) InheritConfig(iConfig *ReleaseConfig) error {
if fa.Redacted {
myFa.Redact()
}
+ switch *myFa.FlagDeclaration.Workflow {
+ case rc_proto.Workflow_MANUAL_NO_INHERIT:
+ // Flag values for this flag are not inherited.
+ continue
+ }
if name == "RELEASE_ACONFIG_VALUE_SETS" {
// If there is a value assigned, add the trace.
if len(fa.Value.GetStringValue()) > 0 {
@@ -203,7 +208,7 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
// TODO: there are some configs that rely on vgsbr being
// present on branches where it isn't. Once the broken configs
// are fixed, we can be more strict. In the meantime, they
- // will wind up inheriting `trunk_stable` instead of the
+ // will wind up inheriting `trunk_staging` instead of the
// non-existent (alias) that they reference today. Once fixed,
// this becomes:
// iConfig, err := configs.GetReleaseConfigStrict(inherit)
@@ -299,6 +304,13 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
// The "root" release config can only contain workflow: MANUAL flags.
return fmt.Errorf("Setting value for non-MANUAL flag %s is not allowed in %s", name, value.path)
}
+ switch *fa.FlagDeclaration.Workflow {
+ case rc_proto.Workflow_MANUAL_BUILD_VARIANT:
+ // Non-BUILD_VARIANT release configs cannot set MANUAL_BUILD_VARIANT flags.
+ if config.ReleaseConfigType != rc_proto.ReleaseConfigType_BUILD_VARIANT {
+ return fmt.Errorf("Setting value for BUILD_VARIANT flag %s is not allowed in %s", name, value.path)
+ }
+ }
if err := fa.UpdateValue(*value); err != nil {
return err
}
@@ -508,7 +520,7 @@ func (config *ReleaseConfig) WriteMakefile(outFile, targetRelease string, config
return os.WriteFile(outFile, []byte(data), 0644)
}
-func (config *ReleaseConfig) WritePartitionBuildFlags(outDir string) error {
+func (config *ReleaseConfig) WritePartitionBuildFlags(product string, outDir string) error {
var err error
for partition, flags := range config.PartitionBuildFlags {
slices.SortFunc(flags.Flags, func(a, b *rc_proto.FlagArtifact) int {
@@ -516,7 +528,7 @@ func (config *ReleaseConfig) WritePartitionBuildFlags(outDir string) error {
})
// The json file name must not be modified as this is read from
// build_flags_json module
- if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s.json", partition)), flags); err != nil {
+ if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s-%s.json", product, partition)), flags); err != nil {
return err
}
}
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index dd98bca0b..d7356bd9f 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -16,6 +16,7 @@ package release_config_lib
import (
"cmp"
+ "errors"
"fmt"
"io/fs"
"os"
@@ -188,7 +189,7 @@ func ReleaseConfigsFactory() (c *ReleaseConfigs) {
releaseAconfigValueSets := FlagArtifact{
FlagDeclaration: &rc_proto.FlagDeclaration{
Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"),
- Namespace: proto.String("android_UNKNOWN"),
+ Namespace: proto.String("build"),
Description: proto.String("Aconfig value sets assembled by release-config"),
Workflow: &workflowManual,
Containers: []string{"system", "system_ext", "product", "vendor"},
@@ -211,15 +212,49 @@ func (configs *ReleaseConfigs) GetSortedReleaseConfigs() (ret []*ReleaseConfig)
return ret
}
-func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) {
+func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap, err error) {
m = &ReleaseConfigMap{
path: protoPath,
ReleaseConfigContributions: make(map[string]*ReleaseConfigContribution),
}
- if protoPath != "" {
- LoadMessage(protoPath, &m.proto)
+ if protoPath == "" {
+ return m, nil
}
- return m
+ LoadMessage(protoPath, &m.proto)
+ if m.proto.DefaultContainers == nil {
+ return nil, fmt.Errorf("Release config map %s lacks default_containers", protoPath)
+ }
+ for _, container := range m.proto.DefaultContainers {
+ if !validContainer(container) {
+ return nil, fmt.Errorf("Release config map %s has invalid container %s", protoPath, container)
+ }
+ }
+ return m, nil
+}
+
+func ReleaseConfigContributionFactory(protoPath string, dirIndex int) (rcc *ReleaseConfigContribution, err error) {
+ rcc = &ReleaseConfigContribution{path: protoPath, DeclarationIndex: dirIndex}
+ if protoPath == "" {
+ return rcc, nil
+ }
+ LoadMessage(protoPath, &rcc.proto)
+
+ switch {
+ case rcc.proto.Name == nil:
+ return nil, fmt.Errorf("%s does not specify name", protoPath)
+ case fmt.Sprintf("%s.textproto", *rcc.proto.Name) != filepath.Base(protoPath):
+ return nil, fmt.Errorf("%s incorrectly declares release config %s", protoPath, *rcc.proto.Name)
+ }
+
+ // Provide a default value for ReleaseConfigType if not specified.
+ if rcc.proto.ReleaseConfigType == nil {
+ if *rcc.proto.Name == "root" {
+ rcc.proto.ReleaseConfigType = rc_proto.ReleaseConfigType_EXPLICIT_INHERITANCE_CONFIG.Enum()
+ } else {
+ rcc.proto.ReleaseConfigType = rc_proto.ReleaseConfigType_RELEASE_CONFIG.Enum()
+ }
+ }
+ return rcc, nil
}
// Find the top of the release config contribution directory.
@@ -260,19 +295,11 @@ func EnumerateReleaseConfigs(dir string) ([]string, error) {
return ret, err
}
-func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
+func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int, declarationsOnly bool) error {
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("%s does not exist\n", path)
}
- m := ReleaseConfigMapFactory(path)
- if m.proto.DefaultContainers == nil {
- return fmt.Errorf("Release config map %s lacks default_containers", path)
- }
- for _, container := range m.proto.DefaultContainers {
- if !validContainer(container) {
- return fmt.Errorf("Release config map %s has invalid container %s", path, container)
- }
- }
+ m, err := ReleaseConfigMapFactory(path)
configs.FilesUsedMap[path] = true
dir := filepath.Dir(path)
// Record any aliases, checking for duplicates.
@@ -287,7 +314,6 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
}
configs.Aliases[name] = alias.Target
}
- var err error
// Temporarily allowlist duplicate flag declaration files to prevent
// more from entering the tree while we work to clean up the duplicates
// that already exist.
@@ -302,31 +328,27 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
DuplicateDeclarationAllowlist[flag] = true
}
}
+ var declarationErrors []error
err = WalkTextprotoFiles(dir, "flag_declarations", func(path string, d fs.DirEntry, err error) error {
- flagDeclaration := FlagDeclarationFactory(path)
- // Container must be specified.
+ // Gather up all errors found in flag declarations and report them together, so that it is easier to
+ // find all of the duplicate declarations, for example.
+ flagDeclaration, err := FlagDeclarationFactory(path)
+ if err != nil {
+ declarationErrors = append(declarationErrors, err)
+ return nil
+ }
+ // If not given, set Containers to the default for this directory.
if flagDeclaration.Containers == nil {
flagDeclaration.Containers = m.proto.DefaultContainers
- } else {
- for _, container := range flagDeclaration.Containers {
- if !validContainer(container) {
- return fmt.Errorf("Flag declaration %s has invalid container %s", path, container)
- }
- }
- }
- if flagDeclaration.Namespace == nil {
- return fmt.Errorf("Flag declaration %s has no namespace.", path)
}
m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration)
name := *flagDeclaration.Name
- if name == "RELEASE_ACONFIG_VALUE_SETS" {
- return fmt.Errorf("%s: %s is a reserved build flag", path, name)
- }
if def, ok := configs.FlagArtifacts[name]; !ok {
configs.FlagArtifacts[name] = &FlagArtifact{FlagDeclaration: flagDeclaration, DeclarationIndex: ConfigDirIndex}
} else if !proto.Equal(def.FlagDeclaration, flagDeclaration) || !DuplicateDeclarationAllowlist[name] {
- return fmt.Errorf("Duplicate definition of %s in %s", *flagDeclaration.Name, path)
+ declarationErrors = append(declarationErrors, fmt.Errorf("Duplicate definition of %s in %s", *flagDeclaration.Name, path))
+ return nil
}
// Set the initial value in the flag artifact.
configs.FilesUsedMap[path] = true
@@ -334,12 +356,17 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
FlagValue{path: path, proto: rc_proto.FlagValue{
Name: proto.String(name), Value: flagDeclaration.Value}})
if configs.FlagArtifacts[name].Redacted {
- return fmt.Errorf("%s may not be redacted by default.", name)
+ declarationErrors = append(declarationErrors, fmt.Errorf("%s may not be redacted by default.", name))
+ return nil
}
return nil
})
if err != nil {
- return err
+ // While we no longer return an error, if we do later, we need to also report that error.
+ declarationErrors = append(declarationErrors, err)
+ }
+ if len(declarationErrors) > 0 {
+ return errors.Join(declarationErrors...)
}
subDirs := func(subdir string) (ret []string) {
@@ -358,63 +385,53 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
}
err = WalkTextprotoFiles(dir, "release_configs", func(path string, d fs.DirEntry, err error) error {
- releaseConfigContribution := &ReleaseConfigContribution{path: path, DeclarationIndex: ConfigDirIndex}
- LoadMessage(path, &releaseConfigContribution.proto)
- name := *releaseConfigContribution.proto.Name
- if fmt.Sprintf("%s.textproto", name) != filepath.Base(path) {
- return fmt.Errorf("%s incorrectly declares release config %s", path, name)
- }
- releaseConfigType := releaseConfigContribution.proto.ReleaseConfigType
- if releaseConfigType == nil {
- if name == "root" {
- releaseConfigType = rc_proto.ReleaseConfigType_EXPLICIT_INHERITANCE_CONFIG.Enum()
- } else {
- releaseConfigType = rc_proto.ReleaseConfigType_RELEASE_CONFIG.Enum()
- }
+ rcc, err := ReleaseConfigContributionFactory(path, ConfigDirIndex)
+ if err != nil {
+ return err
}
+ name := *rcc.proto.Name
if _, ok := configs.ReleaseConfigs[name]; !ok {
configs.ReleaseConfigs[name] = ReleaseConfigFactory(name, ConfigDirIndex)
- configs.ReleaseConfigs[name].ReleaseConfigType = *releaseConfigType
+ configs.ReleaseConfigs[name].ReleaseConfigType = *rcc.proto.ReleaseConfigType
}
config := configs.ReleaseConfigs[name]
- if config.ReleaseConfigType != *releaseConfigType {
- return fmt.Errorf("%s mismatching ReleaseConfigType value %s", path, *releaseConfigType)
+ if config.ReleaseConfigType != *rcc.proto.ReleaseConfigType {
+ return fmt.Errorf("%s mismatching ReleaseConfigType value %s", path, *rcc.proto.ReleaseConfigType)
}
config.FilesUsedMap[path] = true
- config.DisallowLunchUse = config.DisallowLunchUse || releaseConfigContribution.proto.GetDisallowLunchUse()
+ config.DisallowLunchUse = config.DisallowLunchUse || rcc.proto.GetDisallowLunchUse()
inheritNames := make(map[string]bool)
for _, inh := range config.InheritNames {
inheritNames[inh] = true
}
// If this contribution says to inherit something we already inherited, we do not want the duplicate.
- for _, cInh := range releaseConfigContribution.proto.Inherits {
+ for _, cInh := range rcc.proto.Inherits {
if !inheritNames[cInh] {
config.InheritNames = append(config.InheritNames, cInh)
inheritNames[cInh] = true
}
}
- // Only walk flag_values/{RELEASE} for defined releases.
- err2 := WalkTextprotoFiles(dir, filepath.Join("flag_values", name), func(path string, d fs.DirEntry, err error) error {
- flagValue := FlagValueFactory(path)
- if fmt.Sprintf("%s.textproto", *flagValue.proto.Name) != filepath.Base(path) {
- return fmt.Errorf("%s incorrectly sets value for flag %s", path, *flagValue.proto.Name)
- }
- if *flagValue.proto.Name == "RELEASE_ACONFIG_VALUE_SETS" {
- return fmt.Errorf("%s: %s is a reserved build flag", path, *flagValue.proto.Name)
+ if !declarationsOnly {
+ // Only walk flag_values/{RELEASE} for defined releases.
+ err2 := WalkTextprotoFiles(dir, filepath.Join("flag_values", name), func(path string, d fs.DirEntry, err error) error {
+ flagValue, err := FlagValueFactory(path)
+ if err != nil {
+ return err
+ }
+ config.FilesUsedMap[path] = true
+ rcc.FlagValues = append(rcc.FlagValues, flagValue)
+ return nil
+ })
+ if err2 != nil {
+ return err2
}
- config.FilesUsedMap[path] = true
- releaseConfigContribution.FlagValues = append(releaseConfigContribution.FlagValues, flagValue)
- return nil
- })
- if err2 != nil {
- return err2
}
- if releaseConfigContribution.proto.GetAconfigFlagsOnly() {
+ if rcc.proto.GetAconfigFlagsOnly() {
config.AconfigFlagsOnly = true
}
- m.ReleaseConfigContributions[name] = releaseConfigContribution
- config.Contributions = append(config.Contributions, releaseConfigContribution)
+ m.ReleaseConfigContributions[name] = rcc
+ config.Contributions = append(config.Contributions, rcc)
return nil
})
if err != nil {
@@ -533,7 +550,7 @@ func (configs *ReleaseConfigs) GenerateReleaseConfigs(targetRelease string) erro
return nil
}
-func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string, useBuildVar, allowMissing bool) (*ReleaseConfigs, error) {
+func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string, useBuildVar, allowMissing, declarationsOnly bool) (*ReleaseConfigs, error) {
var err error
if len(releaseConfigMapPaths) == 0 {
@@ -553,6 +570,7 @@ func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease strin
configs.allowMissing = allowMissing
mapsRead := make(map[string]bool)
var idx int
+ var loadErrors []error
for _, releaseConfigMapPath := range releaseConfigMapPaths {
// Maintain an ordered list of release config directories.
configDir := filepath.Dir(releaseConfigMapPath)
@@ -564,12 +582,15 @@ func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease strin
configs.configDirs = append(configs.configDirs, configDir)
// Force the path to be the textproto path, so that both the scl and textproto formats can coexist.
releaseConfigMapPath = filepath.Join(configDir, "release_config_map.textproto")
- err = configs.LoadReleaseConfigMap(releaseConfigMapPath, idx)
+ err = configs.LoadReleaseConfigMap(releaseConfigMapPath, idx, declarationsOnly)
if err != nil {
- return nil, err
+ loadErrors = append(loadErrors, err)
}
idx += 1
}
+ if len(loadErrors) > 0 {
+ return nil, errors.Join(loadErrors...)
+ }
// Now that we have all of the release config maps, can meld them and generate the artifacts.
err = configs.GenerateReleaseConfigs(targetRelease)
diff --git a/cmd/release_config/release_config_proto/Android.bp b/cmd/release_config/release_config_proto/Android.bp
index c6869b1fc..943fb8bdc 100644
--- a/cmd/release_config/release_config_proto/Android.bp
+++ b/cmd/release_config/release_config_proto/Android.bp
@@ -31,3 +31,21 @@ bootstrap_go_package {
"release_configs_contributions.pb.go",
],
}
+
+rust_protobuf_host {
+ name: "liball_release_configs_proto",
+ protos: [
+ "build_flags_common.proto",
+ "build_flags_declarations.proto",
+ "build_flags_out.proto",
+ "build_flags_src.proto",
+ "release_configs_contributions.proto",
+ ],
+ crate_name: "all_release_configs_proto",
+ source_stem: "all_release_configs_proto",
+
+ // Keep visibility limited to tests only!
+ visibility: [
+ "//build/make/tools/finalization/finalization-test",
+ ],
+}
diff --git a/cmd/release_config/release_config_proto/build_flags_common.pb.go b/cmd/release_config/release_config_proto/build_flags_common.pb.go
index 7b52b0739..6836a40bc 100644
--- a/cmd/release_config/release_config_proto/build_flags_common.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_common.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.36.5
// protoc v3.21.12
// source: build_flags_common.proto
@@ -26,6 +26,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -49,6 +50,12 @@ const (
// Manually managed outside flags. These are likely to be found in a
// different directory than flags with other workflows.
Workflow_MANUAL Workflow = 3
+ // Manually managed flags that are not inherited. These are likely used to
+ // control release process steps.
+ Workflow_MANUAL_NO_INHERIT Workflow = 4
+ // Manually managed flags for BUILD_VARIANT release configs. These flags may
+ // only be assigned values if release_config_type == BUILD_VARIANT
+ Workflow_MANUAL_BUILD_VARIANT Workflow = 5
)
// Enum value maps for Workflow.
@@ -59,6 +66,8 @@ var (
1: "LAUNCH",
2: "PREBUILT",
3: "MANUAL",
+ 4: "MANUAL_NO_INHERIT",
+ 5: "MANUAL_BUILD_VARIANT",
}
Workflow_value = map[string]int32{
"WORKFLOW_UNSPECIFIED": 0,
@@ -66,6 +75,8 @@ var (
"LAUNCH": 1,
"PREBUILT": 2,
"MANUAL": 3,
+ "MANUAL_NO_INHERIT": 4,
+ "MANUAL_BUILD_VARIANT": 5,
}
)
@@ -108,37 +119,40 @@ func (Workflow) EnumDescriptor() ([]byte, []int) {
var File_build_flags_common_proto protoreflect.FileDescriptor
-var file_build_flags_common_proto_rawDesc = []byte{
+var file_build_flags_common_proto_rawDesc = string([]byte{
0x0a, 0x18, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x61, 0x6e, 0x64, 0x72,
0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x68, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x6b,
- 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57,
- 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18,
- 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x55, 0x6e, 0x73, 0x70, 0x65,
- 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e,
- 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54,
- 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x1a, 0x02,
- 0x10, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f,
- 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-}
+ 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x99, 0x01, 0x0a, 0x08, 0x57, 0x6f, 0x72,
+ 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f,
+ 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x18, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x55, 0x6e, 0x73, 0x70,
+ 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55,
+ 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c,
+ 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12,
+ 0x15, 0x0a, 0x11, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, 0x4e, 0x4f, 0x5f, 0x49, 0x4e, 0x48,
+ 0x45, 0x52, 0x49, 0x54, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c,
+ 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x4e, 0x54, 0x10, 0x05,
+ 0x1a, 0x02, 0x10, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+})
var (
file_build_flags_common_proto_rawDescOnce sync.Once
- file_build_flags_common_proto_rawDescData = file_build_flags_common_proto_rawDesc
+ file_build_flags_common_proto_rawDescData []byte
)
func file_build_flags_common_proto_rawDescGZIP() []byte {
file_build_flags_common_proto_rawDescOnce.Do(func() {
- file_build_flags_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_build_flags_common_proto_rawDescData)
+ file_build_flags_common_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_build_flags_common_proto_rawDesc), len(file_build_flags_common_proto_rawDesc)))
})
return file_build_flags_common_proto_rawDescData
}
var file_build_flags_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_build_flags_common_proto_goTypes = []interface{}{
+var file_build_flags_common_proto_goTypes = []any{
(Workflow)(0), // 0: android.release_config_proto.Workflow
}
var file_build_flags_common_proto_depIdxs = []int32{
@@ -158,7 +172,7 @@ func file_build_flags_common_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_build_flags_common_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_build_flags_common_proto_rawDesc), len(file_build_flags_common_proto_rawDesc)),
NumEnums: 1,
NumMessages: 0,
NumExtensions: 0,
@@ -169,7 +183,6 @@ func file_build_flags_common_proto_init() {
EnumInfos: file_build_flags_common_proto_enumTypes,
}.Build()
File_build_flags_common_proto = out.File
- file_build_flags_common_proto_rawDesc = nil
file_build_flags_common_proto_goTypes = nil
file_build_flags_common_proto_depIdxs = nil
}
diff --git a/cmd/release_config/release_config_proto/build_flags_common.proto b/cmd/release_config/release_config_proto/build_flags_common.proto
index cd9f1e02f..e432a7b9e 100644
--- a/cmd/release_config/release_config_proto/build_flags_common.proto
+++ b/cmd/release_config/release_config_proto/build_flags_common.proto
@@ -37,4 +37,12 @@ enum Workflow {
// Manually managed outside flags. These are likely to be found in a
// different directory than flags with other workflows.
MANUAL = 3;
+
+ // Manually managed flags that are not inherited. These are likely used to
+ // control release process steps.
+ MANUAL_NO_INHERIT = 4;
+
+ // Manually managed flags for BUILD_VARIANT release configs. These flags may
+ // only be assigned values if release_config_type == BUILD_VARIANT
+ MANUAL_BUILD_VARIANT = 5;
}
diff --git a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
index 0029f9996..a9c0ccc12 100644
--- a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.36.5
// protoc v3.21.12
// source: build_flags_declarations.proto
@@ -26,6 +26,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -36,10 +37,7 @@ const (
)
type FlagDeclarationArtifact struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the flag.
// See # name for format detail
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
@@ -56,16 +54,16 @@ type FlagDeclarationArtifact struct {
Workflow *Workflow `protobuf:"varint,205,opt,name=workflow,enum=android.release_config_proto.Workflow" json:"workflow,omitempty"`
// The container for this flag. This overrides any default container given
// in the release_config_map message.
- Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"`
+ Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagDeclarationArtifact) Reset() {
*x = FlagDeclarationArtifact{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_declarations_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_declarations_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagDeclarationArtifact) String() string {
@@ -76,7 +74,7 @@ func (*FlagDeclarationArtifact) ProtoMessage() {}
func (x *FlagDeclarationArtifact) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_declarations_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -141,21 +139,18 @@ func (x *FlagDeclarationArtifact) GetContainers() []string {
}
type FlagDeclarationArtifacts struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The artifacts
FlagDeclarationArtifactList []*FlagDeclarationArtifact `protobuf:"bytes,1,rep,name=flag_declaration_artifact_list,json=flagDeclarationArtifactList" json:"flag_declaration_artifact_list,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagDeclarationArtifacts) Reset() {
*x = FlagDeclarationArtifacts{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_declarations_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_declarations_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagDeclarationArtifacts) String() string {
@@ -166,7 +161,7 @@ func (*FlagDeclarationArtifacts) ProtoMessage() {}
func (x *FlagDeclarationArtifacts) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_declarations_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -190,7 +185,7 @@ func (x *FlagDeclarationArtifacts) GetFlagDeclarationArtifactList() []*FlagDecla
var File_build_flags_declarations_proto protoreflect.FileDescriptor
-var file_build_flags_declarations_proto_rawDesc = []byte{
+var file_build_flags_declarations_proto_rawDesc = string([]byte{
0x0a, 0x1e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x64, 0x65,
0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x1c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
@@ -228,22 +223,22 @@ var file_build_flags_declarations_proto_rawDesc = []byte{
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72,
0x6f, 0x74, 0x6f,
-}
+})
var (
file_build_flags_declarations_proto_rawDescOnce sync.Once
- file_build_flags_declarations_proto_rawDescData = file_build_flags_declarations_proto_rawDesc
+ file_build_flags_declarations_proto_rawDescData []byte
)
func file_build_flags_declarations_proto_rawDescGZIP() []byte {
file_build_flags_declarations_proto_rawDescOnce.Do(func() {
- file_build_flags_declarations_proto_rawDescData = protoimpl.X.CompressGZIP(file_build_flags_declarations_proto_rawDescData)
+ file_build_flags_declarations_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_build_flags_declarations_proto_rawDesc), len(file_build_flags_declarations_proto_rawDesc)))
})
return file_build_flags_declarations_proto_rawDescData
}
var file_build_flags_declarations_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
-var file_build_flags_declarations_proto_goTypes = []interface{}{
+var file_build_flags_declarations_proto_goTypes = []any{
(*FlagDeclarationArtifact)(nil), // 0: android.release_config_proto.FlagDeclarationArtifact
(*FlagDeclarationArtifacts)(nil), // 1: android.release_config_proto.FlagDeclarationArtifacts
(Workflow)(0), // 2: android.release_config_proto.Workflow
@@ -264,37 +259,11 @@ func file_build_flags_declarations_proto_init() {
return
}
file_build_flags_common_proto_init()
- if !protoimpl.UnsafeEnabled {
- file_build_flags_declarations_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagDeclarationArtifact); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_declarations_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagDeclarationArtifacts); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_build_flags_declarations_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_build_flags_declarations_proto_rawDesc), len(file_build_flags_declarations_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -305,7 +274,6 @@ func file_build_flags_declarations_proto_init() {
MessageInfos: file_build_flags_declarations_proto_msgTypes,
}.Build()
File_build_flags_declarations_proto = out.File
- file_build_flags_declarations_proto_rawDesc = nil
file_build_flags_declarations_proto_goTypes = nil
file_build_flags_declarations_proto_depIdxs = nil
}
diff --git a/cmd/release_config/release_config_proto/build_flags_out.pb.go b/cmd/release_config/release_config_proto/build_flags_out.pb.go
index 21a37a921..defc60628 100644
--- a/cmd/release_config/release_config_proto/build_flags_out.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_out.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.36.5
// protoc v3.21.12
// source: build_flags_out.proto
@@ -26,6 +26,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -36,22 +37,19 @@ const (
)
type Tracepoint struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// Path to declaration or value file relative to $TOP
- Source *string `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"`
- Value *Value `protobuf:"bytes,201,opt,name=value" json:"value,omitempty"`
+ Source *string `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"`
+ Value *Value `protobuf:"bytes,201,opt,name=value" json:"value,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *Tracepoint) Reset() {
*x = Tracepoint{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_out_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_out_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *Tracepoint) String() string {
@@ -62,7 +60,7 @@ func (*Tracepoint) ProtoMessage() {}
func (x *Tracepoint) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_out_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -92,25 +90,22 @@ func (x *Tracepoint) GetValue() *Value {
}
type FlagArtifact struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The original declaration
FlagDeclaration *FlagDeclaration `protobuf:"bytes,1,opt,name=flag_declaration,json=flagDeclaration" json:"flag_declaration,omitempty"`
// Value for the flag
Value *Value `protobuf:"bytes,201,opt,name=value" json:"value,omitempty"`
// Trace of where the flag value was assigned.
- Traces []*Tracepoint `protobuf:"bytes,8,rep,name=traces" json:"traces,omitempty"`
+ Traces []*Tracepoint `protobuf:"bytes,8,rep,name=traces" json:"traces,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagArtifact) Reset() {
*x = FlagArtifact{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_out_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_out_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagArtifact) String() string {
@@ -121,7 +116,7 @@ func (*FlagArtifact) ProtoMessage() {}
func (x *FlagArtifact) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_out_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -158,21 +153,18 @@ func (x *FlagArtifact) GetTraces() []*Tracepoint {
}
type FlagArtifacts struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The artifacts
- Flags []*FlagArtifact `protobuf:"bytes,1,rep,name=flags" json:"flags,omitempty"`
+ Flags []*FlagArtifact `protobuf:"bytes,1,rep,name=flags" json:"flags,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagArtifacts) Reset() {
*x = FlagArtifacts{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_out_proto_msgTypes[2]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_out_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagArtifacts) String() string {
@@ -183,7 +175,7 @@ func (*FlagArtifacts) ProtoMessage() {}
func (x *FlagArtifacts) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_out_proto_msgTypes[2]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -206,10 +198,7 @@ func (x *FlagArtifacts) GetFlags() []*FlagArtifact {
}
type ReleaseConfigArtifact struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the release config.
// See # name for format detail
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
@@ -241,15 +230,15 @@ type ReleaseConfigArtifact struct {
// If true, this release config can only be inherited, it cannot be used
// directly in a build.
DisallowLunchUse *bool `protobuf:"varint,10,opt,name=disallow_lunch_use,json=disallowLunchUse" json:"disallow_lunch_use,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfigArtifact) Reset() {
*x = ReleaseConfigArtifact{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_out_proto_msgTypes[3]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_out_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfigArtifact) String() string {
@@ -260,7 +249,7 @@ func (*ReleaseConfigArtifact) ProtoMessage() {}
func (x *ReleaseConfigArtifact) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_out_proto_msgTypes[3]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -346,25 +335,22 @@ func (x *ReleaseConfigArtifact) GetDisallowLunchUse() bool {
}
type ReleaseConfigsArtifact struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The active release config for this build.
ReleaseConfig *ReleaseConfigArtifact `protobuf:"bytes,1,opt,name=release_config,json=releaseConfig" json:"release_config,omitempty"`
// All other release configs defined for this TARGET_PRODUCT.
OtherReleaseConfigs []*ReleaseConfigArtifact `protobuf:"bytes,2,rep,name=other_release_configs,json=otherReleaseConfigs" json:"other_release_configs,omitempty"`
// Map of release_config_artifact.directories to release_config_map message.
ReleaseConfigMapsMap map[string]*ReleaseConfigMap `protobuf:"bytes,3,rep,name=release_config_maps_map,json=releaseConfigMapsMap" json:"release_config_maps_map,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfigsArtifact) Reset() {
*x = ReleaseConfigsArtifact{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_out_proto_msgTypes[4]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_out_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfigsArtifact) String() string {
@@ -375,7 +361,7 @@ func (*ReleaseConfigsArtifact) ProtoMessage() {}
func (x *ReleaseConfigsArtifact) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_out_proto_msgTypes[4]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -413,7 +399,7 @@ func (x *ReleaseConfigsArtifact) GetReleaseConfigMapsMap() map[string]*ReleaseCo
var File_build_flags_out_proto protoreflect.FileDescriptor
-var file_build_flags_out_proto_rawDesc = []byte{
+var file_build_flags_out_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6f, 0x75,
0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
@@ -510,22 +496,22 @@ var file_build_flags_out_proto_rawDesc = []byte{
0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-}
+})
var (
file_build_flags_out_proto_rawDescOnce sync.Once
- file_build_flags_out_proto_rawDescData = file_build_flags_out_proto_rawDesc
+ file_build_flags_out_proto_rawDescData []byte
)
func file_build_flags_out_proto_rawDescGZIP() []byte {
file_build_flags_out_proto_rawDescOnce.Do(func() {
- file_build_flags_out_proto_rawDescData = protoimpl.X.CompressGZIP(file_build_flags_out_proto_rawDescData)
+ file_build_flags_out_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_build_flags_out_proto_rawDesc), len(file_build_flags_out_proto_rawDesc)))
})
return file_build_flags_out_proto_rawDescData
}
var file_build_flags_out_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_build_flags_out_proto_goTypes = []interface{}{
+var file_build_flags_out_proto_goTypes = []any{
(*Tracepoint)(nil), // 0: android.release_config_proto.Tracepoint
(*FlagArtifact)(nil), // 1: android.release_config_proto.FlagArtifact
(*FlagArtifacts)(nil), // 2: android.release_config_proto.FlagArtifacts
@@ -562,73 +548,11 @@ func file_build_flags_out_proto_init() {
return
}
file_build_flags_src_proto_init()
- if !protoimpl.UnsafeEnabled {
- file_build_flags_out_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Tracepoint); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_out_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagArtifact); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_out_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagArtifacts); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_out_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfigArtifact); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_out_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfigsArtifact); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_build_flags_out_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_build_flags_out_proto_rawDesc), len(file_build_flags_out_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
@@ -639,7 +563,6 @@ func file_build_flags_out_proto_init() {
MessageInfos: file_build_flags_out_proto_msgTypes,
}.Build()
File_build_flags_out_proto = out.File
- file_build_flags_out_proto_rawDesc = nil
file_build_flags_out_proto_goTypes = nil
file_build_flags_out_proto_depIdxs = nil
}
diff --git a/cmd/release_config/release_config_proto/build_flags_src.pb.go b/cmd/release_config/release_config_proto/build_flags_src.pb.go
index 9fc4ea461..ecbc00997 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_src.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.36.5
// protoc v3.21.12
// source: build_flags_src.proto
@@ -26,6 +26,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -106,26 +107,23 @@ func (ReleaseConfigType) EnumDescriptor() ([]byte, []int) {
}
type Value struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // Types that are assignable to Val:
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // Types that are valid to be assigned to Val:
//
// *Value_UnspecifiedValue
// *Value_StringValue
// *Value_BoolValue
// *Value_Obsolete
- Val isValue_Val `protobuf_oneof:"val"`
+ Val isValue_Val `protobuf_oneof:"val"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *Value) Reset() {
*x = Value{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *Value) String() string {
@@ -136,7 +134,7 @@ func (*Value) ProtoMessage() {}
func (x *Value) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -151,37 +149,45 @@ func (*Value) Descriptor() ([]byte, []int) {
return file_build_flags_src_proto_rawDescGZIP(), []int{0}
}
-func (m *Value) GetVal() isValue_Val {
- if m != nil {
- return m.Val
+func (x *Value) GetVal() isValue_Val {
+ if x != nil {
+ return x.Val
}
return nil
}
func (x *Value) GetUnspecifiedValue() bool {
- if x, ok := x.GetVal().(*Value_UnspecifiedValue); ok {
- return x.UnspecifiedValue
+ if x != nil {
+ if x, ok := x.Val.(*Value_UnspecifiedValue); ok {
+ return x.UnspecifiedValue
+ }
}
return false
}
func (x *Value) GetStringValue() string {
- if x, ok := x.GetVal().(*Value_StringValue); ok {
- return x.StringValue
+ if x != nil {
+ if x, ok := x.Val.(*Value_StringValue); ok {
+ return x.StringValue
+ }
}
return ""
}
func (x *Value) GetBoolValue() bool {
- if x, ok := x.GetVal().(*Value_BoolValue); ok {
- return x.BoolValue
+ if x != nil {
+ if x, ok := x.Val.(*Value_BoolValue); ok {
+ return x.BoolValue
+ }
}
return false
}
func (x *Value) GetObsolete() bool {
- if x, ok := x.GetVal().(*Value_Obsolete); ok {
- return x.Obsolete
+ if x != nil {
+ if x, ok := x.Val.(*Value_Obsolete); ok {
+ return x.Obsolete
+ }
}
return false
}
@@ -217,10 +223,7 @@ func (*Value_Obsolete) isValue_Val() {}
// The proto used in the source tree.
type FlagDeclaration struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the flag.
// See # name for format detail
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
@@ -237,16 +240,16 @@ type FlagDeclaration struct {
Workflow *Workflow `protobuf:"varint,205,opt,name=workflow,enum=android.release_config_proto.Workflow" json:"workflow,omitempty"`
// The container for this flag. This overrides any default container given
// in the release_config_map message.
- Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"`
+ Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagDeclaration) Reset() {
*x = FlagDeclaration{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagDeclaration) String() string {
@@ -257,7 +260,7 @@ func (*FlagDeclaration) ProtoMessage() {}
func (x *FlagDeclaration) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -322,10 +325,7 @@ func (x *FlagDeclaration) GetContainers() []string {
}
type FlagValue struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// Name of the flag.
// See # name for format detail
Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
@@ -333,16 +333,16 @@ type FlagValue struct {
Value *Value `protobuf:"bytes,201,opt,name=value" json:"value,omitempty"`
// If true, the flag is completely removed from the release config as if
// never declared.
- Redacted *bool `protobuf:"varint,202,opt,name=redacted" json:"redacted,omitempty"`
+ Redacted *bool `protobuf:"varint,202,opt,name=redacted" json:"redacted,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *FlagValue) Reset() {
*x = FlagValue{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[2]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *FlagValue) String() string {
@@ -353,7 +353,7 @@ func (*FlagValue) ProtoMessage() {}
func (x *FlagValue) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[2]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -391,10 +391,7 @@ func (x *FlagValue) GetRedacted() bool {
// This replaces $(call declare-release-config).
type ReleaseConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the release config.
// See # name for format detail
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
@@ -414,15 +411,15 @@ type ReleaseConfig struct {
// If true, this release config can only be inherited, it cannot be used
// directly in a build.
DisallowLunchUse *bool `protobuf:"varint,7,opt,name=disallow_lunch_use,json=disallowLunchUse" json:"disallow_lunch_use,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfig) Reset() {
*x = ReleaseConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[3]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfig) String() string {
@@ -433,7 +430,7 @@ func (*ReleaseConfig) ProtoMessage() {}
func (x *ReleaseConfig) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[3]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -499,23 +496,20 @@ func (x *ReleaseConfig) GetDisallowLunchUse() bool {
// Any aliases. These are used for continuous integration builder config.
type ReleaseAlias struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the alias.
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// The release that `name` is an alias for.
- Target *string `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"`
+ Target *string `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseAlias) Reset() {
*x = ReleaseAlias{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[4]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseAlias) String() string {
@@ -526,7 +520,7 @@ func (*ReleaseAlias) ProtoMessage() {}
func (x *ReleaseAlias) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[4]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -557,25 +551,22 @@ func (x *ReleaseAlias) GetTarget() string {
// This provides the data from release_config_map.mk
type ReleaseConfigMap struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// Any aliases.
Aliases []*ReleaseAlias `protobuf:"bytes,1,rep,name=aliases" json:"aliases,omitempty"`
// Description of this map and its intended use.
Description *string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"`
// The default container for flags declared here.
DefaultContainers []string `protobuf:"bytes,3,rep,name=default_containers,json=defaultContainers" json:"default_containers,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfigMap) Reset() {
*x = ReleaseConfigMap{}
- if protoimpl.UnsafeEnabled {
- mi := &file_build_flags_src_proto_msgTypes[5]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_build_flags_src_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfigMap) String() string {
@@ -586,7 +577,7 @@ func (*ReleaseConfigMap) ProtoMessage() {}
func (x *ReleaseConfigMap) ProtoReflect() protoreflect.Message {
mi := &file_build_flags_src_proto_msgTypes[5]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -624,7 +615,7 @@ func (x *ReleaseConfigMap) GetDefaultContainers() []string {
var File_build_flags_src_proto protoreflect.FileDescriptor
-var file_build_flags_src_proto_rawDesc = []byte{
+var file_build_flags_src_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x73, 0x72,
0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
@@ -713,23 +704,23 @@ var file_build_flags_src_proto_rawDesc = []byte{
0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-}
+})
var (
file_build_flags_src_proto_rawDescOnce sync.Once
- file_build_flags_src_proto_rawDescData = file_build_flags_src_proto_rawDesc
+ file_build_flags_src_proto_rawDescData []byte
)
func file_build_flags_src_proto_rawDescGZIP() []byte {
file_build_flags_src_proto_rawDescOnce.Do(func() {
- file_build_flags_src_proto_rawDescData = protoimpl.X.CompressGZIP(file_build_flags_src_proto_rawDescData)
+ file_build_flags_src_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_build_flags_src_proto_rawDesc), len(file_build_flags_src_proto_rawDesc)))
})
return file_build_flags_src_proto_rawDescData
}
var file_build_flags_src_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_build_flags_src_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_build_flags_src_proto_goTypes = []interface{}{
+var file_build_flags_src_proto_goTypes = []any{
(ReleaseConfigType)(0), // 0: android.release_config_proto.ReleaseConfigType
(*Value)(nil), // 1: android.release_config_proto.Value
(*FlagDeclaration)(nil), // 2: android.release_config_proto.FlagDeclaration
@@ -758,81 +749,7 @@ func file_build_flags_src_proto_init() {
return
}
file_build_flags_common_proto_init()
- if !protoimpl.UnsafeEnabled {
- file_build_flags_src_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Value); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_src_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagDeclaration); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_src_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FlagValue); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_src_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_src_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseAlias); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_build_flags_src_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfigMap); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
- file_build_flags_src_proto_msgTypes[0].OneofWrappers = []interface{}{
+ file_build_flags_src_proto_msgTypes[0].OneofWrappers = []any{
(*Value_UnspecifiedValue)(nil),
(*Value_StringValue)(nil),
(*Value_BoolValue)(nil),
@@ -842,7 +759,7 @@ func file_build_flags_src_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_build_flags_src_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_build_flags_src_proto_rawDesc), len(file_build_flags_src_proto_rawDesc)),
NumEnums: 1,
NumMessages: 6,
NumExtensions: 0,
@@ -854,7 +771,6 @@ func file_build_flags_src_proto_init() {
MessageInfos: file_build_flags_src_proto_msgTypes,
}.Build()
File_build_flags_src_proto = out.File
- file_build_flags_src_proto_rawDesc = nil
file_build_flags_src_proto_goTypes = nil
file_build_flags_src_proto_depIdxs = nil
}
diff --git a/cmd/release_config/release_config_proto/release_configs_contributions.pb.go b/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
index 339e4ba70..22ec35c79 100644
--- a/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
+++ b/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.36.5
// protoc v3.21.12
// source: release_configs_contributions.proto
@@ -26,6 +26,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -36,24 +37,21 @@ const (
)
type ReleaseConfigContributionsArtifact struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The name of the release config.
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// The release config contribution directories that may contribute to this
// release config.
ContributingDirectories []string `protobuf:"bytes,2,rep,name=contributing_directories,json=contributingDirectories" json:"contributing_directories,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfigContributionsArtifact) Reset() {
*x = ReleaseConfigContributionsArtifact{}
- if protoimpl.UnsafeEnabled {
- mi := &file_release_configs_contributions_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_release_configs_contributions_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfigContributionsArtifact) String() string {
@@ -64,7 +62,7 @@ func (*ReleaseConfigContributionsArtifact) ProtoMessage() {}
func (x *ReleaseConfigContributionsArtifact) ProtoReflect() protoreflect.Message {
mi := &file_release_configs_contributions_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -94,21 +92,18 @@ func (x *ReleaseConfigContributionsArtifact) GetContributingDirectories() []stri
}
type ReleaseConfigContributionsArtifacts struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// The artifacts
ReleaseConfigContributionsArtifactList []*ReleaseConfigContributionsArtifact `protobuf:"bytes,1,rep,name=release_config_contributions_artifact_list,json=releaseConfigContributionsArtifactList" json:"release_config_contributions_artifact_list,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *ReleaseConfigContributionsArtifacts) Reset() {
*x = ReleaseConfigContributionsArtifacts{}
- if protoimpl.UnsafeEnabled {
- mi := &file_release_configs_contributions_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_release_configs_contributions_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ReleaseConfigContributionsArtifacts) String() string {
@@ -119,7 +114,7 @@ func (*ReleaseConfigContributionsArtifacts) ProtoMessage() {}
func (x *ReleaseConfigContributionsArtifacts) ProtoReflect() protoreflect.Message {
mi := &file_release_configs_contributions_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -143,7 +138,7 @@ func (x *ReleaseConfigContributionsArtifacts) GetReleaseConfigContributionsArtif
var File_release_configs_contributions_proto protoreflect.FileDescriptor
-var file_release_configs_contributions_proto_rawDesc = []byte{
+var file_release_configs_contributions_proto_rawDesc = string([]byte{
0x0a, 0x23, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72,
@@ -172,22 +167,22 @@ var file_release_configs_contributions_proto_rawDesc = []byte{
0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f,
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70,
0x72, 0x6f, 0x74, 0x6f,
-}
+})
var (
file_release_configs_contributions_proto_rawDescOnce sync.Once
- file_release_configs_contributions_proto_rawDescData = file_release_configs_contributions_proto_rawDesc
+ file_release_configs_contributions_proto_rawDescData []byte
)
func file_release_configs_contributions_proto_rawDescGZIP() []byte {
file_release_configs_contributions_proto_rawDescOnce.Do(func() {
- file_release_configs_contributions_proto_rawDescData = protoimpl.X.CompressGZIP(file_release_configs_contributions_proto_rawDescData)
+ file_release_configs_contributions_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_release_configs_contributions_proto_rawDesc), len(file_release_configs_contributions_proto_rawDesc)))
})
return file_release_configs_contributions_proto_rawDescData
}
var file_release_configs_contributions_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
-var file_release_configs_contributions_proto_goTypes = []interface{}{
+var file_release_configs_contributions_proto_goTypes = []any{
(*ReleaseConfigContributionsArtifact)(nil), // 0: android.release_config_proto.ReleaseConfigContributionsArtifact
(*ReleaseConfigContributionsArtifacts)(nil), // 1: android.release_config_proto.ReleaseConfigContributionsArtifacts
}
@@ -205,37 +200,11 @@ func file_release_configs_contributions_proto_init() {
if File_release_configs_contributions_proto != nil {
return
}
- if !protoimpl.UnsafeEnabled {
- file_release_configs_contributions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfigContributionsArtifact); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_release_configs_contributions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ReleaseConfigContributionsArtifacts); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_release_configs_contributions_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_release_configs_contributions_proto_rawDesc), len(file_release_configs_contributions_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -246,7 +215,6 @@ func file_release_configs_contributions_proto_init() {
MessageInfos: file_release_configs_contributions_proto_msgTypes,
}.Build()
File_release_configs_contributions_proto = out.File
- file_release_configs_contributions_proto_rawDesc = nil
file_release_configs_contributions_proto_goTypes = nil
file_release_configs_contributions_proto_depIdxs = nil
}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index f3931a45e..466c88312 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -33,7 +33,6 @@ import (
"time"
"android/soong/cmd/sbox/sbox_proto"
- "android/soong/makedeps"
"android/soong/response"
"google.golang.org/protobuf/encoding/prototext"
@@ -48,7 +47,6 @@ var (
)
const (
- depFilePlaceholder = "__SBOX_DEPFILE__"
sandboxDirPlaceholder = "__SBOX_SANDBOX_DIR__"
)
@@ -170,14 +168,13 @@ func run() error {
// If there is more than one command in the manifest use a separate directory for each one.
useSubDir := len(manifest.Commands) > 1
- var commandDepFiles []string
for i, command := range manifest.Commands {
localTempDir := tempDir
if useSubDir {
localTempDir = filepath.Join(localTempDir, strconv.Itoa(i))
}
- depFile, err := runCommand(command, localTempDir, i)
+ err := runCommand(command, localTempDir, i)
if err != nil {
// Running the command failed, keep the temporary output directory around in
// case a user wants to inspect it for debugging purposes. Soong will delete
@@ -185,23 +182,6 @@ func run() error {
keepOutDir = true
return err
}
- if depFile != "" {
- commandDepFiles = append(commandDepFiles, depFile)
- }
- }
-
- outputDepFile := manifest.GetOutputDepfile()
- if len(commandDepFiles) > 0 && outputDepFile == "" {
- return fmt.Errorf("Sandboxed commands used %s but output depfile is not set in manifest file",
- depFilePlaceholder)
- }
-
- if outputDepFile != "" {
- // Merge the depfiles from each command in the manifest to a single output depfile.
- err = rewriteDepFiles(commandDepFiles, outputDepFile)
- if err != nil {
- return fmt.Errorf("failed merging depfiles: %w", err)
- }
}
return nil
@@ -286,18 +266,17 @@ func createEnv(command *sbox_proto.Command) ([]string, error) {
return env, nil
}
-// runCommand runs a single command from a manifest. If the command references the
-// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
-func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (depFile string, err error) {
+// runCommand runs a single command from a manifest.
+func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (err error) {
rawCommand := command.GetCommand()
if rawCommand == "" {
- return "", fmt.Errorf("command is required")
+ return fmt.Errorf("command is required")
}
// Remove files from the output directory
err = clearOutputDirectory(command.CopyAfter, outputDir, writeType(writeIfChanged))
if err != nil {
- return "", err
+ return err
}
pathToTempDirInSbox := tempDir
@@ -307,22 +286,21 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
err = os.MkdirAll(tempDir, 0777)
if err != nil {
- return "", fmt.Errorf("failed to create %q: %w", tempDir, err)
+ return fmt.Errorf("failed to create %q: %w", tempDir, err)
}
// Copy in any files specified by the manifest.
err = copyFiles(command.CopyBefore, "", tempDir, requireFromExists, alwaysWrite)
if err != nil {
- return "", err
+ return err
+ }
+ err = copyDirs(command.CopyDirBefore, "", tempDir)
+ if err != nil {
+ return err
}
err = copyRspFiles(command.RspFiles, tempDir, pathToTempDirInSbox)
if err != nil {
- return "", err
- }
-
- if strings.Contains(rawCommand, depFilePlaceholder) {
- depFile = filepath.Join(pathToTempDirInSbox, "deps.d")
- rawCommand = strings.Replace(rawCommand, depFilePlaceholder, depFile, -1)
+ return err
}
if strings.Contains(rawCommand, sandboxDirPlaceholder) {
@@ -333,7 +311,7 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
// running the command.
err = makeOutputDirs(command.CopyAfter, tempDir)
if err != nil {
- return "", err
+ return err
}
scriptName := fmt.Sprintf("sbox_command.%d.bash", commandIndex)
@@ -341,7 +319,7 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
scriptPathInSandbox := joinPath(pathToTempDirInSbox, scriptName)
cmd, err := createCommandScript(rawCommand, scriptPath, scriptPathInSandbox)
if err != nil {
- return "", err
+ return err
}
buf := &bytes.Buffer{}
@@ -354,17 +332,17 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
path := os.Getenv("PATH")
absPath, err := makeAbsPathEnv(path)
if err != nil {
- return "", err
+ return err
}
err = os.Setenv("PATH", absPath)
if err != nil {
- return "", fmt.Errorf("Failed to update PATH: %w", err)
+ return fmt.Errorf("Failed to update PATH: %w", err)
}
}
cmd.Env, err = createEnv(command)
if err != nil {
- return "", err
+ return err
}
err = cmd.Run()
@@ -392,21 +370,21 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
os.Stdout.Write(buf.Bytes())
if err != nil {
- return "", err
+ return err
}
err = validateOutputFiles(command.CopyAfter, tempDir, outputDir, rawCommand)
if err != nil {
- return "", err
+ return err
}
// the created files match the declared files; now move them
err = moveFiles(command.CopyAfter, tempDir, "", writeType(writeIfChanged))
if err != nil {
- return "", err
+ return err
}
- return depFile, nil
+ return nil
}
// makeOutputDirs creates directories in the sandbox dir for every file that has a rule to be copied
@@ -619,6 +597,47 @@ func copyOneFile(from string, to string, forceExecutable bool, exists existsType
return nil
}
+// copyFiles copies files in or out of the sandbox. If exists is allowFromNotExists then errors
+// caused by a from path not existing are ignored. If write is onlyWriteIfChanged then the output
+// file is compared to the input file and not written to if it is the same, avoiding updating
+// the timestamp.
+func copyDirs(copies []*sbox_proto.CopyDir, fromDir, toDir string) error {
+ for _, copyPair := range copies {
+ fromPath := joinPath(fromDir, copyPair.GetFrom())
+ toPath := joinPath(toDir, copyPair.GetTo())
+ err := copyOneDir(fromPath, toPath)
+ if err != nil {
+ return fmt.Errorf("error copying %q to %q: %w", fromPath, toPath, err)
+ }
+ }
+ return nil
+}
+
+func copyOneDir(from, to string) error {
+ stat, err := os.Lstat(from)
+ if err != nil {
+ return err
+ }
+ if !stat.IsDir() {
+ return fmt.Errorf("expected %q to be a directory, but it wasn't", from)
+ }
+ dirEnts, err := os.ReadDir(from)
+ if err != nil {
+ return err
+ }
+ for _, entry := range dirEnts {
+ if entry.IsDir() {
+ err = copyOneDir(filepath.Join(from, entry.Name()), filepath.Join(to, entry.Name()))
+ } else {
+ err = copyOneFile(filepath.Join(from, entry.Name()), filepath.Join(to, entry.Name()), false, requireFromExists, alwaysWrite)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// copyRspFiles copies rsp files into the sandbox with path mappings, and also copies the files
// listed into the sandbox.
func copyRspFiles(rspFiles []*sbox_proto.RspFile, toDir, toDirInSandbox string) error {
@@ -761,40 +780,6 @@ func clearOutputDirectory(copies []*sbox_proto.Copy, outputDir string, write wri
return nil
}
-// Rewrite one or more depfiles so that it doesn't include the (randomized) sandbox directory
-// to an output file.
-func rewriteDepFiles(ins []string, out string) error {
- var mergedDeps []string
- for _, in := range ins {
- data, err := ioutil.ReadFile(in)
- if err != nil {
- return err
- }
-
- deps, err := makedeps.Parse(in, bytes.NewBuffer(data))
- if err != nil {
- return err
- }
- mergedDeps = append(mergedDeps, deps.Inputs...)
- }
-
- deps := makedeps.Deps{
- // Ninja doesn't care what the output file is, so we can use any string here.
- Output: "outputfile",
- Inputs: mergedDeps,
- }
-
- // Make the directory for the output depfile in case it is in a different directory
- // than any of the output files.
- outDir := filepath.Dir(out)
- err := os.MkdirAll(outDir, 0777)
- if err != nil {
- return fmt.Errorf("failed to create %q: %w", outDir, err)
- }
-
- return ioutil.WriteFile(out, deps.Print(), 0666)
-}
-
// joinPath wraps filepath.Join but returns file without appending to dir if file is
// absolute.
func joinPath(dir, file string) string {
diff --git a/cmd/sbox/sbox_proto/sbox.pb.go b/cmd/sbox/sbox_proto/sbox.pb.go
index 271039c50..b7235f26a 100644
--- a/cmd/sbox/sbox_proto/sbox.pb.go
+++ b/cmd/sbox/sbox_proto/sbox.pb.go
@@ -42,9 +42,6 @@ type Manifest struct {
// A list of commands to run in the sandbox.
Commands []*Command `protobuf:"bytes,1,rep,name=commands" json:"commands,omitempty"`
- // If set, GCC-style dependency files from any command that references __SBOX_DEPFILE__ will be
- // merged into the given output file relative to the $PWD when sbox was started.
- OutputDepfile *string `protobuf:"bytes,2,opt,name=output_depfile,json=outputDepfile" json:"output_depfile,omitempty"`
}
func (x *Manifest) Reset() {
@@ -86,13 +83,6 @@ func (x *Manifest) GetCommands() []*Command {
return nil
}
-func (x *Manifest) GetOutputDepfile() string {
- if x != nil && x.OutputDepfile != nil {
- return *x.OutputDepfile
- }
- return ""
-}
-
// SandboxManifest describes a command to run in the sandbox.
type Command struct {
state protoimpl.MessageState
@@ -123,6 +113,8 @@ type Command struct {
// replaced or unset by env. If dont_inherit_env is set, no environment variables will be
// inherited, and instead only the variables in env will be defined.
DontInheritEnv *bool `protobuf:"varint,8,opt,name=dont_inherit_env,json=dontInheritEnv" json:"dont_inherit_env,omitempty"`
+ // A list of directories to copy before running the sandboxed command.
+ CopyDirBefore []*CopyDir `protobuf:"bytes,9,rep,name=copy_dir_before,json=copyDirBefore" json:"copy_dir_before,omitempty"`
}
func (x *Command) Reset() {
@@ -213,6 +205,13 @@ func (x *Command) GetDontInheritEnv() bool {
return false
}
+func (x *Command) GetCopyDirBefore() []*CopyDir {
+ if x != nil {
+ return x.CopyDirBefore
+ }
+ return nil
+}
+
type EnvironmentVariable struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -389,6 +388,62 @@ func (x *Copy) GetExecutable() bool {
return false
}
+// Copy describes a from-to pair of a directory to copy.
+type CopyDir struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ From *string `protobuf:"bytes,1,req,name=from" json:"from,omitempty"`
+ To *string `protobuf:"bytes,2,req,name=to" json:"to,omitempty"`
+}
+
+func (x *CopyDir) Reset() {
+ *x = CopyDir{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_sbox_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CopyDir) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CopyDir) ProtoMessage() {}
+
+func (x *CopyDir) ProtoReflect() protoreflect.Message {
+ mi := &file_sbox_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CopyDir.ProtoReflect.Descriptor instead.
+func (*CopyDir) Descriptor() ([]byte, []int) {
+ return file_sbox_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *CopyDir) GetFrom() string {
+ if x != nil && x.From != nil {
+ return *x.From
+ }
+ return ""
+}
+
+func (x *CopyDir) GetTo() string {
+ if x != nil && x.To != nil {
+ return *x.To
+ }
+ return ""
+}
+
// RspFile describes an rspfile that should be copied into the sandbox directory.
type RspFile struct {
state protoimpl.MessageState
@@ -404,7 +459,7 @@ type RspFile struct {
func (x *RspFile) Reset() {
*x = RspFile{}
if protoimpl.UnsafeEnabled {
- mi := &file_sbox_proto_msgTypes[4]
+ mi := &file_sbox_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -417,7 +472,7 @@ func (x *RspFile) String() string {
func (*RspFile) ProtoMessage() {}
func (x *RspFile) ProtoReflect() protoreflect.Message {
- mi := &file_sbox_proto_msgTypes[4]
+ mi := &file_sbox_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -430,7 +485,7 @@ func (x *RspFile) ProtoReflect() protoreflect.Message {
// Deprecated: Use RspFile.ProtoReflect.Descriptor instead.
func (*RspFile) Descriptor() ([]byte, []int) {
- return file_sbox_proto_rawDescGZIP(), []int{4}
+ return file_sbox_proto_rawDescGZIP(), []int{5}
}
func (x *RspFile) GetFile() string {
@@ -460,7 +515,7 @@ type PathMapping struct {
func (x *PathMapping) Reset() {
*x = PathMapping{}
if protoimpl.UnsafeEnabled {
- mi := &file_sbox_proto_msgTypes[5]
+ mi := &file_sbox_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -473,7 +528,7 @@ func (x *PathMapping) String() string {
func (*PathMapping) ProtoMessage() {}
func (x *PathMapping) ProtoReflect() protoreflect.Message {
- mi := &file_sbox_proto_msgTypes[5]
+ mi := &file_sbox_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -486,7 +541,7 @@ func (x *PathMapping) ProtoReflect() protoreflect.Message {
// Deprecated: Use PathMapping.ProtoReflect.Descriptor instead.
func (*PathMapping) Descriptor() ([]byte, []int) {
- return file_sbox_proto_rawDescGZIP(), []int{5}
+ return file_sbox_proto_rawDescGZIP(), []int{6}
}
func (x *PathMapping) GetFrom() string {
@@ -507,56 +562,60 @@ var File_sbox_proto protoreflect.FileDescriptor
var file_sbox_proto_rawDesc = []byte{
0x0a, 0x0a, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x73, 0x62,
- 0x6f, 0x78, 0x22, 0x5c, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x29,
+ 0x6f, 0x78, 0x22, 0x3b, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x29,
0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0d, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52,
- 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x75, 0x74,
- 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x44, 0x65, 0x70, 0x66, 0x69, 0x6c, 0x65,
- 0x22, 0xb3, 0x02, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2b, 0x0a, 0x0b,
- 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x0a, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x0a, 0x63,
- 0x6f, 0x70, 0x79, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x64,
- 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x68, 0x64, 0x69, 0x72, 0x12,
- 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x02, 0x28, 0x09,
- 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x0a, 0x63, 0x6f, 0x70,
- 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
- 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x09, 0x63, 0x6f, 0x70, 0x79, 0x41,
- 0x66, 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61,
- 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x48,
- 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x09, 0x72, 0x73, 0x70, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73,
- 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x52, 0x73,
- 0x70, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x72, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
- 0x2b, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73,
- 0x62, 0x6f, 0x78, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56,
- 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x28, 0x0a, 0x10,
- 0x64, 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x5f, 0x65, 0x6e, 0x76,
- 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x6f, 0x6e, 0x74, 0x49, 0x6e, 0x68, 0x65,
- 0x72, 0x69, 0x74, 0x45, 0x6e, 0x76, 0x22, 0x7e, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f,
- 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x16, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x75, 0x6e, 0x73,
- 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, 0x73, 0x65,
- 0x74, 0x12, 0x1a, 0x0a, 0x07, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01,
- 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x42, 0x07, 0x0a,
- 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4a, 0x0a, 0x04, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x12,
- 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72,
- 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02,
- 0x74, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62,
- 0x6c, 0x65, 0x22, 0x55, 0x0a, 0x07, 0x52, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c,
- 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e,
- 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e,
- 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x70, 0x61, 0x74,
- 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x31, 0x0a, 0x0b, 0x50, 0x61, 0x74,
- 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d,
- 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02,
- 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x42, 0x23, 0x5a, 0x21,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d,
- 0x64, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x74,
- 0x6f,
+ 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22,
+ 0xea, 0x02, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2b, 0x0a, 0x0b, 0x63,
+ 0x6f, 0x70, 0x79, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x0a, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x0a, 0x63, 0x6f,
+ 0x70, 0x79, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x64, 0x69,
+ 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x68, 0x64, 0x69, 0x72, 0x12, 0x18,
+ 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x02, 0x28, 0x09, 0x52,
+ 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x0a, 0x63, 0x6f, 0x70, 0x79,
+ 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x73,
+ 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x09, 0x63, 0x6f, 0x70, 0x79, 0x41, 0x66,
+ 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x73,
+ 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x61,
+ 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x09, 0x72, 0x73, 0x70, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18,
+ 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x52, 0x73, 0x70,
+ 0x46, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x72, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2b,
+ 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x62,
+ 0x6f, 0x78, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x28, 0x0a, 0x10, 0x64,
+ 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x5f, 0x65, 0x6e, 0x76, 0x18,
+ 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x6f, 0x6e, 0x74, 0x49, 0x6e, 0x68, 0x65, 0x72,
+ 0x69, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x35, 0x0a, 0x0f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x64, 0x69,
+ 0x72, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d,
+ 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x44, 0x69, 0x72, 0x52, 0x0d, 0x63,
+ 0x6f, 0x70, 0x79, 0x44, 0x69, 0x72, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x22, 0x7e, 0x0a, 0x13,
+ 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12,
+ 0x16, 0x0a, 0x05, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00,
+ 0x52, 0x05, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x07, 0x69, 0x6e, 0x68, 0x65, 0x72,
+ 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x68, 0x65,
+ 0x72, 0x69, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4a, 0x0a, 0x04,
+ 0x43, 0x6f, 0x70, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02,
+ 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02,
+ 0x20, 0x02, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x65, 0x63,
+ 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78,
+ 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x2d, 0x0a, 0x07, 0x43, 0x6f, 0x70, 0x79,
+ 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20,
+ 0x02, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x07, 0x52, 0x73, 0x70, 0x46, 0x69,
+ 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09,
+ 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d,
+ 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
+ 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x52, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x31,
+ 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a,
+ 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f,
+ 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02, 0x74,
+ 0x6f, 0x42, 0x23, 0x5a, 0x21, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x2f, 0x73, 0x62, 0x6f, 0x78,
+ 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -571,27 +630,29 @@ func file_sbox_proto_rawDescGZIP() []byte {
return file_sbox_proto_rawDescData
}
-var file_sbox_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_sbox_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_sbox_proto_goTypes = []interface{}{
(*Manifest)(nil), // 0: sbox.Manifest
(*Command)(nil), // 1: sbox.Command
(*EnvironmentVariable)(nil), // 2: sbox.EnvironmentVariable
(*Copy)(nil), // 3: sbox.Copy
- (*RspFile)(nil), // 4: sbox.RspFile
- (*PathMapping)(nil), // 5: sbox.PathMapping
+ (*CopyDir)(nil), // 4: sbox.CopyDir
+ (*RspFile)(nil), // 5: sbox.RspFile
+ (*PathMapping)(nil), // 6: sbox.PathMapping
}
var file_sbox_proto_depIdxs = []int32{
1, // 0: sbox.Manifest.commands:type_name -> sbox.Command
3, // 1: sbox.Command.copy_before:type_name -> sbox.Copy
3, // 2: sbox.Command.copy_after:type_name -> sbox.Copy
- 4, // 3: sbox.Command.rsp_files:type_name -> sbox.RspFile
+ 5, // 3: sbox.Command.rsp_files:type_name -> sbox.RspFile
2, // 4: sbox.Command.env:type_name -> sbox.EnvironmentVariable
- 5, // 5: sbox.RspFile.path_mappings:type_name -> sbox.PathMapping
- 6, // [6:6] is the sub-list for method output_type
- 6, // [6:6] is the sub-list for method input_type
- 6, // [6:6] is the sub-list for extension type_name
- 6, // [6:6] is the sub-list for extension extendee
- 0, // [0:6] is the sub-list for field type_name
+ 4, // 5: sbox.Command.copy_dir_before:type_name -> sbox.CopyDir
+ 6, // 6: sbox.RspFile.path_mappings:type_name -> sbox.PathMapping
+ 7, // [7:7] is the sub-list for method output_type
+ 7, // [7:7] is the sub-list for method input_type
+ 7, // [7:7] is the sub-list for extension type_name
+ 7, // [7:7] is the sub-list for extension extendee
+ 0, // [0:7] is the sub-list for field type_name
}
func init() { file_sbox_proto_init() }
@@ -649,7 +710,7 @@ func file_sbox_proto_init() {
}
}
file_sbox_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RspFile); i {
+ switch v := v.(*CopyDir); i {
case 0:
return &v.state
case 1:
@@ -661,6 +722,18 @@ func file_sbox_proto_init() {
}
}
file_sbox_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RspFile); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_sbox_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PathMapping); i {
case 0:
return &v.state
@@ -684,7 +757,7 @@ func file_sbox_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_sbox_proto_rawDesc,
NumEnums: 0,
- NumMessages: 6,
+ NumMessages: 7,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/cmd/sbox/sbox_proto/sbox.proto b/cmd/sbox/sbox_proto/sbox.proto
index 1158554ab..87740a6e9 100644
--- a/cmd/sbox/sbox_proto/sbox.proto
+++ b/cmd/sbox/sbox_proto/sbox.proto
@@ -22,9 +22,7 @@ message Manifest {
// A list of commands to run in the sandbox.
repeated Command commands = 1;
- // If set, GCC-style dependency files from any command that references __SBOX_DEPFILE__ will be
- // merged into the given output file relative to the $PWD when sbox was started.
- optional string output_depfile = 2;
+ reserved 2;
}
// SandboxManifest describes a command to run in the sandbox.
@@ -60,6 +58,9 @@ message Command {
// replaced or unset by env. If dont_inherit_env is set, no environment variables will be
// inherited, and instead only the variables in env will be defined.
optional bool dont_inherit_env = 8;
+
+ // A list of directories to copy before running the sandboxed command.
+ repeated CopyDir copy_dir_before = 9;
}
message EnvironmentVariable {
@@ -88,6 +89,12 @@ message Copy {
optional bool executable = 3;
}
+// Copy describes a from-to pair of a directory to copy.
+message CopyDir {
+ required string from = 1;
+ required string to = 2;
+}
+
// RspFile describes an rspfile that should be copied into the sandbox directory.
message RspFile {
// The path to the rsp file.
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index cd4e9bdc2..f8b7e42b8 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,6 +21,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "runtime"
"strings"
"time"
@@ -28,13 +29,14 @@ import (
"android/soong/android/allowlists"
"android/soong/shared"
+ androidProtobuf "google.golang.org/protobuf/android"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/deptools"
"github.com/google/blueprint/metrics"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
- androidProtobuf "google.golang.org/protobuf/android"
)
var (
@@ -75,8 +77,6 @@ func init() {
flag.BoolVar(&cmdlineArgs.NoGC, "nogc", false, "turn off GC for debugging")
// Flags representing various modes soong_build can run in
- flag.StringVar(&cmdlineArgs.ModuleGraphFile, "module_graph_file", "", "JSON module graph file to output")
- flag.StringVar(&cmdlineArgs.ModuleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
flag.StringVar(&cmdlineArgs.DocFile, "soong_docs", "", "build documentation file to output")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.StringVar(&cmdlineArgs.SoongVariables, "soong_variables", "soong.variables", "the file contains all build variables")
@@ -88,6 +88,7 @@ func init() {
// the time to remove them yet
flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
flag.BoolVar(&cmdlineArgs.IncrementalBuildActions, "incremental-build-actions", false, "generate build actions incrementally")
+ flag.StringVar(&cmdlineArgs.IncrementalDebugFile, "incremental-debug-file", "", "incremental debug file")
// Disable deterministic randomization in the protobuf package, so incremental
// builds with unrelated Soong changes don't trigger large rebuilds (since we
@@ -128,7 +129,7 @@ func writeNinjaHint(ctx *android.Context) error {
// real long-running jobs cannot run early.
// Therefore, the model should be adjusted in this case.
// The model should also be adjusted if there are critical false negatives.
- predicate := func(j *blueprint.JsonModule) (prioritized bool, weight int) {
+ predicate := func(j *blueprint.WeightedOutputsModuleInfo) (prioritized bool, weight int) {
prioritized = false
weight = 0
for prefix, w := range allowlists.HugeModuleTypePrefixMap {
@@ -138,12 +139,7 @@ func writeNinjaHint(ctx *android.Context) error {
return
}
}
- dep_count := len(j.Deps)
- src_count := 0
- for _, a := range j.Module["Actions"].([]blueprint.JSONAction) {
- src_count += len(a.Inputs)
- }
- input_size := dep_count + src_count
+ input_size := j.DepsCount + j.SrcsCount
// Current threshold is an arbitrary value which only consider recall rather than accuracy.
if input_size > allowlists.INPUT_SIZE_THRESHOLD {
@@ -182,16 +178,6 @@ func writeMetrics(configuration android.Config, eventHandler *metrics.EventHandl
maybeQuit(err, "error writing soong_build metrics %s", metricsFile)
}
-func writeJsonModuleGraphAndActions(ctx *android.Context, cmdArgs android.CmdArgs) {
- graphFile, graphErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleGraphFile))
- maybeQuit(graphErr, "graph err")
- defer graphFile.Close()
- actionsFile, actionsErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleActionsFile))
- maybeQuit(actionsErr, "actions err")
- defer actionsFile.Close()
- ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
-}
-
func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDeps []string) {
eventHandler.Begin("ninja_deps")
defer eventHandler.End("ninja_deps")
@@ -270,8 +256,6 @@ func runSoongOnlyBuild(ctx *android.Context) (string, []string) {
var stopBefore bootstrap.StopBefore
switch ctx.Config().BuildMode {
- case android.GenerateModuleGraph:
- stopBefore = bootstrap.StopBeforeWriteNinja
case android.GenerateDocFile:
stopBefore = bootstrap.StopBeforePrepareBuildActions
default:
@@ -283,9 +267,6 @@ func runSoongOnlyBuild(ctx *android.Context) (string, []string) {
// Convert the Soong module graph into Bazel BUILD files.
switch ctx.Config().BuildMode {
- case android.GenerateModuleGraph:
- writeJsonModuleGraphAndActions(ctx, cmdlineArgs)
- return cmdlineArgs.ModuleGraphFile, ninjaDeps
case android.GenerateDocFile:
// TODO: we could make writeDocs() return the list of documentation files
// written and add them to the .d file. Then soong_docs would be re-run
@@ -329,6 +310,12 @@ func parseAvailableEnv() map[string]string {
func main() {
flag.Parse()
+ if cmdlineArgs.Memprofile == "" {
+ // Go enables memory profile collection automatically if any references
+ // are linked in to the binary.
+ // Disable collection of memory profiles if we won't save one to disk.
+ runtime.MemProfileRate = 0
+ }
soongStartTime := time.Now()
shared.ReexecWithDelveMaybe(delveListen, delvePath)
@@ -356,6 +343,7 @@ func main() {
configCache, incremental = incrementalValid(ctx.Config(), configFile)
}
ctx.SetIncrementalAnalysis(incremental)
+ ctx.SetIncrementalDebugFile(cmdlineArgs.IncrementalDebugFile)
ctx.Register()
finalOutputFile, ninjaDeps := runSoongOnlyBuild(ctx)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 584cc042d..f9e223a1e 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -74,7 +74,7 @@ var commands = []command{
description: "print the value of the legacy make variable VAR to stdout",
simpleOutput: true,
logsPrefix: "dumpvars-",
- config: dumpVarConfig,
+ config: build.NewDumpVarConfig,
stdio: customStdio,
run: dumpVar,
}, {
@@ -82,7 +82,7 @@ var commands = []command{
description: "dump the values of one or more legacy make variables, in shell syntax",
simpleOutput: true,
logsPrefix: "dumpvars-",
- config: dumpVarConfig,
+ config: build.NewDumpVarConfig,
stdio: customStdio,
run: dumpVars,
}, {
@@ -442,11 +442,6 @@ func customStdio() terminal.StdioInterface {
return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
}
-// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
-func dumpVarConfig(ctx build.Context, args ...string) build.Config {
- return build.NewConfig(ctx)
-}
-
func buildActionConfig(ctx build.Context, args ...string) build.Config {
flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
flags.SetOutput(ctx.Writer)
diff --git a/compliance/notice.go b/compliance/notice.go
index c5b0fbebe..ff6f5b6ab 100644
--- a/compliance/notice.go
+++ b/compliance/notice.go
@@ -63,6 +63,8 @@ type NoticeXmlModule struct {
props noticeXmlProperties
+ disabled bool
+
outputFile android.OutputPath
}
@@ -70,9 +72,18 @@ type noticeXmlProperties struct {
Partition_name string
}
+func (nx *NoticeXmlModule) UseGenericConfig() bool {
+ return false
+}
+
func (nx *NoticeXmlModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- prodVars := ctx.Config().ProductVariables()
- buildFingerprintFile := android.PathForArbitraryOutput(ctx, "target", "product", android.String(prodVars.DeviceName), "build_fingerprint.txt")
+ // No build action needs to be done in notice_xml module type if notice xml generation is disabled
+ if ctx.Config().DisableNoticeXmlGeneration() {
+ nx.disabled = true
+ return
+ }
+
+ buildFingerprintFile := ctx.Config().BuildFingerprintFile(ctx)
implicits := []android.Path{buildFingerprintFile}
output := android.PathForModuleOut(ctx, "NOTICE.xml.gz")
@@ -101,5 +112,6 @@ func (nx *NoticeXmlModule) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{{
Class: "ETC",
OutputFile: android.OptionalPathForPath(nx.outputFile),
+ Disabled: nx.disabled,
}}
}
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index 7f50912b5..8658040f6 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -328,7 +328,12 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont
} else if clc.Host == hostPath && clc.Device == devicePath {
// Ok, the same library with the same paths. Don't re-add it, but don't raise an error
// either, as the same library may be reachable via different transitional dependencies.
+ // For the same library brought in by different dependencies, some of them don't carry all the
+ // fields, so we populate the fields from other dependencies when available.
clc.Optional = clc.Optional && optional
+ if len(clc.Subcontexts) == 0 {
+ clc.Subcontexts = subcontexts
+ }
return nil
} else {
// Fail, as someone is trying to add the same library with different paths. This likely
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index af09dbcca..1fb652c3c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -101,6 +101,10 @@ type GlobalConfig struct {
// "true" to force preopt with CMC GC (a.k.a., UFFD GC); "false" to force preopt with CC GC;
// "default" to determine the GC type based on the kernel version file.
EnableUffdGc string
+
+ // The target's `SDK_INT` (ro.build.version.sdk) string value. "" for undefined/indeterminate.
+ // Conditionally used to set assumed values in AOT-compilation.
+ PlatformSdkVersion string
}
var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
@@ -162,6 +166,7 @@ type GlobalSoongConfig struct {
ManifestCheck android.Path
ConstructContext android.Path
UffdGcFlag android.WritablePath
+ AssumeValueFlags android.WritablePath
}
type ModuleConfig struct {
@@ -469,8 +474,8 @@ func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Modul
func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy(
ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
- return android.OtherModulePointerProviderOrDefault(
- ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt
+ return android.OtherModuleProviderOrDefault(
+ ctx, target, android.PrebuiltInfoProvider).ReplacedByPrebuilt
}
// Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that
@@ -514,7 +519,11 @@ func dex2oatPathFromDep(ctx android.ModuleContext) android.Path {
// prebuilt explicitly here instead.
var dex2oatModule android.ModuleProxy
ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
- prebuiltInfo, isPrebuilt := android.OtherModuleProvider(ctx, child, android.PrebuiltModuleInfoProvider)
+ var isPrebuilt, usePrebuilt bool
+ if prebuiltInfo, ok := android.OtherModuleProvider(ctx, child, android.PrebuiltInfoProvider); ok {
+ isPrebuilt = prebuiltInfo.IsPrebuilt
+ usePrebuilt = prebuiltInfo.UsePrebuilt
+ }
if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
// Found the source module, or prebuilt module that has replaced the source.
dex2oatModule = child
@@ -525,7 +534,7 @@ func dex2oatPathFromDep(ctx android.ModuleContext) android.Path {
}
}
if android.EqualModules(parent, dex2oatModule) && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
- if isPrebuilt && prebuiltInfo.UsePrebuilt {
+ if isPrebuilt && usePrebuilt {
dex2oatModule = child // Found a prebuilt that should be used.
}
}
@@ -557,6 +566,7 @@ func createGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig {
ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"),
ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"),
UffdGcFlag: getUffdGcFlagPath(ctx),
+ AssumeValueFlags: getAssumeValueFlagsPath(ctx),
}
}
@@ -609,6 +619,7 @@ type globalJsonSoongConfig struct {
ManifestCheck string
ConstructContext string
UffdGcFlag string
+ AssumeValueFlags string
}
// ParseGlobalSoongConfig parses the given data assumed to be read from the
@@ -631,6 +642,7 @@ func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongC
ManifestCheck: constructPath(ctx, jc.ManifestCheck),
ConstructContext: constructPath(ctx, jc.ConstructContext),
UffdGcFlag: constructWritablePath(ctx, jc.UffdGcFlag),
+ AssumeValueFlags: constructWritablePath(ctx, jc.AssumeValueFlags),
}
return config, nil
@@ -671,6 +683,8 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
return
}
+ buildAssumedValues(ctx, global, config)
+
jc := globalJsonSoongConfig{
Profman: config.Profman.String(),
Dex2oat: config.Dex2oat.String(),
@@ -680,6 +694,7 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
ManifestCheck: config.ManifestCheck.String(),
ConstructContext: config.ConstructContext.String(),
UffdGcFlag: config.UffdGcFlag.String(),
+ AssumeValueFlags: config.AssumeValueFlags.String(),
}
data, err := json.Marshal(jc)
@@ -711,6 +726,7 @@ func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
config.ManifestCheck.String(),
config.ConstructContext.String(),
config.UffdGcFlag.String(),
+ config.AssumeValueFlags.String(),
}, " "))
}
@@ -737,6 +753,27 @@ func buildUffdGcFlag(ctx android.BuilderContext, global *GlobalConfig) {
}
}
+func buildAssumedValues(ctx android.BuilderContext, global *GlobalConfig, globalSoong *GlobalSoongConfig) {
+ assumeValueFlags := getAssumeValueFlagsPath(ctx)
+
+ if global.PlatformSdkVersion != "" {
+ maybeAssumedValues := fmt.Sprintf(`'--assume-value=Landroid/os/Build$VERSION;->SDK_INT:%s'`, global.PlatformSdkVersion)
+ rule := android.NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command()
+ // First check dex2oat to see if it supports `--assume-value=` arguments.
+ // If it does, stash the assumed value args in a reusable output file for compilation.
+ // Otherwise, just create an empty placeholder file that becomes a no-op.
+ // TODO(b/204924812): Remove the args check after prebuilt ART modules are updated from source.
+ cmd.Text("if (").Tool(globalSoong.Dex2oat).Text("--help 2>&1 | grep -q -- --assume-value)").
+ Text("; then echo").Text(maybeAssumedValues).Text(">").Output(assumeValueFlags).
+ Text("; else >").Output(assumeValueFlags).
+ Text("; fi")
+ rule.Restat().Build("dexpreopt_assume_value_flags", "dexpreopt_assume_value_flags")
+ } else {
+ android.WriteFileRuleVerbatim(ctx, assumeValueFlags, "")
+ }
+}
+
func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
return &GlobalConfig{
DisablePreopt: false,
@@ -791,6 +828,7 @@ func globalSoongConfigForTests(ctx android.BuilderContext) *GlobalSoongConfig {
ManifestCheck: android.PathForTesting("manifest_check"),
ConstructContext: android.PathForTesting("construct_context"),
UffdGcFlag: android.PathForOutput(ctx, "dexpreopt_test", "uffd_gc_flag.txt"),
+ AssumeValueFlags: android.PathForOutput(ctx, "dexpreopt_test", "assume_value_flags.txt"),
}
}
@@ -806,3 +844,7 @@ func GetDexpreoptDirName(ctx android.PathContext) string {
func getUffdGcFlagPath(ctx android.PathContext) android.WritablePath {
return android.PathForOutput(ctx, "dexpreopt/uffd_gc_flag.txt")
}
+
+func getAssumeValueFlagsPath(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "dexpreopt/assume_value_flags.txt")
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 699a6757d..f18a9bb21 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -497,6 +497,8 @@ func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig
cmd.FlagWithInput("--profile-file=", profile)
}
+ cmd.Text("$(cat").Input(globalSoong.AssumeValueFlags).Text(")")
+
rule.Install(odexPath, odexInstallPath)
rule.Install(vdexPath, vdexInstallPath)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 500b2ff8c..5e45c62e7 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -120,6 +120,8 @@ func TestDexPreopt(t *testing.T) {
android.AssertStringListContains(t, "", rule.Inputs().RelativeToTop().Strings(),
"out/soong/dexpreopt_test/uffd_gc_flag.txt")
+ android.AssertStringListContains(t, "", rule.Inputs().RelativeToTop().Strings(),
+ "out/soong/dexpreopt_test/assume_value_flags.txt")
}
func TestDexPreoptSystemOther(t *testing.T) {
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index b1fbef566..09adb6bfa 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -180,7 +180,7 @@ func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer {
// FixtureSetBootImageProfiles sets the BootImageProfiles property in the global config.
func FixtureSetBootImageProfiles(profiles ...string) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(ctx android.PathContext, dexpreoptConfig *GlobalConfig) {
- dexpreoptConfig.BootImageProfiles = android.PathsForSource(ctx, profiles)
+ dexpreoptConfig.BootImageProfiles = android.PathsForTesting(profiles...)
})
}
@@ -211,3 +211,10 @@ func FixtureSetEnableUffdGc(value string) android.FixturePreparer {
dexpreoptConfig.EnableUffdGc = value
})
}
+
+// FixtureSetPlatformSdkVersion sets the PlatformSdkVersion property in the global config.
+func FixtureSetPlatformSdkVersion(value string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.PlatformSdkVersion = value
+ })
+}
diff --git a/docs/best_practices.md b/docs/best_practices.md
index 48ed996e7..eaa3b0442 100644
--- a/docs/best_practices.md
+++ b/docs/best_practices.md
@@ -14,8 +14,7 @@ source tree.
## Network access
Never access the network during the build. We expect to enforce this in the
-future, though there will be some level of exceptions for tools like `distcc`
-and `goma`.
+future, though there will be some level of exceptions for tools like `distcc`.
## Paths
diff --git a/docs/perf.md b/docs/perf.md
index 446ba9df2..b64de0ac4 100644
--- a/docs/perf.md
+++ b/docs/perf.md
@@ -6,7 +6,7 @@
soong_ui has tracing built in, so that every build execution's trace can be
viewed. Just open `$OUT_DIR/build.trace.gz` in Chrome's <chrome://tracing>, or
-with [catapult's trace viewer][catapult trace_viewer]. The last few traces are
+with [Perfetto][perfetto]. The last few traces are
stored in `build.trace.#.gz` (larger numbers are older). The associated logs
are stored in `soong.#.log` and `verbose.#.log.gz`.
@@ -289,6 +289,6 @@ A workaround to get out of this state is to remove the build.ninja entry from
sed -i "/\/build.ninja/d" $(get_build_var OUT_DIR)/.ninja_log
```
-[catapult trace_viewer]: https://github.com/catapult-project/catapult/blob/master/tracing/README.md
+[perfetto]: https://ui.perfetto.dev
[ninja parse optimization]: https://android-review.googlesource.com/c/platform/external/ninja/+/461005
[blueprint_microfactory]: https://android-review.googlesource.com/q/topic:%22blueprint_microfactory%22+status:merged
diff --git a/etc/install_symlink.go b/etc/install_symlink.go
index 31da3f653..ee5a56b91 100644
--- a/etc/install_symlink.go
+++ b/etc/install_symlink.go
@@ -87,6 +87,10 @@ func (m *InstallSymlink) GenerateAndroidBuildActions(ctx android.ModuleContext)
name := filepath.Base(m.properties.Installed_location)
installDir := android.PathForModuleInstall(ctx, filepath.Dir(m.properties.Installed_location))
m.installedPath = ctx.InstallAbsoluteSymlink(installDir, name, symlink_target)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"FAKE"}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (m *InstallSymlink) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 7820047ab..da0ae4a23 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -92,6 +92,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory)
ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory)
ctx.RegisterModuleType("prebuilt_any", PrebuiltAnyFactory)
+ ctx.RegisterModuleType("prebuilt_lib", PrebuiltLibFactory)
ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
@@ -106,6 +107,14 @@ type PrebuiltEtcInfo struct {
var PrebuiltEtcInfoProvider = blueprint.NewProvider[PrebuiltEtcInfo]()
+// If this provider is set, it means this module was converted from PRODUCT_COPY_FILES
+type ProductCopyFilesModuleInfo struct {
+ // The entries as they would've appeared in PRODUCT_COPY_FILES, that is, src:dst
+ ProductCopyFileEntries []string
+}
+
+var ProductCopyFilesModuleProvider = blueprint.NewProvider[ProductCopyFilesModuleInfo]()
+
var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
type PrebuiltEtcProperties struct {
@@ -154,6 +163,11 @@ type PrebuiltEtcProperties struct {
// Install to partition oem when set to true.
Oem_specific *bool `android:"arch_variant"`
+
+ // If this prebuilt_* module was auto-generated from a PRODUCT_COPY_FILES entry.
+ // Used for licensing/compliance/SBOM, as some legacy methods of specifying licenses were
+ // specific to PRODUCT_COPY_FILES.
+ From_product_copy_files *bool
}
// Dsts is useful in that it allows prebuilt_* modules to easily map the source files to the
@@ -223,7 +237,7 @@ type PrebuiltEtc struct {
// prebuilt_firmware.
socInstallDirBase string
installDirPaths []android.InstallPath
- additionalDependencies *android.Paths
+ additionalDependencies android.Paths
usedSrcsProperty bool
@@ -344,7 +358,7 @@ func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
// additional steps (like validating the src) before the file is installed.
func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) {
- p.additionalDependencies = &paths
+ p.additionalDependencies = paths
}
func (p *PrebuiltEtc) OutputFile() android.Path {
@@ -522,7 +536,7 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.SkipInstall()
}
for _, ip := range installs {
- ip.addInstallRules(ctx)
+ ip.addInstallRules(ctx, p.additionalDependencies)
}
p.updateModuleInfoJSON(ctx)
@@ -530,6 +544,16 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.SetOutputFiles(p.outputFilePaths.Paths(), "")
SetCommonPrebuiltEtcInfo(ctx, p)
+
+ if proptools.Bool(p.properties.From_product_copy_files) {
+ entries := make([]string, 0, len(installs))
+ for _, install := range installs {
+ entries = append(entries, fmt.Sprintf("%s:%s", install.sourceFilePath, filepath.Join(install.installDirPath.String(), install.filename)))
+ }
+ android.SetProvider(ctx, ProductCopyFilesModuleProvider, ProductCopyFilesModuleInfo{
+ ProductCopyFileEntries: entries,
+ })
+ }
}
func SetCommonPrebuiltEtcInfo(ctx android.ModuleContext, p PrebuiltEtcModule) {
@@ -559,14 +583,15 @@ type installProperties struct {
// utility function to add install rules to the build graph.
// Reduces code duplication between Soong and Mixed build analysis
-func (ip *installProperties) addInstallRules(ctx android.ModuleContext) {
+func (ip *installProperties) addInstallRules(ctx android.ModuleContext, validations android.Paths) {
// Copy the file from src to a location in out/ with the correct `filename`
// This ensures that outputFilePath has the correct name for others to
// use, as the source file may have a different name.
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Output: ip.outputFilePath,
- Input: ip.sourceFilePath,
+ Rule: android.Cp,
+ Output: ip.outputFilePath,
+ Input: ip.sourceFilePath,
+ Validations: validations,
})
installPath := ctx.InstallFile(ip.installDirPath, ip.filename, ip.outputFilePath)
@@ -608,9 +633,6 @@ func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
}
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.Installable())
- if p.additionalDependencies != nil {
- entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...)
- }
},
},
}}
@@ -752,7 +774,7 @@ func PrebuiltUserShareFactory() android.Module {
return module
}
-// prebuild_usr_share_host is for a host prebuilt artifact that is installed in
+// prebuilt_usr_share_host is for a host prebuilt artifact that is installed in
// $(HOST_OUT)/usr/share/<sub_dir> directory.
func PrebuiltUserShareHostFactory() android.Module {
module := &PrebuiltEtc{}
@@ -780,7 +802,7 @@ func PrebuiltUserKeyLayoutFactory() android.Module {
module := &PrebuiltEtc{}
InitPrebuiltEtcModule(module, "usr/keylayout")
// This module is device-only
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
return module
}
@@ -791,7 +813,7 @@ func PrebuiltUserKeyCharsFactory() android.Module {
module := &PrebuiltEtc{}
InitPrebuiltEtcModule(module, "usr/keychars")
// This module is device-only
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
return module
}
@@ -802,7 +824,7 @@ func PrebuiltUserIdcFactory() android.Module {
module := &PrebuiltEtc{}
InitPrebuiltEtcModule(module, "usr/idc")
// This module is device-only
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
return module
}
@@ -862,6 +884,20 @@ func PrebuiltFirmwareFactory() android.Module {
return module
}
+// prebuilt_lib installs a prebuilt file to <partition>/lib directory for system
+// image.
+// If soc_specific property is set to true, the prebuilt file is installed to the
+// vendor <partition>/lib directory for vendor image.
+func PrebuiltLibFactory() android.Module {
+ module := &PrebuiltEtc{}
+ module.socInstallDirBase = "lib"
+ InitPrebuiltEtcModule(module, "lib")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_gpu is for a prebuilt artifact in <partition>/gpu directory.
func PrebuiltGPUFactory() android.Module {
module := &PrebuiltEtc{}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index cb76df2d9..afe0c3f33 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -9,6 +9,7 @@ bootstrap_go_package {
"blueprint",
"soong",
"soong-android",
+ "soong-etc",
"soong-bpf", // for testing
"soong-java", // for testing
"soong-linkerconfig",
@@ -26,6 +27,7 @@ bootstrap_go_package {
"fsverity_metadata.go",
"logical_partition.go",
"raw_binary.go",
+ "recovery_background_pictures.go",
"super_image.go",
"system_image.go",
"system_other.go",
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 20a195313..6b346b87c 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -16,7 +16,6 @@ package filesystem
import (
"android/soong/android"
- "strconv"
"strings"
"github.com/google/blueprint"
@@ -35,7 +34,6 @@ var (
subPartitionsInPartition = map[string][]string{
"system": {"system_ext", "product", "vendor"},
- "vendor": {"odm"},
}
)
@@ -45,6 +43,7 @@ func (f *filesystem) buildAconfigFlagsFiles(
specs map[string]android.PackagingSpec,
dir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
return
@@ -88,18 +87,15 @@ func (f *filesystem) buildAconfigFlagsFiles(
installAconfigFlagsPath := installEtcDir.Join(ctx, "aconfig_flags.pb")
builder.Command().Text("mkdir -p ").Text(installEtcDir.String())
builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String())
+ installPath := fullInstallPath.Join(ctx, "etc/aconfig_flags.pb")
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig_flags.pb"),
+ FullInstallPath: installPath,
SourcePath: aconfigFlagsPb,
})
f.appendToEntry(ctx, installAconfigFlagsPath)
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
- // To enable fingerprint, we need to have v2 storage files. The default version is 1.
- storageFilesVersion := 1
- if ctx.Config().ReleaseFingerprintAconfigPackages() {
- storageFilesVersion = 2
- }
-
+ storageFilesVersion := ctx.Config().ReleaseAconfigStorageVersion()
installAconfigStorageDir := installEtcDir.Join(ctx, "aconfig")
builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String())
@@ -113,16 +109,18 @@ func (f *filesystem) buildAconfigFlagsFiles(
Args: map[string]string{
"container": container,
"fileType": fileType,
- "version": strconv.Itoa(storageFilesVersion),
+ "version": storageFilesVersion,
},
})
builder.Command().
Text("cp").Input(outPath).Text(installPath.String())
+ fip := fullInstallPath.Join(ctx, "etc/aconfig", fileName)
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
SourcePath: outPath,
- FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig", fileName),
+ FullInstallPath: fip,
})
f.appendToEntry(ctx, installPath)
+ *platformGeneratedFiles = append(*platformGeneratedFiles, fip.String())
}
if ctx.Config().ReleaseCreateAconfigStorageFile() {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 8b6ea4937..e9accc5c1 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -18,24 +18,20 @@ import (
"cmp"
"fmt"
"path/filepath"
+ "regexp"
"slices"
"sort"
"strings"
"sync/atomic"
"android/soong/android"
+ "android/soong/etc"
"android/soong/java"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
-var proguardDictToProto = pctx.AndroidStaticRule("proguard_dict_to_proto", blueprint.RuleParams{
- Command: `${symbols_map} -r8 $in -location $location -write_if_changed $out`,
- Restat: true,
- CommandDeps: []string{"${symbols_map}"},
-}, "location")
-
type PartitionNameProperties struct {
// Name of the super partition filesystem module
Super_partition_name *string
@@ -100,6 +96,9 @@ type DeviceProperties struct {
// when dexpreopting apps. So setting this doesn't really do anything except enforce that the
// actual kernel version is as specified here.
Kernel_version *string
+
+ // Precompiled sepolicy only with system + system_ext + product. Used for SELinux tests.
+ Precompiled_sepolicy_without_vendor *string `android:"path"`
}
type androidDevice struct {
@@ -111,9 +110,7 @@ type androidDevice struct {
allImagesZip android.Path
- proguardDictZip android.Path
- proguardDictMapping android.Path
- proguardUsageZip android.Path
+ proguardZips java.ProguardZips
kernelConfig android.Path
kernelVersion android.Path
miscInfo android.Path
@@ -122,6 +119,12 @@ type androidDevice struct {
apkCertsInfo android.Path
targetFilesZip android.Path
updatePackage android.Path
+ otaFilesZip android.Path
+ otaMetadata android.Path
+ partialOtaFilesZip android.Path
+
+ symbolsZipFile android.ModuleOutPath
+ symbolsMappingFile android.ModuleOutPath
}
func AndroidDeviceFactory() android.Module {
@@ -143,10 +146,14 @@ type superPartitionDepTagType struct {
type targetFilesMetadataDepTagType struct {
blueprint.BaseDependencyTag
}
+type fileContextsDepTagType struct {
+ blueprint.BaseDependencyTag
+}
var superPartitionDepTag superPartitionDepTagType
var filesystemDepTag partitionDepTagType
var targetFilesMetadataDepTag targetFilesMetadataDepTagType
+var fileContextsDepTag fileContextsDepTagType
func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
addDependencyIfDefined := func(dep *string) {
@@ -179,6 +186,11 @@ func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
func (a *androidDevice) addDepsForTargetFilesMetadata(ctx android.BottomUpMutatorContext) {
ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), targetFilesMetadataDepTag, "liblz4") // host variant
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), fileContextsDepTag, "file_contexts_bin_gen")
+}
+
+func (a *androidDevice) UseGenericConfig() bool {
+ return false
}
func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -196,11 +208,12 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
allInstalledModules := a.allInstalledModules(ctx)
- a.apkCertsInfo = a.buildApkCertsInfo(ctx, allInstalledModules)
+ a.apkCertsInfo = a.buildApkCertsInfo(ctx)
a.kernelVersion, a.kernelConfig = a.extractKernelVersionAndConfigs(ctx)
a.miscInfo = a.addMiscInfo(ctx)
a.buildTargetFilesZip(ctx, allInstalledModules)
- a.buildProguardZips(ctx, allInstalledModules)
+ a.proguardZips = java.BuildProguardZips(ctx, allInstalledModules)
+ a.buildSymbolsZip(ctx, allInstalledModules)
a.buildUpdatePackage(ctx)
var deps []android.Path
@@ -274,6 +287,12 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps = append(deps, a.copyFilesToProductOutForSoongOnly(ctx))
}
+ trebleLabelingTestTimestamp := a.buildTrebleLabelingTest(ctx)
+
+ // Treble Labeling tests only for 202604 or later
+ if ctx.DeviceConfig().PlatformSepolicyVersion() >= "202604" {
+ validations = append(validations, trebleLabelingTestTimestamp)
+ }
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
@@ -298,17 +317,37 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} else {
buildComplianceMetadata(ctx, filesystemDepTag)
}
+
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ pcf := complianceMetadataInfo.GetProductCopyFiles()
+ for _, m := range allInstalledModules {
+ if info, ok := android.OtherModuleProvider(ctx, m, etc.ProductCopyFilesModuleProvider); ok {
+ pcf = append(pcf, info.ProductCopyFileEntries...)
+ }
+ }
+ complianceMetadataInfo.SetProductCopyFiles(pcf)
+
+ // Add the host tools as deps
+ if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) {
+ for _, hostTool := range ctx.Config().ProductVariables().ProductHostPackages {
+ ctx.Phony("droid", android.PathForPhony(ctx, hostTool+"-host"))
+ }
+ }
+
+ a.checkVintf(ctx)
}
func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.DependencyTag) {
// Collect metadata from deps
filesContained := make([]string, 0)
prebuiltFilesCopied := make([]string, 0)
+ platformGeneratedFiles := make([]string, 0)
for _, tag := range tags {
ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) {
if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok {
filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
+ platformGeneratedFiles = append(platformGeneratedFiles, complianceMetadataInfo.GetPlatformGeneratedFiles()...)
}
})
}
@@ -321,43 +360,70 @@ func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.Depend
prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
sort.Strings(prebuiltFilesCopied)
complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
+
+ platformGeneratedFiles = append(platformGeneratedFiles, complianceMetadataInfo.GetPlatformGeneratedFiles()...)
+ sort.Strings(platformGeneratedFiles)
+ complianceMetadataInfo.SetPlatformGeneratedFiles(platformGeneratedFiles)
+}
+
+type installedOwnerInfo struct {
+ Variation string
+ Prebuilt bool
}
// Returns a list of modules that are installed, which are collected from the dependency
// filesystem and super_image modules.
-func (a *androidDevice) allInstalledModules(ctx android.ModuleContext) []android.Module {
+func (a *androidDevice) allInstalledModules(ctx android.ModuleContext) []android.ModuleOrProxy {
fsInfoMap := a.getFsInfos(ctx)
- allOwners := make(map[string][]string)
+ allOwners := make(map[string][]installedOwnerInfo)
+
for _, partition := range android.SortedKeys(fsInfoMap) {
fsInfo := fsInfoMap[partition]
- for _, owner := range fsInfo.Owners {
- allOwners[owner.Name] = append(allOwners[owner.Name], owner.Variation)
+ for _, owner := range fsInfo.Owners.ToList() {
+ allOwners[owner.Name] = append(allOwners[owner.Name], installedOwnerInfo{
+ Variation: owner.Variation,
+ Prebuilt: owner.Prebuilt,
+ })
}
}
- ret := []android.Module{}
+ ret := []android.ModuleOrProxy{}
ctx.WalkDepsProxy(func(mod, _ android.ModuleProxy) bool {
- if variations, ok := allOwners[ctx.OtherModuleName(mod)]; ok && android.InList(ctx.OtherModuleSubDir(mod), variations) {
+ commonInfo, ok := android.OtherModuleProvider(ctx, mod, android.CommonModuleInfoProvider)
+ if !(ok && commonInfo.ExportedToMake) {
+ return false
+ }
+ prebuiltInfo := android.OtherModuleProviderOrDefault(ctx, mod, android.PrebuiltInfoProvider)
+ name := android.OtherModuleNameWithPossibleOverride(ctx, mod)
+ if variations, ok := allOwners[name]; ok &&
+ android.InList(installedOwnerInfo{
+ Variation: ctx.OtherModuleSubDir(mod),
+ Prebuilt: prebuiltInfo.IsPrebuilt,
+ }, variations) {
ret = append(ret, mod)
}
return true
})
// Remove duplicates
- ret = android.FirstUniqueFunc(ret, func(a, b android.Module) bool {
- return a.String() == b.String()
- })
+ ret = android.FirstUniqueInPlace(ret)
// Sort the modules by their names and variants
- slices.SortFunc(ret, func(a, b android.Module) int {
+ slices.SortFunc(ret, func(a, b android.ModuleOrProxy) int {
return cmp.Compare(a.String(), b.String())
})
return ret
}
-func insertBeforeExtension(file, insertion string) string {
- ext := filepath.Ext(file)
- return strings.TrimSuffix(file, ext) + insertion + ext
+func (a *androidDevice) buildSymbolsZip(ctx android.ModuleContext, allInstalledModules []android.ModuleOrProxy) {
+ a.symbolsZipFile = android.PathForModuleOut(ctx, "symbols.zip")
+ a.symbolsMappingFile = android.PathForModuleOut(ctx, "symbols-mapping.textproto")
+ allInstalledSymbolsPaths, allInstalledSymbolsMappingPaths := android.BuildSymbolsZip(ctx, allInstalledModules, a.symbolsZipFile, a.symbolsMappingFile)
+ if !ctx.Config().KatiEnabled() {
+ ctx.Phony("symbols-files", allInstalledSymbolsPaths...)
+ ctx.Phony("symbols-mappings", allInstalledSymbolsMappingPaths...)
+ ctx.Phony("droidcore-unbundled", android.PathForPhony(ctx, "symbols-files"), android.PathForPhony(ctx, "symbols-mappings"))
+ }
}
func (a *androidDevice) distInstalledFiles(ctx android.ModuleContext) {
@@ -391,9 +457,12 @@ func (a *androidDevice) distFiles(ctx android.ModuleContext) {
if ctx.Config().HasDeviceProduct() {
namePrefix = ctx.Config().DeviceProduct() + "-"
}
- ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
- ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
- ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.proguardZips.DictZip, namePrefix+a.proguardZips.DictZip.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.proguardZips.DictMapping, namePrefix+a.proguardZips.DictMapping.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.proguardZips.UsageZip, namePrefix+a.proguardZips.UsageZip.Base())
+
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.symbolsZipFile, namePrefix+a.symbolsZipFile.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.symbolsMappingFile, namePrefix+a.symbolsMappingFile.Base())
if a.deviceProps.Android_info != nil {
ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info))
@@ -405,12 +474,23 @@ func (a *androidDevice) distFiles(ctx android.ModuleContext) {
}
}
if a.targetFilesZip != nil {
- ctx.DistForGoalWithFilename("target-files-package", a.targetFilesZip, namePrefix+insertBeforeExtension(a.targetFilesZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ ctx.Phony("target-files-package", a.targetFilesZip)
+ ctx.DistForGoalWithFilenameTag("target-files-package", a.targetFilesZip, namePrefix+a.targetFilesZip.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.targetFilesZip, namePrefix+a.targetFilesZip.Base())
}
if a.updatePackage != nil {
- ctx.DistForGoalWithFilename("updatepackage", a.updatePackage, namePrefix+insertBeforeExtension(a.updatePackage.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ ctx.DistForGoalWithFilenameTag("updatepackage", a.updatePackage, namePrefix+a.updatePackage.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.updatePackage, namePrefix+a.updatePackage.Base())
+ }
+ if a.otaFilesZip != nil {
+ ctx.Phony("otapackage", a.otaFilesZip)
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.otaFilesZip, namePrefix+a.otaFilesZip.Base())
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.otaMetadata, namePrefix+a.otaMetadata.Base())
+ }
+ if a.partialOtaFilesZip != nil {
+ ctx.Phony("partialotapackage", a.partialOtaFilesZip)
+ ctx.DistForGoalWithFilenameTag("droidcore-unbundled", a.partialOtaFilesZip, namePrefix+a.partialOtaFilesZip.Base())
}
-
}
}
@@ -421,56 +501,6 @@ func (a *androidDevice) MakeVars(_ android.MakeVarsModuleContext) []android.Modu
return nil
}
-func (a *androidDevice) buildProguardZips(ctx android.ModuleContext, allInstalledModules []android.Module) {
- dictZip := android.PathForModuleOut(ctx, "proguard-dict.zip")
- dictZipBuilder := android.NewRuleBuilder(pctx, ctx)
- dictZipCmd := dictZipBuilder.Command().BuiltTool("soong_zip").Flag("-d").FlagWithOutput("-o ", dictZip)
-
- dictMapping := android.PathForModuleOut(ctx, "proguard-dict-mapping.textproto")
- dictMappingBuilder := android.NewRuleBuilder(pctx, ctx)
- dictMappingCmd := dictMappingBuilder.Command().BuiltTool("symbols_map").Flag("-merge").Output(dictMapping)
-
- protosDir := android.PathForModuleOut(ctx, "proguard_mapping_protos")
-
- usageZip := android.PathForModuleOut(ctx, "proguard-usage.zip")
- usageZipBuilder := android.NewRuleBuilder(pctx, ctx)
- usageZipCmd := usageZipBuilder.Command().BuiltTool("merge_zips").Output(usageZip)
-
- for _, mod := range allInstalledModules {
- if proguardInfo, ok := android.OtherModuleProvider(ctx, mod, java.ProguardProvider); ok {
- // Maintain these out/target/common paths for backwards compatibility. They may be able
- // to be changed if tools look up file locations from the protobuf, but I'm not
- // exactly sure how that works.
- dictionaryFakePath := fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/proguard_dictionary", proguardInfo.Class, proguardInfo.ModuleName)
- dictZipCmd.FlagWithArg("-e ", dictionaryFakePath)
- dictZipCmd.FlagWithInput("-f ", proguardInfo.ProguardDictionary)
- dictZipCmd.Textf("-e out/target/common/obj/%s/%s_intermediates/classes.jar", proguardInfo.Class, proguardInfo.ModuleName)
- dictZipCmd.FlagWithInput("-f ", proguardInfo.ClassesJar)
-
- protoFile := protosDir.Join(ctx, filepath.Dir(dictionaryFakePath), "proguard_dictionary.textproto")
- ctx.Build(pctx, android.BuildParams{
- Rule: proguardDictToProto,
- Input: proguardInfo.ProguardDictionary,
- Output: protoFile,
- Args: map[string]string{
- "location": dictionaryFakePath,
- },
- })
- dictMappingCmd.Input(protoFile)
-
- usageZipCmd.Input(proguardInfo.ProguardUsageZip)
- }
- }
-
- dictZipBuilder.Build("proguard_dict_zip", "Building proguard dictionary zip")
- dictMappingBuilder.Build("proguard_dict_mapping_proto", "Building proguard mapping proto")
- usageZipBuilder.Build("proguard_usage_zip", "Building proguard usage zip")
-
- a.proguardDictZip = dictZip
- a.proguardDictMapping = dictMapping
- a.proguardUsageZip = usageZip
-}
-
// Helper structs for target_files.zip creation
type targetFilesZipCopy struct {
srcModule *string
@@ -482,9 +512,12 @@ type targetFilesystemZipCopy struct {
destSubdir string
}
-func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstalledModules []android.Module) {
+func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstalledModules []android.ModuleOrProxy) {
targetFilesDir := android.PathForModuleOut(ctx, "target_files_dir")
targetFilesZip := android.PathForModuleOut(ctx, "target_files.zip")
+ otaFilesZip := android.PathForModuleOut(ctx, "ota.zip")
+ otaMetadata := android.PathForModuleOut(ctx, "ota_metadata")
+ partialOtaFilesZip := android.PathForModuleOut(ctx, "partial-ota.zip")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Textf("rm -rf %s", targetFilesDir.String())
@@ -576,7 +609,10 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstal
}
if a.partitionProps.Boot_partition_name != nil {
bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
- bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ bootImgInfo, ok := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ if !ok {
+ ctx.PropertyErrorf("boot_partition_name", "Expected a BootimgInfoProvider")
+ }
builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
if bootImgInfo.Dtb != nil {
builder.Command().Textf("cp ").Input(bootImgInfo.Dtb).Textf(" %s/BOOT/dtb", targetFilesDir)
@@ -596,7 +632,11 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstal
builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, *a.deviceProps.Android_info)).Textf(" %s/OTA/android-info.txt", targetFilesDir)
}
- a.copyImagesToTargetZip(ctx, builder, targetFilesDir)
+ builder.Command().Textf("mkdir -p %s/IMAGES", targetFilesDir.String())
+ if a.deviceProps.Bootloader != nil {
+ builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader))).Textf(" %s/IMAGES/bootloader", targetFilesDir.String())
+ }
+
a.copyMetadataToTargetZip(ctx, builder, targetFilesDir, allInstalledModules)
a.targetFilesZip = targetFilesZip
@@ -607,54 +647,48 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstal
FlagWithArg("-C ", targetFilesDir.String()).
FlagWithArg("-D ", targetFilesDir.String()).
Text("-sha256")
- builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
-}
-func (a *androidDevice) copyImagesToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath) {
- // Create an IMAGES/ subdirectory
- builder.Command().Textf("mkdir -p %s/IMAGES", targetFilesDir.String())
- if a.deviceProps.Bootloader != nil {
- builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader))).Textf(" %s/IMAGES/bootloader", targetFilesDir.String())
+ pem, _ := ctx.Config().DefaultAppCertificate(ctx)
+ pemWithoutFileExt := strings.TrimSuffix(pem.String(), ".x509.pem")
+ builder.Command().
+ BuiltTool("ota_from_target_files").
+ Flag("--verbose").
+ FlagWithArg("-k ", pemWithoutFileExt).
+ FlagWithOutput("--output_metadata_path ", otaMetadata).
+ Text(targetFilesDir.String()).
+ Output(otaFilesZip).
+ Implicit(ctx.Config().HostToolPath(ctx, "delta_generator"))
+ a.otaFilesZip = otaFilesZip
+ a.otaMetadata = otaMetadata
+
+ // Partial ota
+ if len(a.deviceProps.Partial_ota_update_partitions) > 0 {
+ builder.Command().
+ BuiltTool("ota_from_target_files").
+ Flag("--verbose").
+ FlagWithArg("-k ", pemWithoutFileExt).
+ FlagForEachArg("--partial ", a.deviceProps.Partial_ota_update_partitions).
+ Text(targetFilesDir.String()).
+ Output(partialOtaFilesZip)
+ a.partialOtaFilesZip = partialOtaFilesZip
}
- // Copy the filesystem ,boot and vbmeta img files to IMAGES/
- ctx.VisitDirectDepsProxyWithTag(filesystemDepTag, func(child android.ModuleProxy) {
- if strings.Contains(child.Name(), "recovery") {
- return // skip recovery.img to match the make packaging behavior
- }
- if info, ok := android.OtherModuleProvider(ctx, child, BootimgInfoProvider); ok {
- // Check Boot img first so that the boot.img is copied and not its dep ramdisk.img
- builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
- } else if info, ok := android.OtherModuleProvider(ctx, child, FilesystemProvider); ok {
- builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
- } else if info, ok := android.OtherModuleProvider(ctx, child, vbmetaPartitionProvider); ok {
- builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
- } else {
- ctx.ModuleErrorf("Module %s does not provide an .img file output for target_files.zip", child.Name())
- }
- })
- if a.partitionProps.Super_partition_name != nil {
- superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
- if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
- for _, partition := range android.SortedKeys(info.SubImageInfo) {
- if info.SubImageInfo[partition].OutputHermetic != nil {
- builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].OutputHermetic).Textf(" %s/IMAGES/", targetFilesDir.String())
- }
- if info.SubImageInfo[partition].MapFile != nil {
- builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String())
- }
- }
- // super_empty.img
- if info.SuperEmptyImage != nil {
- builder.Command().Textf("cp ").Input(info.SuperEmptyImage).Textf(" %s/IMAGES/", targetFilesDir.String())
- }
- } else {
- ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+ builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
+}
+
+func writeFileWithNewLines(ctx android.ModuleContext, path android.WritablePath, contents []string) {
+ builder := &strings.Builder{}
+ for i, content := range contents {
+ builder.WriteString(content)
+ // Do not write a new line at the end
+ if i < len(contents)-1 {
+ builder.WriteString("\n")
}
}
+ android.WriteFileRule(ctx, path, builder.String())
}
-func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath, allInstalledModules []android.Module) {
+func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.ModuleOutPath, allInstalledModules []android.ModuleOrProxy) {
// Create a META/ subdirectory
builder.Command().Textf("mkdir -p %s/META", targetFilesDir.String())
if proptools.Bool(a.deviceProps.Ab_ota_updater) {
@@ -664,23 +698,34 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build
})
builder.Command().Textf("cp").Input(android.PathForSource(ctx, "external/zucchini/version_info.h")).Textf(" %s/META/zucchini_config.txt", targetFilesDir.String())
builder.Command().Textf("cp").Input(android.PathForSource(ctx, "system/update_engine/update_engine.conf")).Textf(" %s/META/update_engine_config.txt", targetFilesDir.String())
- if a.getFsInfos(ctx)["system"].ErofsCompressHints != nil {
- builder.Command().Textf("cp").Input(a.getFsInfos(ctx)["system"].ErofsCompressHints).Textf(" %s/META/erofs_default_compress_hints.txt", targetFilesDir.String())
+ systemFsInfo := a.getFsInfos(ctx)["system"]
+ if systemFsInfo.ErofsCompressHints != nil {
+ builder.Command().Textf("cp").Input(systemFsInfo.ErofsCompressHints).Textf(" %s/META/erofs_default_compress_hints.txt", targetFilesDir.String())
}
// ab_partitions.txt
abPartitionsSorted := android.SortedUniqueStrings(a.deviceProps.Ab_ota_partitions)
- abPartitionsSortedString := proptools.ShellEscape(strings.Join(abPartitionsSorted, "\\n"))
- builder.Command().Textf("echo -e").Flag(abPartitionsSortedString).Textf(" > %s/META/ab_partitions.txt", targetFilesDir.String())
+ abPartitionsFilePath := android.PathForModuleOut(ctx, "target_files_tmp", "ab_partitions.txt")
+ writeFileWithNewLines(ctx, abPartitionsFilePath, abPartitionsSorted)
+ builder.Command().Textf("cp").Input(abPartitionsFilePath).Textf(" %s/META/", targetFilesDir)
// otakeys.txt
abOtaKeysSorted := android.SortedUniqueStrings(a.deviceProps.Ab_ota_keys)
- abOtaKeysSortedString := proptools.ShellEscape(strings.Join(abOtaKeysSorted, "\\n"))
- builder.Command().Textf("echo -e").Flag(abOtaKeysSortedString).Textf(" > %s/META/otakeys.txt", targetFilesDir.String())
+ abOtaKeysFilePath := android.PathForModuleOut(ctx, "target_files_tmp", "otakeys.txt")
+ writeFileWithNewLines(ctx, abOtaKeysFilePath, abOtaKeysSorted)
+ builder.Command().Textf("cp").Input(abOtaKeysFilePath).Textf(" %s/META/", targetFilesDir)
// postinstall_config.txt
- abOtaPostInstallConfigString := proptools.ShellEscape(strings.Join(a.deviceProps.Ab_ota_postinstall_config, "\\n"))
- builder.Command().Textf("echo -e").Flag(abOtaPostInstallConfigString).Textf(" > %s/META/postinstall_config.txt", targetFilesDir.String())
+ abOtaPostInstallConfigFilePath := android.PathForModuleOut(ctx, "target_files_tmp", "postinstall_config.txt")
+ writeFileWithNewLines(ctx, abOtaPostInstallConfigFilePath, a.deviceProps.Ab_ota_postinstall_config)
+ builder.Command().Textf("cp").Input(abOtaPostInstallConfigFilePath).Textf(" %s/META/", targetFilesDir)
// selinuxfc
- if a.getFsInfos(ctx)["system"].SelinuxFc != nil {
- builder.Command().Textf("cp").Input(a.getFsInfos(ctx)["system"].SelinuxFc).Textf(" %s/META/file_contexts.bin", targetFilesDir.String())
+ fileContextsModule := ctx.GetDirectDepProxyWithTag("file_contexts_bin_gen", fileContextsDepTag)
+ outputFiles, ok := android.OtherModuleProvider(ctx, fileContextsModule, android.OutputFilesProvider)
+ if !ok || len(outputFiles.DefaultOutputFiles) != 1 {
+ ctx.ModuleErrorf("Expected exactly 1 output file from file_contexts_bin_gen")
+ } else {
+ selinuxFc := outputFiles.DefaultOutputFiles[0]
+ if selinuxFc != nil {
+ builder.Command().Textf("cp").Input(selinuxFc).Textf(" %s/META/file_contexts.bin", targetFilesDir.String())
+ }
}
}
// Copy $partition_filesystem_config.txt
@@ -716,11 +761,13 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build
}
}
// Copy ramdisk_node_list
- if ramdiskNodeList := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Ramdisk_node_list)); ramdiskNodeList != nil {
+ if proptools.String(a.deviceProps.Ramdisk_node_list) != "" {
+ ramdiskNodeList := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Ramdisk_node_list))
builder.Command().Textf("cp").Input(ramdiskNodeList).Textf(" %s/META/", targetFilesDir.String())
}
// Copy releasetools.py
- if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil {
+ if proptools.String(a.deviceProps.Releasetools_extension) != "" {
+ releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension))
builder.Command().Textf("cp").Input(releaseTools).Textf(" %s/META/", targetFilesDir.String())
}
// apexkeys.txt
@@ -736,7 +783,8 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build
builder.Command().Textf("cp").Input(a.apkCertsInfo).Textf(" %s/META/", targetFilesDir.String())
// Copy fastboot-info.txt
- if fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo)); fastbootInfo != nil {
+ if proptools.String(a.deviceProps.FastbootInfo) != "" {
+ fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo))
// TODO (b/399788523): Autogenerate fastboot-info.txt if there is no source fastboot-info.txt
// https://cs.android.com/android/_/android/platform/build/+/80b9546f8f69e78b8fe1870e0e745d70fc18dfcd:core/Makefile;l=5831-5893;drc=077490384423dff9eac954da5c001c6f0be3fa6e;bpv=0;bpt=0
builder.Command().Textf("cp").Input(fastbootInfo).Textf(" %s/META/fastboot-info.txt", targetFilesDir.String())
@@ -766,7 +814,6 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build
ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
}
}
-
}
var (
@@ -811,7 +858,11 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path {
Textf("echo mkbootimg_args='--header_version %s' >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Boot_partition_name), miscInfo).
// TODO: Use boot's header version for recovery for now since cuttlefish does not set `BOARD_RECOVERY_MKBOOTIMG_ARGS`
Textf(" && echo recovery_mkbootimg_args='--header_version %s' >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Boot_partition_name), miscInfo)
+ } else if a.partitionProps.Vendor_boot_partition_name != nil {
+ builder.Command().
+ Textf("echo mkbootimg_args='--header_version %s' >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Vendor_boot_partition_name), miscInfo)
}
+
if a.partitionProps.Init_boot_partition_name != nil {
builder.Command().
Textf("echo mkbootimg_init_args='--header_version' %s >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Init_boot_partition_name), miscInfo)
@@ -828,7 +879,8 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path {
if fsInfos["system"].ErofsCompressHints != nil {
builder.Command().Textf("echo erofs_default_compress_hints=%s >> %s", fsInfos["system"].ErofsCompressHints, miscInfo)
}
- if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil {
+ if proptools.String(a.deviceProps.Releasetools_extension) != "" {
+ releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension))
builder.Command().Textf("echo tool_extensions=%s >> %s", filepath.Dir(releaseTools.String()), miscInfo)
}
// ramdisk uses `compressed_cpio` fs_type
@@ -915,7 +967,9 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path {
builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo)
}
- builder.Command().Textf("echo blocksize=%s >> %s", proptools.String(a.deviceProps.Flash_block_size), miscInfo)
+ if proptools.String(a.deviceProps.Flash_block_size) != "" {
+ builder.Command().Textf("echo blocksize=%s >> %s", proptools.String(a.deviceProps.Flash_block_size), miscInfo)
+ }
if proptools.Bool(a.deviceProps.Bootloader_in_update_package) {
builder.Command().Textf("echo bootloader_in_update_package=true >> %s", miscInfo)
}
@@ -943,10 +997,12 @@ func (a *androidDevice) getBootimgHeaderVersion(ctx android.ModuleContext, bootI
// - vbmeta_digest.txt
func (a *androidDevice) addImgToTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir string) {
mkbootimg := ctx.Config().HostToolPath(ctx, "mkbootimg")
+ lpmake := ctx.Config().HostToolPath(ctx, "lpmake")
builder.Command().
Textf("PATH=%s:$PATH", ctx.Config().HostToolDir()).
Textf("MKBOOTIMG=%s", mkbootimg).
Implicit(mkbootimg).
+ Implicit(lpmake).
BuiltTool("add_img_to_target_files").
Flag("-a -v -p").
Flag(ctx.Config().HostToolDir()).
@@ -1083,12 +1139,11 @@ func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext
Flag("--tools lz4:"+lz4tool.String()).Implicit(lz4tool).
FlagWithInput("--input ", kernel).
FlagWithOutput("--output-release ", extractedVersionFile).
- FlagWithOutput("--output-configs ", extractedConfigsFile).
- Textf(`&& printf "\n" >> %s`, extractedVersionFile)
+ FlagWithOutput("--output-configs ", extractedConfigsFile)
if specifiedVersion := proptools.String(a.deviceProps.Kernel_version); specifiedVersion != "" {
specifiedVersionFile := android.PathForModuleOut(ctx, "specified_kernel_version.txt")
- android.WriteFileRule(ctx, specifiedVersionFile, specifiedVersion)
+ android.WriteFileRuleVerbatim(ctx, specifiedVersionFile, specifiedVersion)
builder.Command().Text("diff -q").
Input(specifiedVersionFile).
Input(extractedVersionFile).
@@ -1113,62 +1168,199 @@ func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext
return extractedVersionFile, extractedConfigsFile
}
-func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalledModules []android.Module) android.Path {
- // TODO (spandandas): Add compressed
- formatLine := func(cert java.Certificate, name, partition string) string {
- pem := cert.AndroidMkString()
- var key string
- if cert.Key == nil {
- key = ""
- } else {
- key = cert.Key.String()
- }
- return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
- }
-
+func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext) android.Path {
apkCerts := []string{}
- var apkCertsFiles android.Paths
- for _, installedModule := range allInstalledModules {
- partition := ""
- if commonInfo, ok := android.OtherModuleProvider(ctx, installedModule, android.CommonModuleInfoProvider); ok {
- partition = commonInfo.PartitionTag
- } else {
- ctx.ModuleErrorf("%s does not set CommonModuleInfoKey", installedModule.Name())
- }
- if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfoProvider); ok {
- if info.AppSet {
- apkCertsFiles = append(apkCertsFiles, info.ApkCertsFile)
- } else {
- apkCerts = append(apkCerts, formatLine(info.Certificate, info.InstallApkName+".apk", partition))
- }
- } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfosProvider); ok {
- for _, certInfo := range info {
- // Partition information of apk-in-apex is not exported to the legacy Make packaging system.
- // Hardcode the partition to "system"
- apkCerts = append(apkCerts, formatLine(certInfo.Certificate, certInfo.InstallApkName+".apk", "system"))
- }
- } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.RuntimeResourceOverlayInfoProvider); ok {
- apkCerts = append(apkCerts, formatLine(info.Certificate, info.OutputFile.Base(), partition))
- }
- }
- slices.Sort(apkCerts) // sort by name
fsInfos := a.getFsInfos(ctx)
if fsInfos["system"].HasFsverity {
defaultPem, defaultKey := ctx.Config().DefaultAppCertificate(ctx)
- apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifest.apk", "system"))
+ apkCerts = append(apkCerts, java.FormatApkCertsLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifest.apk", "system"))
if info, ok := fsInfos["system_ext"]; ok && info.HasFsverity {
- apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifestSystemExt.apk", "system_ext"))
+ apkCerts = append(apkCerts, java.FormatApkCertsLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifestSystemExt.apk", "system_ext"))
}
}
- apkCertsInfoWithoutAppSets := android.PathForModuleOut(ctx, "apkcerts_without_app_sets.txt")
- android.WriteFileRuleVerbatim(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n")+"\n")
+ apkCertsForBuildManifest := android.PathForModuleOut(ctx, "apkcerts_for_buildmanifest.txt")
+ android.WriteFileRuleVerbatim(ctx, apkCertsForBuildManifest, strings.Join(apkCerts, "\n")+"\n")
apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt")
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cat,
+ Rule: android.CatAndSort,
Description: "combine apkcerts.txt",
Output: apkCertsInfo,
- Inputs: append(apkCertsFiles, apkCertsInfoWithoutAppSets),
+ Inputs: android.Paths{java.ApkCertsFile(ctx), apkCertsForBuildManifest},
})
return apkCertsInfo
}
+
+func findAllPreinstalledApps(partitions []string, fsInfos map[string]FilesystemInfo) android.Paths {
+ var ret android.Paths
+ for _, partition := range partitions {
+ info, ok := fsInfos[partition]
+ if !ok {
+ continue
+ }
+ // use MustCompile, because if `partition` is invalid, then we already did something wrong
+ apkPattern := regexp.MustCompile(partition + `/(app|priv-app)/[^/]+/[^/]+\.apk$`)
+ for _, path := range info.FullInstallPaths {
+ if !path.IsDir && path.SymlinkTarget == "" &&
+ apkPattern.FindString(path.FullInstallPath.String()) != "" {
+ ret = append(ret, path.SourcePath)
+ }
+ }
+ }
+ return android.SortedUniquePaths(ret)
+}
+
+func findInstalledFile(rel string, info FilesystemInfo) android.Path {
+ for _, path := range info.FullInstallPaths {
+ if !path.IsDir && path.SymlinkTarget == "" &&
+ strings.HasSuffix(path.FullInstallPath.String(), rel) {
+ return path.SourcePath
+ }
+ }
+ return nil
+}
+
+func findFilesInPartitions(paths map[string]string, fsInfos map[string]FilesystemInfo) android.Paths {
+ var ret android.Paths
+ for partition, rel := range paths {
+ info, ok := fsInfos[partition]
+ if !ok {
+ continue
+ }
+
+ if path := findInstalledFile(rel, info); path != nil {
+ ret = append(ret, path)
+ }
+ }
+ return android.SortedUniquePaths(ret)
+}
+
+func (a *androidDevice) buildTrebleLabelingTest(ctx android.ModuleContext) android.Path {
+ platformPartitions := []string{
+ "system",
+ "system_ext",
+ "product",
+ }
+
+ vendorPartitions := []string{
+ "vendor",
+ "odm",
+ }
+
+ fsInfos := a.getFsInfos(ctx)
+
+ platformApps := findAllPreinstalledApps(platformPartitions, fsInfos)
+ vendorApps := findAllPreinstalledApps(vendorPartitions, fsInfos)
+
+ platformSeappContextsPaths := map[string]string{
+ "system": "system/etc/selinux/plat_seapp_contexts",
+ "system_ext": "system_ext/etc/selinux/plat_seapp_contexts",
+ "product": "product/etc/selinux/plat_seapp_contexts",
+ }
+ platformSeappContexts := findFilesInPartitions(platformSeappContextsPaths, fsInfos)
+
+ vendorSeappContextsPaths := map[string]string{
+ "vendor": "vendor/etc/selinux/vendor_seapp_contexts",
+ "odm": "odm/etc/selinux/odm_seapp_contexts",
+ }
+ vendorSeappContexts := findFilesInPartitions(vendorSeappContextsPaths, fsInfos)
+
+ vendorFileContextsPaths := map[string]string{
+ "vendor": "vendor/etc/selinux/vendor_file_contexts",
+ "odm": "odm/etc/selinux/odm_file_contexts",
+ }
+ vendorFileContexts := findFilesInPartitions(vendorFileContextsPaths, fsInfos)
+
+ precompiledSepolicyPaths := map[string]string{
+ "odm": "odm/etc/selinux/precompiled_sepolicy",
+ "vendor": "vendor/etc/selinux/precompiled_sepolicy",
+ }
+ precompiledSepolicies := findFilesInPartitions(precompiledSepolicyPaths, fsInfos)
+
+ testTimestamp := android.PathForModuleOut(ctx, "treble_labeling_test.timestamp")
+
+ platformAppsList := android.PathForModuleOut(ctx, "platform_apps.txt")
+ android.WriteFileRule(ctx, platformAppsList, strings.Join(platformApps.Strings(), "\n"))
+ vendorAppsList := android.PathForModuleOut(ctx, "vendor_apps.txt")
+ android.WriteFileRule(ctx, vendorAppsList, strings.Join(vendorApps.Strings(), "\n"))
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+
+ if len(precompiledSepolicies) != 1 {
+ errorMessage := fmt.Sprintf("number of precompiled_sepolicy must be one but was %q", precompiledSepolicies.Strings())
+ rule.Command().
+ Text("echo").
+ Text(proptools.ShellEscape(errorMessage)).
+ Text(" && exit 1").
+ ImplicitOutput(testTimestamp)
+ } else if proptools.String(a.deviceProps.Precompiled_sepolicy_without_vendor) == "" {
+ rule.Command().
+ Text("echo").
+ Text("cannot find precompiled_sepolicy_without_vendor").
+ Text(" && exit 1").
+ ImplicitOutput(testTimestamp)
+ } else {
+ precompiledSepolicyWithoutVendor := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Precompiled_sepolicy_without_vendor))
+ cmd := rule.Command().BuiltTool("treble_labeling_tests").
+ FlagWithInput("--platform_apks ", platformAppsList).
+ FlagWithInput("--vendor_apks ", vendorAppsList).
+ FlagWithInput("--precompiled_sepolicy_without_vendor ", precompiledSepolicyWithoutVendor).
+ FlagWithInput("--precompiled_sepolicy ", precompiledSepolicies[0]). // len(precompiledSepolicies) == 1
+ FlagWithInputList("--platform_seapp_contexts ", platformSeappContexts, " ").
+ FlagWithInputList("--vendor_seapp_contexts ", vendorSeappContexts, " ").
+ FlagWithInputList("--vendor_file_contexts ", vendorFileContexts, " ").
+ FlagWithInput("--aapt2_path ", ctx.Config().HostToolPath(ctx, "aapt2")).
+ Implicits(platformApps).
+ Implicits(vendorApps)
+
+ trackingListFile := ctx.Config().SELinuxTrebleLabelingTrackingListFile(ctx)
+ if trackingListFile != nil {
+ cmd.FlagWithInput("--tracking_list_file ", trackingListFile)
+ }
+
+ if !ctx.Config().EnforceSELinuxTrebleLabeling() {
+ cmd.Flag("--treat_as_warnings")
+ }
+
+ if ctx.Config().Debuggable() {
+ cmd.Flag("--debuggable")
+ }
+
+ cmd.FlagWithOutput("> ", testTimestamp)
+ }
+
+ rule.Build("treble_labeling_test", "SELinux Treble Labeling Test")
+
+ if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) {
+ ctx.Phony("check-selinux-treble-labeling", testTimestamp)
+ }
+
+ return testTimestamp
+}
+
+func (a *androidDevice) checkVintf(ctx android.ModuleContext) {
+ if !proptools.Bool(a.deviceProps.Main_device) {
+ return
+ }
+ if ctx.Config().KatiEnabled() {
+ // Make will generate the vintf checks.
+ return
+ }
+ var checkVintfLogs android.Paths
+ fsInfoMap := a.getFsInfos(ctx)
+ for _, partition := range android.SortedKeys(fsInfoMap) {
+ checkVintfLog := fsInfoMap[partition].checkVintfLog
+ if checkVintfLog != nil {
+ checkVintfLogs = append(checkVintfLogs, checkVintfLog)
+ }
+ }
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.SetPhonyOutput()
+ cmd := rule.Command()
+ for _, checkVintfLog := range checkVintfLogs {
+ cmd.Textf(" echo %s; cat %s; echo; ", checkVintfLog, checkVintfLog).Implicit(checkVintfLog)
+ }
+ cmd.ImplicitOutput(android.PathForPhony(ctx, "check-vintf-all"))
+ rule.Build("check-vintf-all", "check-vintf-all")
+ // TODO (b/415130821): Create the monolithic check_vintf_compatible.log
+}
diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go
index aa06337ca..1a3782b8e 100644
--- a/filesystem/android_device_product_out.go
+++ b/filesystem/android_device_product_out.go
@@ -117,7 +117,7 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont
copyBootImg := func(prop *string, type_ string) {
if proptools.String(prop) != "" {
- partition := ctx.GetDirectDepWithTag(*prop, filesystemDepTag)
+ partition := ctx.GetDirectDepProxyWithTag(*prop, filesystemDepTag)
if info, ok := android.OtherModuleProvider(ctx, partition, BootimgInfoProvider); ok {
installPath := android.PathForModuleInPartitionInstall(ctx, "", type_+".img")
ctx.Build(pctx, android.BuildParams{
@@ -137,7 +137,7 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont
copyBootImg(a.partitionProps.Vendor_boot_partition_name, "vendor_boot")
for _, vbmetaModName := range a.partitionProps.Vbmeta_partitions {
- partition := ctx.GetDirectDepWithTag(vbmetaModName, filesystemDepTag)
+ partition := ctx.GetDirectDepProxyWithTag(vbmetaModName, filesystemDepTag)
if info, ok := android.OtherModuleProvider(ctx, partition, vbmetaPartitionProvider); ok {
installPath := android.PathForModuleInPartitionInstall(ctx, "", info.Name+".img")
ctx.Build(pctx, android.BuildParams{
@@ -152,7 +152,7 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont
}
if proptools.String(a.partitionProps.Super_partition_name) != "" {
- partition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ partition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
if info, ok := android.OtherModuleProvider(ctx, partition, SuperImageProvider); ok {
installPath := android.PathForModuleInPartitionInstall(ctx, "", "super.img")
ctx.Build(pctx, android.BuildParams{
@@ -183,17 +183,6 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont
Implicits: deps,
})
- emptyFile := android.PathForModuleOut(ctx, "empty_file")
- android.WriteFileRule(ctx, emptyFile, "")
-
- // TODO: We don't have these tests building in soong yet. Add phonies for them so that CI builds
- // that try to build them don't error out.
- ctx.Phony("continuous_instrumentation_tests", emptyFile)
- ctx.Phony("continuous_native_tests", emptyFile)
- ctx.Phony("device-tests", emptyFile)
- ctx.Phony("device-platinum-tests", emptyFile)
- ctx.Phony("platform_tests", emptyFile)
-
return copyToProductOutTimestamp
}
@@ -237,7 +226,7 @@ func (a *androidDevice) getFsInfos(ctx android.ModuleContext) map[string]Filesys
}
for _, partitionDefinition := range partitionDefinitions {
if proptools.String(partitionDefinition.prop) != "" {
- partition := ctx.GetDirectDepWithTag(*partitionDefinition.prop, filesystemDepTag)
+ partition := ctx.GetDirectDepProxyWithTag(*partitionDefinition.prop, filesystemDepTag)
if info, ok := android.OtherModuleProvider(ctx, partition, FilesystemProvider); ok {
filesystemInfos[partitionDefinition.ty] = info
} else {
@@ -246,7 +235,7 @@ func (a *androidDevice) getFsInfos(ctx android.ModuleContext) map[string]Filesys
}
}
if a.partitionProps.Super_partition_name != nil {
- superPartition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
for partition := range info.SubImageInfo {
filesystemInfos[partition] = info.SubImageInfo[partition]
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 485eae47c..bf6323707 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -227,8 +227,10 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Set the Filesystem info of the ramdisk dependency.
// `android_device` will use this info to package `target_files.zip`
+ // TODO: Move this under BootimgInfo, as is, it's easy to confuse the bootImg module for
+ // the underlying ramdisk module.
if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
- ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep)
+ ramdiskModule := ctx.GetDirectDepProxyWithTag(ramdisk, bootimgRamdiskDep)
fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider)
android.SetProvider(ctx, FilesystemProvider, fsInfo)
} else {
@@ -238,11 +240,13 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Set BootimgInfo for building target_files.zip
dtbPath := b.getDtbPath(ctx)
android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{
+ Type: b.bootImageType,
Cmdline: b.properties.Cmdline,
Kernel: kernelPath,
Dtb: dtbPath,
Bootconfig: b.getBootconfigPath(ctx),
Output: output,
+ SignedOutput: b.SignedOutputPath(),
PropFileForMiscInfo: b.buildPropFileForMiscInfo(ctx),
HeaderVersion: proptools.String(b.properties.Header_version),
})
@@ -287,11 +291,13 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]()
type BootimgInfo struct {
+ Type bootImageType
Cmdline []string
Kernel android.Path
Dtb android.Path
Bootconfig android.Path
Output android.Path
+ SignedOutput android.Path
PropFileForMiscInfo android.Path
HeaderVersion string
}
@@ -371,12 +377,12 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path)
ramdiskName := proptools.String(b.properties.Ramdisk_module)
if ramdiskName != "" {
ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep)
- if filesystem, ok := ramdisk.(*filesystem); ok {
+ if fsInfo, ok := android.OtherModuleProvider(ctx, ramdisk, FilesystemProvider); ok {
flag := "--ramdisk "
if b.bootImageType.isVendorBoot() {
flag = "--vendor_ramdisk "
}
- cmd.FlagWithInput(flag, filesystem.OutputPath())
+ cmd.FlagWithInput(flag, fsInfo.Output)
} else {
ctx.PropertyErrorf("ramdisk", "%q is not android_filesystem module", ramdisk.Name())
return output
@@ -540,7 +546,7 @@ func (b *bootimg) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Pa
bootImgType := proptools.String(b.properties.Boot_image_type)
addStr("avb_"+bootImgType+"_add_hash_footer_args", b.getAvbHashFooterArgs(ctx))
if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
- ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep)
+ ramdiskModule := ctx.GetDirectDepProxyWithTag(ramdisk, bootimgRamdiskDep)
fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider)
if fsInfo.HasOrIsRecovery {
// Create a dup entry for recovery
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c3c3835f6..f0c7ee7a2 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -41,7 +41,7 @@ func init() {
registerMutators(android.InitRegistrationContext)
pctx.HostBinToolVariable("fileslist", "fileslist")
pctx.HostBinToolVariable("fs_config", "fs_config")
- pctx.HostBinToolVariable("symbols_map", "symbols_map")
+ pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
}
func registerBuildComponents(ctx android.RegistrationContext) {
@@ -81,6 +81,12 @@ var (
Command: `(cd ${rootDir}; find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,${prefix},' | ${fs_config} -C -D ${rootDir} -R "${prefix}" > ${out}`,
CommandDeps: []string{"${fs_config}"},
}, "rootDir", "prefix")
+ zipFiles = pctx.AndroidStaticRule("SnapshotZipFiles", blueprint.RuleParams{
+ Command: `${SoongZipCmd} -r $out.rsp -o $out`,
+ CommandDeps: []string{"${SoongZipCmd}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ })
)
type filesystem struct {
@@ -101,10 +107,11 @@ type filesystem struct {
filesystemBuilder filesystemBuilder
selinuxFc android.Path
+ avbKey android.Path
}
type filesystemBuilder interface {
- BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo)
+ BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo, platformGeneratedFiles *[]string)
// Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
FilterPackagingSpec(spec android.PackagingSpec) bool
// Function that modifies PackagingSpec in PackagingBase.GatherPackagingSpecs() to customize.
@@ -253,11 +260,15 @@ type FilesystemProperties struct {
// Whether this partition is not supported by flashall.
// If true, this partition will not be included in the `updatedpackage` dist artifact.
No_flashall *bool
+
+ // Run checkvintf on the vintf manifests of the filesystem
+ Check_vintf *bool
}
type AndroidFilesystemDeps struct {
System *string
System_ext *string
+ Product *string
}
// Additional properties required to generate erofs FS partitions.
@@ -341,6 +352,13 @@ var dependencyTagWithVisibilityEnforcementBypass = depTagWithVisibilityEnforceme
// contains the description of dev nodes added to the CPIO archive for the ramdisk partition.
const ramdiskDevNodesDescription = "ramdisk_node_list"
+func (f *filesystem) UseGenericConfig() bool {
+ if proptools.Bool(f.properties.Is_auto_generated) {
+ return false
+ }
+ return f.PartitionType() == "system"
+}
+
func (f *filesystem) setDevNodesDescriptionProp() {
if proptools.String(f.properties.Partition_name) == "ramdisk" {
f.properties.Dev_nodes_description_file = proptools.StringPtr(":" + ramdiskDevNodesDescription)
@@ -359,6 +377,12 @@ func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
if f.properties.Android_filesystem_deps.System_ext != nil {
ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext))
}
+ if f.properties.Android_filesystem_deps.Product != nil {
+ if f.PartitionType() != "vendor" {
+ ctx.ModuleErrorf("Product cannot be set for non-vendor partitions.")
+ }
+ ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.Product))
+ }
for _, partition := range f.properties.Include_files_of {
ctx.AddDependency(ctx.Module(), interPartitionInstallDependencyTag, partition)
}
@@ -401,6 +425,7 @@ type InstalledFilesStruct struct {
type InstalledModuleInfo struct {
Name string
Variation string
+ Prebuilt bool
}
type FilesystemInfo struct {
@@ -409,10 +434,6 @@ type FilesystemInfo struct {
// Returns the output file that is signed by avbtool. If this module is not signed, returns
// nil.
SignedOutputPath android.Path
- // An additional hermetic filesystem image.
- // e.g. this will contain inodes with pinned timestamps.
- // This will be copied to target_files.zip
- OutputHermetic android.Path
// A text file containing the list of paths installed on the partition.
FileListFile android.Path
// The root staging directory used to build the output filesystem. If consuming this, make sure
@@ -427,9 +448,6 @@ type FilesystemInfo struct {
// in ninja. In many cases this is the same as RootDir, only in the system partition is it
// different. There, it points to the "system" sub-directory of RootDir.
RebasedDir android.Path
- // A text file with block data of the .img file
- // This is an implicit output of `build_image`
- MapFile android.Path
// Name of the module that produced this FilesystemInfo origionally. (though it may be
// re-exported by super images or boot images)
ModuleName string
@@ -454,7 +472,7 @@ type FilesystemInfo struct {
FilesystemConfig android.Path
- Owners []InstalledModuleInfo
+ Owners depset.DepSet[InstalledModuleInfo]
HasFsverity bool
@@ -471,6 +489,9 @@ type FilesystemInfo struct {
NoFlashall bool
// HasOrIsRecovery returns true for recovery and for ramdisks with a recovery partition.
HasOrIsRecovery bool
+
+ // Results of check_vintf
+ checkVintfLog android.Path
}
// FullInstallPathInfo contains information about the "full install" paths of all the files
@@ -633,24 +654,25 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
FullInstallPath: spec.FullInstallPath(),
RequiresFullInstall: spec.RequiresFullInstall(),
SourcePath: spec.SrcPath(),
- SymlinkTarget: spec.ToGob().SymlinkTarget,
+ SymlinkTarget: spec.SymlinkTarget(),
})
}
+ platformGeneratedFiles := []string{}
f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
- f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths)
- f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir, &fullInstallPaths)
- f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths)
- f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths)
- f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths)
+ f.verifyGenericConfig(ctx, specs)
+ f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+ f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+ f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+ f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+ f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+ checkVintfLog := f.checkVintf(ctx, rebasedDir)
// Assemeble the staging dir and output a timestamp
builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx))
builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName()))
// Create a new rule builder for build_image
builder = android.NewRuleBuilder(pctx, ctx)
- var mapFile android.Path
- var outputHermetic android.WritablePath
var buildImagePropFile android.Path
var buildImagePropFileDeps android.Paths
var extraRootDirs android.Paths
@@ -662,12 +684,6 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
output := android.PathForModuleOut(ctx, f.installFileName())
f.buildImageUsingBuildImage(ctx, builder, buildImageParams{rootDir, buildImagePropFile, buildImagePropFileDeps, output})
f.output = output
- // Create the hermetic img file using a separate rule builder so that it can be built independently
- hermeticBuilder := android.NewRuleBuilder(pctx, ctx)
- outputHermetic = android.PathForModuleOut(ctx, "for_target_files", f.installFileName())
- propFileHermetic := f.propFileForHermeticImg(ctx, hermeticBuilder, buildImagePropFile)
- f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic})
- mapFile = f.getMapFile(ctx)
case compressedCpioType:
f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, true)
case cpioType:
@@ -702,15 +718,36 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
erofsCompressHints = android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints)
}
+ installedFilesStructList := []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rebasedDir, f.output)}
+ if f.partitionName() == "system" {
+ rootDirForInstalledFiles := android.PathForModuleOut(ctx, "root_for_installed_files", "root")
+ copyToRootTimestamp := android.PathForModuleOut(ctx, "root_copy_timestamp")
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("touch").Text(copyToRootTimestamp.String())
+ builder.Command().Text("rm -rf").Text(rootDirForInstalledFiles.String())
+ builder.Command().Text("mkdir -p").Text(rootDirForInstalledFiles.String())
+ builder.Command().
+ Text("rsync").
+ Flag("-a").
+ Flag("--checksum").
+ Flag("--exclude='system/'").
+ Text(rootDir.String() + "/").
+ Text(rootDirForInstalledFiles.String()).
+ Implicit(f.output).
+ ImplicitOutput(copyToRootTimestamp)
+ builder.Build("system_root_dir", "Construct system partition root dir")
+
+ installedFilesStructList = append(installedFilesStructList, buildInstalledFiles(ctx, "root", rootDirForInstalledFiles, copyToRootTimestamp))
+ }
+
fsInfo := FilesystemInfo{
Output: f.OutputPath(),
SignedOutputPath: f.SignedOutputPath(),
- OutputHermetic: outputHermetic,
FileListFile: fileListFile,
RootDir: rootDir,
ExtraRootDirs: extraRootDirs,
RebasedDir: rebasedDir,
- MapFile: mapFile,
ModuleName: ctx.ModuleName(),
BuildImagePropFile: buildImagePropFile,
BuildImagePropFileDeps: buildImagePropFileDeps,
@@ -718,19 +755,24 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
FullInstallPaths: fullInstallPaths,
InstalledFilesDepSet: depset.New(
depset.POSTORDER,
- []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)},
+ installedFilesStructList,
includeFilesInstalledFiles(ctx),
),
- ErofsCompressHints: erofsCompressHints,
- SelinuxFc: f.selinuxFc,
- FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir),
- Owners: f.gatherOwners(specs),
+ ErofsCompressHints: erofsCompressHints,
+ SelinuxFc: f.selinuxFc,
+ FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir),
+ Owners: depset.New(
+ depset.POSTORDER,
+ f.gatherOwners(specs),
+ f.gatherSubPartitionOwners(ctx),
+ ),
HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil,
PropFileForMiscInfo: propFileForMiscInfo,
PartitionSize: f.properties.Partition_size,
PartitionName: f.partitionName(),
HasOrIsRecovery: f.hasOrIsRecovery(ctx),
NoFlashall: proptools.Bool(f.properties.No_flashall),
+ checkVintfLog: checkVintfLog,
}
if proptools.Bool(f.properties.Use_avb) {
fsInfo.UseAvb = true
@@ -738,6 +780,7 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
fsInfo.AvbHashAlgorithm = proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256")
if f.properties.Avb_private_key != nil {
fsInfo.AvbKey = android.PathForModuleSrc(ctx, *f.properties.Avb_private_key)
+ f.avbKey = fsInfo.AvbKey
}
}
@@ -762,6 +805,17 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filesContained = append(filesContained, file.FullInstallPath.String())
}
complianceMetadataInfo.SetFilesContained(filesContained)
+ complianceMetadataInfo.SetPlatformGeneratedFiles(platformGeneratedFiles)
+
+ kernelModuleSrcDestPairs := []string{}
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
+ if pkmi, ok := android.OtherModuleProvider(ctx, dep, android.PrebuiltKernelModulesComplianceMetadataProvider); ok {
+ for i, _ := range pkmi.Srcs {
+ kernelModuleSrcDestPairs = append(kernelModuleSrcDestPairs, pkmi.Srcs[i]+"::"+pkmi.Dests[i])
+ }
+ }
+ })
+ complianceMetadataInfo.SetKernelModuleCopyFiles(kernelModuleSrcDestPairs)
}
func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath {
@@ -817,16 +871,11 @@ func (f *filesystem) setVbmetaPartitionProvider(ctx android.ModuleContext) {
})
}
-func (f *filesystem) getMapFile(ctx android.ModuleContext) android.WritablePath {
- // create the filepath by replacing the extension of the corresponding img file
- return android.PathForModuleOut(ctx, f.installFileName()).ReplaceExtension(ctx, "map")
-}
-
func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) {
visitedModule := map[string]bool{}
packagingSpecs := f.gatherFilteredPackagingSpecs(ctx)
- moduleInFileSystem := func(mod android.Module) bool {
+ moduleInFileSystem := func(mod android.ModuleProxy) bool {
for _, ps := range android.OtherModuleProviderOrDefault(
ctx, mod, android.InstallFilesProvider).PackagingSpecs {
if _, ok := packagingSpecs[ps.RelPathInPackage()]; ok {
@@ -836,7 +885,7 @@ func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) {
return false
}
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
if visitedModule[child.Name()] {
return false
}
@@ -844,14 +893,15 @@ func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) {
visitedModule[child.Name()] = true
return true
}
- if vintfFragments := child.VintfFragments(ctx); vintfFragments != nil {
+
+ if installInfo, ok := android.OtherModuleProvider(ctx, child, android.InstallFilesProvider); ok && len(installInfo.VintfFragmentsPaths) > 0 {
ctx.PropertyErrorf(
"vintf_fragments",
"Module %s is referenced by soong-defined filesystem %s with property vintf_fragments(%s) in use."+
" Use vintf_fragment_modules property instead.",
child.Name(),
f.BaseModuleName(),
- strings.Join(vintfFragments, ", "),
+ strings.Join(installInfo.VintfFragmentsPaths.Strings(), ", "),
)
}
visitedModule[child.Name()] = true
@@ -900,6 +950,7 @@ func (f *filesystem) buildNonDepsFiles(
rootDir android.OutputPath,
rebasedDir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
rebasedPrefix, err := filepath.Rel(rootDir.String(), rebasedDir.String())
if err != nil || strings.HasPrefix(rebasedPrefix, "../") {
@@ -953,16 +1004,19 @@ func (f *filesystem) buildNonDepsFiles(
if !strings.HasPrefix(name, rebasedPrefix) {
installPath = android.PathForModuleInPartitionInstall(ctx, "root", name)
}
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
FullInstallPath: installPath,
SymlinkTarget: target,
})
} else {
if strings.HasPrefix(name, rebasedPrefix) {
+ installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix))
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)),
+ FullInstallPath: installPath,
SymlinkTarget: target,
})
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
}
}
}
@@ -999,6 +1053,79 @@ func (f *filesystem) rootDirString() string {
return f.partitionName()
}
+func (f *filesystem) verifyGenericConfig(ctx android.ModuleContext, specs map[string]android.PackagingSpec) {
+ // This image is not bundled with the platform.
+ if ctx.Config().UnbundledBuild() {
+ return
+ }
+
+ // TODO(b/411581190): These system images include system_ext and product modules in the system
+ // partition. They must be included with a different depTag so that we can skip those non-system
+ // modules in this verification.
+ systemImagesWithSubpartitions := []string{
+ "android_gsi",
+ "aosp_system_image",
+ }
+
+ // Verify that modules installed in the system partition use the generic configiguration. This
+ // also checks there are any unexpected dependencies from system modules to modules installed in
+ // non-system partitions.
+ if !f.UseGenericConfig() || f.partitionName() != "system" || proptools.Bool(f.properties.Is_auto_generated) || android.InList(f.Name(), systemImagesWithSubpartitions) {
+ return
+ }
+
+ allowedModules := []string{
+ // build_flag_system collects information from the metadata for each product.
+ "build_flag_system",
+ // microdroid_ramdisk is an android_filesystem included in the system image.
+ "microdroid_ramdisk",
+ // notice_xml_system collects information from the metadata for each product.
+ "notice_xml_system",
+ // product_config collects all product variables that are required in every partition.
+ "product_config",
+ }
+
+ nonGenericModules := make(map[string]string)
+ visitedModules := make(map[string]bool)
+
+ for _, m := range allowedModules {
+ visitedModules[m] = true
+ }
+
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ moduleName := child.Name()
+ if visitedModules[moduleName] {
+ return false
+ }
+ visitedModules[moduleName] = true
+
+ moduleInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider)
+ if !moduleInfo.Enabled || moduleInfo.Target.Os.Class == android.Host {
+ return false
+ }
+
+ // Skip optional library deps which are mostly from a different partition.
+ depTag := ctx.OtherModuleDependencyTag(child)
+ if java.IsOptionalUsesLibraryDepTag(depTag) {
+ return false
+ }
+
+ // Modules requiring non-generic configuration must not be included in the system image.
+ if !moduleInfo.UseGenericConfig {
+ nonGenericModules[moduleName] = parent.Name()
+ }
+ return true
+ })
+
+ if len(nonGenericModules) > 0 {
+ errStr := "\n"
+ for _, m := range android.SortedKeys(nonGenericModules) {
+ errStr += fmt.Sprintf("\t%q from %q,\n", m, nonGenericModules[m])
+ }
+ ctx.ModuleErrorf("includes non-generic modules:%s", errStr)
+ }
+}
+
type buildImageParams struct {
// inputs
rootDir android.OutputPath
@@ -1045,15 +1172,6 @@ func (f *filesystem) buildImageUsingBuildImage(
builder.Build("build_"+params.output.String(), fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
}
-func (f *filesystem) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path {
- propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
- builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp).
- Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp).
- Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output
- builder.Command().Text("touch").Output(f.getMapFile(ctx))
- return propFilePinnedTimestamp
-}
-
func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path {
builder := android.NewRuleBuilder(pctx, ctx)
fcBin := android.PathForModuleOut(ctx, "file_contexts.bin")
@@ -1094,7 +1212,9 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and
addPath("avb_key_path", key)
}
addStr("partition_name", f.partitionName())
- addStr("avb_add_hashtree_footer_args", f.getAvbAddHashtreeFooterArgs(ctx))
+ avbAddHashTreeFooterArgs, avbAddHashTreeFooterDeps := f.getAvbAddHashtreeFooterArgs(ctx)
+ addStr("avb_add_hashtree_footer_args", avbAddHashTreeFooterArgs)
+ deps = append(deps, avbAddHashTreeFooterDeps...)
}
if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil {
@@ -1179,6 +1299,7 @@ func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android
addStr := func(name string, value string) {
lines = append(lines, fmt.Sprintf("%s=%s", name, value))
}
+ var deps android.Paths
addStr("use_dynamic_partition_size", "true")
addStr("ext_mkuserimg", "mkuserimg_mke2fs")
@@ -1188,7 +1309,9 @@ func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android
if proptools.Bool(f.properties.Use_avb) {
addStr("avb_"+f.partitionName()+"_hashtree_enable", "true")
- addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(f.getAvbAddHashtreeFooterArgs(ctx)))
+ avbAddHashTreeFooterArgs, avbAddHashTreeFooterDeps := f.getAvbAddHashtreeFooterArgs(ctx)
+ addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(avbAddHashTreeFooterArgs))
+ deps = append(deps, avbAddHashTreeFooterDeps...)
}
if f.selinuxFc != nil {
@@ -1239,15 +1362,21 @@ func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android
android.WriteFileRule(ctx, propFilePreProcessing, strings.Join(lines, "\n"))
propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info")
ctx.Build(pctx, android.BuildParams{
- Rule: textFileProcessorRule,
- Input: propFilePreProcessing,
- Output: propFile,
+ Rule: textFileProcessorRule,
+ Input: propFilePreProcessing,
+ Output: propFile,
+ Implicits: deps,
})
return propFile
}
-func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) string {
+// Returns the avb_add_hashtree_footer_args value for this module. This value depends on the
+// contents of some other files, which will be returned as the second return value, and must
+// be tracked as implicit deps. The result should also be passed through textFileProcessorRule
+// to read the files and incorporate the results into the args.
+func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) (string, android.Paths) {
+ var deps android.Paths
avb_add_hashtree_footer_args := ""
if !proptools.BoolDefault(f.properties.Use_fec, true) {
avb_add_hashtree_footer_args += " --do_not_generate_fec"
@@ -1265,11 +1394,17 @@ func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) stri
// We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because
// the build number changed, and we don't want to trigger rebuilds solely based on the build
// number.
- avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx))
+ if ctx.Module().UseGenericConfig() {
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildThumbprintFile(ctx))
+ deps = append(deps, ctx.Config().BuildThumbprintFile(ctx))
+ } else {
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx))
+ deps = append(deps, ctx.Config().BuildFingerprintFile(ctx))
+ }
if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" {
avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch))
}
- return avb_add_hashtree_footer_args
+ return avb_add_hashtree_footer_args, deps
}
// This method checks if there is any property set for the fstype(s) other than
@@ -1293,7 +1428,7 @@ func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsTyp
}
func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, partitions android.Paths) {
- ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(interPartitionInstallDependencyTag, func(m android.ModuleProxy) {
if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
rootDirs = append(rootDirs, fsProvider.RootDir)
partitions = append(partitions, fsProvider.Output)
@@ -1306,7 +1441,7 @@ func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, par
}
func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[InstalledFilesStruct]) {
- ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(interPartitionInstallDependencyTag, func(m android.ModuleProxy) {
if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
ret = append(ret, fsProvider.InstalledFilesDepSet)
}
@@ -1319,7 +1454,7 @@ func (f *filesystem) hasOrIsRecovery(ctx android.ModuleContext) bool {
return true
}
ret := false
- ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(interPartitionInstallDependencyTag, func(m android.ModuleProxy) {
if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok && fsProvider.PartitionName == "recovery" {
ret = true
}
@@ -1397,6 +1532,7 @@ func (f *filesystem) buildEventLogtagsFile(
builder *android.RuleBuilder,
rebasedDir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
if !proptools.Bool(f.properties.Build_logtags) {
return
@@ -1407,12 +1543,14 @@ func (f *filesystem) buildEventLogtagsFile(
builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String())
builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String())
+ installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags")
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags"),
+ FullInstallPath: installPath,
SourcePath: android.MergedLogtagsPath(ctx),
})
f.appendToEntry(ctx, eventLogtagsPath)
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
}
func (f *filesystem) BuildLinkerConfigFile(
@@ -1420,6 +1558,7 @@ func (f *filesystem) BuildLinkerConfigFile(
builder *android.RuleBuilder,
rebasedDir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
if !proptools.Bool(f.properties.Linker_config.Gen_linker_config) {
return
@@ -1431,10 +1570,12 @@ func (f *filesystem) BuildLinkerConfigFile(
output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
builder.Command().Text("cp").Input(intermediateOutput).Output(output)
+ installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb")
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb"),
+ FullInstallPath: installPath,
SourcePath: intermediateOutput,
})
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
f.appendToEntry(ctx, output)
}
@@ -1465,6 +1606,10 @@ func (f *filesystem) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_MODULE_PATH", f.installDir.String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName())
entries.SetString("LOCAL_FILESYSTEM_FILELIST", f.fileListFile.String())
+ if f.avbKey != nil {
+ entries.SetString("LOCAL_FILESYSTEM_AVB_KEY_PATH", f.avbKey.String())
+ }
+ entries.SetString("LOCAL_FILESYSTEM_AVB_ALGORITHM", proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096"))
},
},
}}
@@ -1508,11 +1653,21 @@ func (f *filesystem) gatherOwners(specs map[string]android.PackagingSpec) []Inst
owners = append(owners, InstalledModuleInfo{
Name: spec.Owner(),
Variation: spec.Variation(),
+ Prebuilt: spec.Prebuilt(),
})
}
return owners
}
+func (f *filesystem) gatherSubPartitionOwners(ctx android.ModuleContext) (ret []depset.DepSet[InstalledModuleInfo]) {
+ ctx.VisitDirectDepsProxyWithTag(interPartitionInstallDependencyTag, func(m android.ModuleProxy) {
+ if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
+ ret = append(ret, fsProvider.Owners)
+ }
+ })
+ return
+}
+
// Dexpreopt files are installed to system_other. Collect the packaingSpecs for the dexpreopt files
// from this partition to export to the system_other partition later.
func (f *filesystem) systemOtherFiles(ctx android.ModuleContext) map[string]android.PackagingSpec {
@@ -1653,6 +1808,23 @@ func assertMaxImageSize(builder *android.RuleBuilder, image android.Path, maxSiz
// It visits apps installed in system and system_ext partitions, and adds the autogenerated
// RRO modules to its own deps.
func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) {
+ overlayModuleName := func(child android.ModuleOrProxy, partition string) string {
+ ret := java.AutogeneratedRroModuleName(ctx, child.Name(), partition)
+ // Use the fully qualified name if the app is a soong namespace
+ if ctx.OtherModuleNamespace(child).Path != "." {
+ ret = "//" + ctx.OtherModuleNamespace(child).Path + ":" + ret
+ }
+ return ret
+ }
+ productCharacteristicsOverlayModuleName := func(child android.ModuleOrProxy) string {
+ ret := java.AutogeneratedProductCharacteristicsRroModuleName(ctx, child.Name())
+ // Use the fully qualified name if the app is a soong namespace
+ if ctx.OtherModuleNamespace(child).Path != "." {
+ ret = "//" + ctx.OtherModuleNamespace(child).Path + ":" + ret
+ }
+ return ret
+ }
+
f, ok := ctx.Module().(*filesystem)
if !ok {
return
@@ -1667,18 +1839,23 @@ func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) {
}
return
}
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
depTag := ctx.OtherModuleDependencyTag(child)
+ traverseDeps := true
if parent.Name() == f.Name() && depTag != interPartitionDependencyTag {
- return false // This is a module listed in deps of vendor/product filesystem
+ traverseDeps = false // This is a module listed in deps of vendor/product filesystem
}
- if vendorOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "vendor"); ctx.OtherModuleExists(vendorOverlay) && thisPartition == "vendor" {
+ if vendorOverlay := overlayModuleName(child, "vendor"); ctx.OtherModuleExists(vendorOverlay) && thisPartition == "vendor" {
ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, vendorOverlay)
}
- if productOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "product"); ctx.OtherModuleExists(productOverlay) && thisPartition == "product" {
+ if productOverlay := overlayModuleName(child, "product"); ctx.OtherModuleExists(productOverlay) && thisPartition == "product" {
ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, productOverlay)
}
- return true
+ if productCharacteristics := productCharacteristicsOverlayModuleName(child); ctx.OtherModuleExists(productCharacteristics) && thisPartition == "product" {
+ ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, productCharacteristics)
+ }
+
+ return traverseDeps
})
}
@@ -1695,3 +1872,63 @@ func setCommonFilesystemInfo(ctx android.ModuleContext, m Filesystem) {
SignedOutputPath: m.SignedOutputPath(),
})
}
+
+// Runs checkvintf on the staging directory of the filesystem.
+func (f *filesystem) checkVintf(ctx android.ModuleContext, rebasedDir android.OutputPath) android.Path {
+ if !proptools.Bool(f.properties.Check_vintf) {
+ return nil
+ }
+ checkVintfLog := android.PathForModuleOut(ctx, "vintf", "check_vintf_"+f.PartitionType()+".log")
+ extractedApexDir := android.PathForModuleOut(ctx, "vintf", "apex_extracted")
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ // Use apexd_host to extract the apexes of this partition to an intermediate location.
+ // This intermediate location will be subsequently used by checkvintf.
+ cmd := builder.Command()
+ cmd.Textf("rm -rf %s", checkVintfLog).
+ Textf("rm -rf %s && mkdir -p %s && ", extractedApexDir.String(), extractedApexDir.String()).
+ BuiltTool("apexd_host").
+ FlagWithArg(fmt.Sprintf(" --%s_path ", f.PartitionType()), rebasedDir.String()).
+ FlagWithArg(" --apex_path ", extractedApexDir.String())
+
+ if f.PartitionType() == "system" {
+ cmd.Textf(" && ").
+ BuiltTool("checkvintf").
+ Flag("--check-one").
+ Implicit(f.fileystemStagingDirTimestamp(ctx)).
+ FlagWithArg("--dirmap ", fmt.Sprintf("/system:%s", rebasedDir.String())).
+ FlagWithArg("--dirmap ", fmt.Sprintf("/apex:%s", extractedApexDir.String())).
+ FlagWithOutput(">> ", checkVintfLog).
+ Flag("2>&1 ").
+ Textf(" || ( cat %s && exit 1 ); ", checkVintfLog.String())
+ } else {
+ // checkvintf against each device sku
+ for _, vendorSku := range deviceSkusForCheckVintf(ctx) {
+ cmd.Textf(" && ").
+ BuiltTool("checkvintf").
+ Flag("--check-one").
+ Implicit(f.fileystemStagingDirTimestamp(ctx)).
+ FlagWithArg("--dirmap ", fmt.Sprintf("/vendor:%s", rebasedDir.String())).
+ FlagWithArg("--dirmap ", fmt.Sprintf("/apex:%s", extractedApexDir.String())).
+ FlagWithArg("--property ", "ro.boot.product.vendor.sku="+vendorSku).
+ FlagWithOutput(">> ", checkVintfLog).
+ Flag("2>&1 ").
+ Textf(" || ( cat %s && exit 1 ); ", checkVintfLog.String())
+ }
+ }
+
+ builder.Build(checkVintfLog.Base(), checkVintfLog.Base())
+ return checkVintfLog
+}
+
+func deviceSkusForCheckVintf(ctx android.ModuleContext) []string {
+ // Check vendor SKU=(empty) case when:
+ // - DEVICE_MANIFEST_FILE is not empty; OR
+ // - DEVICE_MANIFEST_FILE is empty AND DEVICE_MANIFEST_SKUS is empty (only vendor manifest fragments are used)
+ if len(ctx.Config().DeviceManifestFiles()) > 0 {
+ return []string{""}
+ } else if len(ctx.Config().DeviceManifestSkus()) == 0 {
+ return []string{""}
+ }
+ return ctx.Config().DeviceManifestSkus()
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index e57e45cb6..2e7f478ff 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -803,3 +803,65 @@ func TestRamdiskPartitionSetsDevNodes(t *testing.T) {
java.CheckModuleHasDependency(t, result.TestContext, "ramdisk_filesystem", "android_common", "ramdisk_node_list"),
)
}
+
+func TestFileSystemWithNativeBridgeDeps(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ fixture,
+ android.PrepareForNativeBridgeEnabled,
+ ).RunTestWithBp(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ compile_multilib: "both",
+ native_bridge_supported: true,
+ deps: ["lib_no_native_bridge", "lib_both"],
+ multilib: {
+ native_bridge: {
+ deps: ["lib_both", "lib_only_native_bridge"],
+ },
+ },
+ }
+
+ cc_library {
+ name: "lib_no_native_bridge",
+ stl: "none",
+ system_shared_libs: [],
+ }
+ // Device arch and NativeBridge arch
+ cc_library {
+ name: "lib_both",
+ native_bridge_supported: true,
+ stl: "none",
+ system_shared_libs: [],
+ }
+ cc_library {
+ name: "lib_only_native_bridge",
+ native_bridge_supported: true,
+ enabled: false,
+ target: {
+ native_bridge: {
+ enabled: true,
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+ }
+ `)
+
+ // produces "myfilesystem.img"
+ result.ModuleForTests(t, "myfilesystem", "android_common").Output("myfilesystem.img")
+
+ fs := result.ModuleForTests(t, "myfilesystem", "android_common").Module().(*filesystem)
+ expected := []string{
+ // Non NativeBridge
+ "lib64/lib_no_native_bridge.so",
+ "lib64/lib_both.so",
+ // NativeBridge
+ "lib/arm/lib_both.so",
+ "lib/arm/lib_only_native_bridge.so",
+ "lib64/arm64/lib_both.so",
+ "lib64/arm64/lib_only_native_bridge.so",
+ }
+ for _, e := range expected {
+ android.AssertStringListContains(t, "missing entry", fs.entries, e)
+ }
+}
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index 89da3182a..465bc6073 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -113,6 +113,7 @@ func (f *filesystem) buildFsverityMetadataFiles(
rootDir android.OutputPath,
rebasedDir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
match := func(path string) bool {
for _, pattern := range f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) {
@@ -280,17 +281,20 @@ func (f *filesystem) buildFsverityMetadataFiles(
builder.Command().Text("cp").Input(apkPath).Text(installedApkPath.String())
builder.Command().Text("cp").Input(idsigPath).Text(installedIdsigPath.String())
+ apkFullInstallPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk", apkNameSuffix))
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
SourcePath: apkPath,
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk", apkNameSuffix)),
+ FullInstallPath: apkFullInstallPath,
})
f.appendToEntry(ctx, installedApkPath)
+ idsigFullInstallPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk.idsig", apkNameSuffix))
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
SourcePath: idsigPath,
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk.idsig", apkNameSuffix)),
+ FullInstallPath: idsigFullInstallPath,
})
f.appendToEntry(ctx, installedIdsigPath)
+ *platformGeneratedFiles = append(*platformGeneratedFiles, apkFullInstallPath.String(), idsigFullInstallPath.String())
}
diff --git a/filesystem/recovery_background_pictures.go b/filesystem/recovery_background_pictures.go
new file mode 100644
index 000000000..0d344174d
--- /dev/null
+++ b/filesystem/recovery_background_pictures.go
@@ -0,0 +1,142 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "android/soong/android"
+)
+
+type recoveryBackgroundPictures struct {
+ android.ModuleBase
+ properties recoveryBackgroundPicturesProperties
+}
+
+type recoveryBackgroundPicturesProperties struct {
+ Image_width *int64
+ Fonts []string `android:"path"`
+ Resources []string `android:"path"`
+}
+
+func RecoveryBackgroundPicturesFactory() android.Module {
+ module := &recoveryBackgroundPictures{}
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ module.AddProperties(&module.properties)
+ return module
+}
+
+func (f *recoveryBackgroundPictures) InstallInRoot() bool {
+ return true
+}
+
+var (
+ recoveryBackgroundTextList = []string{
+ "recovery_installing",
+ "recovery_installing_security",
+ "recovery_erasing",
+ "recovery_error",
+ "recovery_no_command",
+ }
+ recoveryWipeDataTextList = []string{
+ "recovery_cancel_wipe_data",
+ "recovery_factory_data_reset",
+ "recovery_try_again",
+ "recovery_wipe_data_menu_header",
+ "recovery_wipe_data_confirmation",
+ }
+)
+
+func (f *recoveryBackgroundPictures) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ rule := android.NewRuleBuilder(pctx, ctx).
+ Sbox(android.PathForModuleOut(ctx, "images"),
+ android.PathForModuleOut(ctx, "gen.sbox.textproto")).
+ SandboxInputs()
+
+ fontDir, resDir := f.assembleFontsAndRes(ctx, rule)
+ var images android.Paths
+ for _, name := range recoveryBackgroundTextList {
+ image := f.addImageGenRule(ctx, rule, fontDir, resDir, name, true)
+ images = append(images, image)
+ }
+ for _, name := range recoveryWipeDataTextList {
+ image := f.addImageGenRule(ctx, rule, fontDir, resDir, name, false)
+ images = append(images, image)
+ }
+
+ rule.Build("recovery_background_images", "recovery_background_images")
+
+ for _, image := range images {
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "res", "images"), image.Base(), image)
+ }
+}
+
+// Copies the fonts and resources to a well known location inside the sandbox.
+// Returns the assembled font and res dir inside the sandbox.
+func (f *recoveryBackgroundPictures) assembleFontsAndRes(ctx android.ModuleContext, rule *android.RuleBuilder) (android.Path, android.Path) {
+ fontDir := android.PathForModuleOut(ctx, "images", "fonts")
+ fonts := android.PathsForModuleSrc(ctx, f.properties.Fonts)
+
+ // Assemble the fonts at root.
+ cmd := rule.Command()
+ cmd.Textf("mkdir -p %s", cmd.PathForInput(fontDir)).
+ Textf("&& cp -t %s", cmd.PathForInput(fontDir))
+ for _, f := range fonts {
+ cmd.Input(f)
+ }
+
+ // Assemeble the res by preserving rel paths.
+ resDir := android.PathForModuleOut(ctx, "images", "res")
+ cmd.Textf("&& mkdir -p %s", cmd.PathForInput(resDir))
+ for _, res := range android.PathsForModuleSrc(ctx, f.properties.Resources) {
+ relDir := filepath.Dir(res.Rel())
+ cmd.Textf("&& mkdir -p %s/%s", cmd.PathForInput(resDir), relDir).
+ Textf("&& cp %s %s/%s", cmd.PathForInput(res), cmd.PathForInput(resDir), relDir).
+ Implicit(res)
+ }
+
+ return fontDir, resDir
+}
+
+// Adds rules to generate recovery images using RecoveryImageGenerator.jar
+// Returns the paths of the generated recovery images.
+func (f *recoveryBackgroundPictures) addImageGenRule(ctx android.ModuleContext,
+ rule *android.RuleBuilder,
+ fontDir android.Path,
+ resDir android.Path,
+ textName string,
+ centerAlign bool) android.WritablePath {
+ out := android.PathForModuleOut(ctx, "images", strings.TrimPrefix(textName, "recovery_")+"_text.png")
+ generator := ctx.Config().HostJavaToolPath(ctx, "RecoveryImageGenerator.jar")
+ cmd := rule.Command()
+ cmd.Textf("java -jar").Input(generator).
+ FlagWithArg("--image_width ", strconv.FormatInt(*(f.properties.Image_width), 10)).
+ FlagWithArg("--text_name ", textName).
+ FlagWithArg("--font_dir ", cmd.PathForInput(fontDir)).
+ FlagWithArg("--resource_dir ", cmd.PathForInput(resDir)).
+ Implicits(android.PathsForModuleSrc(ctx, f.properties.Resources))
+ if centerAlign {
+ cmd.Flag("--center_alignment ")
+ }
+ cmd.FlagWithOutput("--output_file ", out)
+
+ rule.Command().BuiltTool("zopflipng").
+ ImplicitTool(ctx.Config().HostCcSharedLibPath(ctx, "libc++")).
+ Textf(" -y --iterations=1 --filters=0 %s %s > /dev/null", cmd.PathForInput(out), cmd.PathForInput(out))
+
+ return out
+}
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index cf7e125a0..3a0dcd07d 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -240,8 +240,8 @@ func (s *superImage) buildMiscInfo(ctx android.ModuleContext, superEmpty bool) (
missingPartitionErrorMessage += fmt.Sprintf("%s image listed in partition groups, but its module was not specified. ", partitionType)
return
}
- mod := ctx.GetDirectDepWithTag(*name, subImageDepTag)
- if mod == nil {
+ mod := ctx.GetDirectDepProxyWithTag(*name, subImageDepTag)
+ if mod.IsNil() {
ctx.ModuleErrorf("Could not get dep %q", *name)
return
}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index cc9093f9b..166b052f8 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -49,6 +49,7 @@ func (s *systemImage) BuildLinkerConfigFile(
builder *android.RuleBuilder,
rebasedDir android.OutputPath,
fullInstallPaths *[]FullInstallPathInfo,
+ platformGeneratedFiles *[]string,
) {
if !proptools.Bool(s.filesystem.properties.Linker_config.Gen_linker_config) {
return
@@ -61,10 +62,12 @@ func (s *systemImage) BuildLinkerConfigFile(
linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, s.filesystem.properties.Linker_config.Linker_config_srcs), provideModules, requireModules, intermediateOutput)
builder.Command().Text("cp").Input(intermediateOutput).Output(output)
+ installPath := android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb")
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+ FullInstallPath: installPath,
SourcePath: intermediateOutput,
})
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
} else {
// TODO: This branch is the logic that make uses for the linker config file, which is
// different than linkerconfig.BuildLinkerConfig used above. Keeping both branches for now
@@ -98,10 +101,12 @@ func (s *systemImage) BuildLinkerConfigFile(
// TODO: Make also supports adding an extra append command with PRODUCT_EXTRA_STUB_LIBRARIES,
// but that variable appears to have no usages.
+ installPath := android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb")
*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
- FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+ FullInstallPath: installPath,
SourcePath: output,
})
+ *platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
}
s.appendToEntry(ctx, output)
diff --git a/filesystem/system_other.go b/filesystem/system_other.go
index 32a6cc784..14895bd3f 100644
--- a/filesystem/system_other.go
+++ b/filesystem/system_other.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/google/blueprint"
+ "github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
)
@@ -93,7 +94,7 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext
}
output := android.PathForModuleOut(ctx, "system_other.img")
- stagingDir := android.PathForModuleOut(ctx, "staging_dir")
+ stagingDir := android.PathForModuleOut(ctx, "system_other")
stagingDirTimestamp := android.PathForModuleOut(ctx, "staging_dir.timestamp")
builder := android.NewRuleBuilder(pctx, ctx)
@@ -160,29 +161,17 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext
builder.Build("build_system_other", "build system other")
- // Create a hermetic system_other.img with pinned timestamps
- builder = android.NewRuleBuilder(pctx, ctx)
- outputHermetic := android.PathForModuleOut(ctx, "for_target_files", "system_other.img")
- outputHermeticPropFile := m.propFileForHermeticImg(ctx, builder, propFile)
- builder.Command().
- Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
- BuiltTool("build_image").
- Text(stagingDir.String()). // input directory
- Input(outputHermeticPropFile).
- Implicits(systemInfo.BuildImagePropFileDeps).
- Implicit(fec).
- Implicit(stagingDirTimestamp).
- Output(outputHermetic).
- Text(stagingDir.String())
-
- builder.Build("build_system_other_hermetic", "build system other")
-
fsInfo := FilesystemInfo{
Output: output,
- OutputHermetic: outputHermetic,
RootDir: stagingDir,
+ ModuleName: ctx.ModuleName(),
FilesystemConfig: m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp),
PropFileForMiscInfo: m.buildPropFileForMiscInfo(ctx),
+ InstalledFilesDepSet: depset.New(
+ depset.POSTORDER,
+ []InstalledFilesStruct{buildInstalledFiles(ctx, "system-other", stagingDir, output)},
+ nil,
+ ),
}
android.SetProvider(ctx, FilesystemProvider, fsInfo)
@@ -193,6 +182,7 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext
// Dump compliance metadata
complianceMetadataInfo := ctx.ComplianceMetadataInfo()
complianceMetadataInfo.SetFilesContained(fullInstallPaths)
+ complianceMetadataInfo.SetPlatformGeneratedFiles(fullInstallPaths)
}
func (s *systemOtherImage) generateFilesystemConfig(ctx android.ModuleContext, stagingDir, stagingDirTimestamp android.Path) android.Path {
@@ -209,13 +199,6 @@ func (s *systemOtherImage) generateFilesystemConfig(ctx android.ModuleContext, s
return out
}
-func (f *systemOtherImage) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path {
- propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
- builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp).
- Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp)
- return propFilePinnedTimestamp
-}
-
func (f *systemOtherImage) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path {
var lines []string
addStr := func(name string, value string) {
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index e7a39bef7..c71fbb791 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -16,6 +16,7 @@ package filesystem
import (
"fmt"
+ "slices"
"sort"
"strconv"
"strings"
@@ -177,6 +178,30 @@ func (v *vbmeta) partitionName() string {
// See external/avb/libavb/avb_slot_verify.c#VBMETA_MAX_SIZE
const vbmetaMaxSize = 64 * 1024
+// This is the order that make listed the partitions in. The order is important because
+// it ends up being encoded in the output file. Maintain the order so that the resultant
+// files are easier to compare.
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4833;drc=a951ebf0198006f7fd38073a05c442d0eb92f97b
+var includeDescriptorsFromImgOrder = []string{
+ "boot",
+ "init_boot",
+ "vendor_boot",
+ "vendor_kernel_boot",
+ "system",
+ "vendor",
+ "product",
+ "system_ext",
+ "odm",
+ "vendor_dlkm",
+ "odm_dlkm",
+ "system_dlkm",
+ "dtbo",
+ "pvmfw",
+ "recovery",
+ "vbmeta_system",
+ "vbmeta_vendor",
+}
+
func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) {
builder := android.NewRuleBuilder(pctx, ctx)
cmd := builder.Command().BuiltTool("avbtool").Text("make_vbmeta_image")
@@ -210,24 +235,56 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.FlagWithArg("--prop ", key+":"+value)
}
- for _, p := range ctx.GetDirectDepsWithTag(vbmetaPartitionDep) {
- f, ok := p.(Filesystem)
- if !ok {
- ctx.PropertyErrorf("partitions", "%q(type: %s) is not supported",
- p.Name(), ctx.OtherModuleType(p))
+ type partitionWithName struct {
+ Name string
+ Output android.Path
+ }
+ var includeDescriptorsFromImages []partitionWithName
+ for _, p := range ctx.GetDirectDepsProxyWithTag(vbmetaPartitionDep) {
+ bootImgInfo, ok := android.OtherModuleProvider(ctx, p, BootimgInfoProvider)
+ if ok {
+ includeDescriptorsFromImages = append(includeDescriptorsFromImages, partitionWithName{
+ Name: bootImgInfo.Type.String(),
+ Output: bootImgInfo.SignedOutput,
+ })
continue
}
- signedImage := f.SignedOutputPath()
- if signedImage == nil {
- ctx.PropertyErrorf("partitions", "%q(type: %s) is not signed. Use `use_avb: true`",
+
+ fsInfo, ok := android.OtherModuleProvider(ctx, p, FilesystemProvider)
+ if !ok {
+ ctx.PropertyErrorf("partitions", "%q(type: %s) is not supported, must be a filesystem",
p.Name(), ctx.OtherModuleType(p))
continue
}
- cmd.FlagWithInput("--include_descriptors_from_image ", signedImage)
+ includeDescriptorsFromImages = append(includeDescriptorsFromImages, partitionWithName{
+ Name: fsInfo.PartitionName,
+ Output: fsInfo.SignedOutputPath,
+ })
+ }
+
+ sort.SliceStable(includeDescriptorsFromImages, func(i, j int) bool {
+ iName := includeDescriptorsFromImages[i].Name
+ jName := includeDescriptorsFromImages[j].Name
+ iIndex := slices.Index(includeDescriptorsFromImgOrder, iName)
+ jIndex := slices.Index(includeDescriptorsFromImgOrder, jName)
+ if iIndex < 0 && jIndex < 0 {
+ return iName < jName
+ }
+ if iIndex < 0 {
+ return false
+ }
+ if jIndex < 0 {
+ return true
+ }
+ return iIndex < jIndex
+ })
+
+ for _, partition := range includeDescriptorsFromImages {
+ cmd.FlagWithInput("--include_descriptors_from_image ", partition.Output)
}
seenRils := make(map[int]bool)
- for _, cp := range ctx.GetDirectDepsWithTag(vbmetaChainedPartitionDep) {
+ for _, cp := range ctx.GetDirectDepsProxyWithTag(vbmetaChainedPartitionDep) {
info, ok := android.OtherModuleProvider(ctx, cp, vbmetaPartitionProvider)
if !ok {
ctx.PropertyErrorf("chained_partitions", "Expected all modules in chained_partitions to provide vbmetaPartitionProvider, but %s did not", cp.Name())
diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go
index 0ba0a90dd..02256c16f 100644
--- a/fsgen/boot_imgs.go
+++ b/fsgen/boot_imgs.go
@@ -181,7 +181,7 @@ func createInitBootImage(ctx android.LoadHookContext) bool {
&filesystem.BootimgProperties{
Boot_image_type: proptools.StringPtr("init_boot"),
Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")),
- Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
+ Header_version: proptools.StringPtr(partitionVariables.BoardInitBootHeaderVersion),
Security_patch: securityPatch,
Partition_size: partitionSize,
Use_avb: avbInfo.avbEnable,
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 14aa062fc..8b4856c7d 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -144,17 +144,37 @@ func filesystemCreatorFactory() android.Module {
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
module.AddProperties(&module.properties)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ if !shouldEnableFilesystemCreator(ctx) {
+ return
+ }
generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx)
- avbpubkeyGenerated := createAvbpubkeyModule(ctx)
- createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated)
+ createAvbpubkeyModule(ctx)
+ createFsGenState(ctx, generatedPrebuiltEtcModuleNames)
module.createAvbKeyFilegroups(ctx)
module.createMiscFilegroups(ctx)
module.createInternalModules(ctx)
+ module.createBackgroundPicturesForRecovery(ctx)
})
return module
}
+func shouldEnableFilesystemCreator(ctx android.ConfigContext) bool {
+ if ctx.Config().HasUnbundledBuildApps() || ctx.Config().UnbundledBuild() {
+ // unbundled builds don't build a device. The android_device's dist artifacts
+ // would conflict with the dist artifacts from the unbundled singleton.
+ return false
+ }
+ // We create the filsystem modules even if soong-only mode isn't enabled, so we at least
+ // get analysis time checks running everywhere for more real-world coverage.
+ return true
+}
+
+// This is a build process. It must read all configuration values.
+func (f *filesystemCreator) UseGenericConfig() bool {
+ return false
+}
+
func generatedPartitions(ctx android.EarlyModuleContext) allGeneratedPartitionData {
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
@@ -419,16 +439,17 @@ func (f *filesystemCreator) createDeviceModule(
partitionProps.Vbmeta_partitions = vbmetaPartitions
deviceProps := &filesystem.DeviceProperties{
- Main_device: proptools.BoolPtr(true),
- Ab_ota_updater: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater),
- Ab_ota_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions,
- Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
- Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"),
- Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
- Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion,
- Partial_ota_update_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardPartialOtaUpdatePartitionsList,
- Flash_block_size: proptools.StringPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFlashBlockSize),
- Bootloader_in_update_package: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BootloaderInUpdatePackage),
+ Main_device: proptools.BoolPtr(true),
+ Ab_ota_updater: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater),
+ Ab_ota_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions,
+ Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
+ Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"),
+ Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
+ Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion,
+ Partial_ota_update_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardPartialOtaUpdatePartitionsList,
+ Flash_block_size: proptools.StringPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFlashBlockSize),
+ Bootloader_in_update_package: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BootloaderInUpdatePackage),
+ Precompiled_sepolicy_without_vendor: proptools.StringPtr(":precompiled_sepolicy_without_vendor"),
}
if bootloader, ok := f.createBootloaderFilegroup(ctx); ok {
@@ -451,6 +472,7 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene
fsProps.Build_logtags = proptools.BoolPtr(true)
// https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ fsProps.Check_vintf = proptools.BoolPtr(true)
// Identical to that of the aosp_shared_system_image
if partitionVars.ProductFsverityGenerateMetadata {
fsProps.Fsverity.Inputs = proptools.NewSimpleConfigurable([]string{
@@ -475,24 +497,41 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene
Target: proptools.StringPtr("/storage/self/primary"),
Name: proptools.StringPtr("sdcard"),
},
- {
- Target: proptools.StringPtr("/system_dlkm/lib/modules"),
- Name: proptools.StringPtr("system/lib/modules"),
+ }...,
+ )
+ if ctx.DeviceConfig().VendorPath() == "vendor" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("/vendor"),
+ Name: proptools.StringPtr("system/vendor"),
},
- {
+ )
+ }
+ if ctx.DeviceConfig().ProductPath() == "product" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
Target: proptools.StringPtr("/product"),
Name: proptools.StringPtr("system/product"),
},
- {
+ )
+ }
+ if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
Target: proptools.StringPtr("/system_ext"),
Name: proptools.StringPtr("system/system_ext"),
},
- {
- Target: proptools.StringPtr("/vendor"),
- Name: proptools.StringPtr("system/vendor"),
+ )
+ }
+ if ctx.DeviceConfig().SystemDlkmPath() == "system_dlkm" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("/system_dlkm/lib/modules"),
+ Name: proptools.StringPtr("system/lib/modules"),
},
- }...,
- )
+ )
+ }
+
fsProps.Base_dir = proptools.StringPtr("system")
fsProps.Dirs = proptools.NewSimpleConfigurable(commonPartitionDirs)
fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
@@ -519,28 +558,40 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene
fsProps.Stem = proptools.StringPtr("product.img")
case "vendor":
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/odm"),
- Name: proptools.StringPtr("odm"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor_dlkm/lib/modules"),
- Name: proptools.StringPtr("lib/modules"),
- },
+ fsProps.Check_vintf = proptools.BoolPtr(true)
+ if ctx.DeviceConfig().OdmPath() == "odm" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("/odm"),
+ Name: proptools.StringPtr("odm"),
+ },
+ )
+ }
+ if ctx.DeviceConfig().VendorDlkmPath() == "vendor_dlkm" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("/vendor_dlkm/lib/modules"),
+ Name: proptools.StringPtr("lib/modules"),
+ },
+ )
}
fsProps.Android_filesystem_deps.System = proptools.StringPtr(partitions.nameForType("system"))
if systemExtName := partitions.nameForType("system_ext"); systemExtName != "" {
fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(systemExtName)
}
+ if productName := partitions.nameForType("product"); productName != "" {
+ fsProps.Android_filesystem_deps.Product = proptools.StringPtr(productName)
+ }
fsProps.Security_patch = proptools.StringPtr(partitionVars.VendorSecurityPatch)
fsProps.Stem = proptools.StringPtr("vendor.img")
case "odm":
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/odm_dlkm/lib/modules"),
- Name: proptools.StringPtr("lib/modules"),
- },
+ if ctx.DeviceConfig().OdmDlkmPath() == "odm_dlkm" {
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("/odm_dlkm/lib/modules"),
+ Name: proptools.StringPtr("lib/modules"),
+ },
+ )
}
fsProps.Security_patch = proptools.StringPtr(partitionVars.OdmSecurityPatch)
fsProps.Stem = proptools.StringPtr("odm.img")
@@ -643,7 +694,7 @@ func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partiti
return
}
- baseProps := generateBaseProps(proptools.StringPtr(partition.moduleName))
+ baseProps := generateBaseProps(proptools.StringPtr(partition.moduleName), ctx.Config())
fsProps, supported := generateFsProps(ctx, partitions, partition.partitionType)
if !supported {
@@ -722,6 +773,30 @@ func (f *filesystemCreator) createAvbKeyFilegroups(ctx android.LoadHookContext)
}
}
+func (f *filesystemCreator) createBackgroundPicturesForRecovery(ctx android.LoadHookContext) {
+ name, width := getRecoveryBackgroundPicturesGeneratorModuleName(ctx)
+ if name == "" {
+ return
+ }
+ ctx.CreateModule(
+ filesystem.RecoveryBackgroundPicturesFactory,
+ &struct {
+ Name *string
+ Image_width *int64
+ Fonts []string
+ Resources []string
+ Recovery *bool
+ }{
+ Name: proptools.StringPtr(name),
+ Image_width: proptools.Int64Ptr(width),
+ Fonts: []string{":recovery_noto-fonts_dep", ":recovery_roboto-fonts_dep"},
+ Resources: []string{":bootable_recovery_resources"},
+ Recovery: proptools.BoolPtr(true),
+ },
+ )
+
+}
+
// Creates filegroups for miscellaneous other files
func (f *filesystemCreator) createMiscFilegroups(ctx android.LoadHookContext) {
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
@@ -751,9 +826,11 @@ func (f *filesystemCreator) createMiscFilegroups(ctx android.LoadHookContext) {
func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookContext, partitionType string) {
fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
name := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-kernel-modules", partitionType))
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
props := &struct {
Name *string
Srcs []string
+ Srcs_16k []string
System_deps []string
System_dlkm_specific *bool
Vendor_dlkm_specific *bool
@@ -764,45 +841,53 @@ func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookCont
Options_file *string
Strip_debug_symbols *bool
}{
- Name: proptools.StringPtr(name),
- Strip_debug_symbols: proptools.BoolPtr(false),
+ Name: proptools.StringPtr(name),
}
switch partitionType {
case "system_dlkm":
- props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules).Strings()
+ props.Srcs = android.ExistentPathsForSources(ctx, partitionVars.SystemKernelModules).Strings()
props.System_dlkm_specific = proptools.BoolPtr(true)
- if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelLoadModules) == 0 {
+ if len(partitionVars.SystemKernelLoadModules) == 0 {
// Create empty modules.load file for system
// https://source.corp.google.com/h/googleplex-android/platform/build/+/ef55daac9954896161b26db4f3ef1781b5a5694c:core/Makefile;l=695-700;drc=549fe2a5162548bd8b47867d35f907eb22332023;bpv=1;bpt=0
props.Load_by_default = proptools.BoolPtr(false)
}
- if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelBlocklistFile; blocklistFile != "" {
+ if blocklistFile := partitionVars.SystemKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
case "vendor_dlkm":
- props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules).Strings()
- if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 {
+ props.Srcs = android.ExistentPathsForSources(ctx, partitionVars.VendorKernelModules).Strings()
+ props.Srcs_16k = android.ExistentPathsForSources(ctx, partitionVars.VendorKernelModules2ndStage16kbMode).Strings()
+ if len(partitionVars.SystemKernelModules) > 0 {
props.System_deps = []string{":" + generatedModuleName(ctx.Config(), "system_dlkm-kernel-modules") + "{.modules}"}
}
props.Vendor_dlkm_specific = proptools.BoolPtr(true)
- if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelBlocklistFile; blocklistFile != "" {
+ if blocklistFile := partitionVars.VendorKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ if partitionVars.DoNotStripVendorModules {
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
+ }
case "odm_dlkm":
- props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules).Strings()
+ props.Srcs = android.ExistentPathsForSources(ctx, partitionVars.OdmKernelModules).Strings()
props.Odm_dlkm_specific = proptools.BoolPtr(true)
- if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" {
+ if blocklistFile := partitionVars.OdmKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
case "vendor_ramdisk":
- props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelModules).Strings()
+ props.Srcs = android.ExistentPathsForSources(ctx, partitionVars.VendorRamdiskKernelModules).Strings()
props.Vendor_ramdisk = proptools.BoolPtr(true)
- if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelBlocklistFile; blocklistFile != "" {
+ if blocklistFile := partitionVars.VendorRamdiskKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
- if optionsFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelOptionsFile; optionsFile != "" {
+ if optionsFile := partitionVars.VendorRamdiskKernelOptionsFile; optionsFile != "" {
props.Options_file = proptools.StringPtr(optionsFile)
}
+ if partitionVars.DoNotStripVendorRamdiskModules {
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
+ }
default:
ctx.ModuleErrorf("DLKM is not supported for %s\n", partitionType)
@@ -962,15 +1047,17 @@ func (f *filesystemCreator) createLinkerConfigSourceFilegroups(ctx android.LoadH
}
type filesystemBaseProperty struct {
- Name *string
- Compile_multilib *string
- Visibility []string
+ Name *string
+ Compile_multilib *string
+ Native_bridge_supported *bool
+ Visibility []string
}
-func generateBaseProps(namePtr *string) *filesystemBaseProperty {
+func generateBaseProps(namePtr *string, config android.Config) *filesystemBaseProperty {
return &filesystemBaseProperty{
- Name: namePtr,
- Compile_multilib: proptools.StringPtr("both"),
+ Name: namePtr,
+ Compile_multilib: proptools.StringPtr("both"),
+ Native_bridge_supported: proptools.BoolPtr(config.ProductVariables().NativeBridgeArch != nil),
// The vbmeta modules are currently in the root directory and depend on the partitions
Visibility: []string{"//.", "//build/soong:__subpackages__"},
}
@@ -1125,7 +1212,7 @@ func getAvbInfo(config android.Config, partitionType string) avbInfo {
}
func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string, partitionModuleName string) android.Path {
- partitionImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
+ partitionImage := ctx.GetDirectDepProxyWithTag(partitionModuleName, generatedFilesystemDepTag)
filesystemInfo, ok := android.OtherModuleProvider(ctx, partitionImage, filesystem.FilesystemProvider)
if !ok {
ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName)
@@ -1157,7 +1244,7 @@ func createFailingCommand(ctx android.ModuleContext, message string) android.Pat
}
func createVbmetaDiff(ctx android.ModuleContext, vbmetaModuleName string, vbmetaPartitionName string) android.Path {
- vbmetaModule := ctx.GetDirectDepWithTag(vbmetaModuleName, generatedVbmetaPartitionDepTag)
+ vbmetaModule := ctx.GetDirectDepProxyWithTag(vbmetaModuleName, generatedVbmetaPartitionDepTag)
outputFilesProvider, ok := android.OtherModuleProvider(ctx, vbmetaModule, android.OutputFilesProvider)
if !ok {
ctx.ModuleErrorf("Expected module %s to provide OutputFiles", vbmetaModule)
@@ -1190,6 +1277,9 @@ var generatedFilesystemDepTag imageDepTagType
var generatedVbmetaPartitionDepTag imageDepTagType
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if !shouldEnableFilesystemCreator(ctx) {
+ return
+ }
for _, name := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions.names() {
ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, name)
}
@@ -1199,6 +1289,9 @@ func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if !shouldEnableFilesystemCreator(ctx) {
+ return
+ }
if ctx.ModuleDir() != "build/soong/fsgen" {
ctx.ModuleErrorf("There can only be one soong_filesystem_creator in build/soong/fsgen")
}
@@ -1278,7 +1371,7 @@ func generateBpContent(ctx android.EarlyModuleContext, partitionType string) str
return ""
}
- baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
+ baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)), ctx.Config())
deps := fsGenState.fsDeps[partitionType]
highPriorityDeps := fsGenState.generatedPrebuiltEtcModuleNames
depProps := generateDepStruct(*deps, highPriorityDeps)
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 2c4d3c817..6674dfe4f 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -22,6 +22,7 @@ import (
"android/soong/etc"
"android/soong/filesystem"
"android/soong/java"
+ "android/soong/phony"
"github.com/google/blueprint/proptools"
)
@@ -252,7 +253,7 @@ func TestRemoveOverriddenModulesFromDeps(t *testing.T) {
`),
}),
android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"libfoo", "libbar"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"libfoo", "libbar", "prebuiltA", "prebuiltB"}
}),
).RunTestWithBp(t, `
java_library {
@@ -266,10 +267,19 @@ java_library {
name: "libbaz",
overrides: ["libfoo"], // overrides libfoo
}
+java_import {
+ name: "prebuiltA",
+}
+java_import {
+ name: "prebuiltB",
+ overrides: ["prebuiltA"], // overrides prebuiltA
+}
`)
resolvedSystemDeps := result.TestContext.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps["system"]
_, libFooInDeps := (*resolvedSystemDeps)["libfoo"]
android.AssertBoolEquals(t, "libfoo should not appear in deps because it has been overridden by libbaz. The latter is a required dep of libbar, which is listed in PRODUCT_PACKAGES", false, libFooInDeps)
+ _, prebuiltAInDeps := (*resolvedSystemDeps)["prebuiltA"]
+ android.AssertBoolEquals(t, "prebuiltA should not appear in deps because it has been overridden by prebuiltB. The latter is listed in PRODUCT_PACKAGES", false, prebuiltAInDeps)
}
func TestPrebuiltEtcModuleGen(t *testing.T) {
@@ -660,3 +670,125 @@ func TestPrebuiltEtcModuleGen(t *testing.T) {
}),
)
}
+
+func TestPartitionOfOverrideModules(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ prepareMockRamdiksNodeList,
+ android.PrepareForTestWithNamespace,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }`),
+ "mynamespace/Android.bp": []byte(`
+ soong_namespace{
+ }
+ android_app {
+ name: "system_ext_app_in_namespace",
+ system_ext_specific: true,
+ platform_apis: true,
+ }`),
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.NamespacesToExport = []string{"mynamespace"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"system_ext_override_app", "system_ext_override_app_in_namespace"}
+ }),
+ ).RunTestWithBp(t, `
+android_app {
+ name: "system_ext_app",
+ system_ext_specific: true,
+ platform_apis: true,
+}
+override_android_app {
+ name: "system_ext_override_app",
+ base: "system_ext_app",
+}
+override_android_app {
+ name: "system_ext_override_app_in_namespace",
+ base: "//mynamespace:system_ext_app_in_namespace",
+}
+`)
+ resolvedDeps := result.TestContext.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps["system_ext"]
+ _, overrideAppInSystemExt := (*resolvedDeps)["system_ext_override_app"]
+ android.AssertBoolEquals(t, "Override app should be added to the same partition as the `base`", true, overrideAppInSystemExt)
+ _, overrideAppInSystemExt = (*resolvedDeps)["system_ext_override_app_in_namespace"]
+ android.AssertBoolEquals(t, "Override app should be added to the same partition as the `base`", true, overrideAppInSystemExt)
+}
+
+func TestCrossPartitionRequiredModules(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ prepareMockRamdiksNodeList,
+ android.PrepareForTestWithNamespace,
+ phony.PrepareForTestWithPhony,
+ etc.PrepareForTestWithPrebuiltEtc,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "mynamespace/default-permissions.xml": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }`),
+ "mynamespace/Android.bp": []byte(`
+ soong_namespace{
+ }
+ android_app {
+ name: "some_app_in_namespace",
+ product_specific: true,
+ required: ["some-permissions"],
+ platform_apis: true,
+ }
+ prebuilt_etc {
+ name: "some-permissions",
+ sub_dir: "default-permissions",
+ src: "default-permissions.xml",
+ filename_from_src: true,
+ system_ext_specific: true,
+ }
+`),
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.NamespacesToExport = []string{"mynamespace"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"some_app_in_namespace"}
+ }),
+ ).RunTestWithBp(t, `
+ phony {
+ name: "com.android.vndk.v34",
+ }
+ phony {
+ name: "com.android.vndk.v33",
+ }
+ phony {
+ name: "com.android.vndk.v32",
+ }
+ phony {
+ name: "com.android.vndk.v31",
+ }
+ phony {
+ name: "com.android.vndk.v30",
+ }
+ phony {
+ name: "file_contexts_bin_gen",
+ }
+ phony {
+ name: "notice_xml_system_ext",
+ }
+ `)
+ systemExtFilesystemModule := result.ModuleForTests(t, "test_product_generated_system_ext_image", "android_common")
+ systemExtStagingDirImplicitDeps := systemExtFilesystemModule.Output("staging_dir.timestamp").Implicits
+ android.AssertStringDoesContain(t,
+ "system_ext staging dir expected to contain cross partition require deps",
+ strings.Join(systemExtStagingDirImplicitDeps.Strings(), " "),
+ "mynamespace/some-permissions/android_arm64_armv8-a/default-permissions.xml",
+ )
+}
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index 4f3d2a750..50266801f 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -27,11 +27,14 @@ import (
func RegisterCollectFileSystemDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("fs_collect_deps", collectDepsMutator).MutatesGlobalState()
+ ctx.BottomUp("fs_remove_deps", removeDepsMutator).MutatesGlobalState()
+ ctx.BottomUp("fs_cross_partition_required_deps", crossPartitionRequiredMutator).MutatesGlobalState()
ctx.BottomUp("fs_set_deps", setDepsMutator)
}
var fsGenStateOnceKey = android.NewOnceKey("FsGenState")
var fsGenRemoveOverridesOnceKey = android.NewOnceKey("FsGenRemoveOverrides")
+var fsGenCrossPartitionRequiredDepsOnceKey = android.NewOnceKey("FsGenCrossPartitionRequiredDeps")
// Map of partition module name to its partition that may be generated by Soong.
// Note that it is not guaranteed that all modules returned by this function are successfully
@@ -45,53 +48,130 @@ func getAllSoongGeneratedPartitionNames(config android.Config, partitions []stri
}
type depCandidateProps struct {
- Namespace string
- Multilib string
- Arch []android.ArchType
+ Namespace string
+ Multilib string
+ Arch []android.ArchType
+ NativeBridgeSupport map[android.NativeBridgeSupport]bool
}
// Map of module name to depCandidateProps
type multilibDeps map[string]*depCandidateProps
+func (m *multilibDeps) SortedFullyQualifiedNames() []string {
+ ret := make([]string, len(*m))
+ i := 0
+ for moduleName, props := range *m {
+ ret[i] = fullyQualifiedModuleName(moduleName, props.Namespace)
+ i += 1
+ }
+ return android.SortedUniqueStrings(ret)
+}
+
+type moduleToInstallationProps struct {
+ // Map of _all_ soong module names to their corresponding installation properties
+ // Should not be accessed directly to add entries; Use AddToMap instead.
+ moduleToPropsMap map[string]installationProperties
+}
+
+func (m *moduleToInstallationProps) AddToMap(ctx android.BottomUpMutatorContext, prop *installationProperties) {
+ m.moduleToPropsMap[fullyQualifiedModuleName(ctx.ModuleName(), ctx.Namespace().Path)] = *prop
+}
+
+func (m *moduleToInstallationProps) Get(ctx android.BottomUpMutatorContext) (installationProperties, bool) {
+ return m.GetFromFullyQualifiedModuleName(fullyQualifiedModuleName(ctx.ModuleName(), ctx.Namespace().Path))
+}
+
+func (m *moduleToInstallationProps) GetFromFullyQualifiedModuleName(name string) (installationProperties, bool) {
+ prop, ok := m.moduleToPropsMap[name]
+ if ok {
+ return prop, ok
+ }
+ return installationProperties{}, ok
+}
+
+func (m *moduleToInstallationProps) SortedKeys() []string {
+ return android.SortedKeys(m.moduleToPropsMap)
+}
+
// Information necessary to generate the filesystem modules, including details about their
// dependencies
type FsGenState struct {
// List of modules in `PRODUCT_PACKAGES` and `PRODUCT_PACKAGES_DEBUG`
- depCandidates []string
+ depCandidatesMap map[string]bool
// Map of names of partition to the information of modules to be added as deps
fsDeps map[string]*multilibDeps
// Information about the main soong-generated partitions
soongGeneratedPartitions allGeneratedPartitionData
// Mutex to protect the fsDeps
fsDepsMutex sync.Mutex
- // Map of _all_ soong module names to their corresponding installation properties
- moduleToInstallationProps map[string]installationProperties
+
+ moduleToInstallationProps moduleToInstallationProps
// List of prebuilt_* modules that are autogenerated.
generatedPrebuiltEtcModuleNames []string
// Mapping from a path to an avb key to the name of a filegroup module that contains it
avbKeyFilegroups map[string]string
+ // Name of all native bridge modules
+ nativeBridgeModules map[string]bool
}
type installationProperties struct {
Required []string
Overrides []string
+ Partition string
+ Namespace string
}
func defaultDepCandidateProps(config android.Config) *depCandidateProps {
return &depCandidateProps{
- Namespace: ".",
- Arch: []android.ArchType{config.BuildArch},
+ Namespace: ".",
+ Arch: []android.ArchType{config.DevicePrimaryArchType()},
+ NativeBridgeSupport: map[android.NativeBridgeSupport]bool{android.NativeBridgeDisabled: true},
}
}
-func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string, avbpubkeyGenerated bool) *FsGenState {
- return ctx.Config().Once(fsGenStateOnceKey, func() interface{} {
- partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
- candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug))
- candidates = android.Concat(candidates, generatedPrebuiltEtcModuleNames)
+func productInstalledModules(ctx android.LoadHookContext) []string {
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ allInstalledModules := partitionVars.ProductPackages
+ if ctx.Config().Debuggable() {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesDebug...)
+ if ctx.Config().Eng() {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesEng...)
+ }
+ if android.InList("address", ctx.Config().SanitizeDevice()) {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesDebugAsan...)
+ }
+ if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesDebugJavaCoverage...)
+ }
+ }
+ if android.InList("arm64", []string{ctx.DeviceConfig().DeviceArch(), ctx.DeviceConfig().DeviceSecondaryArch()}) {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesArm64...)
+ }
+ if android.UncheckedFinalApiLevel(29).GreaterThanOrEqualTo(ctx.DeviceConfig().ShippingApiLevel()) {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesShippingApiLevel29...)
+ }
+ if android.UncheckedFinalApiLevel(33).GreaterThanOrEqualTo(ctx.DeviceConfig().ShippingApiLevel()) {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesShippingApiLevel33...)
+ }
+ if android.UncheckedFinalApiLevel(34).GreaterThanOrEqualTo(ctx.DeviceConfig().ShippingApiLevel()) {
+ allInstalledModules = append(allInstalledModules, partitionVars.ProductPackagesShippingApiLevel34...)
+ }
+ return allInstalledModules
+}
+
+func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string) *FsGenState {
+ return ctx.Config().Once(fsGenStateOnceKey, func() interface{} {
+ allInstalledModules := slices.Concat(
+ productInstalledModules(ctx),
+ generatedPrebuiltEtcModuleNames,
+ )
+ candidatesMap := map[string]bool{}
+ for _, candidate := range allInstalledModules {
+ candidatesMap[candidate] = true
+ }
fsGenState := FsGenState{
- depCandidates: candidates,
+ depCandidatesMap: candidatesMap,
fsDeps: map[string]*multilibDeps{
// These additional deps are added according to the cuttlefish system image bp.
"system": {
@@ -100,7 +180,6 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam
"dex_bootjars": defaultDepCandidateProps(ctx.Config()),
"framework_compatibility_matrix.device.xml": defaultDepCandidateProps(ctx.Config()),
"init.environ.rc-soong": defaultDepCandidateProps(ctx.Config()),
- "libcompiler_rt": defaultDepCandidateProps(ctx.Config()),
"libdmabufheap": defaultDepCandidateProps(ctx.Config()),
"libgsi": defaultDepCandidateProps(ctx.Config()),
"llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()),
@@ -126,14 +205,6 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam
"notice_xml_product": defaultDepCandidateProps(ctx.Config()),
},
"system_ext": {
- // VNDK apexes are automatically included.
- // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated.
- // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7
- "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()),
"notice_xml_system_ext": defaultDepCandidateProps(ctx.Config()),
},
"userdata": {},
@@ -178,14 +249,13 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam
},
},
fsDepsMutex: sync.Mutex{},
- moduleToInstallationProps: map[string]installationProperties{},
+ moduleToInstallationProps: moduleToInstallationProps{moduleToPropsMap: map[string]installationProperties{}},
generatedPrebuiltEtcModuleNames: generatedPrebuiltEtcModuleNames,
avbKeyFilegroups: map[string]string{},
+ nativeBridgeModules: map[string]bool{},
}
- if avbpubkeyGenerated {
- (*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config())
- }
+ (*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config())
if len(ctx.Config().DeviceManifestFiles()) > 0 {
(*fsGenState.fsDeps["vendor"])["vendor_manifest.xml"] = defaultDepCandidateProps(ctx.Config())
@@ -195,6 +265,22 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam
(*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config())
(*fsGenState.fsDeps["recovery"])[getRecoveryFontModuleName(ctx)] = defaultDepCandidateProps(ctx.Config())
(*fsGenState.fsDeps["recovery"])[createRecoveryBuildProp(ctx)] = defaultDepCandidateProps(ctx.Config())
+ if name, _ := getRecoveryBackgroundPicturesGeneratorModuleName(ctx); name != "" {
+ (*fsGenState.fsDeps["recovery"])[name] = defaultDepCandidateProps(ctx.Config())
+ }
+ if name := createTargetRecoveryWipeModuleName(ctx); name != "" {
+ (*fsGenState.fsDeps["recovery"])[name] = defaultDepCandidateProps(ctx.Config())
+ }
+
+ // VNDK APEXes are deprecated and are not supported and disabled for riscv64 arch.
+ // Adding these modules as deps of the auto generated riscv64 arch filesystem modules
+ // leads to execution time build error, thus do not add them as deps when building
+ // riscv64 arch product.
+ if ctx.Config().DevicePrimaryArchType() != android.Riscv64 {
+ for _, vndkVersion := range ctx.DeviceConfig().ExtraVndkVersions() {
+ (*fsGenState.fsDeps["system_ext"])["com.android.vndk.v"+vndkVersion] = defaultDepCandidateProps(ctx.Config())
+ }
+ }
return &fsGenState
}).(*FsGenState)
@@ -207,8 +293,7 @@ func checkDepModuleInMultipleNamespaces(mctx android.BottomUpMutatorContext, fou
}
}
-func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *multilibDeps, installPartition string) {
- moduleName := mctx.ModuleName()
+func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *multilibDeps, installPartition string, nbs android.NativeBridgeSupport, moduleName string) {
checkDepModuleInMultipleNamespaces(mctx, *deps, moduleName, installPartition)
if _, ok := (*deps)[moduleName]; ok {
// Prefer the namespace-specific module over the platform module
@@ -216,17 +301,22 @@ func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *multilibD
(*deps)[moduleName].Namespace = mctx.Namespace().Path
}
(*deps)[moduleName].Arch = append((*deps)[moduleName].Arch, mctx.Module().Target().Arch.ArchType)
+ (*deps)[moduleName].NativeBridgeSupport[nbs] = true
} else {
multilib, _ := mctx.Module().DecodeMultilib(mctx)
(*deps)[moduleName] = &depCandidateProps{
- Namespace: mctx.Namespace().Path,
- Multilib: multilib,
- Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType},
+ Namespace: mctx.Namespace().Path,
+ Multilib: multilib,
+ Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType},
+ NativeBridgeSupport: map[android.NativeBridgeSupport]bool{nbs: true},
}
}
}
func collectDepsMutator(mctx android.BottomUpMutatorContext) {
+ if !shouldEnableFilesystemCreator(mctx) {
+ return
+ }
m := mctx.Module()
if m.Target().Os.Class != android.Device {
return
@@ -236,22 +326,41 @@ func collectDepsMutator(mctx android.BottomUpMutatorContext) {
fsGenState.fsDepsMutex.Lock()
defer fsGenState.fsDepsMutex.Unlock()
- if slices.Contains(fsGenState.depCandidates, mctx.ModuleName()) {
+ if _, ok := fsGenState.depCandidatesMap[mctx.ModuleName()]; ok {
installPartition := m.PartitionTag(mctx.DeviceConfig())
// Only add the module as dependency when:
// - its enabled
// - its namespace is included in PRODUCT_SOONG_NAMESPACES
if m.Enabled(mctx) && m.ExportedToMake() {
- appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition)
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition, android.NativeBridgeDisabled, mctx.ModuleName())
+ }
+ }
+
+ if _, ok := fsGenState.depCandidatesMap[mctx.ModuleName()+".native_bridge"]; ok {
+ installPartition := m.PartitionTag(mctx.DeviceConfig())
+ if m.Enabled(mctx) && m.ExportedToMake() {
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition, android.NativeBridgeEnabled, mctx.ModuleName())
+ }
+ } else if _, ok := fsGenState.depCandidatesMap[mctx.ModuleName()+".bootstrap.native_bridge"]; ok {
+ installPartition := m.PartitionTag(mctx.DeviceConfig())
+ if m.Enabled(mctx) && m.ExportedToMake() {
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition, android.NativeBridgeEnabled, mctx.ModuleName())
}
}
+
// store the map of module to (required,overrides) even if the module is not in PRODUCT_PACKAGES.
// the module might be installed transitively.
if m.Enabled(mctx) && m.ExportedToMake() {
- fsGenState.moduleToInstallationProps[m.Name()] = installationProperties{
+ fsGenState.moduleToInstallationProps.AddToMap(mctx, &installationProperties{
Required: m.RequiredModuleNames(mctx),
Overrides: m.Overrides(),
- }
+ Partition: m.PartitionTag(mctx.DeviceConfig()),
+ Namespace: mctx.Namespace().Path,
+ })
+ }
+
+ if mctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ fsGenState.nativeBridgeModules[mctx.ModuleName()] = true
}
}
@@ -260,11 +369,12 @@ type depsStruct struct {
}
type multilibDepsStruct struct {
- Common depsStruct
- Lib32 depsStruct
- Lib64 depsStruct
- Both depsStruct
- Prefer32 depsStruct
+ Common depsStruct
+ Lib32 depsStruct
+ Lib64 depsStruct
+ Both depsStruct
+ Prefer32 depsStruct
+ Native_bridge depsStruct
}
type packagingPropsStruct struct {
@@ -291,7 +401,34 @@ func getBitness(archTypes []android.ArchType) (ret []string) {
return ret
}
+func removeDepsMutator(mctx android.BottomUpMutatorContext) {
+ if !shouldEnableFilesystemCreator(mctx) {
+ return
+ }
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsGenState.fsDepsMutex.Lock()
+ defer fsGenState.fsDepsMutex.Unlock()
+ updatePartitionsOfOverrideModules(mctx)
+}
+
+func crossPartitionRequiredMutator(mctx android.BottomUpMutatorContext) {
+ if !shouldEnableFilesystemCreator(mctx) {
+ return
+ }
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsGenState.fsDepsMutex.Lock()
+ defer fsGenState.fsDepsMutex.Unlock()
+ additionalCrossPartitionRequiredDeps := correctCrossPartitionRequiredDeps(mctx.Config())
+ fullyQualifiedModuleName := fullyQualifiedModuleName(mctx.ModuleName(), mctx.Namespace().Path)
+ if partition, ok := additionalCrossPartitionRequiredDeps[fullyQualifiedModuleName]; ok && mctx.Module().PartitionTag(mctx.DeviceConfig()) == partition {
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[partition], partition, android.NativeBridgeDisabled, mctx.ModuleName())
+ }
+}
+
func setDepsMutator(mctx android.BottomUpMutatorContext) {
+ if !shouldEnableFilesystemCreator(mctx) {
+ return
+ }
removeOverriddenDeps(mctx)
fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
fsDeps := fsGenState.fsDeps
@@ -301,13 +438,46 @@ func setDepsMutator(mctx android.BottomUpMutatorContext) {
// Handwritten image, don't modify it
return
}
- depsStruct := generateDepStruct(*fsDeps[partition], fsGenState.generatedPrebuiltEtcModuleNames)
+ backgroundRecoveryImageGenerator, _ := getRecoveryBackgroundPicturesGeneratorModuleName(mctx)
+ // backgroundRecoveryImageGenerator generates additional images which takes precedence over images files
+ // created by other deps of recovery.img.
+ // Use this in highPriorityDeps
+ depsStruct := generateDepStruct(*fsDeps[partition], append([]string{backgroundRecoveryImageGenerator}, fsGenState.generatedPrebuiltEtcModuleNames...))
if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil {
mctx.ModuleErrorf(err.Error())
}
}
}
+// Adds override apps (override_android_app, override_apex, ...) to the partition of their `base` apps.
+func updatePartitionsOfOverrideModules(mctx android.BottomUpMutatorContext) {
+ if override, ok := mctx.Module().(android.OverrideModule); ok {
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsDeps := fsGenState.fsDeps
+ overridePartition := mctx.Module().PartitionTag(mctx.DeviceConfig())
+ if _, ok := (*fsDeps[overridePartition])[mctx.Module().Name()]; !ok {
+ // The override module is not in PRODUCT_PACKAGES
+ return
+ }
+ base := override.GetOverriddenModuleName()
+ if strings.HasPrefix(base, "//") { // Has path prefix, which is either the path to the module or the namespace
+ pathOrNamspace := strings.TrimPrefix(strings.Split(base, ":")[0], "//")
+ // If the path prefix is not within the exported namespace, it is likely that the
+ // prefix is the path to the module, not the namespace. In that case, drop the
+ // prefix as the non-namespace path prefix is not part of the fully qualified module
+ // name.
+ if !android.InList(pathOrNamspace, mctx.Config().ProductVariables().NamespacesToExport) {
+ base = strings.Split(base, ":")[1]
+ }
+ }
+
+ if baseModuleProps, ok := fsGenState.moduleToInstallationProps.GetFromFullyQualifiedModuleName(base); ok && mctx.Module().Enabled(mctx) && mctx.Module().ExportedToMake() {
+ partition := baseModuleProps.Partition
+ appendDepIfAppropriate(mctx, fsDeps[partition], partition, android.NativeBridgeDisabled, mctx.Module().Name())
+ }
+ }
+}
+
// removeOverriddenDeps collects PRODUCT_PACKAGES and (transitive) required deps.
// it then removes any modules which appear in `overrides` of the above list.
func removeOverriddenDeps(mctx android.BottomUpMutatorContext) {
@@ -319,8 +489,14 @@ func removeOverriddenDeps(mctx android.BottomUpMutatorContext) {
// Step 1: Initialization: Append PRODUCT_PACKAGES to the queue
for _, fsDep := range fsDeps {
- for depName, _ := range *fsDep {
- allDeps = append(allDeps, depName)
+ for depName, moduleInfo := range *fsDep {
+ fullyQualifiedDepName := depName
+ // If depName is not fully qualified and the dep specifies namespace, append the
+ // namespace for correct lookup in Step 2.
+ if !strings.HasPrefix(depName, "//") && !android.InList(moduleInfo.Namespace, []string{"", "."}) {
+ fullyQualifiedDepName = fmt.Sprintf("//%s:%s", moduleInfo.Namespace, fullyQualifiedDepName)
+ }
+ allDeps = append(allDeps, fullyQualifiedDepName)
}
}
@@ -331,11 +507,20 @@ func removeOverriddenDeps(mctx android.BottomUpMutatorContext) {
break
}
depName := allDeps[i]
- for _, overrides := range fsGenState.moduleToInstallationProps[depName].Overrides {
+ props, _ := fsGenState.moduleToInstallationProps.GetFromFullyQualifiedModuleName(depName)
+ for _, overrides := range props.Overrides {
+ if _, ok := fsGenState.nativeBridgeModules[depName]; ok {
+ // Do not remove automatically remove overrides of native bridge modules
+ // Some native_bridge_supported modules override the native_bridge variant
+ // of another module, but not the "main" variant.
+ // Determining this in fsgen requires additional information. Defer this to
+ // android_filesystem.
+ continue
+ }
overridden[overrides] = true
}
// add required dep to the queue.
- allDeps = append(allDeps, fsGenState.moduleToInstallationProps[depName].Required...)
+ allDeps = append(allDeps, props.Required...)
i += 1
}
@@ -349,6 +534,85 @@ func removeOverriddenDeps(mctx android.BottomUpMutatorContext) {
})
}
+type directDepWithParentPartition struct {
+ // name of the install partition of the parent module
+ parentPartition string
+ // fully qualified module name of the "required" direct dep
+ directDepName string
+}
+
+// This function is run only once to compute the list of transitive "required" dependencies
+// where the install partition differs from that of the direct reverse dependency (i.e. parent
+// module). Note that this is done via a graph walk from the top level deps of the autogenerated
+// filesystem modules. Thus, the module will not be included in the returning map even when the
+// install partition differs from that of the parent module if the module is not installed
+// for the target product.
+// The return value is a mapping of fully qualified module names to their install partition.
+func correctCrossPartitionRequiredDeps(config android.Config) map[string]string {
+ return config.Once(fsGenCrossPartitionRequiredDepsOnceKey, func() interface{} {
+ fsGenState := config.Get(fsGenStateOnceKey).(*FsGenState)
+ fsDeps := fsGenState.fsDeps
+ moduleToInstallationProps := fsGenState.moduleToInstallationProps
+
+ // Mapping of fully qualified module name to its list of install partition
+ // Given that a single module cannot be listed as deps of multiple filesystem modules,
+ // the key is a single string value instead of a list of strings
+ ret := make(map[string]string)
+
+ // Add the pair of:
+ // 1. install partition of the top level dep module
+ // 2. fully qualified module name of the direct dep of the top level dep module
+ // to the stack to perform dfs.
+ moduleNamesStack := []directDepWithParentPartition{}
+ for _, partition := range android.SortedKeys(fsDeps) {
+ for _, topLevelModule := range fsDeps[partition].SortedFullyQualifiedNames() {
+ if props, ok := moduleToInstallationProps.GetFromFullyQualifiedModuleName(topLevelModule); ok {
+ for _, requiredModule := range props.Required {
+ moduleNamesStack = append(moduleNamesStack, directDepWithParentPartition{
+ parentPartition: partition,
+ directDepName: fullyQualifiedModuleName(requiredModule, props.Namespace),
+ })
+ }
+ }
+ }
+ }
+
+ // map of fully qualified module names to store the names of modules that have been
+ // visited during the traversal
+ traversalMap := map[string]bool{}
+
+ // Iterate through the stack and find modules where the partition does not match that of
+ // the parent module
+ for len(moduleNamesStack) > 0 {
+ // Pop the last element from the stack
+ visitingModule := moduleNamesStack[len(moduleNamesStack)-1]
+ moduleNamesStack = moduleNamesStack[:len(moduleNamesStack)-1]
+
+ // Add the fully qualified module name to the returning map with its install
+ // partition if it does not match that of its parent.
+ // If the module has already been visited, it means its required direct deps has
+ // already been visited. Thus do not add the required deps to the stack.
+ // If it's the first time visiting the module, add the required deps to the stack and
+ // mark the module visited.
+ if moduleProps, ok := moduleToInstallationProps.GetFromFullyQualifiedModuleName(visitingModule.directDepName); ok {
+ if moduleProps.Partition != visitingModule.parentPartition {
+ ret[visitingModule.directDepName] = moduleProps.Partition
+ }
+ if _, ok := traversalMap[visitingModule.directDepName]; !ok {
+ traversalMap[visitingModule.directDepName] = true
+ for _, requiredModule := range moduleProps.Required {
+ moduleNamesStack = append(moduleNamesStack, directDepWithParentPartition{
+ parentPartition: moduleProps.Partition,
+ directDepName: requiredModule,
+ })
+ }
+ }
+ }
+ }
+ return ret
+ }).(map[string]string)
+}
+
var HighPriorityDeps = []string{}
func isHighPriorityDep(depName string) bool {
@@ -363,6 +627,11 @@ func isHighPriorityDep(depName string) bool {
func generateDepStruct(deps map[string]*depCandidateProps, highPriorityDeps []string) *packagingPropsStruct {
depsStruct := packagingPropsStruct{}
for depName, depProps := range deps {
+ if _, ok := depProps.NativeBridgeSupport[android.NativeBridgeDisabled]; !ok {
+ // Only the native bridge variant of this dep should be added.
+ // This will be done separately.
+ continue
+ }
bitness := getBitness(depProps.Arch)
fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace)
if android.InList(depName, highPriorityDeps) {
@@ -394,12 +663,26 @@ func generateDepStruct(deps map[string]*depCandidateProps, highPriorityDeps []st
depsStruct.Multilib.Common.Deps = append(depsStruct.Multilib.Common.Deps, fullyQualifiedDepName)
}
}
+ // Add the native bridge deps
+ var nativeBridgeDeps []string
+ for depName, depProps := range deps {
+ if _, ok := depProps.NativeBridgeSupport[android.NativeBridgeEnabled]; !ok {
+ continue
+ }
+ if depProps.Namespace != "." { // Add the fully qualified name
+ nativeBridgeDeps = append(nativeBridgeDeps, "//"+depProps.Namespace+":"+depName)
+ } else {
+ nativeBridgeDeps = append(nativeBridgeDeps, depName)
+ }
+ }
+
depsStruct.Deps = android.SortedUniqueStrings(depsStruct.Deps)
depsStruct.Multilib.Lib32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib32.Deps)
depsStruct.Multilib.Lib64.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib64.Deps)
depsStruct.Multilib.Prefer32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Prefer32.Deps)
depsStruct.Multilib.Both.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Both.Deps)
depsStruct.Multilib.Common.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Common.Deps)
+ depsStruct.Multilib.Native_bridge.Deps = android.SortedUniqueStrings(nativeBridgeDeps)
depsStruct.High_priority_deps = android.SortedUniqueStrings(depsStruct.High_priority_deps)
return &depsStruct
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index c0f114caf..05e07a28d 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -32,20 +32,22 @@ type srcBaseFileInstallBaseFileTuple struct {
// prebuilt src files grouped by the install partitions.
// Each groups are a mapping of the relative install path to the name of the files
type prebuiltSrcGroupByInstallPartition struct {
- system map[string][]srcBaseFileInstallBaseFileTuple
- system_ext map[string][]srcBaseFileInstallBaseFileTuple
- product map[string][]srcBaseFileInstallBaseFileTuple
- vendor map[string][]srcBaseFileInstallBaseFileTuple
- recovery map[string][]srcBaseFileInstallBaseFileTuple
+ system map[string][]srcBaseFileInstallBaseFileTuple
+ system_ext map[string][]srcBaseFileInstallBaseFileTuple
+ product map[string][]srcBaseFileInstallBaseFileTuple
+ vendor map[string][]srcBaseFileInstallBaseFileTuple
+ recovery map[string][]srcBaseFileInstallBaseFileTuple
+ vendor_dlkm map[string][]srcBaseFileInstallBaseFileTuple
}
func newPrebuiltSrcGroupByInstallPartition() *prebuiltSrcGroupByInstallPartition {
return &prebuiltSrcGroupByInstallPartition{
- system: map[string][]srcBaseFileInstallBaseFileTuple{},
- system_ext: map[string][]srcBaseFileInstallBaseFileTuple{},
- product: map[string][]srcBaseFileInstallBaseFileTuple{},
- vendor: map[string][]srcBaseFileInstallBaseFileTuple{},
- recovery: map[string][]srcBaseFileInstallBaseFileTuple{},
+ system: map[string][]srcBaseFileInstallBaseFileTuple{},
+ system_ext: map[string][]srcBaseFileInstallBaseFileTuple{},
+ product: map[string][]srcBaseFileInstallBaseFileTuple{},
+ vendor: map[string][]srcBaseFileInstallBaseFileTuple{},
+ recovery: map[string][]srcBaseFileInstallBaseFileTuple{},
+ vendor_dlkm: map[string][]srcBaseFileInstallBaseFileTuple{},
}
}
@@ -77,6 +79,8 @@ func appendIfCorrectInstallPartition(partitionToInstallPathList []partitionToIns
srcMap = srcGroup.vendor
case "recovery":
srcMap = srcGroup.recovery
+ case "vendor_dlkm":
+ srcMap = srcGroup.vendor_dlkm
}
if srcMap != nil {
srcMap[relativeInstallDir] = append(srcMap[relativeInstallDir], srcBaseFileInstallBaseFileTuple{
@@ -134,6 +138,7 @@ func processProductCopyFiles(ctx android.LoadHookContext) map[string]*prebuiltSr
partitionToInstallPathList := []partitionToInstallPath{
{name: "recovery", installPath: "recovery/root"},
{name: "vendor", installPath: ctx.DeviceConfig().VendorPath()},
+ {name: "vendor_dlkm", installPath: ctx.DeviceConfig().VendorDlkmPath()},
{name: "product", installPath: ctx.DeviceConfig().ProductPath()},
{name: "system_ext", installPath: ctx.DeviceConfig().SystemExtPath()},
{name: "system", installPath: "system"},
@@ -157,11 +162,14 @@ func processProductCopyFiles(ctx android.LoadHookContext) map[string]*prebuiltSr
type prebuiltModuleProperties struct {
Name *string
- Soc_specific *bool
- Product_specific *bool
- System_ext_specific *bool
- Recovery *bool
- Ramdisk *bool
+ From_product_copy_files *bool
+
+ Soc_specific *bool
+ Product_specific *bool
+ System_ext_specific *bool
+ Vendor_dlkm_specific *bool
+ Recovery *bool
+ Ramdisk *bool
Srcs []string
@@ -274,6 +282,8 @@ func prebuiltEtcModuleProps(ctx android.LoadHookContext, moduleName, partition,
moduleProps.Product_specific = proptools.BoolPtr(true)
case "vendor":
moduleProps.Soc_specific = proptools.BoolPtr(true)
+ case "vendor_dlkm":
+ moduleProps.Vendor_dlkm_specific = proptools.BoolPtr(true)
case "recovery":
// To match the logic in modulePartition() in android/paths.go
if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() && strings.HasPrefix(destDir, "first_stage_ramdisk") {
@@ -283,6 +293,7 @@ func prebuiltEtcModuleProps(ctx android.LoadHookContext, moduleName, partition,
}
}
+ moduleProps.From_product_copy_files = proptools.BoolPtr(true)
moduleProps.No_full_install = proptools.BoolPtr(true)
moduleProps.NamespaceExportedToMake = true
moduleProps.Visibility = []string{"//visibility:public"}
@@ -404,15 +415,18 @@ func createPrebuiltEtcModules(ctx android.LoadHookContext) (ret []string) {
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "product", srcDir, groupedSource.product)...)
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "vendor", srcDir, groupedSource.vendor)...)
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "recovery", srcDir, groupedSource.recovery)...)
+ ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "vendor_dlkm", srcDir, groupedSource.vendor_dlkm)...)
}
return ret
}
-func createAvbpubkeyModule(ctx android.LoadHookContext) bool {
+func createAvbpubkeyModule(ctx android.LoadHookContext) {
avbKeyPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardAvbKeyPath
if avbKeyPath == "" {
- return false
+ // Use default
+ // https://cs.android.com/android/_/android/platform/build/+/045a3d6a3e359633a14853a5a5e1e4f2a11cbdae:core/Makefile;l=4548;bpv=1;bpt=0;drc=a951ebf0198006f7fd38073a05c442d0eb92f97b
+ avbKeyPath = "external/avb/test/data/testkey_rsa4096.pem"
}
ctx.CreateModuleInDirectory(
etc.AvbpubkeyModuleFactory,
@@ -423,13 +437,14 @@ func createAvbpubkeyModule(ctx android.LoadHookContext) bool {
Private_key *string
No_full_install *bool
Visibility []string
+ Licenses []string
}{
Name: proptools.StringPtr("system_other_avbpubkey"),
Product_specific: proptools.BoolPtr(true),
Private_key: proptools.StringPtr(avbKeyPath),
No_full_install: proptools.BoolPtr(true),
Visibility: []string{"//visibility:public"},
+ Licenses: []string{"Android-Apache-2.0"},
},
)
- return true
}
diff --git a/fsgen/util.go b/fsgen/util.go
index 008f9fef3..356fdbb90 100644
--- a/fsgen/util.go
+++ b/fsgen/util.go
@@ -16,15 +16,17 @@ package fsgen
import (
"android/soong/android"
+ "android/soong/etc"
"android/soong/filesystem"
"fmt"
+ "github.com/google/blueprint/proptools"
"strconv"
"strings"
)
// Returns the appropriate dpi for recovery common resources selection. Replicates the logic in
// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2536;drc=a6af369e71ded123734523ea640b97b70a557cb9
-func getDpi(ctx android.LoadHookContext) string {
+func getDpi(ctx android.EarlyModuleContext) string {
recoveryDensity := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.TargetScreenDensity
if len(recoveryDensity) == 0 {
aaptPreferredConfig := ctx.Config().ProductAAPTPreferredConfig()
@@ -69,6 +71,31 @@ func getRecoveryFontModuleName(ctx android.LoadHookContext) string {
return "recovery-fonts-12"
}
+// Returns the module name and image width for recovery background image generation.
+// https://source.corp.google.com/h/googleplex-android/platform/build/+/f1cb088a1446adc54950bd6b447eac9fc90831f6:core/Makefile;l=2539-2556;drc=acc8d6594498f50db20f04e0e05fff09750c412c;bpv=1;bpt=0
+func getRecoveryBackgroundPicturesGeneratorModuleName(ctx android.EarlyModuleContext) (string, int64) {
+ dpi := getDpi(ctx)
+ if !android.InList(dpi, []string{"xxxhdpi", "xxhdpi"}) {
+ return "", -1
+ }
+ var recoveryUiScreenWidth int64
+ if dpi == "xxxhdpi" {
+ recoveryUiScreenWidth = 1440 - 10
+ } else { // xxhdpi
+ recoveryUiScreenWidth = 1080 - 10
+ }
+
+ if marginWidth, exists := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrivateRecoveryUiProperties["margin_width"]; exists && marginWidth != "" {
+ if marginWidth, err := strconv.ParseInt(marginWidth, 10, 64); err == nil {
+ recoveryUiScreenWidth -= marginWidth
+ } else {
+ ctx.ModuleErrorf("Error parsing TARGET_RECOVERY_UI_MARGIN_WIDTH %s", err)
+ }
+ }
+
+ return generatedModuleNameForPartition(ctx.Config(), "background_recovery_images"), recoveryUiScreenWidth
+}
+
// Returns a new list of symlinks with prefix added to the dest directory for all symlinks
func symlinksWithNamePrefix(symlinks []filesystem.SymlinkDefinition, prefix string) []filesystem.SymlinkDefinition {
ret := make([]filesystem.SymlinkDefinition, len(symlinks))
@@ -77,3 +104,29 @@ func symlinksWithNamePrefix(symlinks []filesystem.SymlinkDefinition, prefix stri
}
return ret
}
+
+// Creates a prebuilt_etc for recovery partition if TARGET_RECOVERY_WIPE is not empty.
+// Returns the name of the autogenerated module.
+func createTargetRecoveryWipeModuleName(ctx android.LoadHookContext) string {
+ recoveryWipe := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.TargetRecoveryWipe
+ if recoveryWipe == "" {
+ return ""
+ }
+ name := generatedModuleName(ctx.Config(), "target_recovery_wipe")
+ ctx.CreateModuleInDirectory(
+ etc.PrebuiltEtcFactory,
+ ".",
+ &struct {
+ Name *string
+ Srcs []string
+ Dsts []string
+ Recovery *bool
+ }{
+ Name: proptools.StringPtr(name),
+ Srcs: []string{recoveryWipe},
+ Dsts: []string{"recovery.wipe"},
+ Recovery: proptools.BoolPtr(true),
+ },
+ )
+ return name
+}
diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go
index 594c40482..13b1a3ea4 100644
--- a/fsgen/vbmeta_partitions.go
+++ b/fsgen/vbmeta_partitions.go
@@ -94,7 +94,7 @@ func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext,
ctx.ModuleErrorf("No rollback index found for chained avb partition %q", chainedName)
continue
}
- ril, err := strconv.ParseInt(props.RollbackIndexLocation, 10, 32)
+ ril, err := strconv.ParseInt(props.RollbackIndexLocation, 10, 64)
if err != nil {
ctx.ModuleErrorf("Rollback index location must be an int, got %q", props.RollbackIndexLocation)
continue
@@ -104,7 +104,7 @@ func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext,
// in soong.
var rollbackIndex *int64
if props.RollbackIndex != ctx.Config().PlatformSecurityPatch() {
- i, err := strconv.ParseInt(props.RollbackIndex, 10, 32)
+ i, err := strconv.ParseInt(props.RollbackIndex, 10, 64)
if err != nil {
ctx.ModuleErrorf("Rollback index must be an int, got %q", props.RollbackIndex)
continue
@@ -161,7 +161,7 @@ func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext,
algorithm = proptools.StringPtr(partitionVars.BoardAvbAlgorithm)
}
if len(partitionVars.BoardAvbRollbackIndex) > 0 {
- parsedRi, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 32)
+ parsedRi, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 64)
if err != nil {
ctx.ModuleErrorf("Rollback index location must be an int, got %q", partitionVars.BoardAvbRollbackIndex)
}
diff --git a/fuzz/Android.bp b/fuzz/Android.bp
index 9d96e481b..0e8b278f8 100644
--- a/fuzz/Android.bp
+++ b/fuzz/Android.bp
@@ -10,6 +10,7 @@ bootstrap_go_package {
],
srcs: [
"fuzz_common.go",
+ "fuzz_common_gob_enc.go",
],
pluginFor: ["soong_build"],
}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index f08378d67..9b540d969 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -28,6 +28,8 @@ import (
"android/soong/android"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
type Lang string
const (
@@ -452,6 +454,7 @@ type FuzzPackagedModule struct {
Data android.Paths
}
+// @auto-generate: gob
type FuzzConfigInfo struct {
Vector Vector
// How privileged the service being fuzzed is.
@@ -474,6 +477,8 @@ type FuzzConfigInfo struct {
// Defaults to false.
UseForPresubmit bool
}
+
+// @auto-generate: gob
type FuzzPackagedModuleInfo struct {
FuzzConfig *FuzzConfigInfo
Dictionary android.Path
@@ -568,10 +573,10 @@ func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bo
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
+func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.ModuleOrProxy, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
// Package the corpora into a zipfile.
var files []FileToZip
- if fuzzModule.Corpus != nil {
+ if len(fuzzModule.Corpus) > 0 {
corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
command := builder.Command().BuiltTool("soong_zip").
Flag("-j").
@@ -582,7 +587,7 @@ func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module and
}
// Package the data into a zipfile.
- if fuzzModule.Data != nil {
+ if len(fuzzModule.Data) > 0 {
dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
command := builder.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", dataZip)
@@ -609,7 +614,7 @@ func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module and
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
+func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.ModuleOrProxy, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
fuzzZip := archDir.Join(ctx, module.Name()+".zip")
command := builder.Command().BuiltTool("soong_zip").
diff --git a/fuzz/fuzz_common_gob_enc.go b/fuzz/fuzz_common_gob_enc.go
new file mode 100644
index 000000000..95a0a03d6
--- /dev/null
+++ b/fuzz/fuzz_common_gob_enc.go
@@ -0,0 +1,241 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package fuzz
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ FuzzConfigInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(FuzzConfigInfo) })
+ FuzzPackagedModuleInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(FuzzPackagedModuleInfo) })
+}
+
+func (r FuzzConfigInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeString(buf, string(r.Vector)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, string(r.ServicePrivilege)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, string(r.Users)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, string(r.FuzzedCodeUsage)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, string(r.AutomaticallyRouteTo)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeString(buf, string(r.UsePlatformLibs)); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.FuzzOnHaikuDevice); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.FuzzOnHaikuHost); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.UseForPresubmit); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *FuzzConfigInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 string
+ err = gobtools.DecodeString(buf, &val2)
+ if err != nil {
+ return err
+ }
+ r.Vector = Vector(val2)
+
+ var val5 string
+ err = gobtools.DecodeString(buf, &val5)
+ if err != nil {
+ return err
+ }
+ r.ServicePrivilege = ServicePrivilege(val5)
+
+ var val8 string
+ err = gobtools.DecodeString(buf, &val8)
+ if err != nil {
+ return err
+ }
+ r.Users = UserData(val8)
+
+ var val11 string
+ err = gobtools.DecodeString(buf, &val11)
+ if err != nil {
+ return err
+ }
+ r.FuzzedCodeUsage = FuzzedCodeUsage(val11)
+
+ var val14 string
+ err = gobtools.DecodeString(buf, &val14)
+ if err != nil {
+ return err
+ }
+ r.AutomaticallyRouteTo = AutomaticallyRouteTo(val14)
+
+ var val17 string
+ err = gobtools.DecodeString(buf, &val17)
+ if err != nil {
+ return err
+ }
+ r.UsePlatformLibs = UsePlatformLibs(val17)
+
+ err = gobtools.DecodeSimple[bool](buf, &r.FuzzOnHaikuDevice)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.FuzzOnHaikuHost)
+ if err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.UseForPresubmit)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+var FuzzConfigInfoGobRegId int16
+
+func (r FuzzConfigInfo) GetTypeId() int16 {
+ return FuzzConfigInfoGobRegId
+}
+
+func (r FuzzPackagedModuleInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ val1 := r.FuzzConfig == nil
+ if err = gobtools.EncodeSimple(buf, val1); err != nil {
+ return err
+ }
+ if !val1 {
+ if err = (*r.FuzzConfig).Encode(buf); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.Dictionary); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Corpus))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.Corpus); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.Corpus[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.Config); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Data))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Data); val3++ {
+ if err = gobtools.EncodeInterface(buf, r.Data[val3]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *FuzzPackagedModuleInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val2 bool
+ if err = gobtools.DecodeSimple(buf, &val2); err != nil {
+ return err
+ }
+ if !val2 {
+ var val1 FuzzConfigInfo
+ if err = val1.Decode(buf); err != nil {
+ return err
+ }
+ r.FuzzConfig = &val1
+ }
+
+ if val5, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val5 == nil {
+ r.Dictionary = nil
+ } else {
+ r.Dictionary = val5.(android.Path)
+ }
+
+ var val8 int32
+ err = gobtools.DecodeSimple[int32](buf, &val8)
+ if err != nil {
+ return err
+ }
+ if val8 > 0 {
+ r.Corpus = make([]android.Path, val8)
+ for val9 := 0; val9 < int(val8); val9++ {
+ if val11, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val11 == nil {
+ r.Corpus[val9] = nil
+ } else {
+ r.Corpus[val9] = val11.(android.Path)
+ }
+ }
+ }
+
+ if val13, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val13 == nil {
+ r.Config = nil
+ } else {
+ r.Config = val13.(android.Path)
+ }
+
+ var val16 int32
+ err = gobtools.DecodeSimple[int32](buf, &val16)
+ if err != nil {
+ return err
+ }
+ if val16 > 0 {
+ r.Data = make([]android.Path, val16)
+ for val17 := 0; val17 < int(val16); val17++ {
+ if val19, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val19 == nil {
+ r.Data[val17] = nil
+ } else {
+ r.Data[val17] = val19.(android.Path)
+ }
+ }
+ }
+
+ return err
+}
+
+var FuzzPackagedModuleInfoGobRegId int16
+
+func (r FuzzPackagedModuleInfo) GetTypeId() int16 {
+ return FuzzPackagedModuleInfoGobRegId
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a7c09e76c..2a0f98f24 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -21,7 +21,6 @@ package genrule
import (
"fmt"
"io"
- "path/filepath"
"strconv"
"strings"
@@ -112,8 +111,8 @@ func (t hostToolDependencyTag) AllowDisabledModuleDependency(target android.Modu
func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy(
ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
- return android.OtherModulePointerProviderOrDefault(
- ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt
+ return android.OtherModuleProviderOrDefault(
+ ctx, target, android.PrebuiltInfoProvider).ReplacedByPrebuilt
}
var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
@@ -157,6 +156,12 @@ type generatorProperties struct {
// Same as srcs, but will add dependencies on modules via a common_os os variation.
Common_os_srcs proptools.Configurable[[]string] `android:"path_common_os"`
+ // Same as srcs, but will add dependencies on modules via for host os variation.
+ Host_first_srcs proptools.Configurable[[]string] `android:"path_host_first"`
+
+ // Same as srcs, but will add dependencies on modules via for host 2nd arch os variation.
+ Host_second_srcs proptools.Configurable[[]string] `android:"path_host_second"`
+
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
@@ -177,6 +182,19 @@ type generatorProperties struct {
// number. Prefer using libbuildversion via the use_version_lib property on
// cc modules.
Uses_order_only_build_number_file *bool
+
+ // When set to true, an additional $(build_date_file) label will be available
+ // to use in the cmd. This will be the location of a text file containing the
+ // build date. The dependency on this file will be "order-only", meaning that
+ // the genrule will not rerun when only this file changes, to avoid rerunning
+ // the genrule every build, because the build date changes every build.
+ // This also means that you should not attempt to consume the build date from
+ // the result of this genrule in another build rule. If you do, the build date
+ // in the second build rule will be stale when the second build rule rebuilds
+ // but this genrule does not. Only certain allowlisted modules are allowed to
+ // use this property, usages of the build date should be kept to the absolute
+ // minimum.
+ Uses_order_only_build_date_file *bool
}
type Module struct {
@@ -219,7 +237,7 @@ type generateTask struct {
in android.Paths
out android.WritablePaths
copyTo android.WritablePaths // For gensrcs to set on gensrcsMerge rule.
- genDir android.WritablePath
+ genDir android.ModuleGenPath
extraInputs map[string][]string
cmd string
@@ -264,6 +282,7 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) {
}
var buildNumberAllowlistKey = android.NewOnceKey("genruleBuildNumberAllowlistKey")
+var buildDateAllowlistKey = android.NewOnceKey("genruleBuildDateAllowlistKey")
// This allowlist should be kept to the bare minimum, it's
// intended for things that existed before the build number
@@ -280,6 +299,20 @@ func isModuleInBuildNumberAllowlist(ctx android.ModuleContext) bool {
"build/soong/tests:gen",
"hardware/google/camera/common/hal/aidl_service:aidl_camera_build_version",
"tools/tradefederation/core:tradefed_zip",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_test_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_test_vm_x86_64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_vm_x86_64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_security_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_security_vm_x86_64.elf",
+ "trusty/vendor/google/aosp/scripts:trusty_tee_package",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_os_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_os_x86_64.elf",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_x86_64.elf",
+ "trusty/vendor/google/proprietary/scripts:trusty_tee_package_goog",
+ "trusty/vendor/google/proprietary/scripts:trusty_widevine_vm_arm64.bin",
+ "trusty/vendor/google/proprietary/scripts:trusty_widevine_vm_x86_64.elf",
"vendor/google/services/LyricCameraHAL/src/apex:com.google.pixel.camera.hal.manifest",
"vendor/google_tradefederation/core:gen_google_tradefed_zip",
// go/keep-sorted end
@@ -295,6 +328,40 @@ func isModuleInBuildNumberAllowlist(ctx android.ModuleContext) bool {
return ok
}
+func isModuleInBuildDateAllowlist(ctx android.ModuleContext) bool {
+ allowlist := ctx.Config().Once(buildDateAllowlistKey, func() interface{} {
+ // Define the allowlist as a list and then copy it into a map so that
+ // gofmt doesn't change unnecessary lines trying to align the values of the map.
+ allowlist := []string{
+ // go/keep-sorted start
+ "build/soong/tests:gen",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_test_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_test_vm_x86_64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_desktop_vm_x86_64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_security_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_security_vm_x86_64.elf",
+ "trusty/vendor/google/aosp/scripts:trusty_tee_package",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_os_arm64.bin",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_os_x86_64.elf",
+ "trusty/vendor/google/aosp/scripts:trusty_test_vm_x86_64.elf",
+ "trusty/vendor/google/proprietary/scripts:trusty_tee_package_goog",
+ "trusty/vendor/google/proprietary/scripts:trusty_widevine_vm_arm64.bin",
+ "trusty/vendor/google/proprietary/scripts:trusty_widevine_vm_x86_64.elf",
+ // go/keep-sorted end
+ }
+ allowlistMap := make(map[string]bool, len(allowlist))
+ for _, a := range allowlist {
+ allowlistMap[a] = true
+ }
+ return allowlistMap
+ }).(map[string]bool)
+
+ _, ok := allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]
+ return ok
+}
+
// generateCommonBuildActions contains build action generation logic
// common to both the mixed build case and the legacy case of genrule processing.
// To fully support genrule in mixed builds, the contents of this function should
@@ -454,6 +521,8 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
srcFiles = append(srcFiles, addLabelsForInputs("device_first_srcs", g.properties.Device_first_srcs.GetOrDefault(ctx, nil), nil)...)
srcFiles = append(srcFiles, addLabelsForInputs("device_common_srcs", g.properties.Device_common_srcs.GetOrDefault(ctx, nil), nil)...)
srcFiles = append(srcFiles, addLabelsForInputs("common_os_srcs", g.properties.Common_os_srcs.GetOrDefault(ctx, nil), nil)...)
+ srcFiles = append(srcFiles, addLabelsForInputs("host_first_src", g.properties.Host_first_srcs.GetOrDefault(ctx, nil), nil)...)
+ srcFiles = append(srcFiles, addLabelsForInputs("host_second_src", g.properties.Host_second_srcs.GetOrDefault(ctx, nil), nil)...)
var copyFrom android.Paths
var outputFiles android.WritablePaths
@@ -485,7 +554,9 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
desc := "generate"
name := "generator"
if task.useNsjail {
- rule = android.NewRuleBuilder(pctx, ctx).Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox"))
+ rule = android.NewRuleBuilder(pctx, ctx).
+ Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox")).
+ DirDepsFile(task.genDir.Join(ctx, "dir_deps.d"))
if task.keepGendir {
rule.NsjailKeepGendir()
}
@@ -502,7 +573,8 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
manifestPath := android.PathForModuleOut(ctx, manifestName)
// Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
- rule = getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
+ rule = android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath).SandboxInputs()
+ rule.DirDepsFile(task.genDir.Join(ctx, "dir_deps.d"))
}
if Bool(g.properties.Write_if_changed) {
rule.Restat()
@@ -551,6 +623,11 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true")
}
return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil
+ case "build_date_file":
+ if !proptools.Bool(g.properties.Uses_order_only_build_date_file) {
+ return reportError("to use the $(build_date_file) label, you must set uses_order_only_build_date_file: true")
+ }
+ return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildDateFile(ctx))), nil
default:
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -603,17 +680,15 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
}
cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
}
-
- if task.useNsjail {
- for _, input := range task.dirSrcs {
- cmd.ImplicitDirectory(input)
- // TODO(b/375551969): remove glob
- if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
- rule.NsjailImplicits(android.PathsForSource(ctx, paths))
- } else {
- ctx.PropertyErrorf("dir_srcs", "can't glob %q", input.String())
- }
+ if proptools.Bool(g.properties.Uses_order_only_build_date_file) {
+ if !isModuleInBuildDateAllowlist(ctx) {
+ ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_date_file: true")
}
+ cmd.OrderOnly(ctx.Config().BuildDateFile(ctx))
+ }
+
+ for _, input := range task.dirSrcs {
+ cmd.ImplicitDirectory(input)
}
// Create the rule to run the genrule command inside sbox.
@@ -801,7 +876,7 @@ func NewGenSrcs() *Module {
// TODO(ccross): this RuleBuilder is a hack to be able to call
// rule.Command().PathForOutput. Replace this with passing the rule into the
// generator.
- rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil))
+ rule := android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil).SandboxInputs()
for _, in := range shard {
outFile := android.GenPathWithExtAndTrimExt(ctx, finalSubDir, in, String(properties.Output_extension), String(properties.Trim_extension))
@@ -891,10 +966,6 @@ func NewGenRule() *Module {
useNsjail := Bool(properties.Use_nsjail)
dirSrcs := android.DirectoryPathsForModuleSrc(ctx, properties.Dir_srcs)
- if len(dirSrcs) > 0 && !useNsjail {
- ctx.PropertyErrorf("dir_srcs", "can't use dir_srcs if use_nsjail is false")
- return nil
- }
keepGendir := Bool(properties.Keep_gendir)
if keepGendir && !useNsjail {
@@ -968,10 +1039,3 @@ func DefaultsFactory(props ...interface{}) android.Module {
return module
}
-
-func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
- if !ctx.DeviceConfig().GenruleSandboxing() {
- return r.SandboxTools()
- }
- return r.SandboxInputs()
-}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index dcec2971b..3f1ca1011 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -19,7 +19,6 @@ import (
"os"
"regexp"
"strconv"
- "strings"
"testing"
"android/soong/android"
@@ -436,9 +435,6 @@ func TestGenruleCmd(t *testing.T) {
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.GenruleSandboxing = proptools.BoolPtr(true)
- }),
android.FixtureModifyContext(func(ctx *android.TestContext) {
ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
}),
@@ -1190,7 +1186,7 @@ func TestGenruleWithGlobPaths(t *testing.T) {
}
}
-func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) {
+func TestGenruleUsesOrderOnlyBuildNumberOrDateFile(t *testing.T) {
testCases := []struct {
name string
bp string
@@ -1199,7 +1195,7 @@ func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) {
expectedCommand string
}{
{
- name: "not allowed when not in allowlist",
+ name: "buld number not allowed when not in allowlist",
fs: android.MockFS{
"foo/Android.bp": []byte(`
genrule {
@@ -1213,7 +1209,7 @@ genrule {
expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`,
},
{
- name: "normal",
+ name: "build number normal",
fs: android.MockFS{
"build/soong/tests/Android.bp": []byte(`
genrule {
@@ -1224,7 +1220,35 @@ genrule {
}
`),
},
- expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`,
+ expectedCommand: `cp __SBOX_SANDBOX_DIR__/out/soong/build_number.txt __SBOX_SANDBOX_DIR__/out/out.txt`,
+ },
+ {
+ name: "build date not allowed when not in allowlist",
+ fs: android.MockFS{
+ "foo/Android.bp": []byte(`
+ genrule {
+ name: "gen",
+ uses_order_only_build_date_file: true,
+ cmd: "cp $(build_date_file) $(out)",
+ out: ["out.txt"],
+ }
+ `),
+ },
+ expectedError: `Only allowlisted modules may use uses_order_only_build_date_file: true`,
+ },
+ {
+ name: "build date normal",
+ fs: android.MockFS{
+ "build/soong/tests/Android.bp": []byte(`
+ genrule {
+ name: "gen",
+ uses_order_only_build_date_file: true,
+ cmd: "cp $(build_date_file) $(out)",
+ out: ["out.txt"],
+ }
+ `),
+ },
+ expectedCommand: `cp __SBOX_SANDBOX_DIR__/out/build_date.txt __SBOX_SANDBOX_DIR__/out/out.txt`,
},
}
@@ -1237,6 +1261,7 @@ genrule {
android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt")
}),
+ android.SetBuildDateFileEnvVarForTests(),
)
if tc.expectedError != "" {
fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
@@ -1244,7 +1269,6 @@ genrule {
result := fixtures.RunTest(t)
if tc.expectedError == "" {
- tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt")
gen := result.Module("gen", "").(*Module)
android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0])
}
diff --git a/go.work b/go.work
index e5389156c..0e49119a8 100644
--- a/go.work
+++ b/go.work
@@ -6,6 +6,7 @@ use (
../../external/golang-protobuf
../../external/starlark-go
../blueprint
+ ../../build/make/tools/dependency_mapper/proto
)
replace (
@@ -14,4 +15,5 @@ replace (
github.com/google/go-cmp v0.0.0 => ../../external/go-cmp
google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
go.starlark.net v0.0.0 => ../../external/starlark-go
+ go.dependencymapper/protoimpl v0.0.0 => ../../build/make/tools/dependency_mapper/proto
)
diff --git a/golang/Android.bp b/golang/Android.bp
index 3eae94fa2..d3bbd51ea 100644
--- a/golang/Android.bp
+++ b/golang/Android.bp
@@ -17,6 +17,7 @@ bootstrap_go_package {
],
testSrcs: [
"golang_test.go",
+ "plugin_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/golang/golang.go b/golang/golang.go
index 9e0744aaf..282ac7805 100644
--- a/golang/golang.go
+++ b/golang/golang.go
@@ -38,10 +38,17 @@ func RegisterGoModuleTypes(ctx android.RegistrationContext) {
ctx.RegisterModuleType("blueprint_go_binary", goBinaryModuleFactory)
}
+// wrapGoPackage is used to increase the depth of the blueprint.ModuleBase struct embedded in bootstrap.GoPackage
+// so that the Go selector rules will choose the blueprint.ModuleBase in android.ModuleBase instead of throwing
+// an ambiguous method error.
+type wrapGoPackage struct {
+ bootstrap.GoPackage
+}
+
// A GoPackage is a module for building Go packages.
type GoPackage struct {
android.ModuleBase
- bootstrap.GoPackage
+ wrapGoPackage
}
func goPackageModuleFactory() android.Module {
@@ -63,10 +70,17 @@ func (g *GoPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
g.GoPackage.GenerateBuildActions(ctx.BlueprintModuleContext())
}
+// wrapGoBinary is used to increase the depth of the blueprint.ModuleBase struct embedded in bootstrap.GoBinary
+// so that the Go selector rules will choose the blueprint.ModuleBase in android.ModuleBase instead of throwing
+// an ambiguous method error.
+type wrapGoBinary struct {
+ bootstrap.GoBinary
+}
+
// A GoBinary is a module for building executable binaries from Go sources.
type GoBinary struct {
android.ModuleBase
- bootstrap.GoBinary
+ wrapGoBinary
outputFile android.Path
}
@@ -114,7 +128,7 @@ func (g *GoBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func usedByBootstrap(name string) bool {
switch name {
- case "loadplugins", "soong_build":
+ case "gob_gen", "loadplugins", "soong_build":
return true
default:
return false
diff --git a/golang/plugin_test.go b/golang/plugin_test.go
new file mode 100644
index 000000000..54a91face
--- /dev/null
+++ b/golang/plugin_test.go
@@ -0,0 +1,54 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package golang
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "github.com/google/blueprint/bootstrap"
+)
+
+func TestPluginAllowList(t *testing.T) {
+ bp := `
+ bootstrap_go_package {
+ name: "bad_plugin",
+ pkgPath: "test/bad",
+ pluginFor: ["soong_build"],
+ }
+
+ bootstrap_go_package {
+ name: "soong-llvm",
+ pkgPath: "test/llvm",
+ pluginFor: ["soong_build"],
+ }
+
+ blueprint_go_binary {
+ name: "soong_build",
+ }
+ `
+
+ android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ RegisterGoModuleTypes(ctx)
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps).UsesReverseDependencies()
+ })
+ android.RegisterPluginSingletonBuildComponents(ctx)
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`New plugins are not supported; however \["bad_plugin"\] were found.`)).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/Android.bp b/java/Android.bp
index 99d9c38a6..65200c27a 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -27,11 +27,13 @@ bootstrap_go_package {
"android_manifest.go",
"android_resources.go",
"androidmk.go",
+ "apkcerts.go",
"app_builder.go",
"app.go",
"app_import.go",
"app_set.go",
"base.go",
+ "base_gob_enc.go",
"boot_jars.go",
"bootclasspath.go",
"bootclasspath_fragment.go",
@@ -58,10 +60,12 @@ bootstrap_go_package {
"hiddenapi_singleton.go",
"jacoco.go",
"java.go",
+ "java_gob_enc.go",
"jdeps.go",
"java_resources.go",
"kotlin.go",
"lint.go",
+ "lint_gob_enc.go",
"legacy_core_platform_api_usage.go",
"platform_bootclasspath.go",
"platform_compat_config.go",
@@ -76,6 +80,7 @@ bootstrap_go_package {
"sdk_library_internal.go",
"support_libraries.go",
"system_modules.go",
+ "system_modules_gob_enc.go",
"systemserver_classpath_fragment.go",
"testing.go",
"tracereferences.go",
diff --git a/java/aapt2.go b/java/aapt2.go
index bae4d1ee3..4efa6655a 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -52,14 +52,15 @@ func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.Writab
}
subDir := filepath.Dir(res.String())
subDir, lastDir := filepath.Split(subDir)
- if isFlagsPath(subDir) {
- var flag string
+ var flag string
+ if isFlagsPath(lastDir) {
+ flag = "." + strings.TrimPrefix(lastDir, "flag")
+ subDir, lastDir = filepath.Split(filepath.Dir(subDir))
+ } else if isFlagsPath(subDir) {
subDir, flag = filepath.Split(filepath.Dir(subDir))
- flag = strings.TrimPrefix(flag, "flag")
- name = fmt.Sprintf("%s_%s.%s%s.flat", lastDir, name, flag, extension)
- } else {
- name = fmt.Sprintf("%s_%s%s.flat", lastDir, name, extension)
+ flag = "." + strings.TrimPrefix(flag, "flag")
}
+ name = fmt.Sprintf("%s_%s%s%s.flat", lastDir, name, flag, extension)
out := android.PathForModuleOut(ctx, "aapt2", subDir, name)
return out
}
@@ -332,15 +333,20 @@ func aapt2ExtractExtraPackages(ctx android.ModuleContext, out android.WritablePa
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} convert --enable-compact-entries ` +
+ Command: `${config.Aapt2Cmd} convert $flags ` +
`--output-format $format $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
- }, "format",
+ }, "format", "flags",
)
// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto
// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path, format string) {
+ extraFlags := []string{"--enable-compact-entries"}
+ if ctx.Config().ReleaseUseSparseEncoding() {
+ extraFlags = append(extraFlags, "--enable-sparse-encoding")
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,
Input: in,
@@ -348,6 +354,7 @@ func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in androi
Description: "convert to " + format,
Args: map[string]string{
"format": format,
+ "flags": strings.Join(extraFlags, " "),
},
})
}
diff --git a/java/aar.go b/java/aar.go
index ad080aa62..c1129f0c8 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -108,6 +108,9 @@ type aaptProperties struct {
// Names of aconfig_declarations modules that specify aconfig flags that the module depends on.
Flags_packages []string
+
+ // The package name of this app. May not be used if `manifest` or `additional_manifests` are provided.
+ Package_name proptools.Configurable[string]
}
type aapt struct {
@@ -144,6 +147,10 @@ type aapt struct {
manifestValues struct {
applicationId string
}
+
+ // Fields written to jdeps
+ assetDirs android.Paths
+ resourceDirs android.Paths
}
type split struct {
@@ -263,6 +270,13 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte
linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
linkFlags = append(linkFlags, "--enable-compact-entries")
+ if ctx.Config().ReleaseUseSparseEncoding() {
+ linkFlags = append(linkFlags, "--enable-sparse-encoding")
+ }
+
+ if ctx.Config().ReleaseUseUncompressedFonts() {
+ linkFlags = append(linkFlags, "--no-compress-fonts")
+ }
// Find implicit or explicit asset and resource dirs
assets := android.PathsRelativeToModuleSourceDir(android.SourceInput{
@@ -276,7 +290,10 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte
} else {
assetDirs = android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
}
+ a.assetDirs = assetDirs
+
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs.GetOrDefault(ctx, nil), "res")
+ a.resourceDirs = resourceDirs
resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
// Glob directories into lists of paths
@@ -452,9 +469,21 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)
// App manifest file
+ packageNameProp := a.aaptProperties.Package_name.Get(ctx)
var manifestFilePath android.Path
if opts.manifestForAapt != nil {
manifestFilePath = opts.manifestForAapt
+ } else if a.isLibrary && packageNameProp.IsPresent() && a.aaptProperties.Manifest == nil && a.aaptProperties.Additional_manifests == nil {
+ // If the only reason that a library needs a manifest file is to give the package name, allow them to do that in
+ // the module declaration. If they are already supplying a manifest, then do not autogenerate a manifest file.
+ generatedManifestPath := android.PathForModuleOut(ctx, "GeneratedManifest.xml")
+ manifestString := `<?xml version="1.0" encoding="utf-8"?>
+<!-- Automatically generated by Soong. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="` + packageNameProp.Get() + `" />
+`
+ android.WriteFileRule(ctx, generatedManifestPath, manifestString)
+ ctx.SetOutputFiles([]android.Path{generatedManifestPath}, ".gen_xml")
+ manifestFilePath = generatedManifestPath
} else {
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestFilePath = android.PathForModuleSrc(ctx, manifestFile)
@@ -975,6 +1004,17 @@ func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ packageNameProp := a.aaptProperties.Package_name.Get(ctx)
+ if packageNameProp.IsPresent() {
+ if a.aaptProperties.Manifest != nil {
+ ctx.PropertyErrorf("package_name", "cannot be used with `manifest`")
+ return
+ }
+ if a.aaptProperties.Additional_manifests != nil {
+ ctx.PropertyErrorf("package_name", "cannot be used with `additional_manifests`")
+ return
+ }
+ }
a.aapt.isLibrary = true
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
if a.usesLibrary.shouldDisableDexpreopt {
@@ -1042,6 +1082,7 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
var res android.Paths
if a.androidLibraryProperties.BuildAAR {
BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
+ android.SetProvider(ctx, AARProvider, AARInfo{Aar: a.aarFile})
}
prebuiltJniPackages := android.Paths{}
@@ -1070,6 +1111,11 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
a.setOutputFiles(ctx)
buildComplianceMetadata(ctx)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ moduleInfoJSON.ClassesJar = []string{a.Library.implementationAndResourcesJar.String()}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (a *AndroidLibrary) setOutputFiles(ctx android.ModuleContext) {
@@ -1086,6 +1132,8 @@ func (a *aapt) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
if a.rJar != nil {
dpInfo.Jars = append(dpInfo.Jars, a.rJar.String())
}
+ dpInfo.Asset_dirs = append(dpInfo.Asset_dirs, a.assetDirs.Strings()...)
+ dpInfo.Resource_dirs = append(dpInfo.Resource_dirs, a.resourceDirs.Strings()...)
}
// android_library builds and links sources into a `.jar` file for the device along with Android resources.
@@ -1248,10 +1296,6 @@ func (a *AARImport) Name() string {
return a.prebuilt.Name(a.ModuleBase.Name())
}
-func (a *AARImport) JacocoReportClassesFile() android.Path {
- return nil
-}
-
func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
if !ctx.Config().AlwaysUsePrebuiltSdks() {
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
@@ -1267,6 +1311,7 @@ func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs.GetOrDefault(ctx, nil)...)
a.usesLibrary.deps(ctx, false)
+ a.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
type JniPackageInfo struct {
@@ -1585,6 +1630,11 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar")
buildComplianceMetadata(ctx)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ moduleInfoJSON.ClassesJar = []string{a.implementationAndResourcesJarFile.String()}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (a *AARImport) HeaderJars() android.Paths {
@@ -1656,5 +1706,12 @@ func AARImportFactory() android.Module {
}
func (a *AARImport) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- dpInfo.Jars = append(dpInfo.Jars, a.implementationJarFile.String(), a.rJar.String())
+ dpInfo.Jars = append(dpInfo.Jars, a.implementationJarFile.String(), a.rJar.String(), a.aarPath.String())
+ dpInfo.Static_libs = append(dpInfo.Static_libs, a.properties.Static_libs.GetOrDefault(ctx, nil)...)
+}
+
+type AARInfo struct {
+ Aar android.Path
}
+
+var AARProvider = blueprint.NewProvider[AARInfo]()
diff --git a/java/aar_test.go b/java/aar_test.go
index 088ad6c92..520759682 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -131,7 +131,7 @@ func TestLibraryFlagsPackages(t *testing.T) {
android.AssertStringDoesContain(t,
"aapt2 link command expected to pass feature flags arguments",
linkInFlags,
- "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/bar/aconfig-flags.txt --feature-flags @out/soong/.intermediates/baz/aconfig-flags.txt",
)
}
@@ -181,3 +181,29 @@ func TestAndroidLibraryOutputFilesRel(t *testing.T) {
android.AssertStringEquals(t, "baz relative output path",
"baz.jar", bazOutputPaths[0].Rel())
}
+
+func TestAndroidLibraryManifests(t *testing.T) {
+ t.Parallel()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ package_name: "com.android.foo",
+ java_resources: ["foo.txt"],
+ }
+ `)
+
+ foo := result.ModuleForTests(t, "foo", "android_common")
+
+ fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
+
+ android.AssertPathsRelativeToTopEquals(t, "foo manifest path",
+ []string{"out/soong/.intermediates/foo/android_common/GeneratedManifest.xml"},
+ foo.OutputFiles(result.TestContext, t, ".gen_xml"))
+ android.AssertPathsRelativeToTopEquals(t, "foo output path",
+ []string{"out/soong/.intermediates/foo/android_common/withres/foo.jar"}, fooOutputPaths)
+
+ android.AssertStringEquals(t, "foo relative output path",
+ "foo.jar", fooOutputPaths[0].Rel())
+}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 7dd95c9ac..a7453ee6b 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -68,7 +68,7 @@ func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionLev
return false
}
// If this a module targeting an unreleased SDK (MTS or unbundled builds), return 10000
- return targetSdkVersionLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
+ return targetSdkVersionLevel.IsPreview() && (ctx.Config().HasUnbundledBuildApps() || includedInMts(ctx.Module()))
}
// Helper function that returns true if android_test, android_test_helper_app, java_test are in an MTS suite.
diff --git a/java/androidmk.go b/java/androidmk.go
index f155232de..97707d76b 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -102,8 +102,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
- if library.jacocoReportClassesFile != nil {
- entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
+ if library.jacocoInfo.ReportClassesFile != nil {
+ entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoInfo.ReportClassesFile)
}
requiredUsesLibs, optionalUsesLibs := library.classLoaderContexts.UsesLibs()
@@ -113,8 +113,6 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", library.dexer.proguardUsageZip)
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
- entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
-
if library.dexpreopter.configPath != nil {
entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
}
@@ -336,8 +334,8 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if app.bundleFile != nil {
entries.SetPath("LOCAL_SOONG_BUNDLE", app.bundleFile)
}
- if app.jacocoReportClassesFile != nil {
- entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile)
+ if app.jacocoInfo.ReportClassesFile != nil {
+ entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoInfo.ReportClassesFile)
}
entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary)
entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", app.dexer.proguardUsageZip)
@@ -359,7 +357,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
if app.embeddedJniLibs {
- jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
+ jniSymbols := JNISymbolsInstalls(app.jniLibs, app.installPathForJNISymbols.String())
entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
} else {
var names []string
@@ -383,8 +381,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
}
- entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
-
entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", app.logtagsSrcs.Strings()...)
},
},
diff --git a/java/apkcerts.go b/java/apkcerts.go
new file mode 100644
index 000000000..8aba27b9d
--- /dev/null
+++ b/java/apkcerts.go
@@ -0,0 +1,126 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "android/soong/android"
+ "fmt"
+ "slices"
+ "strings"
+
+ "github.com/google/blueprint"
+)
+
+func init() {
+ android.InitRegistrationContext.RegisterParallelSingletonType("apkcerts_singleton", apkCertsSingletonFactory)
+}
+
+// Info that should be included into the apkcerts.txt file.
+// The info can be provided as either a text file containing a subset of the final apkcerts.txt,
+// or as a certificate and name. The text file will be preferred if it exists
+type ApkCertInfo struct {
+ ApkCertsFile android.Path
+
+ Certificate Certificate
+ Name string
+
+ // True if LOCAL_MODULE_TAGS would contain "tests" in a make build.
+ // In make this caused the partition in the apkcerts.txt file to be "data" instead of "system"
+ Test bool
+}
+
+var ApkCertInfoProvider = blueprint.NewProvider[ApkCertInfo]()
+
+type ApkCertsInfo []ApkCertInfo
+
+var ApkCertsInfoProvider = blueprint.NewProvider[ApkCertsInfo]()
+
+func apkCertsSingletonFactory() android.Singleton {
+ return &apkCertsSingleton{}
+}
+
+type apkCertsSingleton struct{}
+
+func (a *apkCertsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ apkCerts := []string{}
+ var apkCertsFiles android.Paths
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
+ commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider)
+ if !ok || commonInfo.SkipAndroidMkProcessing {
+ return
+ }
+ if info, ok := android.OtherModuleProvider(ctx, m, android.HideApexVariantFromMakeProvider); ok && info.HideApexVariantFromMake {
+ return
+ }
+
+ partition := commonInfo.PartitionTag
+
+ specifiesPartition := commonInfo.SocSpecific || commonInfo.Vendor ||
+ commonInfo.Proprietary || commonInfo.SystemExtSpecific || commonInfo.ProductSpecific ||
+ commonInfo.DeviceSpecific
+
+ if info, ok := android.OtherModuleProvider(ctx, m, ApkCertsInfoProvider); ok {
+ for _, certInfo := range info {
+ if certInfo.ApkCertsFile != nil {
+ apkCertsFiles = append(apkCertsFiles, certInfo.ApkCertsFile)
+ } else {
+ // Partition information of apk-in-apex is not exported to the legacy Make packaging system.
+ // Hardcode the partition to "system"
+ apkCerts = append(apkCerts, FormatApkCertsLine(certInfo.Certificate, certInfo.Name, "system"))
+ }
+ }
+ } else if info, ok := android.OtherModuleProvider(ctx, m, ApkCertInfoProvider); ok {
+ if info.ApkCertsFile != nil {
+ apkCertsFiles = append(apkCertsFiles, info.ApkCertsFile)
+ } else {
+ // From base_rules.mk
+ if info.Test && partition == "system" && !specifiesPartition {
+ partition = "data"
+ }
+
+ apkCerts = append(apkCerts, FormatApkCertsLine(info.Certificate, info.Name, partition))
+ }
+ }
+ })
+ slices.Sort(apkCerts) // sort by name
+ apkCertsInfoWithoutAppSets := android.PathForOutput(ctx, "apkcerts_singleton", "apkcerts_without_app_sets.txt")
+ android.WriteFileRule(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n"))
+ apkCertsInfo := ApkCertsFile(ctx)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CatAndSortAndUnique,
+ Description: "combine apkcerts.txt",
+ Output: apkCertsInfo,
+ Inputs: append(apkCertsFiles, apkCertsInfoWithoutAppSets),
+ })
+}
+
+func (s *apkCertsSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("SOONG_APKCERTS_FILE", ApkCertsFile(ctx).String())
+}
+
+func ApkCertsFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "apkcerts_singleton", "apkcerts.txt")
+}
+
+func FormatApkCertsLine(cert Certificate, name, partition string) string {
+ pem := cert.AndroidMkString()
+ var key string
+ if cert.Key == nil {
+ key = ""
+ } else {
+ key = cert.Key.String()
+ }
+ return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
+}
diff --git a/java/app.go b/java/app.go
index 8ed0b46f4..cb1f36fa5 100644
--- a/java/app.go
+++ b/java/app.go
@@ -78,15 +78,20 @@ type AppInfo struct {
Privileged bool
OutputFile android.Path
InstallApkName string
- JacocoReportClassesFile android.Path
+ JacocoInfo JacocoInfo
Certificate Certificate
PrivAppAllowlist android.OptionalPath
OverriddenManifestPackageName *string
ApkCertsFile android.Path
+ JniLibs []jniLib
+ JniCoverageOutputs android.Paths
+ PackedAdditionalOutputs android.Path
}
var AppInfoProvider = blueprint.NewProvider[*AppInfo]()
+type AppInfos []AppInfo
+
// AndroidManifest.xml merging
// package splits
@@ -413,11 +418,18 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon
TestOnly: true,
})
appInfo := &AppInfo{
- Updatable: Bool(a.appProperties.Updatable),
- TestHelperApp: true,
+ Updatable: Bool(a.appProperties.Updatable),
+ TestHelperApp: true,
+ JniLibs: a.jniLibs,
+ JniCoverageOutputs: a.jniCoverageOutputs,
}
setCommonAppInfo(appInfo, a)
android.SetProvider(ctx, AppInfoProvider, appInfo)
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: appInfo.Certificate,
+ Name: appInfo.InstallApkName + ".apk",
+ Test: true,
+ })
moduleInfoJSON := ctx.ModuleInfoJSON()
moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
@@ -427,11 +439,43 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon
moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
}
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: a.appTestHelperAppProperties.Test_suites,
+ var data []android.DataPath
+ for _, d := range a.extraOutputFiles {
+ data = append(data, android.DataPath{SrcPath: d})
+ }
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: a.appTestHelperAppProperties.Test_suites,
+ MainFile: a.outputFile,
+ MainFileStem: a.installApkName,
+ MainFileExt: ".apk",
+ NeedsArchFolder: true,
+ NonArchData: data,
+ PerTestcaseDirectory: proptools.Bool(a.appTestHelperAppProperties.Per_testcase_directory),
+ DisableTestConfig: true,
})
}
+func (a *AndroidApp) baseSymbolInfo(ctx android.ModuleContext) *cc.SymbolInfo {
+ return &cc.SymbolInfo{
+ Name: a.BaseModuleName(),
+ ModuleDir: ctx.ModuleDir(),
+ Uninstallable: a.IsSkipInstall() || !proptools.BoolDefault(a.properties.Installable, true) || a.NoFullInstall(),
+ }
+}
+
+func (a *AndroidApp) GetJniSymbolInfos(ctx android.ModuleContext, JniSymbolInstallPath android.Path) []*cc.SymbolInfo {
+ infos := []*cc.SymbolInfo{}
+ for _, install := range JNISymbolsInstalls(a.jniLibs, JniSymbolInstallPath.String()) {
+ info := a.baseSymbolInfo(ctx)
+ info.UnstrippedBinaryPath = install.From
+ info.ModuleDir = filepath.Dir(install.To)
+ info.InstalledStem = filepath.Base(install.To)
+
+ infos = append(infos, info)
+ }
+ return infos
+}
+
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkAppSdkVersions(ctx)
a.checkEmbedJnis(ctx)
@@ -452,15 +496,21 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
EmbeddedJNILibs: embeddedJniLibs,
MergedManifestFile: a.mergedManifest,
OverriddenManifestPackageName: &overriddenName,
+ JniLibs: a.jniLibs,
+ JniCoverageOutputs: a.jniCoverageOutputs,
}
setCommonAppInfo(appInfo, a)
android.SetProvider(ctx, AppInfoProvider, appInfo)
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: appInfo.Certificate,
+ Name: appInfo.InstallApkName + ".apk",
+ })
a.requiredModuleNames = a.getRequiredModuleNames(ctx)
if a.dexer.proguardDictionary.Valid() {
android.SetProvider(ctx, ProguardProvider, ProguardInfo{
- ModuleName: ctx.ModuleName(),
+ ModuleName: android.ModuleNameWithPossibleOverride(ctx),
Class: "APPS",
ProguardDictionary: a.dexer.proguardDictionary.Path(),
ProguardUsageZip: a.dexer.proguardUsageZip.Path(),
@@ -836,9 +886,9 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages andro
return jniJarFile
}
-func (a *AndroidApp) JNISymbolsInstalls(installPath string) android.RuleBuilderInstalls {
+func JNISymbolsInstalls(jniLibs []jniLib, installPath string) android.RuleBuilderInstalls {
var jniSymbols android.RuleBuilderInstalls
- for _, jniLib := range a.jniLibs {
+ for _, jniLib := range jniLibs {
if jniLib.unstrippedFile != nil {
jniSymbols = append(jniSymbols, android.RuleBuilderInstall{
From: jniLib.unstrippedFile,
@@ -937,12 +987,17 @@ func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.P
}
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
+ a.jacocoInfo.Class = "APPS"
+
var apkDeps android.Paths
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
}
+ android.SetProvider(ctx, android.HideApexVariantFromMakeProvider, android.HideApexVariantFromMakeInfo{
+ HideApexVariantFromMake: a.hideApexVariantFromMake,
+ })
a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
@@ -1011,7 +1066,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.linter.mergedManifest = a.aapt.mergedManifestFile
a.linter.manifest = a.aapt.manifestPath
a.linter.resources = a.aapt.resourceFiles
- a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
+ a.linter.buildModuleReportZip = ctx.Config().HasUnbundledBuildApps()
dexJarFile, packageResources, javaInfo := a.dexBuildActions(ctx)
@@ -1079,6 +1134,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
bundleFile := android.PathForModuleOut(ctx, "base.zip")
BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
a.bundleFile = bundleFile
+ android.SetProvider(ctx, BundleProvider, BundleInfo{Bundle: bundleFile})
allowlist := a.createPrivappAllowlist(ctx)
if allowlist != nil {
@@ -1115,7 +1171,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
}
}
}
- ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
+ a.installedOutputFile = ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
}
ctx.CheckbuildFile(a.outputFile)
@@ -1151,6 +1207,14 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.setOutputFiles(ctx)
buildComplianceMetadata(ctx)
+
+ if !a.hideApexVariantFromMake && !a.IsHideFromMake() {
+ if a.embeddedJniLibs {
+ cc.CopySymbolsAndSetSymbolsInfoProvider(ctx, &cc.SymbolInfos{
+ Symbols: a.GetJniSymbolInfos(ctx, a.installPathForJNISymbols),
+ })
+ }
+ }
}
func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) {
@@ -1323,7 +1387,7 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) {
// Skip dependencies that are only available to APEXes; they are developed with updatability
// in mind and don't need manual approval.
- if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform {
+ if android.OtherModuleProviderOrDefault(ctx, to, android.PlatformAvailabilityInfoProvider).NotAvailableToPlatform {
return true
}
@@ -1458,7 +1522,7 @@ func AndroidAppFactory() android.Module {
return
}
- rroPackageName := a.Name() + "__" + strings.ReplaceAll(characteristics, ",", "_") + "__auto_generated_characteristics_rro"
+ rroPackageName := AutogeneratedProductCharacteristicsRroModuleName(ctx, a.Name())
rroManifestName := rroPackageName + "_manifest"
a.appProperties.ProductCharacteristicsRROPackageName = proptools.StringPtr(rroPackageName)
@@ -1511,7 +1575,19 @@ func AndroidAppFactory() android.Module {
}
func AutogeneratedRroModuleName(ctx android.EarlyModuleContext, moduleName, partition string) string {
- return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().DeviceProduct(), partition)
+ // auto_generated_rro is installed to the product or vendor partition and
+ // are specific to target product. To add the auto_generated_rro to the
+ // required list of the original app module, the target product name is
+ // required.
+ // TODO(b/412526509): Remove the rro dependency from the system partition.
+ // So, the original system module does not need to know the target product
+ // name. Instead, add a reverse dependency from the rro to the original
+ // system module to see if the module exists.
+ return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().Getenv("TARGET_PRODUCT"), partition)
+}
+
+func AutogeneratedProductCharacteristicsRroModuleName(ctx android.EarlyModuleContext, moduleName string) string {
+ return moduleName + "__" + strings.ReplaceAll(ctx.Config().ProductAAPTCharacteristics(), ",", "_") + "__auto_generated_characteristics_rro"
}
type createModuleContext interface {
@@ -1646,6 +1722,12 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
a.generateAndroidBuildActions(ctx)
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: a.Certificate(),
+ Name: a.InstallApkName() + ".apk",
+ Test: true,
+ })
+
for _, c := range a.testProperties.Test_options.Tradefed_options {
configs = append(configs, c)
}
@@ -1664,22 +1746,29 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...)
a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Host_common_data)...)
- // Install test deps
- if !ctx.Config().KatiEnabled() {
- pathInTestCases := android.PathForModuleInstall(ctx, ctx.Module().Name())
- if a.testConfig != nil {
- ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig)
- }
- dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
- if dynamicConfig.Valid() {
- ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path())
- }
- testDeps := append(a.data, a.extraTestConfigs...)
- for _, data := range android.SortedUniquePaths(testDeps) {
- dataPath := android.DataPath{SrcPath: data}
- ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath})
- }
- }
+ a.data = android.SortedUniquePaths(a.data)
+ a.extraTestConfigs = android.SortedUniquePaths(a.extraTestConfigs)
+
+ var testData []android.DataPath
+ for _, data := range a.data {
+ dataPath := android.DataPath{SrcPath: data}
+ testData = append(testData, dataPath)
+ }
+ for _, d := range a.extraOutputFiles {
+ testData = append(testData, android.DataPath{SrcPath: d})
+ }
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: a.testProperties.Test_suites,
+ MainFile: a.outputFile,
+ MainFileStem: a.installApkName,
+ MainFileExt: ".apk",
+ ConfigFile: a.testConfig,
+ ExtraConfigs: a.extraTestConfigs,
+ NonArchData: testData,
+ CompatibilitySupportFiles: a.data,
+ NeedsArchFolder: true,
+ PerTestcaseDirectory: proptools.Bool(a.testProperties.Per_testcase_directory),
+ })
android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
TestcaseRelDataFiles: testcaseRel(a.data),
@@ -1714,10 +1803,6 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
moduleInfoJSON.AutoTestConfig = []string{"true"}
}
moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...)
-
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: a.testProperties.Test_suites,
- })
}
func testcaseRel(paths android.Paths) []string {
@@ -2047,14 +2132,31 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo
}
}
+func (u *usesLibrary) depsFromLibs(ctx android.BottomUpMutatorContext, libDeps []android.Module) {
+ // For library dependencies that are component libraries (like stubs), add the implementation
+ // as a dependency (dexpreopt needs to be against the implementation library, not stubs).
+ for _, dep := range libDeps {
+ if dep != nil {
+ if component, ok := android.OtherModuleProvider(ctx, dep, SdkLibraryComponentDependencyInfoProvider); ok {
+ if lib := component.OptionalSdkLibraryImplementation; lib != nil {
+ // Add library as optional if it's one of the optional compatibility libs or it's
+ // explicitly listed in the optional_uses_libs property.
+ tag := usesLibReqTag
+ if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
+ android.InList(*lib, u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) {
+ tag = usesLibOptTag
+ }
+ ctx.AddVariationDependencies(nil, tag, *lib)
+ }
+ }
+ }
+ }
+}
+
// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree.
func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), func(s string) bool {
- exists := ctx.OtherModuleExists(s)
- if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) {
- fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s)
- }
- return exists
+ return ctx.OtherModuleExists(s)
})
return optionalUsesLibs
}
@@ -2085,7 +2187,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
// Skip stub libraries. A dependency on the implementation library has been added earlier,
// so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed
// from implementation libraries by their name, which is different as it has a suffix.
- if comp := javaInfo.SdkLibraryComponentDependencyInfo; comp != nil {
+ if comp, ok := android.OtherModuleProvider(ctx, m, SdkLibraryComponentDependencyInfoProvider); ok {
if impl := comp.OptionalSdkLibraryImplementation; impl != nil && *impl != dep {
return
}
@@ -2180,6 +2282,10 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a
cmd.FlagWithArg("--missing-optional-uses-library ", lib)
}
+ for _, lib := range ctx.Config().BootJars() {
+ cmd.FlagWithArg("--bootclasspath-libs ", lib)
+ }
+
rule.Build("verify_uses_libraries", "verify <uses-library>")
return outputFile
}
@@ -2206,7 +2312,7 @@ type androidApp interface {
Privileged() bool
InstallApkName() string
OutputFile() android.Path
- JacocoReportClassesFile() android.Path
+ JacocoInfo() JacocoInfo
Certificate() Certificate
BaseModuleName() string
PrivAppAllowlist() android.OptionalPath
@@ -2220,11 +2326,13 @@ func setCommonAppInfo(appInfo *AppInfo, m androidApp) {
appInfo.Privileged = m.Privileged()
appInfo.OutputFile = m.OutputFile()
appInfo.InstallApkName = m.InstallApkName()
- appInfo.JacocoReportClassesFile = m.JacocoReportClassesFile()
+ appInfo.JacocoInfo = m.JacocoInfo()
appInfo.Certificate = m.Certificate()
appInfo.PrivAppAllowlist = m.PrivAppAllowlist()
}
-type AppInfos []AppInfo
+type BundleInfo struct {
+ Bundle android.Path
+}
-var AppInfosProvider = blueprint.NewProvider[AppInfos]()
+var BundleProvider = blueprint.NewProvider[BundleInfo]()
diff --git a/java/app_import.go b/java/app_import.go
index 9fb13ba3c..93686a991 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -105,8 +105,6 @@ type AndroidAppImport struct {
installPath android.InstallPath
hideApexVariantFromMake bool
-
- provenanceMetaDataFile android.Path
}
type AndroidAppImportProperties struct {
@@ -122,7 +120,7 @@ type AndroidAppImportProperties struct {
// Set this flag to true if the prebuilt apk is already signed. The certificate property must not
// be set for presigned modules.
- Presigned *bool
+ Presigned proptools.Configurable[bool] `android:"replace_instead_of_append"`
// Name of the signing certificate lineage file or filegroup module.
Lineage *string `android:"path"`
@@ -157,7 +155,7 @@ type AndroidAppImportProperties struct {
Relative_install_path *string
// Whether the prebuilt apk can be installed without additional processing. Default is false.
- Preprocessed *bool
+ Preprocessed proptools.Configurable[bool] `android:"replace_instead_of_append"`
// Whether or not to skip checking the preprocessed apk for proper alignment and uncompressed
// JNI libs and dex files. Default is false
@@ -289,7 +287,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
// Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
// with them may invalidate pre-existing signature data.
- if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || Bool(a.properties.Preprocessed)) {
+ if ctx.InstallInTestcases() && (a.properties.Presigned.GetOrDefault(ctx, false) || a.properties.Preprocessed.GetOrDefault(ctx, false)) {
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Output: outputPath,
@@ -320,7 +318,7 @@ func (a *AndroidAppImport) extractSubApk(
// Returns whether this module should have the dex file stored uncompressed in the APK.
func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
- if ctx.Config().UnbundledBuild() || proptools.Bool(a.properties.Preprocessed) {
+ if ctx.Config().UnbundledBuild() || a.properties.Preprocessed.GetOrDefault(ctx, false) {
return false
}
@@ -355,11 +353,19 @@ func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch(
func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.generateAndroidBuildActions(ctx)
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"APPS"}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+
appInfo := &AppInfo{
Prebuilt: true,
}
setCommonAppInfo(appInfo, a)
android.SetProvider(ctx, AppInfoProvider, appInfo)
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: appInfo.Certificate,
+ Name: appInfo.InstallApkName + ".apk",
+ })
}
func (a *AndroidAppImport) InstallApkName() string {
@@ -380,19 +386,18 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
a.hideApexVariantFromMake = true
}
- if Bool(a.properties.Preprocessed) {
- if a.properties.Presigned != nil && !*a.properties.Presigned {
+ if a.properties.Preprocessed.GetOrDefault(ctx, false) {
+ if !a.properties.Presigned.GetOrDefault(ctx, true) {
ctx.ModuleErrorf("Setting preprocessed: true implies presigned: true, so you cannot set presigned to false")
}
- t := true
- a.properties.Presigned = &t
+ a.properties.Presigned.AppendSimpleValue(true)
}
numCertPropsSet := 0
if a.properties.Certificate.GetOrDefault(ctx, "") != "" {
numCertPropsSet++
}
- if Bool(a.properties.Presigned) {
+ if a.properties.Presigned.GetOrDefault(ctx, false) {
numCertPropsSet++
}
if Bool(a.properties.Default_dev_cert) {
@@ -438,7 +443,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
installDir := android.PathForModuleInstall(ctx, pathFragments...)
a.dexpreopter.isApp = true
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
- a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
+ a.dexpreopter.isPresignedPrebuilt = a.properties.Presigned.GetOrDefault(ctx, false)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
@@ -476,7 +481,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
// Sign or align the package if package has not been preprocessed
- if proptools.Bool(a.properties.Preprocessed) {
+ if a.properties.Preprocessed.GetOrDefault(ctx, false) {
validationStamp := a.validatePresignedApk(ctx, srcApk)
output := android.PathForModuleOut(ctx, apkFilename)
ctx.Build(pctx, android.BuildParams{
@@ -487,7 +492,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
})
a.outputFile = output
a.certificate = PresignedCertificate
- } else if !Bool(a.properties.Presigned) {
+ } else if !a.properties.Presigned.GetOrDefault(ctx, false) {
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
_, _, certificates := collectAppDeps(ctx, a, false, false)
@@ -524,7 +529,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
artifactPath := android.PathForModuleSrc(ctx, a.properties.Apk.GetOrDefault(ctx, ""))
- a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
+ provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
providePrebuiltInfo(ctx,
@@ -554,7 +559,7 @@ func (a *AndroidAppImport) validatePresignedApk(ctx android.ModuleContext, srcAp
if proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
extraArgs = append(extraArgs, "--skip-preprocessed-apk-checks")
}
- if proptools.Bool(a.properties.Preprocessed) {
+ if a.properties.Preprocessed.GetOrDefault(ctx, false) {
extraArgs = append(extraArgs, "--preprocessed")
}
@@ -581,18 +586,14 @@ func (a *AndroidAppImport) OutputFile() android.Path {
return a.outputFile
}
-func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
- return nil
+func (a *AndroidAppImport) JacocoInfo() JacocoInfo {
+ return JacocoInfo{}
}
func (a *AndroidAppImport) Certificate() Certificate {
return a.certificate
}
-func (a *AndroidAppImport) ProvenanceMetaDataFile() android.Path {
- return a.provenanceMetaDataFile
-}
-
func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath {
return android.OptionalPath{}
}
@@ -788,8 +789,24 @@ func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContex
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: a.testProperties.Test_suites,
+ var data []android.DataPath
+ for _, d := range a.data {
+ data = append(data, android.DataPath{SrcPath: d})
+ }
+
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: a.testProperties.Test_suites,
+ MainFile: a.outputFile,
+ MainFileStem: a.outputFile.Base(),
+ NeedsArchFolder: true,
+ Data: data,
+ CompatibilitySupportFiles: a.data,
+ })
+
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: a.Certificate(),
+ Name: a.InstallApkName() + ".apk",
+ Test: true,
})
}
diff --git a/java/app_set.go b/java/app_set.go
index 6a2c678a8..e7bef6e4f 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -131,7 +131,7 @@ type prebuiltInfoProps struct {
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
// with information about whether source or prebuilt of an apex was used during the build.
func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
- info := android.PrebuiltInfo{
+ info := android.PrebuiltJsonInfo{
Name: p.baseModuleName,
Is_prebuilt: p.isPrebuilt,
}
@@ -140,7 +140,7 @@ func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo)
info.Prebuilt_info_file_path = prebuiltInfoFile.String()
}
- android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+ android.SetProvider(ctx, android.PrebuiltJsonInfoProvider, info)
}
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -193,9 +193,13 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext)
)
android.SetProvider(ctx, AppInfoProvider, &AppInfo{
- AppSet: true,
- Privileged: as.Privileged(),
- OutputFile: as.OutputFile(),
+ AppSet: true,
+ Privileged: as.Privileged(),
+ OutputFile: as.OutputFile(),
+ ApkCertsFile: as.apkcertsFile,
+ PackedAdditionalOutputs: as.packedOutput,
+ })
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
ApkCertsFile: as.apkcertsFile,
})
}
diff --git a/java/app_test.go b/java/app_test.go
index a8b39b7d1..a33c6b10c 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -15,6 +15,8 @@
package java
import (
+ "encoding/json"
+ "errors"
"fmt"
"path/filepath"
"reflect"
@@ -3475,9 +3477,6 @@ func TestUsesLibraries(t *testing.T) {
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildWarningBadOptionalUsesLibsAllowlist = []string{"app", "prebuilt"}
- }),
).RunTestWithBp(t, bp)
app := result.ModuleForTests(t, "app", "android_common")
@@ -3532,6 +3531,178 @@ func TestUsesLibraries(t *testing.T) {
"--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/app/product_packages.txt")
}
+func extractContextJson(cmd string) (map[string]interface{}, error) {
+ var clc map[string]interface{}
+ for _, flag := range strings.Split(cmd, " ") {
+ if value, match := strings.CutPrefix(flag, "--context-json='"); match {
+ value = strings.TrimSuffix(value, "'")
+ if err := json.Unmarshal([]byte(value), &clc); err != nil {
+ return nil, err
+ }
+ return clc, nil
+ }
+ }
+ return nil, errors.New("--context-json not found")
+}
+
+func TestClassLoaderContext_SdkLibrary(t *testing.T) {
+ bp := `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ sdk_version: "current",
+ uses_libs: ["bar"],
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["b.java"],
+ api_packages: ["bar"],
+ sdk_version: "current",
+ }
+
+ android_app {
+ name: "app",
+ srcs: ["app.java"],
+ libs: ["foo.stubs"],
+ uses_libs: ["foo"],
+ sdk_version: "current",
+ }
+
+ android_app {
+ name: "app2",
+ srcs: ["app.java"],
+ libs: ["foo.impl"],
+ uses_libs: ["foo"],
+ sdk_version: "current",
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo", "bar"),
+ ).RunTestWithBp(t, bp)
+
+ {
+ fooXml := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml")
+ fooXmlContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooXml)
+ android.AssertStringDoesContain(t, "", fooXmlContents, `dependency="bar"`)
+ }
+
+ {
+ fooImpl := result.ModuleForTests(t, "foo.impl", "android_common")
+ cmd := fooImpl.Rule("dexpreopt").RuleParams.Command
+
+ clc, err := extractContextJson(cmd)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ deps := clc["any"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(deps))
+ bar := deps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "bar", bar["Name"].(string))
+ }
+
+ for _, name := range []string{"app", "app2"} {
+ app := result.ModuleForTests(t, name, "android_common")
+ cmd := app.Rule("dexpreopt").RuleParams.Command
+
+ clc, err := extractContextJson(cmd)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ deps := clc["any"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(deps))
+ foo := deps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "foo", foo["Name"].(string))
+ fooDeps := foo["Subcontexts"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(fooDeps))
+ bar := fooDeps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "bar", bar["Name"].(string))
+ }
+}
+
+func TestClassLoaderContext_SdkLibrary2(t *testing.T) {
+ bp := `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ sdk_version: "current",
+ libs: ["bar.impl"],
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["b.java"],
+ api_packages: ["bar"],
+ sdk_version: "current",
+ }
+
+ android_app {
+ name: "app",
+ srcs: ["app.java"],
+ libs: ["foo.stubs"],
+ uses_libs: ["foo"],
+ sdk_version: "current",
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo", "bar"),
+ ).RunTestWithBp(t, bp)
+
+ {
+ fooXml := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml")
+ fooXmlContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooXml)
+ android.AssertStringDoesContain(t, "", fooXmlContents, `dependency="bar"`)
+ }
+
+ {
+ fooImpl := result.ModuleForTests(t, "foo.impl", "android_common")
+ cmd := fooImpl.Rule("dexpreopt").RuleParams.Command
+
+ clc, err := extractContextJson(cmd)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ deps := clc["any"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(deps))
+ bar := deps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "bar", bar["Name"].(string))
+ }
+
+ {
+ app := result.ModuleForTests(t, "app", "android_common")
+ cmd := app.Rule("dexpreopt").RuleParams.Command
+
+ clc, err := extractContextJson(cmd)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ deps := clc["any"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(deps))
+ foo := deps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "foo", foo["Name"].(string))
+ fooDeps := foo["Subcontexts"].([]interface{})
+ android.AssertIntEquals(t, "", 1, len(fooDeps))
+ bar := fooDeps[0].(map[string]interface{})
+ android.AssertStringEquals(t, "", "bar", bar["Name"].(string))
+ }
+}
+
func TestDexpreoptBcp(t *testing.T) {
t.Parallel()
bp := `
@@ -4578,7 +4749,7 @@ func TestAppFlagsPackages(t *testing.T) {
android.AssertStringDoesContain(t,
"aapt2 link command expected to pass feature flags arguments",
linkInFlags,
- "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/bar/aconfig-flags.txt --feature-flags @out/soong/.intermediates/baz/aconfig-flags.txt",
)
aapt2CompileRule := foo.Rule("android/soong/java.aapt2Compile")
@@ -4586,7 +4757,7 @@ func TestAppFlagsPackages(t *testing.T) {
android.AssertStringDoesContain(t,
"aapt2 compile command expected to pass feature flags arguments",
compileFlags,
- "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/bar/aconfig-flags.txt --feature-flags @out/soong/.intermediates/baz/aconfig-flags.txt",
)
}
@@ -4658,12 +4829,12 @@ func TestAppFlagsPackagesPropagation(t *testing.T) {
android.AssertStringDoesContain(t,
"aapt2 link command expected to pass feature flags arguments of flags_packages and that of its static libs",
linkInFlags,
- "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/bar/aconfig-flags.txt --feature-flags @out/soong/.intermediates/baz/aconfig-flags.txt",
)
android.AssertStringDoesNotContain(t,
"aapt2 link command expected to not pass feature flags arguments of flags_packages of its libs",
linkInFlags,
- "--feature-flags @out/soong/.intermediates/foo/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/foo/aconfig-flags.txt",
)
}
@@ -4902,6 +5073,7 @@ func TestResourcesWithFlagDirectories(t *testing.T) {
"res/flag(!test.package.flag2)/values/bools.xml": nil,
"res/flag(test.package.flag1)/values-config/strings_google_services.xml": nil,
"res/flags(test.package.flag1)/values/strings.xml": nil,
+ "res/drawable/flag(test.package.flag1)/qs_flashlight_icon_off.xml": nil,
}),
).RunTestWithBp(t, `
android_library {
@@ -4940,6 +5112,12 @@ func TestResourcesWithFlagDirectories(t *testing.T) {
compileOutputPaths,
"out/soong/.intermediates/foo/android_common/aapt2/res/values_strings.(test.package.flag1).arsc.flat",
)
+ android.AssertStringListContains(
+ t,
+ "Expected to generate flag path when it is a subdirectory of resource type subdirectory",
+ compileOutputPaths,
+ "out/soong/.intermediates/foo/android_common/aapt2/res/drawable_qs_flashlight_icon_off.(test.package.flag1).xml.flat",
+ )
}
func TestAutogeneratedStaticRro(t *testing.T) {
diff --git a/java/base.go b/java/base.go
index 8aa0109d0..7d56522b9 100644
--- a/java/base.go
+++ b/java/base.go
@@ -15,7 +15,6 @@
package java
import (
- "encoding/gob"
"fmt"
"path/filepath"
"reflect"
@@ -33,6 +32,8 @@ import (
"android/soong/java/config"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// This file contains the definition and the implementation of the base module that most
// source-based Java module structs embed.
@@ -94,12 +95,18 @@ type CommonProperties struct {
// See kotlinc's `-language-version` flag.
Kotlin_lang_version *string
+ // Whether this target supports compilation with the kotlin-incremental-client.
+ Kotlin_incremental *bool
+
// list of java libraries that will be in the classpath
Libs []string `android:"arch_variant"`
// list of java libraries that will be compiled into the resulting jar
Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
+ // List of Kotlin libraries whose `internal` members are accessible to this library
+ Associates []string `android:"arch_variant"`
+
// manifest file to be included in resulting jar
Manifest *string `android:"path"`
@@ -229,6 +236,11 @@ type CommonProperties struct {
// If true, then only the headers are built and not the implementation jar.
Headers_only *bool
+ // If specified, this is used for this library's header jar, rather than generating it. This
+ // should only be used if the library adds nothing new to the header jars vs the provided path.
+ // For example, this could be used if the module only adds implementation code.
+ Header_jar_override string `android:"path,arch_variant"`
+
// A list of files or dependencies to make available to the build sandbox. This is
// useful if source files are symlinks, the targets of the symlinks must be listed here.
// Note that currently not all actions implemented by android_apps are sandboxed, so you
@@ -251,6 +263,9 @@ type CommonProperties struct {
// If true, the "Ravenizer" tool will remove all Mockito and DexMaker
// classes from the output jar.
Strip_mockito *bool
+
+ // Extra arguments passed to Ravenizer
+ Flags []string
}
// Contributing api surface of the stub module. Is not visible to bp modules, and should
@@ -505,11 +520,12 @@ type Module struct {
dexJarFile OptionalDexJarPath
// output file containing uninstrumented classes that will be instrumented by jacoco
- jacocoReportClassesFile android.Path
+ jacocoInfo JacocoInfo
// output file of the module, which may be a classes jar or a dex jar
- outputFile android.Path
- extraOutputFiles android.Paths
+ outputFile android.Path
+ installedOutputFile android.Path
+ extraOutputFiles android.Paths
exportAidlIncludeDirs android.Paths
ignoredAidlPermissionList android.Paths
@@ -867,6 +883,17 @@ func (j *Module) staticLibs(ctx android.BaseModuleContext) []string {
return j.properties.Static_libs.GetOrDefault(ctx, nil)
}
+func (j *Module) incrementalKotlin(config android.Config) bool {
+ incremental := proptools.BoolDefault(
+ j.properties.Kotlin_incremental, config.PartialCompileFlags().Enable_inc_kotlin)
+ nonIncrementalFlags := []string{"-Xmulti-platform", "-Xexpect-actual-classes"}
+ for _, flag := range nonIncrementalFlags {
+ incremental = incremental && !slices.Contains(j.properties.Kotlincflags, flag)
+ }
+
+ return incremental
+}
+
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if ctx.Device() {
j.linter.deps(ctx)
@@ -892,24 +919,7 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
traceRefs := j.dexProperties.Optimize.Trace_references_from.GetOrDefault(ctx, []string{})
ctx.AddVariationDependencies(nil, traceReferencesTag, traceRefs...)
- // For library dependencies that are component libraries (like stubs), add the implementation
- // as a dependency (dexpreopt needs to be against the implementation library, not stubs).
- for _, dep := range libDeps {
- if dep != nil {
- if component, ok := dep.(SdkLibraryComponentDependency); ok {
- if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
- // Add library as optional if it's one of the optional compatibility libs or it's
- // explicitly listed in the optional_uses_libs property.
- tag := usesLibReqTag
- if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
- android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) {
- tag = usesLibOptTag
- }
- ctx.AddVariationDependencies(nil, tag, *lib)
- }
- }
- }
- }
+ j.usesLibrary.depsFromLibs(ctx, libDeps)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, j.properties.Kotlin_plugins...)
@@ -943,10 +953,17 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
+ incremental := j.incrementalKotlin(ctx.Config())
if j.useCompose(ctx) {
- ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
+ if incremental {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), composeEmbeddablePluginTag,
+ "kotlin-compose-compiler-embeddable-plugin")
+ }
+ ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), composePluginTag,
"kotlin-compose-compiler-plugin")
}
+
+ j.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
func hasSrcExt(srcs []string, ext string) bool {
@@ -1152,14 +1169,6 @@ func (j *Module) collectJavacFlags(
return flags
}
-func (j *Module) AddJSONData(d *map[string]interface{}) {
- (&j.ModuleBase).AddJSONData(d)
- (*d)["Java"] = map[string]interface{}{
- "SourceExtensions": j.sourceExtensions,
- }
-
-}
-
func (j *Module) addGeneratedSrcJars(path android.Path) {
j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
}
@@ -1284,10 +1293,10 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars
- localHeaderJars, combinedHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
+ localHeaderJars, _, preJarjarHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
extraCombinedJars)
- combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false)
+ combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, preJarjarHeaderJarFile, jarName, "turbine", false)
if jarjared {
localHeaderJars = android.Paths{combinedHeaderJarFile}
transitiveStaticLibsHeaderJars = nil
@@ -1301,6 +1310,9 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
return nil
}
j.headerJarFile = combinedHeaderJarFile
+ if deps.headerJarOverride.Valid() {
+ j.headerJarFile = deps.headerJarOverride.Path()
+ }
if len(localHeaderJars) > 0 {
ctx.CheckbuildFile(localHeaderJars...)
@@ -1312,6 +1324,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
j.outputFile = j.headerJarFile
return &JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ LocalHeaderJarsPreJarjar: android.PathsIfNonNil(preJarjarHeaderJarFile),
LocalHeaderJars: localHeaderJars,
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8,
@@ -1323,6 +1336,8 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
SdkVersion: j.SdkVersion(ctx),
+ OverrideMinSdkVersion: j.overridableProperties.Min_sdk_version,
+ Installable: BoolDefault(j.properties.Installable, true),
}
}
@@ -1367,23 +1382,73 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
kotlincFlags = append(kotlincFlags, "-no-jdk")
}
+ var kotlincPluginFlags []string
for _, plugin := range deps.kotlinPlugins {
- kotlincFlags = append(kotlincFlags, "-Xplugin="+plugin.String())
+ kotlincPluginFlags = append(kotlincPluginFlags, "-Xplugin="+plugin.String())
+ }
+ if len(kotlincPluginFlags) > 0 {
+ // optimization.
+ ctx.Variable(pctx, "kotlincPluginFlags", strings.Join(kotlincPluginFlags, " "))
+ flags.kotlincPluginFlags += "$kotlincPluginFlags"
}
flags.kotlincDeps = append(flags.kotlincDeps, deps.kotlinPlugins...)
+ if deps.composePlugin.Valid() {
+ flags.composePluginFlag = "-Xplugin=" + deps.composePlugin.String()
+ ctx.Variable(pctx, "composePluginFlag", flags.composePluginFlag)
+ flags.kotlincDeps = append(flags.kotlincDeps, deps.composePlugin.Path())
+ }
+ if deps.composeEmbeddablePlugin.Valid() {
+ flags.composeEmbeddablePluginFlag = "-Xplugin=" + deps.composeEmbeddablePlugin.String()
+ ctx.Variable(pctx, "composeEmbeddablePluginFlag", flags.composeEmbeddablePluginFlag)
+ flags.kotlincDeps = append(flags.kotlincDeps, deps.composeEmbeddablePlugin.Path())
+ }
+
+ // TODO(b/403236545): Remove this once the Kotlin compiler version is >= 2.2.0.
+ if j.useCompose(ctx) {
+ kotlincFlags = append(kotlincFlags, "-P", "plugin:androidx.compose.compiler.plugins.kotlin:featureFlag=+OptimizeNonSkippingGroups")
+ }
+
if len(kotlincFlags) > 0 {
+ // Flags with `-J` as a prefix are meant to be passed to java directly.
+ // When running the kotlin-incremental-client, flags are first parsed by a bash
+ // script that eagerly takes all the leading arguments that start with `-J` and feeds
+ // them to java. Any `-J` arguments that occur elsewhere (i.e. after a non-J argument)
+ // fail to pass through to java as expected.
+ slices.SortStableFunc(kotlincFlags, func(a, b string) int {
+ aHasPrefix := strings.HasPrefix(a, "-J")
+ bHasPrefix := strings.HasPrefix(b, "-J")
+
+ // If only a has the prefix, it should come before b
+ if aHasPrefix && !bHasPrefix {
+ return -1
+ } else if bHasPrefix && !aHasPrefix {
+ return 1
+ }
+ return 0 // Otherwise maintain their order
+ })
// optimization.
ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
flags.kotlincFlags += "$kotlincFlags"
}
+ incrementalKotlin := j.incrementalKotlin(ctx.Config())
+
// Collect common .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
+ kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
+ kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
+
+ kotlinCompileData := KotlinCompileData{
+ diffFile: kotlinJar.ReplaceExtension(ctx, "source_diff"),
+ pcStateFileNew: kotlinJar.ReplaceExtension(ctx, "pc_state.new"),
+ pcStateFilePrior: kotlinJar.ReplaceExtension(ctx, "pc_state"),
+ }
+
if len(flags.processorPath) > 0 {
// Use kapt for annotation processing
kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
@@ -1396,9 +1461,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
flags.processors = nil
}
- kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
- kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
- j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags, kotlinCompileData, incrementalKotlin)
if ctx.Failed() {
return nil
}
@@ -1421,6 +1484,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
var localHeaderJars android.Paths
var shardingHeaderJars android.Paths
var repackagedHeaderJarFile android.Path
+ var combinedHeaderJarFile android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enableSharding = true
@@ -1432,9 +1496,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
}
extraJars := slices.Clone(kotlinHeaderJars)
extraJars = append(extraJars, extraCombinedJars...)
- var combinedHeaderJarFile android.Path
- localHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
- shardingHeaderJars = localHeaderJars
+ localHeaderJars, shardingHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
var jarjared bool
j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false)
@@ -1464,6 +1526,24 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
break
}
}
+
+ // turbine is disabled when API generating APs are present, in which case,
+ // we would want to process annotations before moving to incremental javac
+ var genAnnoSrcJar android.Path
+ if ctx.Device() && ctx.Config().PartialCompileFlags().Enable_inc_javac && disableTurbine {
+ srcJarsForTurbine := slices.Clone(srcJars)
+ if len(flags.processorPath) > 0 {
+ genAnnoSrcJar, _ = j.generateJavaAnnotations(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, nil)
+ flags.processorPath = nil
+ flags.processors = nil
+ srcJarsForTurbine = append(srcJarsForTurbine, genAnnoSrcJar)
+ }
+ // turbine was disabled, lets run it now
+ turbineExtraJars := slices.Clone(kotlinHeaderJars)
+ turbineExtraJars = append(turbineExtraJars, extraCombinedJars...)
+ _, shardingHeaderJars, _ = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJarsForTurbine, deps, flags, jarName, turbineExtraJars)
+ }
+
var extraJarDeps android.Paths
if Bool(j.properties.Errorprone.Enabled) {
// If error-prone is enabled, enable errorprone flags on the regular
@@ -1486,7 +1566,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
- transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, false, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1503,7 +1583,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize)
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
- nil, flags, extraJarDeps)
+ nil, nil, flags, extraJarDeps, nil)
classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
localImplementationJars = append(localImplementationJars, classes)
}
@@ -1516,13 +1596,13 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5)
for idx, shardSrcJars := range shardSrcJarsList {
classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
- nil, shardSrcJars, flags, extraJarDeps)
+ nil, shardSrcJars, nil, flags, extraJarDeps, nil)
classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
localImplementationJars = append(localImplementationJars, classes)
}
}
} else {
- classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
+ classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, shardingHeaderJars, flags, extraJarDeps, genAnnoSrcJar)
classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
localImplementationJars = append(localImplementationJars, classes)
}
@@ -1685,10 +1765,12 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
if j.ravenizer.enabled {
ravenizerInput := outputFile
ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", "", jarName)
- ravenizerArgs := ""
+
+ ravenizerArgs := j.properties.Ravenizer.Flags
if proptools.Bool(j.properties.Ravenizer.Strip_mockito) {
- ravenizerArgs = "--strip-mockito"
+ ravenizerArgs = append(ravenizerArgs, "--strip-mockito")
}
+
TransformRavenizer(ctx, ravenizerOutput, ravenizerInput, ravenizerArgs)
outputFile = ravenizerOutput
localImplementationJars = android.Paths{ravenizerOutput}
@@ -1835,7 +1917,11 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
// If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
if dexArtProfileOutput != nil {
- j.dexpreopter.SetRewrittenProfile(dexArtProfileOutput)
+ if concretePtr, ok := dexArtProfileOutput.(*android.OutputPath); ok {
+ if concretePtr != nil {
+ j.dexpreopter.SetRewrittenProfile(dexArtProfileOutput)
+ }
+ }
}
// merge dex jar with resources if necessary
@@ -1864,11 +1950,13 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
- libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
- if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
- libName = strings.TrimSuffix(libName, ".impl")
+ if dexArtProfileOutput != nil {
+ libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
+ if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
+ libName = strings.TrimSuffix(libName, ".impl")
+ }
+ j.dexpreopt(ctx, libName, dexOutputFile)
}
- j.dexpreopt(ctx, libName, dexOutputFile)
outputFile = dexOutputFile
@@ -1905,7 +1993,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data)
- if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
+ if !apexInfo.IsForPlatform() && ctx.Config().HasUnbundledBuildApps() {
j.linter.buildModuleReportZip = true
}
j.linter.lint(ctx)
@@ -1925,11 +2013,16 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
j.outputFile = outputFile.WithoutRel()
+ if deps.headerJarOverride.Valid() {
+ j.headerJarFile = deps.headerJarOverride.Path()
+ }
return &JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- RepackagedHeaderJars: android.PathsIfNonNil(repackagedHeaderJarFile),
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ LocalHeaderJarsPreJarjar: android.PathsIfNonNil(combinedHeaderJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(repackagedHeaderJarFile),
LocalHeaderJars: localHeaderJars,
+ KotlinHeaderJars: kotlinHeaderJars,
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
TransitiveStaticLibsImplementationJars: completeStaticLibsImplementationJars,
TransitiveStaticLibsResourceJars: completeStaticLibsResourceJars,
@@ -1946,11 +2039,13 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
ExportedPlugins: j.exportedPluginJars,
ExportedPluginClasses: j.exportedPluginClasses,
ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- JacocoReportClassesFile: j.jacocoReportClassesFile,
+ JacocoInfo: j.jacocoInfo,
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
SdkVersion: j.SdkVersion(ctx),
OutputFile: j.outputFile,
+ OverrideMinSdkVersion: j.overridableProperties.Min_sdk_version,
+ Installable: BoolDefault(j.properties.Installable, true),
}
}
@@ -2018,7 +2113,7 @@ func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
}
func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.Path {
+ srcFiles, srcJars, localHeaderJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths, genAnnoSrcJar android.Path) android.Path {
kzipName := pathtools.ReplaceExtension(jarName, "kzip")
annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
@@ -2029,7 +2124,13 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
}
classes := android.PathForModuleOut(ctx, "javac", jarName)
- TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
+ // enable incremental javac when corresponding flags are enabled and
+ // header jars are present
+ if ctx.Config().PartialCompileFlags().Enable_inc_javac && len(localHeaderJars) > 0 {
+ TransformJavaToClassesInc(ctx, classes, srcFiles, srcJars, localHeaderJars, annoSrcJar, flags, extraJarDeps, genAnnoSrcJar)
+ } else {
+ TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
+ }
if ctx.Config().EmitXrefRules() && ctx.Module() == ctx.PrimaryModule() {
extractionFile := android.PathForModuleOut(ctx, kzipName)
@@ -2044,6 +2145,20 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
return classes
}
+func (j *Module) generateJavaAnnotations(ctx android.ModuleContext, jarName string, idx int,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) (android.Path, android.Path) {
+
+ annoSrcJar := android.PathForModuleOut(ctx, "javac-apt", "anno.srcjar")
+ if idx >= 0 {
+ annoSrcJar = android.PathForModuleOut(ctx, "javac-apt", "anno-"+strconv.Itoa(idx)+".srcjar")
+ jarName += strconv.Itoa(idx)
+ }
+
+ classes := android.PathForModuleOut(ctx, "javac-apt", jarName)
+ GenerateJavaAnnotations(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
+ return annoSrcJar, classes
+}
+
// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
// since some of these flags may be used internally.
func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
@@ -2073,7 +2188,21 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (localHeaderJars android.Paths, combinedHeaderJar android.Path) {
+ extraJars android.Paths) (localHeaderJars, localHeaderJarsForSharding android.Paths, combinedHeaderJar android.Path) {
+
+ if deps.headerJarOverride.Valid() {
+ // If we are sharding, we need the pre-jarjar override path; localHeaderJars always
+ // needs the jarjared version.
+ localHeaderJars = append(android.Paths{deps.headerJarOverride.Path()}, extraJars...)
+ var headerJar android.Path
+ if deps.headerJarOverridePreJarjar.Valid() {
+ headerJar = deps.headerJarOverridePreJarjar.Path()
+ } else {
+ headerJar = deps.headerJarOverride.Path()
+ }
+ localHeaderJarsForSharding = append(android.Paths{headerJar}, extraJars...)
+ return localHeaderJars, localHeaderJarsForSharding, deps.headerJarOverride.Path()
+ }
if len(srcFiles) > 0 || len(srcJars) > 0 {
// Compile java sources into turbine.jar.
@@ -2089,13 +2218,14 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
depSet := depset.New(depset.PREORDER, localHeaderJars, deps.transitiveStaticLibsHeaderJars)
jars := depSet.ToList()
+ var combinedHeaderJarOutputPath android.WritablePath
// we cannot skip the combine step for now if there is only one jar
// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
- combinedHeaderJarOutputPath := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ combinedHeaderJarOutputPath = android.PathForModuleOut(ctx, "turbine-combined", jarName)
TransformJarsToJar(ctx, combinedHeaderJarOutputPath, "for turbine", jars, android.OptionalPath{},
false, nil, []string{"META-INF/TRANSITIVE"})
- return localHeaderJars, combinedHeaderJarOutputPath
+ return localHeaderJars, localHeaderJars, combinedHeaderJarOutputPath
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
@@ -2106,7 +2236,12 @@ func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
- j.jacocoReportClassesFile = jacocoReportClassesFile
+ j.jacocoInfo.ReportClassesFile = jacocoReportClassesFile
+ j.jacocoInfo.ModuleName = android.ModuleNameWithPossibleOverride(ctx)
+ // Allow overriding the class before instrument() is called
+ if j.jacocoInfo.Class == "" {
+ j.jacocoInfo.Class = "JAVA_LIBRARIES"
+ }
return instrumentedJar
}
@@ -2251,8 +2386,8 @@ func (j *Module) Stem() string {
return j.stem
}
-func (j *Module) JacocoReportClassesFile() android.Path {
- return j.jacocoReportClassesFile
+func (j *Module) JacocoInfo() JacocoInfo {
+ return j.jacocoInfo
}
func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
@@ -2463,6 +2598,15 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ case headerJarOverrideTag:
+ if dep.HeaderJars == nil {
+ ctx.ModuleErrorf("%s does not provide header jars", otherName)
+ } else if len(dep.HeaderJars) > 1 {
+ ctx.ModuleErrorf("%s provides too many header jars", otherName)
+ } else {
+ deps.headerJarOverride = android.OptionalPathForPath(dep.HeaderJars[0])
+ deps.headerJarOverridePreJarjar = android.OptionalPathForPath(dep.LocalHeaderJarsPreJarjar[0])
+ }
case java9LibTag:
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
@@ -2519,6 +2663,18 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
} else {
ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
}
+ case composeEmbeddablePluginTag:
+ if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
+ deps.composeEmbeddablePlugin = android.OptionalPathForPath(dep.ImplementationAndResourcesJars[0])
+ } else {
+ ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
+ }
+ case composePluginTag:
+ if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
+ deps.composePlugin = android.OptionalPathForPath(dep.ImplementationAndResourcesJars[0])
+ } else {
+ ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
+ }
case kotlinPluginTag:
if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
@@ -2556,6 +2712,8 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case staticLibTag:
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
}
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, DroidStubsInfoProvider); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigProtoFiles...)
} else {
switch tag {
case bootClasspathTag:
@@ -2645,6 +2803,7 @@ const (
RenameUseExclude
)
+// @auto-generate: gob
type JarJarProviderData struct {
// Mapping of class names: original --> renamed. If the value is "", the class will be
// renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
@@ -2669,12 +2828,11 @@ var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"
func init() {
android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
-
- gob.Register(BaseJarJarProviderData{})
}
// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
// whether they are java modules or not.
+// @auto-generate: gob
type BaseJarJarProviderData struct {
JarJarProviderData JarJarProviderData
}
@@ -2849,6 +3007,15 @@ func (this Module) GetDebugString() string {
// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
// us, and if it's been set, apply the jarjar_prefix property to rename them.
func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData {
+
+ // Stop collect jarjar_prefix jarjar rules if the module has test sdk scope.
+ // If a module uses test API scope, which means in its source code and static dependencies
+ // it could only use API exposed through the test surface. So it should not apply the jarjar
+ // rules set by any bootclass path jar
+ if ctx.Config().ReleaseJarjarFlagsInFramework() && module.SdkVersion(ctx).Kind == android.SdkTest {
+ return nil
+ }
+
// Gather repackage information from deps
result := collectDirectDepsProviders(ctx)
diff --git a/java/base_gob_enc.go b/java/base_gob_enc.go
new file mode 100644
index 000000000..a99c98670
--- /dev/null
+++ b/java/base_gob_enc.go
@@ -0,0 +1,89 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package java
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ JarJarProviderDataGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(JarJarProviderData) })
+ BaseJarJarProviderDataGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(BaseJarJarProviderData) })
+}
+
+func (r JarJarProviderData) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Rename))); err != nil {
+ return err
+ }
+ for k, v := range r.Rename {
+ if err = gobtools.EncodeString(buf, k); err != nil {
+ return err
+ }
+ if err = gobtools.EncodeString(buf, v); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *JarJarProviderData) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val1 int32
+ err = gobtools.DecodeSimple[int32](buf, &val1)
+ if err != nil {
+ return err
+ }
+ if val1 > 0 {
+ r.Rename = make(map[string]string, val1)
+ for val2 := 0; val2 < int(val1); val2++ {
+ var k string
+ var v string
+ err = gobtools.DecodeString(buf, &k)
+ if err != nil {
+ return err
+ }
+ err = gobtools.DecodeString(buf, &v)
+ if err != nil {
+ return err
+ }
+ r.Rename[k] = v
+ }
+ }
+
+ return err
+}
+
+var JarJarProviderDataGobRegId int16
+
+func (r JarJarProviderData) GetTypeId() int16 {
+ return JarJarProviderDataGobRegId
+}
+
+func (r BaseJarJarProviderData) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = r.JarJarProviderData.Encode(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *BaseJarJarProviderData) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if err = r.JarJarProviderData.Decode(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var BaseJarJarProviderDataGobRegId int16
+
+func (r BaseJarJarProviderData) GetTypeId() int16 {
+ return BaseJarJarProviderDataGobRegId
+}
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 3c3bd550c..75a35f13c 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -21,11 +21,18 @@ import (
// isActiveModule returns true if the given module should be considered for boot
// jars, i.e. if it's enabled and the preferred one in case of source and
// prebuilt alternatives.
-func isActiveModule(ctx android.ConfigurableEvaluatorContext, module android.Module) bool {
- if !module.Enabled(ctx) {
- return false
+func isActiveModule(ctx android.ModuleContext, module android.ModuleOrProxy) bool {
+ if android.EqualModules(ctx.Module(), module) {
+ if !ctx.Module().Enabled(ctx) {
+ return false
+ }
+ } else {
+ info := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ if !info.Enabled {
+ return false
+ }
}
- return android.IsModulePreferred(module)
+ return android.IsModulePreferredProxy(ctx, module)
}
// buildRuleForBootJarsPackageCheck generates the build rule to perform the boot jars package
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 98fb417d0..6c82d330c 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -71,8 +71,8 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st
// gatherFragments collects fragments that are direct dependencies of this module, as well as
// any fragments in apexes via the dependency on the apex. It returns a list of the fragment
// modules and map from apex name to the fragment in that apex.
-func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[string]android.Module) {
- var fragments []android.Module
+func gatherFragments(ctx android.BaseModuleContext) ([]android.ModuleProxy, map[string]android.ModuleProxy) {
+ var fragments []android.ModuleProxy
type fragmentInApex struct {
module string
@@ -82,7 +82,7 @@ func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[strin
var fragmentsInApexes []fragmentInApex
// Find any direct dependencies, as well as a list of the modules in apexes.
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
t := ctx.OtherModuleDependencyTag(module)
if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
if bcpTag.moduleInApex != "" {
@@ -93,13 +93,13 @@ func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[strin
}
})
- fragmentsMap := make(map[string]android.Module)
+ fragmentsMap := make(map[string]android.ModuleProxy)
for _, fragmentInApex := range fragmentsInApexes {
- var found android.Module
+ var found android.ModuleProxy
// Find a desired module in an apex.
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
t := ctx.OtherModuleDependencyTag(child)
- if parent == ctx.Module() {
+ if android.EqualModules(parent, ctx.Module()) {
if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment && ctx.OtherModuleName(child) == fragmentInApex.apex {
// This is the dependency from this module to the apex, recurse into it.
return true
@@ -112,7 +112,7 @@ func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[strin
return false
} else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == fragmentInApex.module {
// This is the desired module inside the apex.
- if found != nil && child != found {
+ if !found.IsNil() && child != found {
panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
fragmentInApex.module, fragmentInApex.apex, found, child))
}
@@ -120,7 +120,7 @@ func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[strin
}
return false
})
- if found != nil {
+ if !found.IsNil() {
if existing, exists := fragmentsMap[fragmentInApex.apex]; exists {
ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", fragmentInApex.apex, fragmentInApex.module, existing)
} else {
@@ -137,9 +137,10 @@ func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[strin
// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
// added by addDependencyOntoApexModulePair.
-func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) {
- var modules []android.Module
- modulesToApex := make(map[android.Module]string)
+func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext,
+ tagType bootclasspathDependencyTagType) ([]android.ModuleProxy, map[android.ModuleProxy]string) {
+ var modules []android.ModuleProxy
+ modulesToApex := make(map[android.ModuleProxy]string)
type moduleInApex struct {
module string
@@ -148,7 +149,7 @@ func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType boot
var modulesInApexes []moduleInApex
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
t := ctx.OtherModuleDependencyTag(module)
if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
if bcpTag.moduleInApex != "" {
@@ -160,10 +161,10 @@ func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType boot
})
for _, moduleInApex := range modulesInApexes {
- var found android.Module
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ var found android.ModuleProxy
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
t := ctx.OtherModuleDependencyTag(child)
- if parent == ctx.Module() {
+ if android.EqualModules(parent, ctx.Module()) {
if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex {
// recurse into the apex
return true
@@ -177,7 +178,7 @@ func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType boot
} else if IsBootclasspathFragmentContentDepTag(t) {
return false
} else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
- if found != nil && child != found {
+ if !found.IsNil() && child != found {
panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
moduleInApex.module, moduleInApex.apex, found, child))
}
@@ -185,7 +186,7 @@ func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType boot
}
return false
})
- if found != nil {
+ if !found.IsNil() {
modules = append(modules, found)
if existing, exists := modulesToApex[found]; exists && existing != moduleInApex.apex {
ctx.ModuleErrorf("module %s is in two apexes, %s and %s", moduleInApex.module, existing, moduleInApex.apex)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index a09416dc4..4505a40c4 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -41,7 +41,14 @@ func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContex
ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory)
}
-type BootclasspathFragmentInfo struct{}
+type BootclasspathFragmentInfo struct {
+ ImageName *string
+ Contents []string
+ ApiStubLibs []string
+ CorePlatformApiStubLibs []string
+ Fragments []ApexVariantReference
+ ProfilePathOnHost android.Path
+}
var BootclasspathFragmentInfoProvider = blueprint.NewProvider[BootclasspathFragmentInfo]()
@@ -73,10 +80,10 @@ func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() b
// SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if
// they were specified using java_boot_libs or java_sdk_libs.
-func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(ctx android.ModuleContext, child android.ModuleProxy) android.SdkMemberType {
// If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs
// property, otherwise treat if it was specified in the java_boot_libs property.
- if javaSdkLibrarySdkMemberType.IsInstance(child) {
+ if javaSdkLibrarySdkMemberType.IsInstance(ctx, child) {
return javaSdkLibrarySdkMemberType
}
@@ -267,7 +274,8 @@ type commonBootclasspathFragment interface {
// Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the
// module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a
// versioned sdk.
- produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
+ produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.ModuleProxy, fragments []android.ModuleProxy,
+ input HiddenAPIFlagInput) *HiddenAPIOutput
// getProfilePath returns the path to the boot image profile.
getProfilePath() android.Path
@@ -392,7 +400,7 @@ type BootclasspathFragmentApexContentInfo struct {
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
-func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) {
+func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.ModuleOrProxy) (android.Path, error) {
// A bootclasspath_fragment cannot use a prebuilt library so Name() will return the base name
// without a prebuilt_ prefix so is safe to use as the key for the contentModuleDexJarPaths.
name := module.Name()
@@ -530,9 +538,13 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// Generate classpaths.proto config
b.generateClasspathProtoBuildActions(ctx)
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"FAKE"}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+
// Gather the bootclasspath fragment's contents.
- var contents []android.Module
- ctx.VisitDirectDeps(func(module android.Module) {
+ var contents []android.ModuleProxy
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
if IsBootclasspathFragmentContentDepTag(tag) {
contents = append(contents, module)
@@ -544,7 +556,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
- if android.IsModulePrebuilt(ctx.Module()) {
+ if android.IsModulePrebuilt(ctx, ctx.Module()) {
b.profilePath = ctx.Module().(*PrebuiltBootclasspathFragmentModule).produceBootImageProfile(ctx)
} else {
b.profilePath = b.produceBootImageProfileFromSource(ctx, contents, hiddenAPIOutput.EncodedBootDexFilesByModule)
@@ -562,14 +574,21 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
b.HideFromMake()
}
- android.SetProvider(ctx, BootclasspathFragmentInfoProvider, BootclasspathFragmentInfo{})
+ android.SetProvider(ctx, BootclasspathFragmentInfoProvider, BootclasspathFragmentInfo{
+ ImageName: b.properties.Image_name,
+ Contents: b.properties.Contents.GetOrDefault(ctx, nil),
+ ApiStubLibs: b.properties.Api.Stub_libs.GetOrDefault(ctx, nil),
+ CorePlatformApiStubLibs: b.properties.Core_platform_api.Stub_libs.GetOrDefault(ctx, nil),
+ Fragments: b.properties.Fragments,
+ ProfilePathOnHost: b.profilePath,
+ })
}
// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
// empty string if this module should not provide a boot image profile.
func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string {
// Only use the profile from the module that is preferred.
- if !isActiveModule(ctx, ctx.Module()) {
+ if !android.IsModulePreferredProxy(ctx, ctx.Module()) {
return ""
}
@@ -646,7 +665,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext)
// TODO(b/202896428): Add better way to handle this.
_, unknown = android.RemoveFromList("android.car-module", unknown)
if isApexVariant(ctx) && len(unknown) > 0 {
- if android.IsModulePrebuilt(ctx.Module()) {
+ if android.IsModulePrebuilt(ctx, ctx.Module()) {
// prebuilt bcpf. the validation of this will be done at the top-level apex
providerClasspathFragmentValidationInfoProvider(ctx, unknown)
} else if !disableSourceApexVariant(ctx) && android.IsModulePreferred(ctx.Module()) {
@@ -676,7 +695,8 @@ func providerClasspathFragmentValidationInfoProvider(ctx android.ModuleContext,
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {
+func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.ModuleProxy,
+ fragments []android.ModuleProxy) *HiddenAPIOutput {
// Create hidden API input structure.
input := b.createHiddenAPIFlagInput(ctx, contents, fragments)
@@ -720,7 +740,8 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
// from the properties on this module and its dependencies.
-func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) HiddenAPIFlagInput {
+func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.ModuleProxy,
+ fragments []android.ModuleProxy) HiddenAPIFlagInput {
// Merge the HiddenAPIInfo from all the fragment dependencies.
dependencyHiddenApiInfo := newHiddenAPIInfo()
dependencyHiddenApiInfo.mergeFromFragmentDeps(ctx, fragments)
@@ -752,7 +773,7 @@ func (b *BootclasspathFragmentModule) isTestFragment() bool {
// generateHiddenApiFlagRules generates rules to generate hidden API flags and compute the signature
// patterns file.
-func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput {
+func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.ModuleProxy, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput {
// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
// paths to the created files.
flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix)
@@ -781,7 +802,8 @@ func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.Mod
// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
// for the fragment as well as encoding the flags in the boot dex jars.
-func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.ModuleProxy,
+ fragments []android.ModuleProxy, input HiddenAPIFlagInput) *HiddenAPIOutput {
// Gather information about the boot dex files for the boot libraries provided by this fragment.
bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
@@ -805,11 +827,12 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
// Filter the contents list to remove any modules that do not support the target build release.
// The current build release supports all the modules.
- contentsForSdkSnapshot := []android.Module{}
+ contentsForSdkSnapshot := []android.ModuleProxy{}
for _, module := range contents {
// If the module has a min_sdk_version that is higher than the target build release then it will
// not work on the target build release and so must not be included in the sdk snapshot.
- minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ minApiLevel := android.MinApiLevelForSdkSnapshot(commonInfo)
if minApiLevel.GreaterThan(targetApiLevel) {
continue
}
@@ -843,7 +866,8 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
}
// produceBootImageProfileFromSource builds the boot image profile from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext, contents []android.Module, modules bootDexJarByModule) android.WritablePath {
+func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext,
+ contents []android.ModuleProxy, modules bootDexJarByModule) android.WritablePath {
apex := b.getProfileProviderApex(ctx)
if apex == "" {
return nil
@@ -897,8 +921,8 @@ func (b *bootclasspathFragmentMemberType) AddDependencies(ctx android.SdkDepende
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (b *bootclasspathFragmentMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*BootclasspathFragmentModule)
+func (b *bootclasspathFragmentMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ _, ok := android.OtherModuleProvider(ctx, module, BootclasspathFragmentInfoProvider)
return ok
}
@@ -958,15 +982,15 @@ type bootclasspathFragmentSdkMemberProperties struct {
Filtered_flags_path android.OptionalPath `supported_build_releases:"Tiramisu+"`
}
-func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- module := variant.(*BootclasspathFragmentModule)
+func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ mctx := ctx.SdkModuleContext()
+ module, _ := android.OtherModuleProvider(mctx, variant, BootclasspathFragmentInfoProvider)
- b.Image_name = module.properties.Image_name
- b.Contents = module.properties.Contents.GetOrDefault(ctx.SdkModuleContext(), nil)
+ b.Image_name = module.ImageName
+ b.Contents = module.Contents
// Get the hidden API information from the module.
- mctx := ctx.SdkModuleContext()
- hiddenAPIInfo, _ := android.OtherModuleProvider(mctx, module, HiddenAPIInfoForSdkProvider)
+ hiddenAPIInfo, _ := android.OtherModuleProvider(mctx, variant, HiddenAPIInfoForSdkProvider)
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
// Copy all the generated file paths.
@@ -982,11 +1006,11 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro
b.Filtered_flags_path = android.OptionalPathForPath(hiddenAPIInfo.FilteredFlagsPath)
// Copy stub_libs properties.
- b.Stub_libs = module.properties.Api.Stub_libs.GetOrDefault(mctx, nil)
- b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs.GetOrDefault(mctx, nil)
+ b.Stub_libs = module.ApiStubLibs
+ b.Core_platform_stub_libs = module.CorePlatformApiStubLibs
// Copy fragment properties.
- b.Fragments = module.properties.Fragments
+ b.Fragments = module.Fragments
}
func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -1108,7 +1132,8 @@ func (module *PrebuiltBootclasspathFragmentModule) Name() string {
}
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext,
+ contents []android.ModuleProxy, fragments []android.ModuleProxy, input HiddenAPIFlagInput) *HiddenAPIOutput {
pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
if src == nil {
return defaultPath
diff --git a/java/builder.go b/java/builder.go
index dff0032d8..3251dfd9c 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -20,6 +20,7 @@ package java
import (
"path/filepath"
+ "slices"
"strconv"
"strings"
@@ -33,13 +34,101 @@ import (
var (
pctx = android.NewPackageContext("android/soong/java")
+ // Unzips java src files from supplied jars into a directory provided.
+ extractSrcJars = pctx.AndroidStaticRule("javac-extract-srcJars",
+ blueprint.RuleParams{
+ Command: `rm -rf "$extractDir" && mkdir -p "$extractDir" && ${config.ZipSyncCmd} -d "$extractDir" -l "$out" -f "*.java" $jars`,
+ CommandDeps: []string{
+ "${config.ZipSyncCmd}",
+ },
+ }, "extractDir", "jars",
+ )
+
+ // Removes all outputs of inc-javac rule
+ javacIncClean = pctx.AndroidStaticRule("javac-inc-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "${srcJarDir}" "${outDir}" "${annoDir}" "${annoSrcJar}" "${builtOut}"`,
+ }, "srcJarDir", "outDir", "annoDir", "annoSrcJar", "builtOut",
+ )
+
+ // Incremental javac rule
+ // The idea of this rule is to make javac incremental, i.e. use the input and
+ // output of previous javac execution to reduce the src lists.
+ // This rule is very similar to the normal javac rule with a few differences:
+ // * Does not unzip srcJars in the rule
+ // * Does not remove the temp directories containing classes/generated sources
+ // * Saves the states of a bunch of input params, when javac executes successfully.
+ // * Runs additional tools on the output to prepare for next iteration
+ javacInc, javacIncRE = pctx.MultiCommandRemoteStaticRules("javac-inc",
+ blueprint.RuleParams{
+ Command: `rm -rf "$annoSrcJar.tmp" "$out.tmp" && ` +
+ `mkdir -p "$annoDir" && ` +
+ `if [ -s $out.rsp ] && [ -s $srcJarList ] ; then ` +
+ `echo >> $out.rsp; fi && ` +
+ `cat $srcJarList >> $out.rsp && ` +
+ `if [ -s $genAnnoSrcJarList ] ; then ` +
+ `echo >> $out.rsp && cat $genAnnoSrcJarList >> $out.rsp; fi && ` +
+ `${config.IncrementalJavacInputCmd} ` +
+ `--srcs $out.rsp --classDir $outDir --deps $javacDeps --javacTarget $out --srcDepsProto $out.proto --localHeaderJars $localHeaderJars && ` +
+ `mkdir -p "$outDir" && ` +
+ `(if [ -s $out.inc.rsp ] ; then ` +
+ `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
+ `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
+ `$processorpath $processor $javacFlags $bootClasspath $classpath ` +
+ `-source $javaVersion -target $javaVersion ` +
+ `-d $outDir -s $annoDir @$out.inc.rsp ; fi ) && ` +
+ `cat $out.rem.rsp | xargs rm -f && ` +
+ `$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar.tmp -C $annoDir -D $annoDir && ` +
+ `$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
+ `if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
+ `if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
+ `if [ -f "$out.input.pc_state.new" ]; then mv "$out.input.pc_state.new" "$out.input.pc_state" && ` +
+ `rm -rf $out.input.pc_state.new; fi && ` +
+ `if [ -f "$out.deps.pc_state.new" ]; then mv "$out.deps.pc_state.new" "$out.deps.pc_state" && ` +
+ `rm -rf $out.deps.pc_state.new; fi && ` +
+ `if [ -f "$out.headers.pc_state.new" ]; then mv "$out.headers.pc_state.new" "$out.headers.pc_state" && ` +
+ `rm -rf $out.headers.pc_state.new; fi && ` +
+ `if [ -f $out.rsp ] && [ -f $out ]; then ` +
+ `${config.DependencyMapperJavacCmd} --src-path $out.rsp --jar-path $out --dependency-map-path $out.proto; fi`,
+ CommandDeps: []string{
+ "${config.DependencyMapperJavacCmd}",
+ "${config.IncrementalJavacInputCmd}",
+ "${config.JavacCmd}",
+ "${config.ZipSyncCmd}",
+ },
+ CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Restat: true,
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ }, map[string]*remoteexec.REParams{
+ "$javaTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$out.tmp"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$annoSrcJarTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$annoDir"},
+ OutputFiles: []string{"$annoSrcJar.tmp"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJarList", "genAnnoSrcJarList",
+ "outDir", "annoDir", "annoSrcJar", "javaVersion", "javacDeps", "localHeaderJars"}, nil)
+
// Compiling java is not conducive to proper dependency tracking. The path-matches-class-name
// requirement leads to unpredictable generated source file names, and a single .java file
// will get compiled into multiple .class files if it contains inner classes. To work around
// this, all java rules write into separate directories and then are combined into a .jar file
// (if the rule produces .class files) or a .srcjar file (if the rule produces .java files).
// .srcjar files are unzipped into a temporary directory when compiled with javac.
- // TODO(b/143658984): goma can't handle the --system argument to javac.
javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar.tmp" "$srcJarDir" "$out.tmp" && ` +
@@ -312,10 +401,12 @@ var (
blueprint.RuleParams{
Command: `${aconfig} dump-cache --dedup --format=protobuf ` +
`--out ${out} ` +
- `${flags_path} ` +
+ `@$out.rsp ` +
`${filter_args} `,
- CommandDeps: []string{"${aconfig}"},
- Description: "aconfig_bool",
+ CommandDeps: []string{"${aconfig}"},
+ Description: "aconfig_bool",
+ Rspfile: "$out.rsp",
+ RspfileContent: "${flags_path}",
}, "flags_path", "filter_args")
generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule",
@@ -374,9 +465,12 @@ type javaBuilderFlags struct {
errorProneExtraJavacFlags string
errorProneProcessorPath classpath
- kotlincFlags string
- kotlincClasspath classpath
- kotlincDeps android.Paths
+ kotlincFlags string
+ kotlincPluginFlags string
+ composePluginFlag string
+ composeEmbeddablePluginFlag string
+ kotlincClasspath classpath
+ kotlincDeps android.Paths
proto android.ProtoFlags
}
@@ -387,6 +481,14 @@ func DefaultJavaBuilderFlags() javaBuilderFlags {
}
}
+func TransformJavaToClassesInc(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles, srcJars, headerJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths, genAnnoSrcJar android.Path) {
+
+ // Compile java sources into .class files
+ desc := "javac-inc"
+ transformJavaToClassesInc(ctx, outputFile, srcFiles, srcJars, headerJars, annoSrcJar, flags, deps, "javac", desc, genAnnoSrcJar)
+}
+
func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths) {
@@ -395,8 +497,18 @@ func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
if shardIdx >= 0 {
desc += strconv.Itoa(shardIdx)
}
+ transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, false, flags, deps, "javac", desc)
+}
+func GenerateJavaAnnotations(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
+ srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths) {
+
+ // Generate src files from Java Annotations.
+ desc := "javac-apt"
+ if shardIdx >= 0 {
+ desc += strconv.Itoa(shardIdx)
+ }
- transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, flags, deps, "javac", desc)
+ transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, true, flags, deps, "javac-apt", desc)
}
// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
@@ -588,6 +700,153 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
})
}
+// Similar to transformJavaToClasses, with additional tweaks to make java
+// compilation work incrementally (i.e. work with a smaller subset of src java files
+// rather than the full set)
+func transformJavaToClassesInc(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles, srcJars, shardingHeaderJars android.Paths, annoSrcJar android.WritablePath,
+ flags javaBuilderFlags, deps android.Paths, intermediatesDir, desc string, genAnnoSrcJar android.Path) {
+
+ javacClasspath := flags.classpath
+
+ var bootClasspath string
+ if flags.javaVersion.usesJavaModules() {
+ var systemModuleDeps android.Paths
+ bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device())
+ deps = append(deps, systemModuleDeps...)
+ javacClasspath = append(flags.java9Classpath, javacClasspath...)
+ } else {
+ deps = append(deps, flags.bootClasspath...)
+ if len(flags.bootClasspath) == 0 && ctx.Device() {
+ // explicitly specify -bootclasspath "" if the bootclasspath is empty to
+ // ensure java does not fall back to the default bootclasspath.
+ bootClasspath = `-bootclasspath ""`
+ } else {
+ bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath")
+ }
+ }
+
+ deps = append(deps, flags.processorPath...)
+ deps = append(deps, javacClasspath...)
+
+ // The file containing dependencies of the current module
+ // Any change in them may warrant changes in the incremental compilation
+ // source set.
+ javacDeps := outputFile.ReplaceExtension(ctx, "jar.deps.rsp")
+ android.WriteFileRule(ctx, javacDeps, strings.Join(deps.Strings(), "\n"))
+ deps = append(deps, javacDeps)
+
+ // Add localHeader Jars in classpath, they are required for incremental compilation.
+ // These are conspicuously not added to javacDeps file, as a change in them
+ // does not warrant full re-compilation.
+ javacClasspath = append(classpath(slices.Clone(shardingHeaderJars)), javacClasspath...)
+ deps = append(deps, shardingHeaderJars...)
+ shardingHeaderRsp := outputFile.ReplaceExtension(ctx, "jar.headers.rsp")
+ android.WriteFileRule(ctx, shardingHeaderRsp, strings.Join(shardingHeaderJars.Strings(), "\n"))
+ deps = append(deps, shardingHeaderRsp)
+
+ // Doing this now, sow that they are not added to javacDeps file
+ deps = append(deps, srcJars...)
+
+ classpathArg := javacClasspath.FormJavaClassPath("-classpath")
+
+ // Keep the command line under the MAX_ARG_STRLEN limit by putting the classpath argument into an rsp file
+ // if it is too long.
+ const classpathLimit = 64 * 1024
+ if len(classpathArg) > classpathLimit {
+ classpathRspFile := outputFile.ReplaceExtension(ctx, "classpath")
+ android.WriteFileRule(ctx, classpathRspFile, classpathArg)
+ deps = append(deps, classpathRspFile)
+ classpathArg = "@" + classpathRspFile.String()
+ }
+
+ processor := "-proc:none"
+ if len(flags.processors) > 0 {
+ processor = "-processor " + strings.Join(flags.processors, ",")
+ }
+
+ srcJarDir := "srcjars"
+ outDir := "classes"
+ annoDir := "anno"
+ srcJarList := android.PathForModuleOut(ctx, intermediatesDir, srcJarDir, "list")
+ deps = append(deps, srcJarList)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractSrcJars,
+ Description: "javacExtractSrcJars",
+ Inputs: srcJars,
+ Output: srcJarList,
+ Args: map[string]string{
+ "extractDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
+ "jars": strings.Join(srcJars.Strings(), " "),
+ },
+ })
+
+ genAnnoSrcJarList := android.PathForModuleOut(ctx, intermediatesDir, annoDir, "list")
+ deps = append(deps, genAnnoSrcJarList)
+ var jars string
+ if genAnnoSrcJar != nil {
+ jars = genAnnoSrcJar.String()
+ } else {
+ jars = ""
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractSrcJars,
+ Description: "javacExtractAnnoSrcJar",
+ Input: genAnnoSrcJar,
+ Output: genAnnoSrcJarList,
+ Args: map[string]string{
+ "extractDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+ "jars": jars,
+ },
+ })
+
+ rule := javacInc
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: desc,
+ Output: outputFile,
+ ImplicitOutput: annoSrcJar,
+ Inputs: srcFiles,
+ Implicits: deps,
+ Args: map[string]string{
+ "javacFlags": flags.javacFlags,
+ "bootClasspath": bootClasspath,
+ "classpath": classpathArg,
+ "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
+ "processor": processor,
+ "srcJarList": srcJarList.String(),
+ "genAnnoSrcJarList": genAnnoSrcJarList.String(),
+ "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
+ "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+ "annoSrcJar": annoSrcJar.String(),
+ "javaVersion": flags.javaVersion.String(),
+ "javacDeps": javacDeps.String(),
+ "localHeaderJars": shardingHeaderRsp.String(),
+ },
+ })
+
+ // The Phony Clean rule allows javac to move from incremental to full, without
+ // re-analysis by removing all the outputs of javac, triggering all rules
+ // that generate them.
+ cleanPhonyPath := android.PathForModuleOut(ctx, "dex", outputFile.String()+"-partialcompileclean").OutputPath
+ // Generate the rule for partial compile clean.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: javacIncClean,
+ Description: "javacIncClean",
+ Output: cleanPhonyPath,
+ Args: map[string]string{
+ "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
+ "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
+ "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+ "annoSrcJar": annoSrcJar.String(),
+ "builtOut": outputFile.String(),
+ },
+ PhonyOutput: true,
+ })
+ ctx.Phony("partialcompileclean", cleanPhonyPath)
+}
+
// transformJavaToClasses takes source files and converts them to a jar containing .class files.
// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain
// sources. flags contains various command line flags to be passed to the compiler.
@@ -597,8 +856,11 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
// be printed at build time. The stem argument provides the file name of the output jar, and
// suffix will be appended to various intermediate files and directories to avoid collisions when
// this function is called twice in the same module directory.
+//
+// This method can also be used to only process Annotations, without completely
+// compiling java sources.
func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- shardIdx int, srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath,
+ shardIdx int, srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, onlyGenerateAnnotations bool,
flags javaBuilderFlags, deps android.Paths,
intermediatesDir, desc string) {
@@ -640,7 +902,11 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
processor := "-proc:none"
if len(flags.processors) > 0 {
- processor = "-processor " + strings.Join(flags.processors, ",")
+ if onlyGenerateAnnotations {
+ processor = "-proc:only -processor " + strings.Join(flags.processors, ",")
+ } else {
+ processor = "-processor " + strings.Join(flags.processors, ",")
+ }
}
srcJarDir := "srcjars"
@@ -852,14 +1118,14 @@ func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePat
}
func TransformRavenizer(ctx android.ModuleContext, outputFile android.WritablePath,
- inputFile android.Path, ravenizerArgs string) {
+ inputFile android.Path, ravenizerArgs []string) {
ctx.Build(pctx, android.BuildParams{
Rule: ravenizer,
Description: "ravenizer",
Output: outputFile,
Input: inputFile,
Args: map[string]string{
- "ravenizerArgs": ravenizerArgs,
+ "ravenizerArgs": strings.Join(ravenizerArgs, " "),
},
})
}
@@ -920,6 +1186,10 @@ func (x *classpath) FormRepeatedClassPath(optName string) []string {
return flags
}
+func (x *classpath) FirstUniquePaths() classpath {
+ return classpath(android.FirstUniquePaths(x.Paths()))
+}
+
// Convert a classpath to an android.Paths
func (x *classpath) Paths() android.Paths {
return append(android.Paths(nil), (*x)...)
diff --git a/java/classpath_element.go b/java/classpath_element.go
index 4af277012..263a5f116 100644
--- a/java/classpath_element.go
+++ b/java/classpath_element.go
@@ -28,7 +28,7 @@ import (
// ClasspathElement represents a component that contributes to a classpath. That can be
// either a java module or a classpath fragment module.
type ClasspathElement interface {
- Module() android.Module
+ Module() android.ModuleProxy
String() string
}
@@ -36,11 +36,11 @@ type ClasspathElements []ClasspathElement
// ClasspathFragmentElement is a ClasspathElement that encapsulates a classpath fragment module.
type ClasspathFragmentElement struct {
- Fragment android.Module
- Contents []android.Module
+ Fragment android.ModuleProxy
+ Contents []android.ModuleProxy
}
-func (b *ClasspathFragmentElement) Module() android.Module {
+func (b *ClasspathFragmentElement) Module() android.ModuleProxy {
return b.Fragment
}
@@ -56,10 +56,10 @@ var _ ClasspathElement = (*ClasspathFragmentElement)(nil)
// ClasspathLibraryElement is a ClasspathElement that encapsulates a java library.
type ClasspathLibraryElement struct {
- Library android.Module
+ Library android.ModuleProxy
}
-func (b *ClasspathLibraryElement) Module() android.Module {
+func (b *ClasspathLibraryElement) Module() android.ModuleProxy {
return b.Library
}
@@ -118,10 +118,10 @@ type ClasspathElementContext interface {
// ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]),
// ClasspathLibraryElement(framework),
// ClasspathLibraryElement(ext),
-func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module,
- libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) ClasspathElements {
+func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.ModuleProxy, fragments []android.ModuleProxy,
+ libraryToApex map[android.ModuleProxy]string, apexNameToFragment map[string]android.ModuleProxy) ClasspathElements {
- fragmentToElement := map[android.Module]*ClasspathFragmentElement{}
+ fragmentToElement := map[android.ModuleProxy]*ClasspathFragmentElement{}
elements := []ClasspathElement{}
var currentElement ClasspathElement
@@ -130,11 +130,11 @@ skipLibrary:
for _, library := range libraries {
var element ClasspathElement
if libraryApex, ok := libraryToApex[library]; ok {
- var fragment android.Module
+ var fragment android.ModuleProxy
// Make sure that the library is in only one fragment of the classpath.
if f, ok := apexNameToFragment[libraryApex]; ok {
- if fragment == nil {
+ if fragment.IsNil() {
// This is the first fragment so just save it away.
fragment = f
} else if f != fragment {
@@ -148,7 +148,7 @@ skipLibrary:
// There is no fragment associated with the library's apex.
}
- if fragment == nil {
+ if fragment.IsNil() {
ctx.ModuleErrorf("library %s is from apexes %s which have no corresponding fragment in %s",
library, []string{libraryApex}, fragments)
// Skip over this library entirely as otherwise the resulting classpath elements would
@@ -184,7 +184,7 @@ skipLibrary:
// including the library.
fragmentElement := &ClasspathFragmentElement{
Fragment: fragment,
- Contents: []android.Module{library},
+ Contents: []android.ModuleProxy{library},
}
// Store it away so we can detect when attempting to create another element for the same
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 88a8fb80a..6b9dc194a 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -104,17 +104,14 @@ type classpathJar struct {
func gatherPossibleApexModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
set := map[string]struct{}{}
for _, name := range contents {
- dep := ctx.GetDirectDepWithTag(name, tag)
- if dep == nil && ctx.Config().AllowMissingDependencies() {
+ dep := ctx.GetDirectDepProxyWithTag(name, tag)
+ if dep.IsNil() && ctx.Config().AllowMissingDependencies() {
// Ignore apex boot jars from dexpreopt if it does not exist, and missing deps are allowed.
continue
}
- set[ModuleStemForDeapexing(dep)] = struct{}{}
- if m, ok := dep.(ModuleWithStem); ok {
- set[m.Stem()] = struct{}{}
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
+ info := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider)
+ set[ModuleStemForDeapexing(ctx, dep)] = struct{}{}
+ set[info.Stem] = struct{}{}
}
return android.SortedKeys(set)
}
@@ -129,12 +126,15 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
classpath: classpathType,
path: paths[i],
}
- ctx.VisitDirectDepsIf(func(m android.Module) bool {
- return m.Name() == configuredJars.Jar(i)
- }, func(m android.Module) {
- if s, ok := m.(*SdkLibrary); ok {
- minSdkVersion := s.MinSdkVersion(ctx)
- maxSdkVersion := s.MaxSdkVersion(ctx)
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
+ if m.Name() != configuredJars.Jar(i) {
+ return
+ }
+ if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
+ info := android.OtherModuleProviderOrDefault(ctx, m, JavaInfoProvider)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ minSdkVersion := *commonInfo.MinSdkVersion.ApiLevel
+ maxSdkVersion := info.MaxSdkVersion
// TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
if minSdkVersion.Specified() {
if minSdkVersion.IsCurrent() {
diff --git a/java/config/config.go b/java/config/config.go
index fdb8d7886..3538aa155 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -160,6 +160,9 @@ func init() {
pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
pctx.HostBinToolVariable("FindInputDeltaCmd", "find_input_delta")
+ pctx.HostBinToolVariable("IncrementalJavacInputCmd", "incremental_javac_input")
+ pctx.HostBinToolVariable("IncrementalDexInputCmd", "incremental_dex_input")
+ pctx.HostBinToolVariable("DependencyMapperJavacCmd", "dependency-mapper")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh")
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index ffb025d9c..bbf580253 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -26,6 +26,7 @@ var (
)
func init() {
+ pctx.HostBinToolVariable("KotlinIncrementalClientBinary", "kotlin-incremental-client")
pctx.SourcePathVariable("KotlincCmd", "external/kotlinc/bin/kotlinc")
pctx.SourcePathVariable("KotlinCompilerJar", "external/kotlinc/lib/kotlin-compiler.jar")
pctx.SourcePathVariable("KotlinPreloaderJar", "external/kotlinc/lib/kotlin-preloader.jar")
@@ -33,6 +34,7 @@ func init() {
pctx.SourcePathVariable("KotlinScriptRuntimeJar", "external/kotlinc/lib/kotlin-script-runtime.jar")
pctx.SourcePathVariable("KotlinTrove4jJar", "external/kotlinc/lib/trove4j.jar")
pctx.SourcePathVariable("KotlinKaptJar", "external/kotlinc/lib/kotlin-annotation-processing.jar")
+ pctx.SourcePathVariable("KotlinKaptEmbeddableJar", "external/kotlinc/lib/kotlin-annotation-processing-embeddable-2.1.10.jar")
pctx.SourcePathVariable("KotlinAnnotationJar", "external/kotlinc/lib/annotations-13.0.jar")
pctx.SourcePathVariable("KotlinStdlibJar", KotlinStdlibJar)
pctx.SourcePathVariable("KotlinAbiGenPluginJar", "external/kotlinc/lib/jvm-abi-gen.jar")
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 04def3e28..283d04598 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -102,7 +102,7 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont
var transitiveImplementationJars []depset.DepSet[android.Path]
var transitiveResourceJars []depset.DepSet[android.Path]
- ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(deviceHostConverterDepTag, func(m android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
d.headerJars = append(d.headerJars, dep.HeaderJars...)
d.implementationJars = append(d.implementationJars, dep.ImplementationJars...)
@@ -158,6 +158,21 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont
setExtraJavaInfo(ctx, d, javaInfo)
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ if ctx.Os() != android.Windows { // Make does not support Windows Java modules
+ if d.combinedImplementationJar != nil {
+ ctx.CheckbuildFile(d.combinedImplementationJar)
+ }
+ if d.combinedHeaderJar != nil {
+ ctx.CheckbuildFile(d.combinedHeaderJar)
+ }
+ }
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if d.combinedImplementationJar != nil {
+ moduleInfoJSON.ClassesJar = []string{d.combinedImplementationJar.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (d *DeviceHostConverter) HeaderJars() android.Paths {
@@ -184,10 +199,6 @@ func (d *DeviceHostConverter) ClassLoaderContexts() dexpreopt.ClassLoaderContext
return nil
}
-func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path {
- return nil
-}
-
func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Class: "JAVA_LIBRARIES",
diff --git a/java/dex.go b/java/dex.go
index e3058e9bf..fa38d6131 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -15,6 +15,8 @@
package java
import (
+ "fmt"
+ "path/filepath"
"strconv"
"strings"
@@ -25,6 +27,10 @@ import (
"android/soong/remoteexec"
)
+func init() {
+ pctx.HostBinToolVariable("symbols_map", "symbols_map")
+}
+
type DexProperties struct {
// If set to true, compile dex regardless of installable. Defaults to false.
Compile_dex *bool
@@ -80,9 +86,10 @@ type DexProperties struct {
Shrink *bool
// If true, optimize bytecode. Defaults to false.
- Optimize *bool
+ Optimize proptools.Configurable[bool] `android:"replace_instead_of_append"`
- // If true, obfuscate bytecode. Defaults to false.
+ // If true, obfuscate bytecode by renaming packages, classes, and members.
+ // Defaults to false.
Obfuscate *bool
// If true, do not use the flag files generated by aapt that automatically keep
@@ -135,6 +142,11 @@ type DexProperties struct {
// TODO(b/212737576): Handle this implicitly using bottom-up deps mutation and implicit
// creation of a proxy `.impl` library.
Trace_references_from proptools.Configurable[[]string] `android:"arch_variant"`
+
+ // Add libraries using `--classpath` instead of `--libs`, to allow overrides. This
+ // should normally not be used, but can be necessary when running R8 on the boot
+ // classpath itself.
+ Import_libraries_as_classpath *bool
}
// Keep the data uncompressed. We always need uncompressed dex for execution,
@@ -182,10 +194,125 @@ func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleCont
return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault())
}
-func (d *dexer) optimizeOrObfuscateEnabled(ctx android.EarlyModuleContext) bool {
- return d.effectiveOptimizeEnabled(ctx) && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
+func (d *dexer) optimizeOrObfuscateEnabled(ctx android.ModuleContext) bool {
+ return d.effectiveOptimizeEnabled(ctx) && (d.dexProperties.Optimize.Optimize.GetOrDefault(ctx, false) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
}
+// Removes all outputs of d8Inc rule
+var d8IncClean = pctx.AndroidStaticRule("d8Inc-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "${outDir}" "${builtOut}" "${d8Deps}"`,
+ }, "outDir", "d8Flags", "d8Deps", "zipFlags", "mergeZipsFlags", "builtOut",
+)
+
+var d8Inc, d8IncRE = pctx.MultiCommandRemoteStaticRules("d8Inc",
+ blueprint.RuleParams{
+ Command: `mkdir -p "$outDir" "$outDir/packages" && ` +
+ `${config.IncrementalDexInputCmd} ` +
+ `--classesJar $in --dexTarget $out --deps $d8Deps --outputDir $outDir --packageOutputDir $outDir/packages && ` +
+ `$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in --packages $out.rsp --mod-packages $out.inc.rsp --package-output $outDir/packages && ` +
+ `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `if [ -f "$out.input.pc_state.new" ]; then mv "$out.input.pc_state.new" "$out.input.pc_state" && ` +
+ `rm -rf $out.input.pc_state.new; fi && ` +
+ `if [ -f "$out.deps.pc_state.new" ]; then mv "$out.deps.pc_state.new" "$out.deps.pc_state" && ` +
+ `rm -rf $out.deps.pc_state.new; fi && ` +
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
+ CommandDeps: []string{
+ "${config.IncrementalDexInputCmd}",
+ "${config.D8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ }, map[string]*remoteexec.REParams{
+ "$d8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "d8"},
+ Inputs: []string{"${config.D8Jar}"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$outDir/classes.dex.jar"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags", "d8Deps"}, nil)
+
+// Include all of the args for d8IncR8, so that we can generate the partialcompileclean target's build using the same list.
+var d8IncR8Clean = pctx.AndroidStaticRule("d8Incr8-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "${outDir}" "${outDict}" "${outConfig}" "${outUsage}" "${outUsageZip}" "${outUsageDir}" ` +
+ `"${resourcesOutput}" "${outR8ArtProfile}" ${builtOut} ${d8Deps}`,
+ }, "outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "builtOut",
+ "d8Flags", "d8Deps", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile", "implicits",
+)
+
+var d8IncR8, d8IncR8RE = pctx.MultiCommandRemoteStaticRules("d8Incr8",
+ blueprint.RuleParams{
+ Command: `mkdir -p "$outDir" "$outDir/packages" && ` +
+ `rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
+ `mkdir -p $$(dirname ${outUsage}) && ` +
+ `if [ -n "$${SOONG_USE_PARTIAL_COMPILE}" ]; then ` +
+ ` for f in "${outConfig}" "${outDict}" "${outUsage}" "${resourcesOutput}"; do ` +
+ ` test -n "$${f}" && test ! -f "$${f}" && mkdir -p "$$(dirname "$${f}")" && touch "$${f}" || true; ` +
+ ` done && ` +
+ ` ${config.IncrementalDexInputCmd} --classesJar $in --dexTarget $out --deps $d8Deps --outputDir $outDir --packageOutputDir $outDir/packages && ` +
+ ` $d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in --packages $out.rsp --mod-packages $out.inc.rsp --package-output $outDir/packages; ` +
+ `else ` +
+ ` rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ ` $r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` +
+ ` --no-data-resources ` +
+ ` -printmapping ${outDict} ` +
+ ` -printconfiguration ${outConfig} ` +
+ ` -printusage ${outUsage} ` +
+ ` --deps-file ${out}.d && ` +
+ ` touch "${outDict}" "${outConfig}" "${outUsage}"; ` +
+ `fi && ` +
+ `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
+ `rm -rf ${outUsageDir} && ` +
+ `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `if [ -f "$out.input.pc_state.new" ]; then mv "$out.input.pc_state.new" "$out.input.pc_state" && ` +
+ `rm -rf $out.input.pc_state.new; fi && ` +
+ `if [ -f "$out.deps.pc_state.new" ]; then mv "$out.deps.pc_state.new" "$out.deps.pc_state" && ` +
+ `rm -rf $out.deps.pc_state.new; fi && ` +
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `,
+ CommandDeps: []string{
+ "${config.IncrementalDexInputCmd}",
+ "${config.D8Cmd}",
+ "${config.R8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ }, map[string]*remoteexec.REParams{
+ "$d8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "d8"},
+ Inputs: []string{"${config.D8Jar}"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$r8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "r8"},
+ Inputs: []string{"$implicits", "${config.R8Jar}"},
+ OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}", "${outR8ArtProfile}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$outDir/classes.dex.jar"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
+ "d8Flags", "d8Deps", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
+
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -195,6 +322,7 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
`rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
CommandDeps: []string{
"${config.D8Cmd}",
+ "${config.D8Jar}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -250,7 +378,9 @@ var d8r8, d8r8RE = pctx.MultiCommandRemoteStaticRules("d8r8",
`rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `,
CommandDeps: []string{
"${config.D8Cmd}",
+ "${config.D8Jar}",
"${config.R8Cmd}",
+ "${config.R8Jar}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -301,6 +431,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
Deps: blueprint.DepsGCC,
CommandDeps: []string{
"${config.R8Cmd}",
+ "${config.R8Jar}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -330,8 +461,14 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
}, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
"r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
+var proguardDictToProto = pctx.AndroidStaticRule("proguard_dict_to_proto", blueprint.RuleParams{
+ Command: `${symbols_map} -r8 $in -location $location -write_if_changed $out`,
+ Restat: true,
+ CommandDeps: []string{"${symbols_map}"},
+}, "location")
+
func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
- dexParams *compileDexParams) (flags []string, deps android.Paths) {
+ dexParams *compileDexParams) (flags []string, deps android.Paths, incD8Compatible bool) {
flags = d.dexProperties.Dxflags
// Translate all the DX flags to D8 ones until all the build files have been migrated
@@ -401,36 +538,41 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
}
flags = append(flags, "--min-api "+strconv.Itoa(minApiFlagValue))
+ incD8Compatible = false
+ // Incremental d8 does not have libraries passed to it for speed, so any
+ // desugaring with library classes is not possible.
+ // To cater for this we only enable incD8 when platform build flag is passed
+ // as it automatically disables desugaring.
if addAndroidPlatformBuildFlag {
flags = append(flags, "--android-platform-build")
+ incD8Compatible = true
}
- return flags, deps
+ return flags, deps, incD8Compatible
}
-func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
+func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams, useD8Inc bool) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
flags := dexParams.flags
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
-
d8Deps = append(d8Deps, flags.bootClasspath...)
d8Deps = append(d8Deps, flags.dexClasspath...)
-
- if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
- d8Flags = append(d8Flags, flags...)
- d8Deps = append(d8Deps, deps...)
- artProfileOutput = profileOutput
+ if !useD8Inc {
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ d8Flags = append(d8Flags, flags...)
+ d8Deps = append(d8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
}
return d8Flags, d8Deps, artProfileOutput
}
-func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, debugMode bool) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
- flags := dexParams.flags
- opt := d.dexProperties.Optimize
+func (d *dexer) r8DepLibFlags(ctx android.ModuleContext, dexParams *compileDexParams) (r8Flags []string, r8Deps android.Paths) {
+ var depLibs classpath
// When an app contains references to APIs that are not in the SDK specified by
// its LOCAL_SDK_VERSION for example added by support library or by runtime
- // classes added by desugaring, we artifically raise the "SDK version" "linked" by
+ // classes added by desugaring, we artificially raise the "SDK version" "linked" by
// ProGuard, to
// - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
// - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
@@ -443,14 +585,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
}
})
- r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
- r8Deps = append(r8Deps, proguardRaiseDeps...)
+ depLibs = append(depLibs, proguardRaiseDeps...)
}
- r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
- r8Deps = append(r8Deps, flags.bootClasspath...)
- r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
- r8Deps = append(r8Deps, flags.dexClasspath...)
+ depLibs = append(depLibs, dexParams.flags.bootClasspath...)
+ depLibs = append(depLibs, dexParams.flags.dexClasspath...)
transitiveStaticLibsLookupMap := map[android.Path]bool{}
for _, jar := range d.transitiveStaticLibsHeaderJarsForR8.ToList() {
@@ -465,8 +604,27 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
transitiveHeaderJars = append(transitiveHeaderJars, jar)
}
transitiveClasspath := classpath(transitiveHeaderJars)
- r8Flags = append(r8Flags, transitiveClasspath.FormJavaClassPath("-libraryjars"))
- r8Deps = append(r8Deps, transitiveClasspath...)
+ depLibs = append(depLibs, transitiveClasspath...)
+
+ depLibs = depLibs.FirstUniquePaths()
+ r8Deps = append(r8Deps, depLibs...)
+
+ var libraryDepArg string
+ if Bool(d.dexProperties.Optimize.Import_libraries_as_classpath) {
+ libraryDepArg = "--classpath "
+ } else {
+ libraryDepArg = "--lib "
+ }
+ r8Flags = append(r8Flags, depLibs.FormRepeatedClassPath(libraryDepArg)...)
+
+ return r8Flags, r8Deps
+}
+
+func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, debugMode, useD8Inc bool) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
+ r8Flags, r8Deps = d.r8DepLibFlags(ctx, dexParams)
+
+ flags := dexParams.flags
+ opt := d.dexProperties.Optimize
flagFiles := android.Paths{
android.PathForSource(ctx, "build/make/core/proguard.flags"),
@@ -525,7 +683,8 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
// Avoid unnecessary stack frame noise by only injecting source map ids for non-debug
// optimized or obfuscated targets.
- if (Bool(opt.Optimize) || Bool(opt.Obfuscate)) && !debugMode {
+ optimize := opt.Optimize.GetOrDefault(ctx, false)
+ if (optimize || Bool(opt.Obfuscate)) && !debugMode {
// TODO(b/213833843): Allow configuration of the prefix via a build variable.
var sourceFilePrefix = "go/retraceme "
var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
@@ -538,7 +697,7 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
r8Flags = append(r8Flags, "-dontshrink")
}
- if !Bool(opt.Optimize) {
+ if !optimize {
r8Flags = append(r8Flags, "-dontoptimize")
}
@@ -569,10 +728,12 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
}
}
- if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
- r8Flags = append(r8Flags, flags...)
- r8Deps = append(r8Deps, deps...)
- artProfileOutput = profileOutput
+ if !useD8Inc {
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ r8Flags = append(r8Flags, flags...)
+ r8Deps = append(r8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
}
if ctx.Config().UseR8StoreStoreFenceConstructorInlining() {
@@ -623,21 +784,23 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
cleanPhonyPath := android.PathForModuleOut(ctx, "dex", dexParams.jarName+"-partialcompileclean").OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
- zipFlags := "--ignore_missing_files"
+ zipFlags := "--ignore_missing_files --quiet"
if proptools.Bool(d.dexProperties.Uncompress_dex) {
zipFlags += " -L 0"
}
- commonFlags, commonDeps := d.dexCommonFlags(ctx, dexParams)
+ commonFlags, commonDeps, incD8Compatible := d.dexCommonFlags(ctx, dexParams)
// Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true.
mergeZipsFlags := ""
if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) {
- mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins"
+ mergeZipsFlags = "-stripFile META-INF/**/*.kotlin_module -stripFile **/*.kotlin_builtins"
}
useR8 := d.effectiveOptimizeEnabled(ctx)
useD8 := !useR8 || ctx.Config().PartialCompileFlags().Use_d8
+ // d8Inc is applicable only when d8 is allowed.
+ useD8Inc := useD8 && ctx.Config().PartialCompileFlags().Enable_inc_d8 && incD8Compatible
rbeR8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8")
rbeD8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8")
var rule blueprint.Rule
@@ -669,7 +832,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
}...)
description = "r8"
debugMode := android.InList("--debug", commonFlags)
- r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode)
+ r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode, useD8Inc)
deps = append(deps, r8Deps...)
args["r8Flags"] = strings.Join(append(commonFlags, r8Flags...), " ")
if r8ArtProfileOutputPath != nil {
@@ -694,25 +857,61 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
args["implicits"] = strings.Join(deps.Strings(), ",")
}
}
+ cleanupD8R8, cleanupD8IncR8, cleanupD8Inc := false, false, false
if useD8 {
description = "d8"
- d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+ d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams, useD8Inc)
deps = append(deps, d8Deps...)
deps = append(deps, commonDeps...)
args["d8Flags"] = strings.Join(append(commonFlags, d8Flags...), " ")
if d8ArtProfileOutputPath != nil {
artProfileOutputPath = d8ArtProfileOutputPath
}
+ // The file containing dependencies of the current module
+ // Any change in them may warrant changes in the incremental dex compilation
+ // source set.
+ if useD8Inc {
+ d8DepsFile := android.PathForModuleOut(ctx, dexParams.jarName+".dex.deps.rsp")
+ android.WriteFileRule(ctx, d8DepsFile, strings.Join(deps.Strings(), "\n"))
+ deps = append(deps, d8DepsFile)
+ args["d8Deps"] = d8DepsFile.String()
+ }
// If we are generating both d8 and r8, only use RBE when both are enabled.
switch {
+ // r8 is the selected rule, useD8Inc is the override
+ case useR8 && rule == r8 && useD8Inc:
+ rule = d8IncR8
+ cleanupD8IncR8 = true
+ description = "d8IncR8"
+ // r8 is the selected rule, useD8 is the override
case useR8 && rule == r8:
rule = d8r8
+ cleanupD8R8 = true
description = "d8r8"
+ // rbeR8 is the selected rule, useD8Inc is the override
+ case useR8 && rule == r8RE && useD8Inc:
+ rule = d8IncR8RE
+ cleanupD8IncR8 = true
+ description = "d8IncR8"
+ // rbeR8 is the selected rule, useD8 is the override
case useR8 && rule == r8RE && rbeD8:
rule = d8r8RE
+ cleanupD8R8 = true
description = "d8r8"
+ // rbeD8 is the selected rule, useD8Inc is the override
+ case rbeD8 && useD8Inc:
+ rule = d8IncRE
+ cleanupD8Inc = true
+ description = "d8Inc"
+ // rbeD8 is the selected rule
case rbeD8:
rule = d8RE
+ // D8 is the selected rule, useD8Inc is the override
+ case useD8Inc:
+ rule = d8Inc
+ cleanupD8Inc = true
+ description = "d8Inc"
+ // D8 is the selected rule
default:
rule = d8
}
@@ -732,7 +931,8 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
Implicits: deps,
Args: args,
})
- if useR8 && useD8 {
+ // Run cleanup when d8r8 was used
+ if cleanupD8R8 {
// Generate the rule for partial compile clean.
args["builtOut"] = javalibJar.String()
ctx.Build(pctx, android.BuildParams{
@@ -744,6 +944,32 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
})
ctx.Phony("partialcompileclean", cleanPhonyPath)
}
+ // Run cleanup when d8IncR8 was used
+ if cleanupD8IncR8 {
+ // Generate the rule for partial compile clean.
+ args["builtOut"] = javalibJar.String()
+ ctx.Build(pctx, android.BuildParams{
+ Rule: d8IncR8Clean,
+ Description: "d8IncR8Clean",
+ Output: cleanPhonyPath,
+ Args: args,
+ PhonyOutput: true,
+ })
+ ctx.Phony("partialcompileclean", cleanPhonyPath)
+ }
+ // Run cleanup when d8Inc was used
+ if cleanupD8Inc {
+ // Generate the rule for partial compile clean.
+ args["builtOut"] = javalibJar.String()
+ ctx.Build(pctx, android.BuildParams{
+ Rule: d8IncClean,
+ Description: "d8IncClean",
+ Output: cleanPhonyPath,
+ Args: args,
+ PhonyOutput: true,
+ })
+ ctx.Phony("partialcompileclean", cleanPhonyPath)
+ }
if proptools.Bool(d.dexProperties.Uncompress_dex) {
alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
@@ -754,6 +980,64 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
return javalibJar, artProfileOutputPath
}
+type ProguardZips struct {
+ DictZip android.Path
+ DictMapping android.Path
+ UsageZip android.Path
+}
+
+func BuildProguardZips(ctx android.ModuleContext, modules []android.ModuleOrProxy) ProguardZips {
+ dictZip := android.PathForModuleOut(ctx, "proguard-dict.zip")
+ dictZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ dictZipCmd := dictZipBuilder.Command().BuiltTool("soong_zip").Flag("-d").FlagWithOutput("-o ", dictZip)
+
+ dictMapping := android.PathForModuleOut(ctx, "proguard-dict-mapping.textproto")
+ dictMappingBuilder := android.NewRuleBuilder(pctx, ctx)
+ dictMappingCmd := dictMappingBuilder.Command().BuiltTool("symbols_map").Flag("-merge").Output(dictMapping)
+
+ protosDir := android.PathForModuleOut(ctx, "proguard_mapping_protos")
+
+ usageZip := android.PathForModuleOut(ctx, "proguard-usage.zip")
+ usageZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ usageZipCmd := usageZipBuilder.Command().BuiltTool("merge_zips").Output(usageZip)
+
+ for _, mod := range modules {
+ if proguardInfo, ok := android.OtherModuleProvider(ctx, mod, ProguardProvider); ok {
+ // Maintain these out/target/common paths for backwards compatibility. They may be able
+ // to be changed if tools look up file locations from the protobuf, but I'm not
+ // exactly sure how that works.
+ dictionaryFakePath := fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/proguard_dictionary", proguardInfo.Class, proguardInfo.ModuleName)
+ dictZipCmd.FlagWithArg("-e ", dictionaryFakePath)
+ dictZipCmd.FlagWithInput("-f ", proguardInfo.ProguardDictionary)
+ dictZipCmd.Textf("-e out/target/common/obj/%s/%s_intermediates/classes.jar", proguardInfo.Class, proguardInfo.ModuleName)
+ dictZipCmd.FlagWithInput("-f ", proguardInfo.ClassesJar)
+
+ protoFile := protosDir.Join(ctx, filepath.Dir(dictionaryFakePath), "proguard_dictionary.textproto")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: proguardDictToProto,
+ Input: proguardInfo.ProguardDictionary,
+ Output: protoFile,
+ Args: map[string]string{
+ "location": dictionaryFakePath,
+ },
+ })
+ dictMappingCmd.Input(protoFile)
+
+ usageZipCmd.Input(proguardInfo.ProguardUsageZip)
+ }
+ }
+
+ dictZipBuilder.Build("proguard_dict_zip", "Building proguard dictionary zip")
+ dictMappingBuilder.Build("proguard_dict_mapping_proto", "Building proguard mapping proto")
+ usageZipBuilder.Build("proguard_usage_zip", "Building proguard usage zip")
+
+ return ProguardZips{
+ DictZip: dictZip,
+ DictMapping: dictMapping,
+ UsageZip: usageZip,
+ }
+}
+
type ProguardInfo struct {
ModuleName string
Class string
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index e8e1cd405..c42997b92 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -644,7 +644,7 @@ func checkSystemServerOrder(ctx android.ModuleContext, libName string) {
config := dexpreopt.GetGlobalConfig(ctx)
jars := config.AllSystemServerClasspathJars(ctx)
jarIndex := config.AllSystemServerJars(ctx).IndexOfJar(libName)
- ctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(dep android.ModuleProxy, parent android.ModuleProxy) bool {
tag := ctx.OtherModuleDependencyTag(dep)
// Ideally this should only be walking relevant dependencies, but to maintain existing behavior
// for now just exclude any known irrelevant dependencies that would lead to incorrect errors.
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 228704355..f302915b4 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -540,7 +540,7 @@ func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
// This dependency will be used to get the path to the deapexed dex boot jars and profile (via a provider)
func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorContext, apexes ...string) {
psi := android.PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(apexContributionsMetadataDepTag, func(am android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(apexContributionsMetadataDepTag, func(am android.ModuleProxy) {
if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists {
psi = info
}
@@ -562,9 +562,9 @@ func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorConte
}
}
-func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
+func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.ModuleProxy {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
- fragments := make(map[string]android.Module)
+ fragments := make(map[string]android.ModuleProxy)
type moduleInApexPair struct {
module string
@@ -574,7 +574,7 @@ func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.
var modulesInApexes []moduleInApexPair
// Find the list of modules in apexes.
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
if !isActiveModule(ctx, child) {
return false
}
@@ -596,7 +596,7 @@ func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.
for _, moduleInApex := range modulesInApexes {
// Find a desired module in an apex.
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
t := ctx.OtherModuleDependencyTag(child)
if bcpTag, ok := t.(bootclasspathDependencyTag); ok {
if bcpTag.typ == platform {
@@ -615,10 +615,10 @@ func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.
}
return fragments
- }).(map[string]android.Module)
+ }).(map[string]android.ModuleProxy)
}
-func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.Module {
+func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.ModuleProxy {
return gatherBootclasspathFragments(ctx)[apexName]
}
@@ -767,6 +767,7 @@ func (d *dexpreoptBootJars) buildBootZip(ctx android.ModuleContext) {
Inputs: []android.Path{
bootZipMetadataTmp,
globalSoong.UffdGcFlag,
+ globalSoong.AssumeValueFlags,
newlineFile,
},
Output: bootZipMetadata,
@@ -863,7 +864,7 @@ func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig)
type apexJarModulePair struct {
apex string
- jarModule android.Module
+ jarModule android.ModuleProxy
}
func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []apexJarModulePair {
@@ -923,9 +924,9 @@ func (m *apexNameToApexExportsInfoMap) javaLibraryDexPathOnHost(ctx android.Modu
}
// Returns the stem of an artifact inside a prebuilt apex
-func ModuleStemForDeapexing(m android.Module) string {
- bmn, _ := m.(interface{ BaseModuleName() string })
- return bmn.BaseModuleName()
+func ModuleStemForDeapexing(ctx android.OtherModuleProviderContext, m android.ModuleOrProxy) string {
+ info := android.OtherModuleProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ return info.BaseModuleName
}
// Returns the java libraries exported by the apex for hiddenapi and dexpreopt
@@ -934,11 +935,11 @@ func ModuleStemForDeapexing(m android.Module) string {
// 2. Legacy: An edge to java_library or java_import (java_sdk_library) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNameToApexExportsInfoMap apexNameToApexExportsInfoMap) android.Path {
- if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, ModuleStemForDeapexing(pair.jarModule)); found {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, ModuleStemForDeapexing(ctx, pair.jarModule)); found {
return dex
}
// TODO: b/308174306 - Remove the legacy mechanism
- if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
+ if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(ctx, pair.jarModule) {
// This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
// files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
// a source APEX because there is no guarantee that it is the same as the jar packed into the
@@ -949,7 +950,7 @@ func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNam
} else {
// Use exactly the same jar that is packed into the APEX.
fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
- if fragment == nil {
+ if fragment.IsNil() {
ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
pair.jarModule.Name(),
@@ -1110,20 +1111,25 @@ func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameT
}
// TODO: b/308174306 - Remove the legacy mechanism
fragment := getBootclasspathFragmentByApex(ctx, apexName)
- if fragment == nil {
+ if fragment.IsNil() {
ctx.ModuleErrorf("Boot image config imports profile from '%[2]s', but a "+
"bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
"dependency of dex_bootjars",
apexName)
return nil
}
- return fragment.(commonBootclasspathFragment).getProfilePath()
+
+ if info, ok := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentInfoProvider); ok {
+ return info.ProfilePathOnHost
+ } else {
+ panic(fmt.Errorf("missing BootclasspathFragmentInfoProvider in %s", fragment))
+ }
}
func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap {
apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{}
- ctx.VisitDirectDeps(func(am android.Module) {
+ ctx.VisitDirectDepsProxy(func(am android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(am)
if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
if bcpTag.moduleInApex == "" {
@@ -1323,6 +1329,8 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
cmd.Flag(global.BootFlags)
}
+ cmd.Text("$(cat").Input(globalSoong.AssumeValueFlags).Text(")")
+
if extraFlags != "" {
cmd.Flag(extraFlags)
}
@@ -1381,6 +1389,10 @@ const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
+// bootImageProfileRuleCommon contains the common logic for generating boot image profiles for both
+// the platform and the ART module when building from source.
+// Building from prebuilts is not handled here. Instead, the profile is extracted from the prebuilt
+// ART module.
func bootImageProfileRuleCommon(ctx android.ModuleContext, name string, dexFiles android.Paths, dexLocations []string) android.WritablePath {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -1389,33 +1401,35 @@ func bootImageProfileRuleCommon(ctx android.ModuleContext, name string, dexFiles
return nil
}
- defaultProfile := "frameworks/base/boot/boot-image-profile.txt"
- // If ART is prebuilt, primarily in next release configs, this will still use
- // the profile from source which represent the latest code, so it may not
- // correspond to the BCP jars in the prebuilt APEX, but this is the profile we
- // have access to.
- artProfile := "art/build/boot/boot-image-profile.txt"
- extraProfile := "frameworks/base/boot/boot-image-profile-extra.txt"
-
rule := android.NewRuleBuilder(pctx, ctx)
var profiles android.Paths
if len(global.BootImageProfiles) > 0 {
+ // The most common case. The profiles are specified by
+ // `PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION`.
+ // - On a bundled build, this list contains both the ART profile and the frameworks profile.
+ // - On an unbundled build with ART source code being present, this list only contains the ART
+ // profile.
profiles = append(profiles, global.BootImageProfiles...)
- } else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
- profiles = append(profiles, path.Path())
} else {
- // No profile (not even a default one, which is the case on some branches
- // like master-art-host that don't have frameworks/base).
+ // No profile specified. This means we are building an unbundled build with ART source code
+ // being absent, meaning we are not building the platform or the ART module, so we don't need
+ // a profile.
// Return nil and continue without profile.
return nil
}
- if path := android.ExistentPathForSource(ctx, artProfile); path.Valid() {
- profiles = append(profiles, path.Path())
- }
+ extraProfile := "frameworks/base/boot/boot-image-profile-extra.txt"
if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() {
profiles = append(profiles, path.Path())
}
+
+ // Remove duplicates while preserving order to ensure deterministic builds.
+ profiles = android.FirstUniquePaths(profiles)
+
+ // We concatenate the profiles into a single file. Later, `profman` filters the entries based on
+ // `dexFiles` to only keep the relevant ones. For example, when this function is called for
+ // generating the profile for the ART module, `profman` only keeps the entries for the ART module
+ // and not the platform.
bootImageProfile := android.PathForModuleOut(ctx, name, "boot-image-profile.txt")
rule.Command().Text("cat").Inputs(profiles).Text(">").Output(bootImageProfile)
@@ -1621,7 +1635,7 @@ func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(m)
if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
if bcpTag.moduleInApex != "" {
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
index 9d0f539ba..f7d46144a 100644
--- a/java/dexpreopt_check.go
+++ b/java/dexpreopt_check.go
@@ -95,16 +95,17 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod
global := dexpreopt.GetGlobalConfig(ctx)
targets := ctx.Config().Targets[android.Android]
- ctx.VisitDirectDepsWithTag(systemServerJarDepTag, func(systemServerJar android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(systemServerJarDepTag, func(systemServerJar android.ModuleProxy) {
partition := "system"
- if systemServerJar.InstallInSystemExt() && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, systemServerJar, android.CommonModuleInfoProvider)
+ if commonInfo.SystemExtSpecific && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() {
partition = ctx.DeviceConfig().SystemExtPath() // system_ext
}
var dexLocation string
- if m, ok := systemServerJar.(ModuleWithStem); ok {
- dexLocation = dexpreopt.GetSystemServerDexLocation(ctx, global, m.Stem())
+ if javaInfo, ok := android.OtherModuleProvider(ctx, systemServerJar, JavaInfoProvider); ok {
+ dexLocation = dexpreopt.GetSystemServerDexLocation(ctx, global, javaInfo.Stem)
} else {
- ctx.PropertyErrorf("dexpreopt_systemserver_check", "%v is not a ModuleWithStem", systemServerJar.Name())
+ ctx.PropertyErrorf("dexpreopt_systemserver_check", "%v does not have JavaInfo", systemServerJar.Name())
}
odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType, partition)
odexPath := getInstallPath(ctx, odexLocation)
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index f437da02c..775966153 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -402,3 +402,44 @@ func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) {
android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs())
}
+
+func TestAssumeValueFlags(t *testing.T) {
+ for _, platformSdkVersion := range []string{"", "28"} {
+ t.Run(platformSdkVersion, func(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithDexpreopt,
+ dexpreopt.PrepareForTestWithDexpreoptConfig,
+ dexpreopt.FixtureSetEnableUffdGc("false"),
+ dexpreopt.FixtureSetPlatformSdkVersion(platformSdkVersion),
+ )
+
+ result := preparers.RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ installable: true,
+ dex_preopt: {
+ profile: "art-profile",
+ },
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }`)
+
+ ctx := result.TestContext
+
+ // Ensure that we always have a valid (but possibly empty) assumed
+ // value flags file for use with dex2oat input.
+ ctx.SingletonForTests(t, "dexpreopt-soong-config").Output("out/soong/dexpreopt/assume_value_flags.txt")
+
+ // If the SDK version is set, it should exist in the command to
+ // generate the assumed value flags file for use with dex2oat input.
+ if platformSdkVersion != "" {
+ rule := ctx.SingletonForTests(t, "dexpreopt-soong-config").Rule("dexpreopt_assume_value_flags")
+ android.AssertStringDoesContain(t, "", rule.RuleParams.Command,
+ "echo '--assume-value=Landroid/os/Build$$VERSION;->SDK_INT:"+platformSdkVersion+"'")
+ android.AssertStringPathsRelativeToTopEquals(t, "", ctx.Config(), []string{
+ "out/soong/dexpreopt/assume_value_flags.txt",
+ }, rule.AllOutputs())
+ }
+ })
+ }
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 3faf294de..a65427f8b 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -195,9 +195,6 @@ func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersio
"them instead.")
}
return false
- } else if ctx.Config().PartialCompileFlags().Disable_stub_validation &&
- !ctx.Config().BuildFromTextStub() {
- return false
} else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
return true
} else if String(apiToCheck.Api_file) != "" {
@@ -432,8 +429,8 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
for _, src := range j.properties.Srcs {
if moduleName, tag := android.SrcIsModuleWithTag(src); moduleName != "" {
otherModule := android.GetModuleProxyFromPathDep(ctx, moduleName, tag)
- if otherModule != nil {
- if dep, ok := android.OtherModuleProvider(ctx, *otherModule, android.CodegenInfoProvider); ok {
+ if !otherModule.IsNil() {
+ if dep, ok := android.OtherModuleProvider(ctx, otherModule, android.CodegenInfoProvider); ok {
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
}
}
@@ -651,9 +648,9 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule
ctx.PropertyErrorf("custom_template", "must specify a template")
}
- ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- cmd.FlagWithArg("-templatedir ", t.dir.String()).Implicits(t.deps)
+ ctx.VisitDirectDepsProxyWithTag(droiddocTemplateTag, func(m android.ModuleProxy) {
+ if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
+ cmd.FlagWithArg("-templatedir ", t.Dir.String()).Implicits(t.Deps)
} else {
ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_exported_dir", ctx.OtherModuleName(m))
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index b30c8448a..c2a5c046e 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -18,6 +18,7 @@ import (
"fmt"
"path/filepath"
"regexp"
+ "slices"
"strings"
"github.com/google/blueprint"
@@ -36,6 +37,7 @@ type StubsInfo struct {
}
type DroidStubsInfo struct {
+ AconfigProtoFiles android.Paths
CurrentApiTimestamp android.Path
EverythingStubsInfo StubsInfo
ExportableStubsInfo StubsInfo
@@ -437,6 +439,8 @@ func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
if d.properties.Api_levels_module != nil {
ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
}
+
+ d.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
@@ -593,6 +597,18 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an
filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
+ // If generating the android API then include android.test.*.jars in the set
+ // of files passed to Metalava.
+ filenames := []string{filename}
+ if filename == "android.jar" {
+ filenames = append(
+ filenames,
+ "android.test.base.jar",
+ "android.test.mock.jar",
+ "android.test.runner.jar",
+ )
+ }
+
// TODO: Avoid the duplication of API surfaces, reuse apiScope.
// Add all relevant --android-jar-pattern patterns for Metalava.
// When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
@@ -648,7 +664,7 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an
extensions_dir = t.Dir.String() + "/extensions"
}
cmd.Implicit(dep)
- } else if depBase == filename {
+ } else if slices.Contains(filenames, depBase) {
// Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc..
cmd.Implicit(dep)
} else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
@@ -688,7 +704,16 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an
addPattern(AndroidPlusUpdatableJar)
}
+ // Always add the main jar, e.g. android.jar. This will be overridden by
+ // android-plus-updatable.jar if a pattern for it was added as that comes
+ // first and neither has a library placeholder.
addPattern(filename)
+
+ // If additional file names were added then they are assumed to be
+ // libraries so match them using a {library} placeholder.
+ if len(filenames) > 1 {
+ addPattern("{library}.jar")
+ }
}
if extensions_dir != "" {
@@ -1251,7 +1276,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Add options for the other optional tasks: API-lint and check-released.
// We generate separate timestamp files for them.
- doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint
+ doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
writeSdkValues := Bool(d.properties.Write_sdk_values)
@@ -1380,15 +1405,12 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if d.apiLintTimestamp != nil {
cmd.Validation(d.apiLintTimestamp)
}
-
if d.checkLastReleasedApiTimestamp != nil {
cmd.Validation(d.checkLastReleasedApiTimestamp)
}
-
if d.checkNullabilityWarningsTimestamp != nil {
cmd.Validation(d.checkNullabilityWarningsTimestamp)
}
-
rule.Build("metalavaCurrentApiCheck", "check current API")
d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
@@ -1407,6 +1429,9 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Input(d.removedApiFile).Flag(removedApiFile.String())
msg = "failed to update public API"
+ if ctx.Config().GetBuildFlagBool("RELEASE_SRC_DIR_IS_READ_ONLY") {
+ msg += ". You may need `BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true`"
+ }
rule.Command().
Text("touch").Output(d.updateCurrentApiTimestamp).
@@ -1419,6 +1444,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
droidInfo := DroidStubsInfo{
+ AconfigProtoFiles: deps.aconfigProtoFiles,
CurrentApiTimestamp: d.CurrentApiTimestamp(),
EverythingStubsInfo: StubsInfo{},
ExportableStubsInfo: StubsInfo{},
@@ -1593,6 +1619,10 @@ func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
return d.stubsSrcJar, nil
}
+func (p *PrebuiltStubsSources) DepsMutator(ctx android.BottomUpMutatorContext) {
+ p.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
+}
+
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(p.properties.Srcs) != 1 {
ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
diff --git a/java/fuzz.go b/java/fuzz.go
index 0e239f0ec..922585b8d 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -51,6 +51,12 @@ type JavaFuzzTest struct {
jniFilePaths android.Paths
}
+type JavaFuzzTestInfo struct {
+ JniFilePaths android.Paths
+}
+
+var JavaFuzzTestInfoProvider = blueprint.NewProvider[JavaFuzzTestInfo]()
+
// java_fuzz builds and links sources into a `.jar` file for the device.
// This generates .class files in a jar which can then be instrumented before
// fuzzing in Android Runtime (ART: Android OS on emulator or device)
@@ -131,9 +137,41 @@ func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
- j.Test.GenerateAndroidBuildActions(ctx)
+ checkMinSdkVersionMts(ctx, j.MinSdkVersion(ctx))
+ j.Test.generateAndroidBuildActionsWithConfig(ctx, nil)
+
+ var compatibilitySupportFiles android.Paths
+ compatibilitySupportFiles = append(compatibilitySupportFiles, j.implementationJarFile)
+ compatibilitySupportFiles = append(compatibilitySupportFiles, j.jniFilePaths...)
+ compatibilitySupportFiles = append(compatibilitySupportFiles, j.fuzzPackagedModule.Corpus...)
+ if j.fuzzPackagedModule.Dictionary != nil {
+ compatibilitySupportFiles = append(compatibilitySupportFiles, j.fuzzPackagedModule.Dictionary)
+ }
+
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: j.testProperties.Test_suites,
+ MainFile: j.outputFile,
+ MainFileStem: j.Stem(),
+ MainFileExt: ".jar",
+ ConfigFile: j.testConfig,
+ ExtraConfigs: j.extraTestConfigs,
+ NeedsArchFolder: ctx.Device(),
+ CompatibilitySupportFiles: compatibilitySupportFiles,
+ PerTestcaseDirectory: proptools.Bool(j.testProperties.Per_testcase_directory),
+ })
+
+ fuzzModuleValidator := fuzz.FuzzModule{
+ j.ModuleBase,
+ j.DefaultableModuleBase,
+ j.ApexModuleBase,
+ }
- fuzz.SetFuzzPackagedModuleInfo(ctx, &j.fuzzPackagedModule)
+ if fuzz.IsValid(ctx, fuzzModuleValidator) {
+ fuzz.SetFuzzPackagedModuleInfo(ctx, &j.fuzzPackagedModule)
+ android.SetProvider(ctx, JavaFuzzTestInfoProvider, JavaFuzzTestInfo{
+ JniFilePaths: j.jniFilePaths,
+ })
+ }
}
type javaFuzzPackager struct {
@@ -149,9 +187,9 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
s.FuzzTargets = make(map[string]bool)
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
// Discard non-fuzz targets.
- javaFuzzModule, ok := module.(*JavaFuzzTest)
+ javaInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
if !ok {
return
}
@@ -159,25 +197,21 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
if !ok {
return
}
+ javaFuzzTestInfo, ok := android.OtherModuleProvider(ctx, module, JavaFuzzTestInfoProvider)
+ if !ok {
+ return
+ }
+
+ commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
hostOrTargetString := "target"
- if javaFuzzModule.Target().HostCross {
+ if commonInfo.Target.HostCross {
hostOrTargetString = "host_cross"
- } else if javaFuzzModule.Host() {
+ } else if commonInfo.Host {
hostOrTargetString = "host"
}
- fuzzModuleValidator := fuzz.FuzzModule{
- javaFuzzModule.ModuleBase,
- javaFuzzModule.DefaultableModuleBase,
- javaFuzzModule.ApexModuleBase,
- }
-
- if ok := fuzz.IsValid(ctx, fuzzModuleValidator); !ok {
- return
- }
-
- archString := javaFuzzModule.Arch().ArchType.String()
+ archString := commonInfo.Target.Arch.ArchType.String()
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -188,14 +222,17 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder)
// Add .jar
- if !javaFuzzModule.Host() {
- files = append(files, fuzz.FileToZip{SourceFilePath: javaFuzzModule.implementationJarFile, DestinationPathPrefix: "classes"})
+ if !commonInfo.Host {
+ for _, jar := range javaInfo.ImplementationJars {
+ files = append(files, fuzz.FileToZip{SourceFilePath: jar, DestinationPathPrefix: "classes"})
+ }
}
- files = append(files, fuzz.FileToZip{SourceFilePath: javaFuzzModule.outputFile})
+ outputFile := android.OutputFileForModule(ctx, module, "")
+ files = append(files, fuzz.FileToZip{SourceFilePath: outputFile})
// Add jni .so files
- for _, fPath := range javaFuzzModule.jniFilePaths {
+ for _, fPath := range javaFuzzTestInfo.JniFilePaths {
files = append(files, fuzz.FileToZip{SourceFilePath: fPath})
}
@@ -205,6 +242,14 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
}
})
s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
+
+ // Create the phony and dist rules
+ ctx.Phony("haiku-java", s.Packages...)
+ ctx.DistForGoals([]string{"haiku-java"}, s.Packages...)
+ for _, target := range android.SortedKeys(s.FuzzTargets) {
+ ctx.Phony("haiku-java", android.PathForPhony(ctx, target))
+ }
+
}
func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
diff --git a/java/genrule_combiner.go b/java/genrule_combiner.go
index 357dc2c76..db6af1ad2 100644
--- a/java/genrule_combiner.go
+++ b/java/genrule_combiner.go
@@ -95,7 +95,7 @@ func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext)
// Collect the headers first, so that aconfig flag values for the libraries will override
// values from the headers (if they are different).
- ctx.VisitDirectDepsWithTag(genruleCombinerHeaderDepTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(genruleCombinerHeaderDepTag, func(m android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
j.headerJars = append(j.headerJars, dep.HeaderJars...)
@@ -113,7 +113,7 @@ func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.PropertyErrorf("headers", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
}
})
- ctx.VisitDirectDepsWithTag(staticLibTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(staticLibTag, func(m android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
j.implementationJars = append(j.implementationJars, dep.ImplementationJars...)
j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.ImplementationAndResourcesJars...)
@@ -178,6 +178,12 @@ func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.SetOutputFiles(javaInfo.HeaderJars, ".hjar")
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if j.combinedImplementationJar != nil {
+ moduleInfoJSON.ClassesJar = []string{j.combinedImplementationJar.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (j *GenruleCombiner) GeneratedSourceFiles() android.Paths {
@@ -220,10 +226,6 @@ func (j *GenruleCombiner) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
return nil
}
-func (j *GenruleCombiner) JacocoReportClassesFile() android.Path {
- return nil
-}
-
func (j *GenruleCombiner) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Class: "JAVA_LIBRARIES",
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index c9a1f2bbe..fe2521cca 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -44,8 +44,7 @@ type hiddenAPI struct {
//
// This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
- bootDexJarPath OptionalDexJarPath
- bootDexJarPathErr error
+ bootDexJarPath OptionalDexJarPath
// The paths to the classes jars that contain classes and class members annotated with
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
@@ -57,10 +56,7 @@ type hiddenAPI struct {
uncompressDexState *bool
}
-func (h *hiddenAPI) bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath {
- if h.bootDexJarPathErr != nil {
- ctx.ModuleErrorf(h.bootDexJarPathErr.Error())
- }
+func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
return h.bootDexJarPath
}
@@ -81,7 +77,7 @@ type hiddenAPIModule interface {
}
type hiddenAPIIntf interface {
- bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath
+ bootDexJar() OptionalDexJarPath
classesJars() android.Paths
uncompressDex() *bool
}
@@ -131,11 +127,6 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ
h.active = isModuleInBootClassPath(ctx, module)
}
-// Store any error encountered during the initialization of hiddenapi structure (e.g. unflagged co-existing prebuilt apexes)
-func (h *hiddenAPI) initHiddenAPIError(err error) {
- h.bootDexJarPathErr = err
-}
-
func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
// Get the configured platform and apex boot jars.
nonApexBootJars := ctx.Config().NonApexBootJars()
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 365005835..d7272433c 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -197,7 +197,7 @@ func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
return false
}
-func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+func (b hiddenAPIStubsDependencyTag) SdkMemberType(ctx android.ModuleContext, child android.ModuleProxy) android.SdkMemberType {
// Do not add additional dependencies to the sdk.
if b.fromAdditionalDependency {
return nil
@@ -205,7 +205,7 @@ func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android
// If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
// property, otherwise treat if it was specified in the java_header_libs property.
- if javaSdkLibrarySdkMemberType.IsInstance(child) {
+ if javaSdkLibrarySdkMemberType.IsInstance(ctx, child) {
return javaSdkLibrarySdkMemberType
}
@@ -296,7 +296,7 @@ func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScop
// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
-func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
+func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.ModuleProxy, kind android.SdkKind) android.Path {
var dexJar OptionalDexJarPath
if sdkLibrary, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
if ctx.Config().ReleaseHiddenApiExportableStubs() {
@@ -304,8 +304,8 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
} else {
dexJar = sdkLibrary.EverythingStubDexJarPaths[kind]
}
- } else if j, ok := module.(UsesLibraryDependency); ok {
- dexJar = j.DexJarBuildPath(ctx)
+ } else if j, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok && j.UsesLibraryDependencyInfo != nil {
+ dexJar = j.DexJarBuildPath
} else {
ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
return nil
@@ -586,7 +586,7 @@ func newHiddenAPIInfo() *HiddenAPIInfo {
return &info
}
-func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
+func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.ModuleProxy) {
// Merge all the information from the fragments. The fragments form a DAG so it is possible that
// this will introduce duplicates so they will be resolved after processing all the fragments.
for _, fragment := range fragments {
@@ -656,7 +656,7 @@ func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
type StubDexJarsByModule map[string]ModuleStubDexJars
// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
-func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
+func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.ModuleProxy, scope *HiddenAPIScope, stubDexJar android.Path) {
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
// Each named module provides one dex jar for each scope. However, in some cases different API
@@ -685,13 +685,14 @@ func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module and
// conscrypt.module.public.api java_sdk_library which will be the case once the former has been
// migrated to a module_lib API.
name = "conscrypt.module.public.api"
- } else if d, ok := module.(SdkLibraryComponentDependency); ok {
- sdkLibraryName := d.SdkLibraryName()
- if sdkLibraryName != nil {
- // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
- // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
- // use `foo` as the name.
- name = *sdkLibraryName
+ } else {
+ if slcDepInfo, ok := android.OtherModuleProvider(ctx, module, SdkLibraryComponentDependencyInfoProvider); ok {
+ if sdkLibraryName := slcDepInfo.SdkLibraryName; sdkLibraryName != nil {
+ // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
+ // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
+ // use `foo` as the name.
+ name = *sdkLibraryName
+ }
}
}
stubDexJarsByScope := s[name]
@@ -785,7 +786,7 @@ func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPa
i.SplitPackages = p.Hidden_api.Split_packages
}
-func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
+func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.ModuleProxy) {
for _, module := range contents {
if info, ok := android.OtherModuleProvider(ctx, module, hiddenAPIPropertyInfoProvider); ok {
i.FlagFilesByCategory.append(info.FlagFilesByCategory)
@@ -844,8 +845,8 @@ func newHiddenAPIFlagInput() HiddenAPIFlagInput {
// dependencies added in hiddenAPIAddStubLibDependencies.
//
// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
-func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
- addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
+func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.ModuleProxy) {
+ addFromModule := func(ctx android.ModuleContext, module android.ModuleProxy, apiScope *HiddenAPIScope) {
sdkKind := apiScope.sdkKind
dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
if dexJar != nil {
@@ -868,7 +869,7 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten
}
}
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
apiScope := hiddenAPIStubsTag.apiScope
@@ -927,7 +928,7 @@ type HiddenAPIFlagOutput struct {
type bootDexJarByModule map[string]android.Path
// addPath adds the path for a module to the map.
-func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
+func (b bootDexJarByModule) addPath(module android.ModuleProxy, path android.Path) {
b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
}
@@ -1168,7 +1169,7 @@ func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name strin
// * metadata.csv
// * index.csv
// * all-flags.csv
-func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
+func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.ModuleProxy, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
hiddenApiSubDir := "modular-hiddenapi" + suffix
// Generate the stub-flags.csv.
@@ -1176,7 +1177,7 @@ func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootD
buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
// Extract the classes jars from the contents.
- classesJars := extractClassesJarsFromModules(contents)
+ classesJars := extractClassesJarsFromModules(ctx, contents)
// Generate the set of flags from the annotations in the source code.
annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
@@ -1266,7 +1267,7 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix s
// 1. New: Direct deps to _selected_ apexes. The apexes contain a ApexExportsInfo
// 2. Legacy: An edge to java_sdk_library(_import) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
-func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
+func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.ModuleProxy) bootDexJarByModule {
bootDexJars := bootDexJarByModule{}
apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
@@ -1283,28 +1284,12 @@ func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android
if _, exists := bootDexJars[android.RemoveOptionalPrebuiltPrefix(module.Name())]; exists {
continue
}
- hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
- if hiddenAPIModule == nil {
- continue
- }
- bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
+ bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, module)
bootDexJars.addPath(module, bootDexJar)
}
return bootDexJars
}
-func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
- if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
- return hiddenAPIModule
- } else if _, ok := module.(*DexImport); ok {
- // Ignore this for the purposes of hidden API processing
- } else {
- ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
- }
-
- return nil
-}
-
// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
type bootDexInfo struct {
// The path to the dex jar that has not had hidden API flags encoded into it.
@@ -1332,15 +1317,16 @@ func (b bootDexInfoByModule) bootDexJars() android.Paths {
// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
// each of the supplied modules which must implement hiddenAPIModule.
-func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
+func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.ModuleProxy) bootDexInfoByModule {
bootDexJarsByModule := bootDexInfoByModule{}
for _, module := range contents {
- hiddenAPIModule := module.(hiddenAPIModule)
- bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
+ bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, module)
+ info := android.OtherModuleProviderOrDefault(ctx, module, JavaInfoProvider)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
bootDexJarsByModule[module.Name()] = bootDexInfo{
path: bootDexJar,
- uncompressDex: *hiddenAPIModule.uncompressDex(),
- minSdkVersion: hiddenAPIModule.MinSdkVersion(ctx),
+ uncompressDex: Bool(info.UncompressDexState),
+ minSdkVersion: *commonInfo.MinSdkVersion.ApiLevel,
}
}
@@ -1352,37 +1338,31 @@ func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android
// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is unset or
// invalid, then create a fake path and either report an error immediately or defer reporting of the
// error until the path is actually used.
-func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
- bootDexJar := module.bootDexJar(ctx)
- if !bootDexJar.Valid() {
+func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module android.ModuleProxy) android.Path {
+ info := android.OtherModuleProviderOrDefault(ctx, module, JavaInfoProvider)
+ if !info.BootDexJarPath.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
- handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
+ handleMissingDexBootFile(ctx, module, fake, info.BootDexJarPath.InvalidReason())
return fake
}
- return bootDexJar.Path()
+
+ return info.BootDexJarPath.Path()
}
// extractClassesJarsFromModules extracts the class jars from the supplied modules.
-func extractClassesJarsFromModules(contents []android.Module) android.Paths {
+func extractClassesJarsFromModules(ctx android.ModuleContext, contents []android.ModuleProxy) android.Paths {
classesJars := android.Paths{}
for _, module := range contents {
- classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
+ if info, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ classesJars = append(classesJars, info.HiddenapiClassesJarPaths...)
+ }
}
return classesJars
}
-// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
-func retrieveClassesJarsFromModule(module android.Module) android.Paths {
- if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
- return hiddenAPIModule.classesJars()
- }
-
- return nil
-}
-
// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
// Soong but should instead only be reported in ninja if the file is actually built.
-func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
+func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.ModuleOrProxy) bool {
// Any missing dependency should be allowed.
if ctx.Config().AllowMissingDependencies() {
return true
@@ -1423,7 +1403,7 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
// a prebuilt modules that has other variants which are part of an APEX.
//
// TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
- if android.IsModulePrebuilt(module) {
+ if android.IsModulePrebuilt(ctx, module) {
// An inactive source module can still contribute to the APEX but an inactive prebuilt module
// should not contribute to anything. So, rather than have a missing dex jar cause a Soong
// failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
@@ -1445,7 +1425,7 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
// file depending on the value returned from deferReportingMissingBootDexJar.
-func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath, reason string) {
+func handleMissingDexBootFile(ctx android.ModuleContext, module android.ModuleOrProxy, fake android.WritablePath, reason string) {
if deferReportingMissingBootDexJar(ctx, module) {
// Create an error rule that pretends to create the output file but will actually fail if it
// is run.
@@ -1467,14 +1447,12 @@ func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module,
// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
// However, under certain conditions, e.g. errors, or special build configurations it will return
// a path to a fake file.
-func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
- bootDexJar := module.(interface {
- DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
- }).DexJarBuildPath(ctx)
- if !bootDexJar.Valid() {
+func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.ModuleProxy) android.Path {
+ info := android.OtherModuleProviderOrDefault(ctx, module, JavaInfoProvider)
+ if !info.DexJarBuildPath.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
- handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
+ handleMissingDexBootFile(ctx, module, fake, info.DexJarBuildPath.InvalidReason())
return fake
}
- return bootDexJar.Path()
+ return info.DexJarBuildPath.Path()
}
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index 1e30c5f82..52e444c6e 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -62,8 +62,9 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F
for _, element := range classpathElements {
switch e := element.(type) {
case *ClasspathLibraryElement:
- classesJars := retrieveClassesJarsFromModule(e.Module())
- monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...)
+ if info, ok := android.OtherModuleProvider(ctx, e.Module(), JavaInfoProvider); ok {
+ monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, info.HiddenapiClassesJarPaths...)
+ }
case *ClasspathFragmentElement:
fragment := e.Module()
@@ -79,7 +80,7 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F
}
// append appends all the files from the supplied info to the corresponding files in this struct.
-func (i *MonolithicHiddenAPIInfo) append(ctx android.ModuleContext, otherModule android.Module, other *HiddenAPIInfo) {
+func (i *MonolithicHiddenAPIInfo) append(ctx android.ModuleContext, otherModule android.ModuleOrProxy, other *HiddenAPIInfo) {
i.FlagsFilesByCategory.append(other.FlagFilesByCategory)
i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPath)
i.MetadataPaths = append(i.MetadataPaths, other.MetadataPath)
diff --git a/java/jacoco.go b/java/jacoco.go
index 696a0cc37..7a80314c1 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -19,6 +19,7 @@ package java
import (
"fmt"
"path/filepath"
+ "slices"
"strings"
"github.com/google/blueprint"
@@ -28,6 +29,10 @@ import (
"android/soong/java/config"
)
+func init() {
+ android.InitRegistrationContext.RegisterParallelSingletonType("device_tests_jacoco_zip", deviceTestsJacocoZipSingletonFactory)
+}
+
var (
jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{
Command: `rm -rf $tmpDir && mkdir -p $tmpDir && ` +
@@ -167,3 +172,62 @@ func jacocoFilterToSpec(filter string) (string, error) {
return spec, nil
}
+
+type JacocoInfo struct {
+ ReportClassesFile android.Path
+ Class string
+ ModuleName string
+}
+
+var ApexJacocoInfoProvider = blueprint.NewProvider[[]JacocoInfo]()
+
+type BuildJacocoZipContext interface {
+ android.BuilderContext
+ android.OtherModuleProviderContext
+}
+
+func BuildJacocoZip(ctx BuildJacocoZipContext, modules []android.ModuleOrProxy, outputFile android.WritablePath) {
+ jacocoZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ jacocoZipCmd := jacocoZipBuilder.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", outputFile).
+ Flag("-L 0")
+ for _, m := range modules {
+ if javaInfo, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok && javaInfo.JacocoInfo.ReportClassesFile != nil {
+ jacoco := javaInfo.JacocoInfo
+ jacocoZipCmd.FlagWithArg("-e ", fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/jacoco-report-classes.jar", jacoco.Class, jacoco.ModuleName)).
+ FlagWithInput("-f ", jacoco.ReportClassesFile)
+ } else if info, ok := android.OtherModuleProvider(ctx, m, ApexJacocoInfoProvider); ok {
+ for _, jacoco := range info {
+ jacocoZipCmd.FlagWithArg("-e ", fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/jacoco-report-classes.jar", jacoco.Class, jacoco.ModuleName)).
+ FlagWithInput("-f ", jacoco.ReportClassesFile)
+ }
+ }
+ }
+
+ jacocoZipBuilder.Build("jacoco_report_classes_zip", "Building jacoco report zip")
+}
+
+func deviceTestsJacocoZipSingletonFactory() android.Singleton {
+ return &deviceTestsJacocoZipSingleton{}
+}
+
+type deviceTestsJacocoZipSingleton struct{}
+
+// GenerateBuildActions implements android.Singleton.
+func (d *deviceTestsJacocoZipSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var deviceTestModules []android.ModuleOrProxy
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
+ if tsm, ok := android.OtherModuleProvider(ctx, m, android.TestSuiteInfoProvider); ok {
+ if slices.Contains(tsm.TestSuites, "device-tests") {
+ deviceTestModules = append(deviceTestModules, m)
+ }
+ }
+ })
+
+ jacocoZip := DeviceTestsJacocoReportZip(ctx)
+ BuildJacocoZip(ctx, deviceTestModules, jacocoZip)
+}
+
+func DeviceTestsJacocoReportZip(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "device_tests_jacoco_report_classes_all.jar")
+}
diff --git a/java/java.go b/java/java.go
index 7032078eb..e6315ec77 100644
--- a/java/java.go
+++ b/java/java.go
@@ -38,6 +38,8 @@ import (
"android/soong/tradefed"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
registerJavaBuildComponents(android.InitRegistrationContext)
@@ -103,8 +105,8 @@ var (
PropertyName: "java_header_libs",
SupportsSdk: true,
},
- func(_ android.SdkMemberContext, j *Library) android.Path {
- headerJars := j.HeaderJars()
+ func(_ android.SdkMemberContext, j android.ModuleProxy, javaInfo *JavaInfo) android.Path {
+ headerJars := javaInfo.HeaderJars
if len(headerJars) != 1 {
panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
}
@@ -116,8 +118,8 @@ var (
}
// Export implementation classes jar as part of the sdk.
- exportImplementationClassesJar = func(_ android.SdkMemberContext, j *Library) android.Path {
- implementationJars := j.ImplementationAndResourcesJars()
+ exportImplementationClassesJar = func(_ android.SdkMemberContext, j android.ModuleProxy, javaInfo *JavaInfo) android.Path {
+ implementationJars := javaInfo.ImplementationAndResourcesJars
if len(implementationJars) != 1 {
panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
}
@@ -160,9 +162,9 @@ var (
PropertyName: "java_boot_libs",
SupportsSdk: true,
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
+ func(ctx android.SdkMemberContext, j android.ModuleProxy, javaInfo *JavaInfo) android.Path {
if snapshotRequiresImplementationJar(ctx) {
- return exportImplementationClassesJar(ctx, j)
+ return exportImplementationClassesJar(ctx, j, javaInfo)
}
// Java boot libs are only provided in the SDK to provide access to their dex implementation
@@ -202,7 +204,7 @@ var (
// This was only added in Tiramisu.
SupportedBuildReleaseSpecification: "Tiramisu+",
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
+ func(ctx android.SdkMemberContext, _ android.ModuleProxy, _ *JavaInfo) android.Path {
// Java systemserver libs are only provided in the SDK to provide access to their dex
// implementation jar for use by dexpreopting. They do not need to provide an actual
// implementation jar but the java_import will need a file that exists so just copy an empty
@@ -234,6 +236,7 @@ var (
}, "jar_name", "partition", "main_class")
)
+// @auto-generate: gob
type ProguardSpecInfo struct {
// If true, proguard flags files will be exported to reverse dependencies across libs edges
// If false, proguard flags files will only be exported to reverse dependencies across
@@ -263,11 +266,6 @@ type UsesLibraryDependencyInfo struct {
ClassLoaderContexts dexpreopt.ClassLoaderContextMap
}
-type SdkLibraryComponentDependencyInfo struct {
- // The name of the implementation library for the optional SDK library or nil, if there isn't one.
- OptionalSdkLibraryImplementation *string
-}
-
type ProvidesUsesLibInfo struct {
ProvidesUsesLib *string
}
@@ -281,6 +279,14 @@ type ModuleWithSdkDepInfo struct {
Stubs bool
}
+type ApexDependencyInfo struct {
+ // These fields can be different from the ones in JavaInfo, for example, for sdk_library
+ // the following fields are set since sdk_library inherits the implementations of
+ // ApexDependency from base, but the same-named fields are not set in JavaInfo.
+ HeaderJars android.Paths
+ ImplementationAndResourcesJars android.Paths
+}
+
// JavaInfo contains information about a java module for use by modules that depend on it.
type JavaInfo struct {
// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
@@ -290,6 +296,11 @@ type JavaInfo struct {
RepackagedHeaderJars android.Paths
+ // list of header jars that have not been jarjared. This should only be used as part of
+ // handling header_jar_override, where we need to use this as the header jars for this implementation of
+ // The only place this is needed is when `header_jar_override` on another module references this module.
+ LocalHeaderJarsPreJarjar android.Paths
+
// set of header jars for all transitive libs deps
TransitiveLibsHeaderJarsForR8 depset.DepSet[android.Path]
@@ -319,6 +330,9 @@ type JavaInfo struct {
// LocalHeaderJars is a list of jars that contain classes from this module, but not from any static dependencies.
LocalHeaderJars android.Paths
+ // KotlinHeaderJars is a jar that only contains Kotlin classes from this module, but not from any static dependencies.
+ KotlinHeaderJars android.Paths
+
// AidlIncludeDirs is a list of directories that should be passed to the aidl tool when
// depending on this module.
AidlIncludeDirs android.Paths
@@ -345,9 +359,9 @@ type JavaInfo struct {
// requiring disbling turbine for any modules that depend on it.
ExportedPluginDisableTurbine bool
- // JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
+ // JacocoInfo contains the path to a jar containing uninstrumented classes that will be
// instrumented by jacoco.
- JacocoReportClassesFile android.Path
+ JacocoInfo JacocoInfo
// StubsLinkType provides information about whether the provided jars are stub jars or
// implementation jars. If the provider is set by java_sdk_library, the link type is "unknown"
@@ -369,8 +383,6 @@ type JavaInfo struct {
UsesLibraryDependencyInfo *UsesLibraryDependencyInfo
- SdkLibraryComponentDependencyInfo *SdkLibraryComponentDependencyInfo
-
ProvidesUsesLibInfo *ProvidesUsesLibInfo
MissingOptionalUsesLibs []string
@@ -392,6 +404,11 @@ type JavaInfo struct {
// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
BootDexJarPath OptionalDexJarPath
+ // The paths to the classes jars that contain classes and class members annotated with
+ // the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
+ // processing.
+ HiddenapiClassesJarPaths android.Paths
+
// The compressed state of the dex file being encoded. This is used to ensure that the encoded
// dex file has the same state.
UncompressDexState *bool
@@ -433,8 +450,15 @@ type JavaInfo struct {
DexpreopterInfo *DexpreopterInfo
- XrefJavaFiles android.Paths
- XrefKotlinFiles android.Paths
+ XrefJavaFiles android.Paths
+ XrefKotlinFiles android.Paths
+ OverrideMinSdkVersion *string
+ CompileDex *bool
+ SystemModules string
+ Installable bool
+ ApexDependencyInfo *ApexDependencyInfo
+
+ MaxSdkVersion android.ApiLevel
}
var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]()
@@ -453,7 +477,8 @@ type DexpreopterInfo struct {
}
type JavaLibraryInfo struct {
- Prebuilt bool
+ Prebuilt bool
+ PermittedPackages []string
}
var JavaLibraryInfoProvider = blueprint.NewProvider[JavaLibraryInfo]()
@@ -558,37 +583,59 @@ func IsJniDepTag(depTag blueprint.DependencyTag) bool {
return depTag == jniLibTag || depTag == jniInstallTag
}
+func IsOptionalUsesLibraryDepTag(depTag blueprint.DependencyTag) bool {
+ if tag, ok := depTag.(usesLibraryDependencyTag); ok {
+ return tag.optional
+ }
+ return depTag == r8LibraryJarTag
+}
+
+// A tag that is used for staging the dependencies of a module, for populating uses libraries
+// dependencies.
+type usesLibStagingTagStruct struct {
+ blueprint.BaseDependencyTag
+}
+
+// Mark this tag so dependencies that use it are excluded from APEX contents.
+func (t usesLibStagingTagStruct) ExcludeFromApexContents() {}
+
+var _ android.ExcludeFromApexContentsTag = (*usesLibStagingTagStruct)(nil)
+
var (
- dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
- dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
- staticLibTag = dependencyTag{name: "staticlib", static: true}
- libTag = dependencyTag{name: "javalib", runtimeLinked: true}
- sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
- java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
- pluginTag = dependencyTag{name: "plugin", toolchain: true}
- errorpronePluginTag = dependencyTag{name: "errorprone-plugin", toolchain: true}
- exportedPluginTag = dependencyTag{name: "exported-plugin", toolchain: true}
- bootClasspathTag = dependencyTag{name: "bootclasspath", runtimeLinked: true}
- systemModulesTag = dependencyTag{name: "system modules", runtimeLinked: true}
- frameworkResTag = dependencyTag{name: "framework-res"}
- lineageResTag = dependencyTag{name: "org.lineageos.platform-res"}
- kotlinPluginTag = dependencyTag{name: "kotlin-plugin", toolchain: true}
- proguardRaiseTag = dependencyTag{name: "proguard-raise"}
- certificateTag = dependencyTag{name: "certificate"}
- instrumentationForTag = dependencyTag{name: "instrumentation_for"}
- extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true}
- jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
- r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
- traceReferencesTag = dependencyTag{name: "trace-references"}
- syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
- javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
- aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
- jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
- usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
- usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
- usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
- usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false)
- usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true)
+ dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
+ dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
+ staticLibTag = dependencyTag{name: "staticlib", static: true}
+ libTag = dependencyTag{name: "javalib", runtimeLinked: true}
+ sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
+ java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
+ pluginTag = dependencyTag{name: "plugin", toolchain: true}
+ errorpronePluginTag = dependencyTag{name: "errorprone-plugin", toolchain: true}
+ exportedPluginTag = dependencyTag{name: "exported-plugin", toolchain: true}
+ bootClasspathTag = dependencyTag{name: "bootclasspath", runtimeLinked: true}
+ systemModulesTag = dependencyTag{name: "system modules", runtimeLinked: true}
+ frameworkResTag = dependencyTag{name: "framework-res"}
+ lineageResTag = dependencyTag{name: "org.lineageos.platform-res"}
+ kotlinPluginTag = dependencyTag{name: "kotlin-plugin", toolchain: true}
+ composeEmbeddablePluginTag = dependencyTag{name: "compose-embeddable-plugin", toolchain: true}
+ composePluginTag = dependencyTag{name: "compose-plugin", toolchain: true}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ certificateTag = dependencyTag{name: "certificate"}
+ headerJarOverrideTag = dependencyTag{name: "header-jar-override"}
+ instrumentationForTag = dependencyTag{name: "instrumentation_for"}
+ extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true}
+ jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
+ r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
+ traceReferencesTag = dependencyTag{name: "trace-references"}
+ syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
+ javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+ aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
+ jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
+ usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
+ usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
+ usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
+ usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false)
+ usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true)
+ usesLibStagingTag = usesLibStagingTagStruct{}
)
// A list of tags for deps used for compiling a module.
@@ -607,6 +654,8 @@ var (
bootClasspathTag,
systemModulesTag,
java9LibTag,
+ composePluginTag,
+ composeEmbeddablePluginTag,
kotlinPluginTag,
syspropPublicStubDepTag,
instrumentationForTag,
@@ -721,9 +770,14 @@ type deps struct {
srcJars android.Paths
systemModules *systemModules
aidlPreprocess android.OptionalPath
+ composeEmbeddablePlugin android.OptionalPath
+ composePlugin android.OptionalPath
kotlinPlugins android.Paths
aconfigProtoFiles android.Paths
+ headerJarOverride android.OptionalPath
+ headerJarOverridePreJarjar android.OptionalPath
+
disableTurbine bool
transitiveStaticLibsHeaderJars []depset.DepSet[android.Path]
@@ -1152,7 +1206,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
})
android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{
- Prebuilt: false,
+ Prebuilt: false,
+ PermittedPackages: j.properties.Permitted_packages,
})
if javaInfo != nil {
@@ -1160,8 +1215,6 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
javaInfo.ExtraOutputFiles = j.extraOutputFiles
javaInfo.DexJarFile = j.dexJarFile
javaInfo.InstallFile = j.installFile
- javaInfo.BootDexJarPath = j.bootDexJarPath
- javaInfo.UncompressDexState = j.uncompressDexState
javaInfo.Active = j.active
javaInfo.BuiltInstalled = j.builtInstalled
javaInfo.ConfigPath = j.configPath
@@ -1186,7 +1239,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if j.dexer.proguardDictionary.Valid() {
android.SetProvider(ctx, ProguardProvider, ProguardInfo{
- ModuleName: ctx.ModuleName(),
+ ModuleName: android.ModuleNameWithPossibleOverride(ctx),
Class: "JAVA_LIBRARIES",
ProguardDictionary: j.dexer.proguardDictionary.Path(),
ProguardUsageZip: j.dexer.proguardUsageZip.Path(),
@@ -1232,7 +1285,7 @@ func buildComplianceMetadata(ctx android.ModuleContext) {
// Static deps
staticDepNames := make([]string, 0)
staticDepFiles := android.Paths{}
- ctx.VisitDirectDepsWithTag(staticLibTag, func(module android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(staticLibTag, func(module android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
staticDepNames = append(staticDepNames, module.Name())
staticDepFiles = append(staticDepFiles, dep.ImplementationJars...)
@@ -1286,6 +1339,9 @@ func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
j.usesLibrary.deps(ctx, false)
j.deps(ctx)
+ if j.properties.Header_jar_override != "" {
+ ctx.AddVariationDependencies(nil, headerJarOverrideTag, j.properties.Header_jar_override)
+ }
if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
if dexpreopt.IsDex2oatNeeded(ctx) {
dexpreopt.RegisterToolDeps(ctx)
@@ -1340,7 +1396,7 @@ type librarySdkMemberType struct {
// Function to retrieve the appropriate output jar (implementation or header) from
// the library.
- jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path
+ jarToExportGetter func(ctx android.SdkMemberContext, j android.ModuleProxy, javaInfo *JavaInfo) android.Path
// Function to compute the snapshot relative path to which the named library's
// jar should be copied.
@@ -1360,9 +1416,9 @@ func (mt *librarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*Library)
- return ok
+func (mt *librarySdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ info, ok := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider)
+ return ok && !info.Prebuilt
}
func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
@@ -1389,26 +1445,30 @@ type librarySdkMemberProperties struct {
DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"`
}
-func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- j := variant.(*Library)
+func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ //j := variant.(*Library)
+ mctx := ctx.SdkModuleContext()
+ commonInfo := android.OtherModulePointerProviderOrDefault(mctx, variant, android.CommonModuleInfoProvider)
+ javaInfo := android.OtherModulePointerProviderOrDefault(mctx, variant, JavaInfoProvider)
+ libraryInfo := android.OtherModuleProviderOrDefault(mctx, variant, JavaLibraryInfoProvider)
- p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j)
+ p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, variant, javaInfo)
- p.AidlIncludeDirs = j.AidlIncludeDirs()
+ p.AidlIncludeDirs = javaInfo.AidlIncludeDirs
- p.PermittedPackages = j.PermittedPackagesForUpdatableBootJars()
+ p.PermittedPackages = libraryInfo.PermittedPackages
// If the min_sdk_version was set then add the canonical representation of the API level to the
// snapshot.
- if j.overridableProperties.Min_sdk_version != nil {
- canonical, err := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
+ if javaInfo.OverrideMinSdkVersion != nil {
+ canonical, err := android.ReplaceFinalizedCodenames(mctx.Config(), commonInfo.MinSdkVersion.ApiLevel.String())
if err != nil {
ctx.ModuleErrorf("%s", err)
}
p.MinSdkVersion = proptools.StringPtr(canonical)
}
- if j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+ if javaInfo.ProfileGuided {
p.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
}
@@ -1660,6 +1720,12 @@ type JavaTestImport struct {
dexJarFile android.Path
}
+type JavaTestInfo struct {
+ TestConfig android.Path
+}
+
+var JavaTestInfoProvider = blueprint.NewProvider[JavaTestInfo]()
+
func (j *Test) InstallInTestcases() bool {
// Host java tests install into $(HOST_OUT_JAVA_LIBRARIES), and then are copied into
// testcases by base_rules.mk.
@@ -1815,6 +1881,7 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+ j.Test.javaTestSetTestsuiteInfo(ctx)
android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
TestcaseRelDataFiles: testcaseRel(j.data),
OutputFile: j.outputFile,
@@ -1837,6 +1904,7 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
checkMinSdkVersionMts(ctx, j.MinSdkVersion(ctx))
j.generateAndroidBuildActionsWithConfig(ctx, nil)
+ j.javaTestSetTestsuiteInfo(ctx)
}
func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
@@ -1942,29 +2010,29 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext,
}
}
moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, j.testProperties.Test_mainline_modules...)
+}
+func (j *Test) javaTestSetTestsuiteInfo(ctx android.ModuleContext) {
// Install test deps
- if !ctx.Config().KatiEnabled() {
- pathInTestCases := android.PathForModuleInstall(ctx, "testcases", ctx.ModuleName())
- if j.testConfig != nil {
- ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".config", j.testConfig)
- }
- dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
- if dynamicConfig.Valid() {
- ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
- }
- testDeps := append(j.data, j.extraTestConfigs...)
- for _, data := range android.SortedUniquePaths(testDeps) {
- dataPath := android.DataPath{SrcPath: data}
- ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath})
- }
- if j.outputFile != nil {
- ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".jar", j.outputFile)
- }
+ var testData []android.DataPath
+ for _, data := range j.data {
+ dataPath := android.DataPath{SrcPath: data}
+ testData = append(testData, dataPath)
}
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: j.testProperties.Test_suites,
+ MainFile: j.outputFile,
+ MainFileStem: j.Stem(),
+ MainFileExt: ".jar",
+ ConfigFile: j.testConfig,
+ ExtraConfigs: j.extraTestConfigs,
+ NeedsArchFolder: ctx.Device(),
+ NonArchData: testData,
+ PerTestcaseDirectory: proptools.Bool(j.testProperties.Per_testcase_directory),
+ })
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: j.testProperties.Test_suites,
+ android.SetProvider(ctx, JavaTestInfoProvider, JavaTestInfo{
+ TestConfig: j.testConfig,
})
}
@@ -1979,12 +2047,20 @@ func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContex
moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
}
optionalConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml")
+ var config android.Path
if optionalConfig.Valid() {
+ config = optionalConfig.Path()
moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String())
}
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: j.testHelperLibraryProperties.Test_suites,
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: j.testHelperLibraryProperties.Test_suites,
+ MainFile: j.outputFile,
+ MainFileStem: j.Stem(),
+ MainFileExt: ".jar",
+ ConfigFile: config,
+ NeedsArchFolder: ctx.Device(),
+ PerTestcaseDirectory: proptools.Bool(j.testHelperLibraryProperties.Per_testcase_directory),
})
}
@@ -2008,8 +2084,8 @@ func (mt *testSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, d
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*Test)
+func (mt *testSdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ _, ok := android.OtherModuleProvider(ctx, module, JavaTestInfoProvider)
return ok
}
@@ -2028,16 +2104,14 @@ type testSdkMemberProperties struct {
TestConfig android.Path
}
-func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- test := variant.(*Test)
-
- implementationJars := test.ImplementationJars()
+func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ implementationJars := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, JavaInfoProvider).ImplementationJars
if len(implementationJars) != 1 {
- panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name()))
+ panic(fmt.Errorf("there must be only one implementation jar from %q", variant.Name()))
}
p.JarToExport = implementationJars[0]
- p.TestConfig = test.testConfig
+ p.TestConfig = android.OtherModuleProviderOrDefault(ctx.SdkModuleContext(), variant, JavaTestInfoProvider).TestConfig
}
func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -2358,6 +2432,10 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon
})
}
+func (ap *JavaApiContribution) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ap.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
+}
+
type ApiLibrary struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -2546,7 +2624,6 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
!ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
- !ctx.Config().PartialCompileFlags().Disable_stub_validation &&
proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
@@ -2584,6 +2661,8 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName)
}
+
+ al.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
// Map where key is the api scope name and value is the int value
@@ -2722,7 +2801,15 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
}
- al.addValidation(ctx, cmd, al.validationPaths)
+ // While we could use SOONG_USE_PARTIAL_COMPILE in the validation's rule, that would unduly
+ // complicate the code for minimal benefit. Instead, add a phony
+ // target to let the developer manually run the validation if they so
+ // desire.
+ ctx.Phony("stub-validation", al.validationPaths...)
+ ctx.Phony(ctx.ModuleName()+"-stub-validation", al.validationPaths...)
+ if !ctx.Config().PartialCompileFlags().Disable_stub_validation {
+ al.addValidation(ctx, cmd, al.validationPaths)
+ }
generateRevertAnnotationArgs(ctx, cmd, al.stubsType, al.aconfigProtoFiles)
@@ -2789,6 +2876,13 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
setExtraJavaInfo(ctx, al, javaInfo)
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if al.stubsJar != nil {
+ moduleInfoJSON.ClassesJar = []string{al.stubsJar.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -3006,10 +3100,6 @@ func (j *Import) CreatedByJavaSdkLibraryName() *string {
return j.properties.Created_by_java_sdk_library_name
}
-func (a *Import) JacocoReportClassesFile() android.Path {
- return nil
-}
-
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...)
@@ -3017,6 +3107,8 @@ func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
sdkDeps(ctx, android.SdkContext(j), j.dexer)
}
+
+ j.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
func (j *Import) commonBuildActions(ctx android.ModuleContext) {
@@ -3268,13 +3360,21 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{
- Prebuilt: true,
+ Prebuilt: true,
+ PermittedPackages: j.properties.Permitted_packages,
})
ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, "")
ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, ".jar")
buildComplianceMetadata(ctx)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if j.combinedImplementationFile != nil {
+ moduleInfoJSON.ClassesJar = []string{j.combinedImplementationFile.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
@@ -3476,10 +3576,6 @@ func (j *DexImport) Stem() string {
return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
}
-func (a *DexImport) JacocoReportClassesFile() android.Path {
- return nil
-}
-
func (j *DexImport) IsInstallable() bool {
return true
}
@@ -3498,7 +3594,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &j.dexpreopter)
- inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
+ inputJar := android.PathForModuleSrc(ctx, j.properties.Jars[0])
dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
if j.dexpreopter.uncompressedDex {
@@ -3544,6 +3640,8 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
javaInfo := &JavaInfo{}
setExtraJavaInfo(ctx, j, javaInfo)
+ javaInfo.BootDexJarPath = j.dexJarFile
+
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
android.SetProvider(ctx, JavaDexImportInfoProvider, JavaDexImportInfo{})
@@ -3695,7 +3793,7 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.ModuleProxy,
if lib, ok := android.OtherModuleProvider(ctx, depModule, SdkLibraryInfoProvider); ok && lib.SharedLibrary {
// A shared SDK library. This should be added as a top-level CLC element.
sdkLib = &depName
- } else if lib := dep.SdkLibraryComponentDependencyInfo; lib != nil && lib.OptionalSdkLibraryImplementation != nil {
+ } else if lib, ok := android.OtherModuleProvider(ctx, depModule, SdkLibraryComponentDependencyInfoProvider); ok && lib.OptionalSdkLibraryImplementation != nil {
if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation)+".impl" {
sdkLib = lib.OptionalSdkLibraryImplementation
}
@@ -3823,12 +3921,6 @@ func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo
}
}
- if slcDep, ok := module.(SdkLibraryComponentDependency); ok {
- javaInfo.SdkLibraryComponentDependencyInfo = &SdkLibraryComponentDependencyInfo{
- OptionalSdkLibraryImplementation: slcDep.OptionalSdkLibraryImplementation(),
- }
- }
-
if pul, ok := module.(ProvidesUsesLib); ok {
javaInfo.ProvidesUsesLibInfo = &ProvidesUsesLibInfo{
ProvidesUsesLib: pul.ProvidesUsesLib(),
@@ -3857,6 +3949,18 @@ func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo
javaInfo.DexJarBuildPath = mm.DexJarBuildPath(ctx)
}
+ if ham, ok := module.(hiddenAPIModule); ok {
+ javaInfo.BootDexJarPath = ham.bootDexJar()
+ javaInfo.HiddenapiClassesJarPaths = ham.classesJars()
+ javaInfo.UncompressDexState = ham.uncompressDex()
+ }
+
+ if mm, ok := module.(interface {
+ MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
+ }); ok {
+ javaInfo.MaxSdkVersion = mm.MaxSdkVersion(ctx)
+ }
+
if di, ok := module.(DexpreopterInterface); ok {
javaInfo.DexpreopterInfo = &DexpreopterInfo{
OutputProfilePathOnHost: di.OutputProfilePathOnHost(),
@@ -3869,4 +3973,16 @@ func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo
javaInfo.XrefJavaFiles = xr.XrefJavaFiles()
javaInfo.XrefKotlinFiles = xr.XrefKotlinFiles()
}
+
+ if sdk, ok := module.(android.SdkContext); ok {
+ javaInfo.SystemModules = sdk.SystemModules()
+ javaInfo.SdkVersion = sdk.SdkVersion(ctx)
+ }
+
+ if ap, ok := module.(ApexDependency); ok {
+ javaInfo.ApexDependencyInfo = &ApexDependencyInfo{
+ HeaderJars: ap.HeaderJars(),
+ ImplementationAndResourcesJars: ap.ImplementationAndResourcesJars(),
+ }
+ }
}
diff --git a/java/java_gob_enc.go b/java/java_gob_enc.go
new file mode 100644
index 000000000..69d21c8ab
--- /dev/null
+++ b/java/java_gob_enc.go
@@ -0,0 +1,54 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package java
+
+import (
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ ProguardSpecInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(ProguardSpecInfo) })
+}
+
+func (r ProguardSpecInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, r.Export_proguard_flags_files); err != nil {
+ return err
+ }
+
+ if err = r.ProguardFlagsFiles.EncodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.UnconditionallyExportedProguardFlags.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *ProguardSpecInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Export_proguard_flags_files)
+ if err != nil {
+ return err
+ }
+
+ if err = r.ProguardFlagsFiles.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.UnconditionallyExportedProguardFlags.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var ProguardSpecInfoGobRegId int16
+
+func (r ProguardSpecInfo) GetTypeId() int16 {
+ return ProguardSpecInfoGobRegId
+}
diff --git a/java/java_test.go b/java/java_test.go
index 1ba78d49b..6e80dcd34 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2740,16 +2740,6 @@ func TestMultiplePrebuilts(t *testing.T) {
contents: ["%v"],
}
`
- hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
hasFileWithStem := func(m android.TestingModule, stem string) bool {
t.Helper()
@@ -2793,7 +2783,8 @@ func TestMultiplePrebuilts(t *testing.T) {
// check that rdep gets the correct variation of dep
foo := ctx.ModuleForTests(t, "foo", "android_common")
expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_common")
- android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName),
+ true, android.HasDirectDep(ctx, foo.Module(), expectedDependency.Module()))
// check that output file of dep is always bar.jar
// The filename should be agnostic to source/prebuilt/prebuilt_version
@@ -2920,6 +2911,59 @@ func TestApiLibraryAconfigDeclarations(t *testing.T) {
android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml")
}
+func TestDroidstubsAconfigPropagation(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+
+ java_library {
+ name: "baz",
+ srcs: [
+ ":foo",
+ ],
+ }
+ `)
+
+ bazModule := result.ModuleForTests(t, "baz", "android_common").Module()
+ javaInfo, _ := android.OtherModuleProvider(result, bazModule, JavaInfoProvider)
+ aconfigProtos := javaInfo.AconfigIntermediateCacheOutputPaths
+
+ android.AssertIntEquals(t, "Expected to provide one aconfig proto file", 1, len(aconfigProtos))
+ android.AssertStringDoesContain(
+ t,
+ "Expected to provide bar/aconfig-cache.pb",
+ strings.Join(aconfigProtos.Strings(), " "),
+ "bar/aconfig-cache.pb",
+ )
+}
+
func TestTestOnly(t *testing.T) {
t.Parallel()
ctx := android.GroupFixturePreparers(
@@ -3150,7 +3194,7 @@ func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTe
}
}
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m android.Module) {
addActuals(m, android.TestOnlyProviderKey)
})
@@ -3171,7 +3215,7 @@ func TestNativeRequiredDepOfJavaBinary(t *testing.T) {
t.Parallel()
findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module {
var ret []blueprint.Module
- ctx.VisitDirectDeps(module, func(dep blueprint.Module) {
+ ctx.VisitDirectDeps(module, func(dep android.Module) {
if dep.Name() == depName {
ret = append(ret, dep)
}
diff --git a/java/jdeps.go b/java/jdeps.go
index 56142c89b..c624e13bd 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -100,7 +100,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont
Rule: android.Touch,
Output: jfpath,
})
- ctx.DistForGoals([]string{"general-tests", "dist_files"}, j.outputPath)
+ ctx.DistForGoals([]string{"general-tests", "dist_files", "module-info"}, j.outputPath)
}
func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error {
diff --git a/java/kotlin.go b/java/kotlin.go
index 308bb0305..68890bdda 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -26,25 +26,99 @@ import (
"github.com/google/blueprint"
)
-var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports{Goma: true},
+type KotlinCompileData struct {
+ pcStateFileNew android.OutputPath
+ pcStateFilePrior android.OutputPath
+ diffFile android.OutputPath
+}
+
+const inputDeltaCmd = `${config.FindInputDeltaCmd} --target "$out" ` +
+ `--inputs_file "$out.rsp" --new_state "$newStateFile" --prior_state "$priorStateFile" > $sourceDeltaFile`
+
+const nonIncKotlinCmd = `rm -rf "$classesDir" "$headerClassesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
+ `mkdir -p "$classesDir" "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
+ `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
+ `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
+ ` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
+ ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
+ `${config.KotlincCmd} ${config.KotlincGlobalFlags} ` +
+ ` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
+ ` $kotlincFlags -jvm-target $kotlinJvmTarget $composePluginFlag $kotlincPluginFlags -Xbuild-file=$kotlinBuildFile ` +
+ ` -kotlin-home $emptyDir ` +
+ ` -Xplugin=${config.KotlinAbiGenPluginJar} ` +
+ ` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` +
+ `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` +
+ `${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` +
+ `rm -rf "$srcJarDir" "$classesDir" "$headerClassesDir" `
+
+const moveDeltaStateFile = `mv $newStateFile $priorStateFile && rm $sourceDeltaFile`
+
+var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports{},
blueprint.RuleParams{
- Command: `rm -rf "$classesDir" "$headerClassesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
- `mkdir -p "$classesDir" "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
+ Command: inputDeltaCmd + ` && ` + nonIncKotlinCmd + ` && ` + moveDeltaStateFile,
+ CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
+ "${config.KotlincCmd}",
+ "${config.KotlinCompilerJar}",
+ "${config.KotlinPreloaderJar}",
+ "${config.KotlinReflectJar}",
+ "${config.KotlinScriptRuntimeJar}",
+ "${config.KotlinStdlibJar}",
+ "${config.KotlinTrove4jJar}",
+ "${config.KotlinAnnotationJar}",
+ "${config.KotlinAbiGenPluginJar}",
+ "${config.GenKotlinBuildFileCmd}",
+ "${config.SoongZipCmd}",
+ "${config.ZipSyncCmd}",
+ },
+ Rspfile: "$out.rsp",
+ RspfileContent: `$in`,
+ Restat: true,
+ },
+ "kotlincFlags", "composePluginFlag", "kotlincPluginFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir",
+ "classesDir", "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir",
+ "newStateFile", "priorStateFile", "sourceDeltaFile", "name")
+
+// TODO: does incremental work with RBE?
+var kotlinIncremental = pctx.AndroidRemoteStaticRule("kotlin-incremental", android.RemoteRuleSupports{},
+ blueprint.RuleParams{
+ Command: // Incremental
+
+ inputDeltaCmd + ` && ` +
+
+ `if [ "$$SOONG_USE_PARTIAL_COMPILE" = "true" ]; then ` +
+ `rm -rf "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
+ `mkdir -p "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
- `${config.KotlincCmd} ${config.KotlincGlobalFlags} ` +
+ `${config.KotlinIncrementalClientBinary} ${config.KotlincGlobalFlags} ` +
` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
- ` $kotlincFlags -jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile ` +
- ` -kotlin-home $emptyDir ` +
+ ` $kotlincFlags $composeEmbeddablePluginFlag $kotlincPluginFlags ` +
+ ` -jvm-target $kotlinJvmTarget -build-file=$kotlinBuildFile ` +
+ ` -source-delta-file=$sourceDeltaFile` +
+ ` -kotlin-home=$emptyDir ` +
+ ` -root-dir=$incrementalRootDir` +
+ ` -output-dir=$outputDir` +
+ ` -build-dir=$buildDir ` +
+ ` -working-dir=$workDir ` +
` -Xplugin=${config.KotlinAbiGenPluginJar} ` +
` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` +
`${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` +
- `rm -rf "$srcJarDir" "$classesDir" "$headerClassesDir"`,
+ `rm -rf "$srcJarDir" ; ` +
+
+ // Else non incremental
+ `else ` +
+ nonIncKotlinCmd + ` ; ` +
+ `fi && ` +
+ moveDeltaStateFile,
+
CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
"${config.KotlincCmd}",
+ "${config.KotlinIncrementalClientBinary}",
"${config.KotlinCompilerJar}",
"${config.KotlinPreloaderJar}",
"${config.KotlinReflectJar}",
@@ -61,8 +135,9 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports
RspfileContent: `$in`,
Restat: true,
},
- "kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir",
- "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
+ "kotlincFlags", "composeEmbeddablePluginFlag", "composePluginFlag", "kotlincPluginFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "incrementalRootDir",
+ "classesDir", "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir",
+ "name", "outputDir", "buildDir", "workDir", "newStateFile", "priorStateFile", "sourceDeltaFile")
var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
blueprint.RuleParams{
@@ -74,7 +149,7 @@ var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
// Skip header jars, those should not have an effect on kythe results.
` --args '${config.KotlincGlobalFlags} ` +
` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
- ` $kotlincFlags -jvm-target $kotlinJvmTarget ` +
+ ` $kotlincFlags $kotlincPluginFlags -jvm-target $kotlinJvmTarget ` +
`${config.KotlincKytheGlobalFlags}'`,
CommandDeps: []string{
"${config.KotlinKytheExtractor}",
@@ -83,7 +158,14 @@ var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
Rspfile: "$out.rsp",
RspfileContent: "$in",
},
- "classpath", "kotlincFlags", "commonSrcFilesList", "kotlinJvmTarget", "outJar", "srcJars", "srcJarDir",
+ "classpath", "kotlincFlags", "kotlincPluginFlags", "commonSrcFilesList", "kotlinJvmTarget", "outJar", "srcJars", "srcJarDir",
+)
+
+var kotlinIncrementalClean = pctx.AndroidStaticRule("kotlin-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "$cpSnapshot" "$outDir" "$buildDir" "$workDir"`,
+ },
+ "cpSnapshot", "outDir", "buildDir", "workDir",
)
func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath {
@@ -104,10 +186,10 @@ func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Path
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
- srcFiles, commonSrcFiles, srcJars android.Paths,
- flags javaBuilderFlags) {
+ srcFiles, commonSrcFiles, srcJars android.Paths, flags javaBuilderFlags, compileData KotlinCompileData, incremental bool) {
var deps android.Paths
+ var orderOnlyDeps android.Paths
deps = append(deps, flags.kotlincClasspath...)
deps = append(deps, flags.kotlincDeps...)
deps = append(deps, srcJars...)
@@ -123,43 +205,97 @@ func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutp
commonSrcFilesArg = "--common_srcs " + commonSrcsList.String()
}
+ associateJars := getAssociateJars(ctx, j.properties.Associates)
+ if len(associateJars) > 0 {
+ flags.kotlincFlags += " -Xfriend-paths=" + strings.Join(associateJars.Strings(), ",")
+ deps = append(deps, associateJars...)
+
+ // Prepend the associates classes jar in the classpath, so that they take priority over the other jars.
+ var newClasspath classpath
+ newClasspath = append(newClasspath, associateJars...)
+ newClasspath = append(newClasspath, flags.kotlincClasspath...)
+ flags.kotlincClasspath = newClasspath
+ }
+
classpathRspFile := android.PathForModuleOut(ctx, "kotlinc", "classpath.rsp")
android.WriteFileRule(ctx, classpathRspFile, strings.Join(flags.kotlincClasspath.Strings(), " "))
deps = append(deps, classpathRspFile)
+ rule := kotlinc
+ description := "kotlinc"
+ incrementalRootDir := android.PathForModuleOut(ctx, "kotlinc")
+ outputDir := "classes"
+ buildDir := "build"
+ workDir := "work"
+ args := map[string]string{
+ "classpath": classpathRspFile.String(),
+ "kotlincFlags": flags.kotlincFlags,
+ "kotlincPluginFlags": flags.kotlincPluginFlags,
+ "commonSrcFilesArg": commonSrcFilesArg,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "classesDir": android.PathForModuleOut(ctx, "kotlinc", outputDir).String(),
+ "headerClassesDir": android.PathForModuleOut(ctx, "kotlinc", "header_classes").String(),
+ "headerJar": headerOutputFile.String(),
+ "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
+ "kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
+ "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
+ "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
+ "name": kotlinName,
+ "newStateFile": compileData.pcStateFileNew.String(),
+ "priorStateFile": compileData.pcStateFilePrior.String(),
+ "sourceDeltaFile": compileData.diffFile.String(),
+ "composePluginFlag": flags.composePluginFlag,
+ }
+ if incremental {
+ rule = kotlinIncremental
+ description = "kotlin-incremental"
+ args["outputDir"] = outputDir
+ args["buildDir"] = buildDir
+ args["workDir"] = workDir
+ args["incrementalRootDir"] = incrementalRootDir.String()
+ args["sourceDeltaFile"] = compileData.diffFile.String()
+ args["composeEmbeddablePluginFlag"] = flags.composeEmbeddablePluginFlag
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: kotlinc,
- Description: "kotlinc",
- Output: outputFile,
- ImplicitOutput: headerOutputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: rule,
+ Description: description,
+ Inputs: srcFiles,
+ Implicits: deps,
+ OrderOnly: orderOnlyDeps,
+ Output: outputFile,
+ ImplicitOutputs: []android.WritablePath{headerOutputFile, compileData.pcStateFilePrior},
+ Args: args,
+ })
+
+ cleanPhonyPath := android.PathForModuleOut(ctx, "partialcompileclean", kotlinName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: kotlinIncrementalClean,
+ Description: "kotlin-partialcompileclean",
+ Output: cleanPhonyPath,
+ Inputs: android.Paths{},
Args: map[string]string{
- "classpath": classpathRspFile.String(),
- "kotlincFlags": flags.kotlincFlags,
- "commonSrcFilesArg": commonSrcFilesArg,
- "srcJars": strings.Join(srcJars.Strings(), " "),
- "classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
- "headerClassesDir": android.PathForModuleOut(ctx, "kotlinc", "header_classes").String(),
- "headerJar": headerOutputFile.String(),
- "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
- "kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
- "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
- "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
- "name": kotlinName,
+ // TODO: add this cp snapshot as a param to the incremental compiler.
+ "cpSnapshot": incrementalRootDir.Join(ctx, "shrunk-classpath-snapshot.bin").String(),
+ "outDir": incrementalRootDir.Join(ctx, outputDir).String(),
+ "buildDir": incrementalRootDir.Join(ctx, buildDir).String(),
+ "workDir": incrementalRootDir.Join(ctx, workDir).String(),
},
+ PhonyOutput: true,
})
+ ctx.Phony("partialcompileclean", cleanPhonyPath)
// Emit kythe xref rule
if (ctx.Config().EmitXrefRules()) && ctx.Module() == ctx.PrimaryModule() {
extractionFile := outputFile.ReplaceExtension(ctx, "kzip")
args := map[string]string{
- "classpath": classpathRspFile.String(),
- "kotlincFlags": flags.kotlincFlags,
- "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
- "outJar": outputFile.String(),
- "srcJars": strings.Join(srcJars.Strings(), " "),
- "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars.xref").String(),
+ "classpath": classpathRspFile.String(),
+ "kotlincFlags": flags.kotlincFlags,
+ "kotlincPluginFlags": flags.kotlincPluginFlags,
+ "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
+ "outJar": outputFile.String(),
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars.xref").String(),
}
if commonSrcsList.Valid() {
args["commonSrcFilesList"] = "--common_srcs @" + commonSrcsList.String()
@@ -176,7 +312,49 @@ func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutp
}
}
-var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{Goma: true},
+func getAssociateJars(ctx android.ModuleContext, associates []string) android.Paths {
+ if len(associates) == 0 {
+ return nil
+ }
+
+ associatesFound := make(map[string]bool)
+ for _, name := range associates {
+ associatesFound[name] = false
+ }
+
+ var associateJars android.Paths
+ ctx.VisitDirectDepsProxy(func(depModule android.ModuleProxy) {
+ depName := ctx.OtherModuleName(depModule)
+ _, isAssociate := associatesFound[depName]
+ if !isAssociate {
+ return
+ }
+
+ associatesFound[depName] = true
+ depInfo, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider)
+ if !ok {
+ ctx.PropertyErrorf("Associates", "associate module '%s' is not a Java module", depName)
+ return
+ }
+
+ if len(depInfo.KotlinHeaderJars) == 0 {
+ ctx.PropertyErrorf("Associates", "associate module '%s' is not a Kotlin module", depName)
+ return
+ }
+
+ associateJars = append(associateJars, depInfo.KotlinHeaderJars...)
+ })
+
+ for name, found := range associatesFound {
+ if !found {
+ ctx.PropertyErrorf("Associates", "associate module '%s' must also be listed as a direct dependency (e.g. in static_libs or libs)", name)
+ }
+ }
+
+ return associateJars
+}
+
+var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{},
blueprint.RuleParams{
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
@@ -187,7 +365,8 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
`${config.KotlincCmd} ${config.KotlincGlobalFlags} ` +
`${config.KaptSuppressJDK9Warnings} ${config.KotlincSuppressJDK9Warnings} ` +
- `${config.JavacHeapFlags} $kotlincFlags -Xplugin=${config.KotlinKaptJar} ` +
+ `${config.JavacHeapFlags} $kotlincFlags ` +
+ `-Xplugin=${config.KotlinKaptJar} ` +
`-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` +
`-P plugin:org.jetbrains.kotlin.kapt3:classes=$kaptDir/classes ` +
`-P plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptDir/stubs ` +
@@ -198,7 +377,6 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
- `if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.FindInputDeltaCmd}",
@@ -214,7 +392,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
Restat: true,
},
"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
- "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
+ "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir",
"kotlinBuildFile", "name", "classesJarOut")
// kotlinKapt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 4b56cff1c..b2556b7af 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -199,6 +199,34 @@ func TestKotlin(t *testing.T) {
}
}
+func TestSortKotlincFlags(t *testing.T) {
+ t.Parallel()
+
+ t.Run("Successful sorting of kotlincFlags", func(t *testing.T) {
+ t.Parallel()
+ bp := `
+ java_library {
+ name: "Foo",
+ srcs: ["Foo.kt"],
+ kotlincflags: ["-Ja", "-Xb", "-JCz", "-JCy", "-JCx", "-Xd"]
+ }
+ `
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ module := result.ModuleForTests(t, "Foo", "android_common")
+ kotlincRule := module.Rule("kotlinc")
+ expectedFlags := "-Ja -JCz -JCy -JCx -Xb -Xd"
+
+ kotlincFlags := kotlincRule.Args["kotlincFlags"]
+ if !strings.Contains(kotlincFlags, expectedFlags) {
+ t.Errorf("kotlincFlags expected to have -J flags sorted first:\n Flags: %s\n Expected: %s", kotlincFlags, expectedFlags)
+ }
+ })
+
+}
+
func TestKapt(t *testing.T) {
t.Parallel()
bp := `
@@ -462,7 +490,7 @@ func TestKotlinCompose(t *testing.T) {
withCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
android.AssertStringDoesContain(t, "missing compose compiler plugin",
- withCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
+ withCompose.VariablesForTestsRelativeToTop()["composePluginFlag"], "-Xplugin="+composeCompiler.String())
android.AssertStringListContains(t, "missing kapt compose compiler dependency",
withCompose.Rule("kapt").Implicits.Strings(), composeCompiler.String())
@@ -471,7 +499,7 @@ func TestKotlinCompose(t *testing.T) {
noCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
android.AssertStringDoesNotContain(t, "unexpected compose compiler plugin",
- noCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
+ noCompose.VariablesForTestsRelativeToTop()["composePluginFlag"], "-Xplugin="+composeCompiler.String())
}
func TestKotlinPlugin(t *testing.T) {
@@ -510,7 +538,7 @@ func TestKotlinPlugin(t *testing.T) {
withKotlinPlugin.Rule("kotlinc").Implicits.Strings(), kotlinPlugin.String())
android.AssertStringDoesContain(t, "missing kotlin plugin",
- withKotlinPlugin.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+kotlinPlugin.String())
+ withKotlinPlugin.VariablesForTestsRelativeToTop()["kotlincPluginFlags"], "-Xplugin="+kotlinPlugin.String())
android.AssertStringListContains(t, "missing kapt kotlin plugin dependency",
withKotlinPlugin.Rule("kapt").Implicits.Strings(), kotlinPlugin.String())
@@ -521,3 +549,95 @@ func TestKotlinPlugin(t *testing.T) {
android.AssertStringDoesNotContain(t, "unexpected kotlin plugin",
noKotlinPlugin.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+kotlinPlugin.String())
}
+
+func TestKotlinAssociates(t *testing.T) {
+ t.Parallel()
+
+ targets := []string{"FooUtils", "FooTest"}
+ for _, target := range targets {
+ t.Run("Successful associate linking of "+target, func(t *testing.T) {
+ t.Parallel()
+ bp := `
+ java_library {
+ name: "Foo",
+ srcs: ["Foo.kt"],
+ }
+
+ java_library {
+ name: "FooUtils",
+ srcs: ["FooUtils.kt"],
+ libs: ["Foo"],
+ associates: ["Foo"],
+ }
+
+ java_test {
+ name: "FooTest",
+ srcs: ["FooTest.kt"],
+ static_libs: ["Foo"],
+ associates: ["Foo"],
+ }
+ `
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ module := result.ModuleForTests(t, target, "android_common")
+ kotlincRule := module.Rule("kotlinc")
+ expectedFriendPath := "out/soong/.intermediates/Foo/android_common/kotlin_headers/Foo.jar"
+ expectedFlag := "-Xfriend-paths=" + expectedFriendPath
+
+ kotlincFlags := kotlincRule.Args["kotlincFlags"]
+ if !strings.Contains(kotlincFlags, expectedFlag) {
+ t.Errorf("kotlincFlags missing expected friend path:\n Flags: %s\n Expected: %s", kotlincFlags, expectedFlag)
+ }
+
+ classpathRspFile := module.Output("kotlinc/classpath.rsp")
+ classpathContent := android.ContentFromFileRuleForTests(t, result.TestContext, classpathRspFile)
+ classpathEntries := strings.Fields(classpathContent)
+ android.AssertStringPathRelativeToTopEquals(t, "first classpath entry", result.Config, expectedFriendPath, classpathEntries[0])
+ })
+ }
+
+ t.Run("Error: Associate not a dependency", func(t *testing.T) {
+ t.Parallel()
+ bp := `
+ java_library {
+ name: "Foo",
+ srcs: ["Foo.kt"],
+ }
+
+ java_library {
+ name: "FooUtils",
+ srcs: ["FooUtils.kt"],
+ associates: ["Foo"],
+ }
+ `
+ android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\QAssociates: associate module 'Foo' must also be listed as a direct dependency\E`,
+ )).RunTestWithBp(t, bp)
+ })
+
+ t.Run("Error: Associate not a Kotlin module", func(t *testing.T) {
+ t.Parallel()
+ bp := `
+ java_library {
+ name: "Foo",
+ srcs: ["Foo.java"],
+ }
+
+ java_library {
+ name: "FooUtils",
+ srcs: ["FooUtils.kt"],
+ libs: ["Foo"],
+ associates: ["Foo"],
+ }
+ `
+ android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\QAssociates: associate module 'Foo' is not a Kotlin module\E`,
+ )).RunTestWithBp(t, bp)
+ })
+}
diff --git a/java/lint.go b/java/lint.go
index dc1e51ffb..7f6c67a5a 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -28,6 +28,8 @@ import (
"android/soong/remoteexec"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
// lint checks automatically enforced for modules that have different min_sdk_version than
// sdk_version
var updatabilityChecks = []string{"NewApi"}
@@ -196,6 +198,7 @@ var allLintDatabasefiles = map[android.SdkKind]lintDatabaseFiles{
var LintProvider = blueprint.NewProvider[*LintInfo]()
+// @auto-generate: gob
type LintInfo struct {
HTML android.Path
Text android.Path
@@ -580,9 +583,31 @@ func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, v
xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
lintZip(ctx, xmlList, xmlZip, validations)
+ android.SetProvider(ctx, ModuleLintReportZipsProvider, ModuleLintReportZipsInfo{
+ HtmlZip: htmlZip,
+ TextZip: textZip,
+ XmlZip: xmlZip,
+ })
+
return android.Paths{htmlZip, textZip, xmlZip}
}
+type ModuleLintReportZipsInfo struct {
+ HtmlZip android.Path
+ TextZip android.Path
+ XmlZip android.Path
+}
+
+func (i *ModuleLintReportZipsInfo) AllReports() android.Paths {
+ return android.Paths{
+ i.HtmlZip,
+ i.TextZip,
+ i.XmlZip,
+ }
+}
+
+var ModuleLintReportZipsProvider = blueprint.NewProvider[ModuleLintReportZipsInfo]()
+
type lintSingleton struct {
htmlZip android.WritablePath
textZip android.WritablePath
@@ -652,19 +677,20 @@ func copiedLintDatabaseFilesPath(ctx android.PathContext, name string) android.W
}
func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
+ // Dists of lint reports in unbundled builds is handled by unbundled_builder in unbundled.go
if ctx.Config().UnbundledBuild() {
return
}
var outputs []*LintInfo
- var dirs []string
ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ platformAvailabilitInfo := android.OtherModuleProviderOrDefault(ctx, m, android.PlatformAvailabilityInfoProvider)
if ctx.Config().KatiEnabled() && !commonInfo.ExportedToMake {
return
}
- if commonInfo.IsApexModule && commonInfo.NotAvailableForPlatform {
+ if commonInfo.IsApexModule && platformAvailabilitInfo.NotAvailableToPlatform {
apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
// There are stray platform variants of modules in apexes that are not available for
@@ -678,8 +704,6 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
}
})
- dirs = android.SortedUniqueStrings(dirs)
-
zip := func(outputPath android.WritablePath, get func(*LintInfo) android.Path) {
var paths android.Paths
@@ -705,10 +729,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
zip(l.referenceBaselineZip, func(l *LintInfo) android.Path { return l.ReferenceBaseline })
ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
-
- if !ctx.Config().UnbundledBuild() {
- ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
- }
+ ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
}
func init() {
diff --git a/java/lint_gob_enc.go b/java/lint_gob_enc.go
new file mode 100644
index 000000000..9779a7639
--- /dev/null
+++ b/java/lint_gob_enc.go
@@ -0,0 +1,110 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package java
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ LintInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(LintInfo) })
+}
+
+func (r LintInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeInterface(buf, r.HTML); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.Text); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.XML); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.ReferenceBaseline); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveHTML.EncodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveText.EncodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveXML.EncodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveBaseline.EncodeInterface(buf); err != nil {
+ return err
+ }
+ return err
+}
+
+func (r *LintInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ if val2, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val2 == nil {
+ r.HTML = nil
+ } else {
+ r.HTML = val2.(android.Path)
+ }
+
+ if val4, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val4 == nil {
+ r.Text = nil
+ } else {
+ r.Text = val4.(android.Path)
+ }
+
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.XML = nil
+ } else {
+ r.XML = val6.(android.Path)
+ }
+
+ if val8, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val8 == nil {
+ r.ReferenceBaseline = nil
+ } else {
+ r.ReferenceBaseline = val8.(android.Path)
+ }
+
+ if err = r.TransitiveHTML.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveText.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveXML.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = r.TransitiveBaseline.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ return err
+}
+
+var LintInfoGobRegId int16
+
+func (r LintInfo) GetTypeId() int16 {
+ return LintInfoGobRegId
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 155afc6c2..130f625e9 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -51,16 +51,16 @@ type platformBootclasspathModule struct {
properties platformBootclasspathProperties
// The apex:module pairs obtained from the configured modules.
- configuredModules []android.Module
+ configuredModules []android.ModuleProxy
// The apex:module pairs obtained from the fragments.
- fragments []android.Module
+ fragments []android.ModuleProxy
// The map of apex to the fragments they contain.
- apexNameToFragment map[string]android.Module
+ apexNameToFragment map[string]android.ModuleProxy
// The map of library modules in the bootclasspath to the fragments that contain them.
- libraryToApex map[android.Module]string
+ libraryToApex map[android.ModuleProxy]string
// Path to the monolithic hiddenapi-flags.csv file.
hiddenAPIFlagsCSV android.OutputPath
@@ -181,8 +181,8 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo
// Do not add implLibModule to allModules as the impl lib is only used to collect the
// transitive source files
- var implLibModule []android.Module
- ctx.VisitDirectDepsWithTag(platformBootclasspathImplLibDepTag, func(m android.Module) {
+ var implLibModule []android.ModuleProxy
+ ctx.VisitDirectDepsProxyWithTag(platformBootclasspathImplLibDepTag, func(m android.ModuleProxy) {
implLibModule = append(implLibModule, m)
})
@@ -251,7 +251,7 @@ func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) andr
// checkPlatformModules ensures that the non-updatable modules supplied are not part of an
// apex module.
-func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.Module) {
+func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.ModuleProxy) {
// TODO(satayev): change this check to only allow core-icu4j, all apex jars should not be here.
for _, m := range modules {
apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
@@ -266,7 +266,7 @@ func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleCon
}
// checkApexModules ensures that the apex modules supplied are not from the platform.
-func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext, modules []android.Module) {
+func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext, modules []android.ModuleProxy) {
for _, m := range modules {
apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
fromUpdatableApex := apexInfo.Updatable
@@ -298,8 +298,10 @@ func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module,
- fragments []android.Module, libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) bootDexJarByModule {
+func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.ModuleProxy,
+ fragments []android.ModuleProxy, libraryToApex map[android.ModuleProxy]string,
+ apexNameToFragment map[string]android.ModuleProxy) bootDexJarByModule {
+
createEmptyHiddenApiFiles := func() {
paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
for _, path := range paths {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index d2ec8bd4f..4d43ba9a6 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -44,8 +44,12 @@ func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext
}
type PlatformCompatConfigInfo struct {
- CompatConfig android.OutputPath
- SubDir string
+ CompatConfig android.OutputPath
+ SubDir string
+ CompatConfigMetadata android.Path
+ // Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
+ IncludeInMergedXml bool
+ Prebuilt bool
}
var PlatformCompatConfigInfoProvider = blueprint.NewProvider[PlatformCompatConfigInfo]()
@@ -99,14 +103,6 @@ type platformCompatConfigMetadataProvider interface {
includeInMergedXml() bool
}
-type PlatformCompatConfigMetadataInfo struct {
- CompatConfigMetadata android.Path
- // Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
- IncludeInMergedXml bool
-}
-
-var PlatformCompatConfigMetadataInfoProvider = blueprint.NewProvider[PlatformCompatConfigMetadataInfo]()
-
type PlatformCompatConfigIntf interface {
android.Module
@@ -141,13 +137,11 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon
ctx.SetOutputFiles(android.Paths{p.configFile}, "")
android.SetProvider(ctx, PlatformCompatConfigInfoProvider, PlatformCompatConfigInfo{
- CompatConfig: p.CompatConfig(),
- SubDir: p.SubDir(),
- })
-
- android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
+ CompatConfig: p.CompatConfig(),
+ SubDir: p.SubDir(),
CompatConfigMetadata: p.compatConfigMetadata(),
IncludeInMergedXml: p.includeInMergedXml(),
+ Prebuilt: false,
})
}
@@ -173,9 +167,9 @@ func (b *compatConfigMemberType) AddDependencies(ctx android.SdkDependencyContex
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (b *compatConfigMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*platformCompatConfig)
- return ok
+func (b *compatConfigMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ info, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigInfoProvider)
+ return ok && !info.Prebuilt
}
func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
@@ -192,9 +186,8 @@ type compatConfigSdkMemberProperties struct {
Metadata android.Path
}
-func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- module := variant.(*platformCompatConfig)
- b.Metadata = module.metadataFile
+func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ b.Metadata = android.OtherModuleProviderOrDefault(ctx.SdkModuleContext(), variant, PlatformCompatConfigInfoProvider).CompatConfigMetadata
}
func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -252,9 +245,10 @@ var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
- android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
+ android.SetProvider(ctx, PlatformCompatConfigInfoProvider, PlatformCompatConfigInfo{
CompatConfigMetadata: module.compatConfigMetadata(),
IncludeInMergedXml: module.includeInMergedXml(),
+ Prebuilt: true,
})
}
@@ -280,7 +274,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet
if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigMetadataInfoProvider); ok {
+ if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigInfoProvider); ok {
if !android.IsModulePreferredProxy(ctx, module) {
return
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 17fdae962..7d927fc0e 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -20,8 +20,6 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
func intPtr(v int) *int {
@@ -40,7 +38,7 @@ func TestPrebuiltApis_SystemModulesCreation(t *testing.T) {
).RunTest(t)
sdkSystemModules := []string{}
- result.VisitAllModules(func(module blueprint.Module) {
+ result.VisitAllModules(func(module android.Module) {
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
if strings.HasPrefix(name, "sdk_") && strings.HasSuffix(name, "_system_modules") {
sdkSystemModules = append(sdkSystemModules, name)
diff --git a/java/ravenwood.go b/java/ravenwood.go
index a942dc653..b096a2592 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -16,6 +16,7 @@ package java
import (
"strconv"
+ "android/soong/aconfig"
"android/soong/android"
"android/soong/tradefed"
@@ -37,14 +38,16 @@ var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
var ravenwoodTestResourceApkTag = dependencyTag{name: "ravenwoodtestresapk"}
var ravenwoodTestInstResourceApkTag = dependencyTag{name: "ravenwoodtest-inst-res-apk"}
+var allAconfigModuleTag = dependencyTag{name: "all_aconfig"}
var genManifestProperties = pctx.AndroidStaticRule("genManifestProperties",
blueprint.RuleParams{
Command: "echo targetSdkVersionInt=$targetSdkVersionInt > $out && " +
"echo targetSdkVersionRaw=$targetSdkVersionRaw >> $out && " +
"echo packageName=$packageName >> $out && " +
- "echo instPackageName=$instPackageName >> $out",
- }, "targetSdkVersionInt", "targetSdkVersionRaw", "packageName", "instPackageName")
+ "echo instPackageName=$instPackageName >> $out && " +
+ "echo instrumentationClass=$instrumentationClass >> $out",
+ }, "targetSdkVersionInt", "targetSdkVersionRaw", "packageName", "instPackageName", "instrumentationClass")
const ravenwoodUtilsName = "ravenwood-utils"
const ravenwoodRuntimeName = "ravenwood-runtime"
@@ -87,8 +90,12 @@ type ravenwoodTestProperties struct {
// Specify the package name of this test module.
// This will be set to the test Context's package name.
- //(i.e. Instrumentation.getContext().getPackageName())
+ // (i.e. Instrumentation.getContext().getPackageName())
Inst_package_name *string
+
+ // Specify the name of the Instrumentation subclass to use.
+ // (e.g. "androidx.test.runner.AndroidJUnitRunner")
+ Instrumentation_class *string
}
type ravenwoodTest struct {
@@ -97,7 +104,9 @@ type ravenwoodTest struct {
ravenwoodTestProperties ravenwoodTestProperties
testProperties testProperties
- testConfig android.Path
+
+ testConfig android.Path
+ data android.Paths
forceOSType android.OsType
forceArchType android.ArchType
@@ -168,13 +177,31 @@ func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
r.forceArchType = ctx.Config().BuildArch
r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- TestConfigProp: r.testProperties.Test_config,
- TestConfigTemplateProp: r.testProperties.Test_config_template,
- TestSuites: r.testProperties.Test_suites,
- AutoGenConfig: r.testProperties.Auto_gen_config,
- DeviceTemplate: "${RavenwoodTestConfigTemplate}",
- HostTemplate: "${RavenwoodTestConfigTemplate}",
+ TestConfigProp: r.testProperties.Test_config,
+ TestConfigTemplateProp: r.testProperties.Test_config_template,
+ OptionsForAutogenerated: r.testProperties.Test_options.Tradefed_options,
+ TestRunnerOptions: r.testProperties.Test_options.Test_runner_options,
+ TestSuites: r.testProperties.Test_suites,
+ AutoGenConfig: r.testProperties.Auto_gen_config,
+ DeviceTemplate: "${RavenwoodTestConfigTemplate}",
+ HostTemplate: "${RavenwoodTestConfigTemplate}",
})
+ r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_common_data)...)
+
+ r.data = android.SortedUniquePaths(r.data)
+
+ var testData []android.DataPath
+ for _, data := range r.data {
+ dataPath := android.DataPath{SrcPath: data}
+ testData = append(testData, dataPath)
+ }
+ for _, d := range r.extraOutputFiles {
+ testData = append(testData, android.DataPath{SrcPath: d})
+ }
// Always enable Ravenizer for ravenwood tests.
r.Library.ravenizer.enabled = true
@@ -244,20 +271,28 @@ func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
targetSdkVersionInt := r.TargetSdkVersion(ctx).FinalOrFutureInt() // FinalOrFutureInt may be 10000.
packageName := proptools.StringDefault(r.ravenwoodTestProperties.Package_name, "")
instPackageName := proptools.StringDefault(r.ravenwoodTestProperties.Inst_package_name, "")
+ instClassName := proptools.StringDefault(r.ravenwoodTestProperties.Instrumentation_class, "")
ctx.Build(pctx, android.BuildParams{
Rule: genManifestProperties,
Description: "genManifestProperties",
Output: propertiesOutputPath,
Args: map[string]string{
- "targetSdkVersionInt": strconv.Itoa(targetSdkVersionInt),
- "targetSdkVersionRaw": targetSdkVersion,
- "packageName": packageName,
- "instPackageName": instPackageName,
+ "targetSdkVersionInt": strconv.Itoa(targetSdkVersionInt),
+ "targetSdkVersionRaw": targetSdkVersion,
+ "packageName": packageName,
+ "instPackageName": instPackageName,
+ "instrumentationClass": instClassName,
},
})
installProps := ctx.InstallFile(installPath, "ravenwood.properties", propertiesOutputPath)
installDeps = append(installDeps, installProps)
+ // Copy data files
+ for _, data := range r.data {
+ installedData := ctx.InstallFile(installPath, data.Rel(), data)
+ installDeps = append(installDeps, installedData)
+ }
+
// Install our JAR with all dependencies
ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
@@ -338,6 +373,10 @@ func (r *ravenwoodLibgroup) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs.GetOrDefault(ctx, nil) {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
}
+
+ if r.Name() == ravenwoodRuntimeName {
+ ctx.AddVariationDependencies(nil, allAconfigModuleTag, aconfig.AllAconfigModule)
+ }
}
func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -355,11 +394,17 @@ func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContex
names: jniDepNames,
})
+ install := func(to android.InstallPath, srcs ...android.Path) {
+ for _, s := range srcs {
+ ctx.InstallFile(to, s.Base(), s)
+ }
+ }
+
// Install our runtime into expected location for packaging
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
for _, lib := range r.ravenwoodLibgroupProperties.Libs {
libModule := ctx.GetDirectDepProxyWithTag(lib, ravenwoodLibContentTag)
- if libModule == nil {
+ if libModule.IsNil() {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{lib})
} else {
@@ -368,24 +413,50 @@ func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContex
continue
}
libJar := android.OutputFileForModule(ctx, libModule, "")
- ctx.InstallFile(installPath, lib+".jar", libJar)
+ ctx.InstallFile(installPath, libJar.Base(), libJar)
}
soInstallPath := android.PathForModuleInstall(ctx, r.BaseModuleName()).Join(ctx, getLibPath(r.forceArchType))
for _, jniLib := range jniLibs {
- ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
+ install(soInstallPath, jniLib.path)
}
dataInstallPath := installPath.Join(ctx, "ravenwood-data")
data := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Data)
for _, file := range data {
- ctx.InstallFile(dataInstallPath, file.Base(), file)
+ install(dataInstallPath, file)
}
fontsInstallPath := installPath.Join(ctx, "fonts")
fonts := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Fonts)
for _, file := range fonts {
- ctx.InstallFile(fontsInstallPath, file.Base(), file)
+ install(fontsInstallPath, file)
+ }
+
+ // Copy aconfig flag storage files.
+ if r.Name() == ravenwoodRuntimeName {
+ allAconfigFound := false
+ if allAconfig := ctx.GetDirectDepProxyWithTag(aconfig.AllAconfigModule, allAconfigModuleTag); !allAconfig.IsNil() {
+ aadi, ok := android.OtherModuleProvider(ctx, allAconfig, aconfig.AllAconfigDeclarationsInfoProvider)
+ if ok {
+ // Binary proto file and the text proto.
+ // We don't really use the text proto file, but having this would make debugging easier.
+ install(installPath.Join(ctx, "aconfig/metadata/aconfig/etc"), aadi.ParsedFlagsFile, aadi.TextProtoFlagsFile)
+
+ // The "new" storage files.
+ install(installPath.Join(ctx, "aconfig/metadata/aconfig/maps"), aadi.StoragePackageMap, aadi.StorageFlagMap)
+ install(installPath.Join(ctx, "aconfig/metadata/aconfig/boot"), aadi.StorageFlagVal, aadi.StorageFlagInfo)
+
+ allAconfigFound = true
+ }
+ }
+ if !allAconfigFound {
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{aconfig.AllAconfigModule})
+ } else {
+ ctx.ModuleErrorf("missing dependency %q", aconfig.AllAconfigModule)
+ }
+ }
}
// Normal build should perform install steps
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
index d6493bcfa..55084bf22 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "android/soong/aconfig"
"runtime"
"testing"
@@ -27,6 +28,9 @@ var prepareRavenwoodRuntime = android.GroupFixturePreparers(
RegisterRavenwoodBuildComponents(ctx)
}),
android.FixtureAddTextFile("ravenwood/Android.bp", `
+ all_aconfig_declarations {
+ name: "all_aconfig_declarations",
+ }
cc_library_shared {
name: "ravenwood-runtime-jni1",
host_supported: true,
@@ -55,6 +59,11 @@ var prepareRavenwoodRuntime = android.GroupFixturePreparers(
srcs: ["Services.java"],
}
java_library_static {
+ name: "ravenwood-runtime-extra",
+ stem: "runtime-extra",
+ srcs: ["Extra.java"],
+ }
+ java_library_static {
name: "framework-rules.ravenwood",
srcs: ["Rules.java"],
}
@@ -79,6 +88,7 @@ var prepareRavenwoodRuntime = android.GroupFixturePreparers(
libs: [
"framework-minus-apex.ravenwood",
"framework-services.ravenwood",
+ "ravenwood-runtime-extra",
],
jni_libs: [
"ravenwood-runtime-jni1",
@@ -111,6 +121,7 @@ func TestRavenwoodRuntime(t *testing.T) {
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
etc.PrepareForTestWithPrebuiltEtc,
+ aconfig.PrepareForTestWithAconfigBuildComponents,
prepareRavenwoodRuntime,
).RunTest(t)
@@ -124,11 +135,20 @@ func TestRavenwoodRuntime(t *testing.T) {
runtime := ctx.ModuleForTests(t, "ravenwood-runtime", "android_common")
runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-services.ravenwood.jar")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/runtime-extra.jar")
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni1.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/ravenwood-data/app1.apk")
runtime.Output(installPathPrefix + "/ravenwood-runtime/fonts/Font.ttf")
+
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/etc/all_aconfig_declarations.pb")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/etc/all_aconfig_declarations.textproto")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/maps/all_aconfig_declarations.package.map")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/maps/all_aconfig_declarations.flag.map")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/boot/all_aconfig_declarations.flag.info")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/aconfig/metadata/aconfig/boot/all_aconfig_declarations.val")
+
utils := ctx.ModuleForTests(t, "ravenwood-utils", "android_common")
utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
}
@@ -142,6 +162,7 @@ func TestRavenwoodTest(t *testing.T) {
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
etc.PrepareForTestWithPrebuiltEtc,
+ aconfig.PrepareForTestWithAconfigBuildComponents,
prepareRavenwoodRuntime,
).RunTestWithBp(t, `
cc_library_shared {
@@ -176,12 +197,17 @@ func TestRavenwoodTest(t *testing.T) {
"jni-lib1",
"ravenwood-runtime-jni2",
],
+ data: [
+ "data/file1.txt",
+ "data2/sub/file2",
+ ],
resource_apk: "app2",
inst_resource_apk: "app3",
sdk_version: "test_current",
target_sdk_version: "34",
package_name: "a.b.c",
inst_package_name: "x.y.z",
+ instrumentation_class: "androidx.test.runner.AndroidJUnitRunner",
}
android_ravenwood_test {
name: "ravenwood-test-empty",
@@ -213,6 +239,8 @@ func TestRavenwoodTest(t *testing.T) {
module.Output(installPathPrefix + "/ravenwood-test/lib64/libpink.so")
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk")
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-inst-res.apk")
+ module.Output(installPathPrefix + "/ravenwood-test/data/file1.txt")
+ module.Output(installPathPrefix + "/ravenwood-test/data2/sub/file2")
module = ctx.ModuleForTests(t, "ravenwood-test-empty", "android_common")
module.Output(installPathPrefix + "/ravenwood-test-empty/ravenwood.properties")
diff --git a/java/robolectric.go b/java/robolectric.go
index 1d204a4e0..cee194777 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -149,6 +149,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
extraTestRunnerOptions = append(extraTestRunnerOptions, tradefed.Option{Name: "java-flags", Value: "-Drobolectric.strict.mode=true"})
}
+ extraTestRunnerOptions = append(extraTestRunnerOptions, r.testProperties.Test_options.Test_runner_options...)
var extraOptions []tradefed.Option
var javaHome = ctx.Config().Getenv("ANDROID_JAVA_HOME")
@@ -406,7 +407,7 @@ func (r *robolectricRuntimes) GenerateAndroidBuildActions(ctx android.ModuleCont
if !ctx.Config().AlwaysUsePrebuiltSdks() && r.props.Lib != nil {
runtimeFromSourceModule := ctx.GetDirectDepProxyWithTag(String(r.props.Lib), libTag)
- if runtimeFromSourceModule == nil {
+ if runtimeFromSourceModule.IsNil() {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{String(r.props.Lib)})
} else {
diff --git a/java/rro.go b/java/rro.go
index 4ae8d7fc7..57b9da052 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -213,6 +213,11 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
Theme: r.Theme(),
})
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: r.Certificate(),
+ Name: r.outputFile.Base(),
+ })
+
ctx.SetOutputFiles([]android.Path{r.outputFile}, "")
buildComplianceMetadata(ctx)
@@ -261,6 +266,17 @@ func RuntimeResourceOverlayFactory() android.Module {
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.properties.Overrides)
+
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
+ // Make this module product_specific by default. Keep this in sync with rroPartition()
+ if !ctx.DeviceSpecific() && !ctx.SocSpecific() && !ctx.SystemExtSpecific() {
+ proptools.AppendMatchingProperties(ctx.Module().GetProperties(), &struct {
+ Product_specific *bool
+ }{
+ Product_specific: proptools.BoolPtr(true),
+ }, nil)
+ }
+ })
return module
}
@@ -358,12 +374,12 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.
}
var rroDirs android.Paths
// Get rro dirs of the base app
- ctx.VisitDirectDepsWithTag(rroDepTag, func(m android.Module) {
- aarDep, _ := m.(AndroidLibraryDependency)
+ ctx.VisitDirectDepsProxyWithTag(rroDepTag, func(m android.ModuleProxy) {
+ javaInfo, _ := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
if ctx.InstallInProduct() {
- rroDirs = filterRRO(aarDep.RRODirsDepSet(), product)
+ rroDirs = filterRRO(javaInfo.AndroidLibraryDependencyInfo.RRODirsDepSet, product)
} else {
- rroDirs = filterRRO(aarDep.RRODirsDepSet(), device)
+ rroDirs = filterRRO(javaInfo.AndroidLibraryDependencyInfo.RRODirsDepSet, device)
}
})
@@ -421,6 +437,11 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.
OutputFile: signed,
Certificate: a.certificate,
})
+
+ android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
+ Certificate: a.certificate,
+ Name: signed.Base(),
+ })
}
func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
diff --git a/java/rro_test.go b/java/rro_test.go
index 3e4fed51e..faf82af84 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -355,7 +355,7 @@ func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) {
android.AssertStringDoesContain(t,
"aapt2 link command expected to pass feature flags arguments",
linkInFlags,
- "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ "--feature-flags @out/soong/.intermediates/bar/aconfig-flags.txt --feature-flags @out/soong/.intermediates/baz/aconfig-flags.txt",
)
}
diff --git a/java/sdk.go b/java/sdk.go
index d676164e9..d1c7c0112 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -99,7 +99,7 @@ func systemModuleKind(sdkKind android.SdkKind, apiLevel android.ApiLevel) androi
return systemModuleKind
}
-func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext) sdkDep {
+func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext SdkVersionContext) sdkDep {
sdkVersion := sdkContext.SdkVersion(ctx)
if !sdkVersion.Valid() {
ctx.PropertyErrorf("sdk_version", "invalid version %q", sdkVersion.Raw)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 00ba8b2fb..4eec2ff35 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -17,9 +17,11 @@ package java
import (
"errors"
"fmt"
+ "maps"
"path"
"path/filepath"
"reflect"
+ "slices"
"sort"
"strings"
"sync"
@@ -38,11 +40,11 @@ type scopeDependencyTag struct {
apiScope *apiScope
// Function for extracting appropriate path information from the dependency.
- depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.Module) error
+ depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.ModuleProxy) error
}
// Extract tag specific information from the dependency.
-func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) {
+func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.ModuleProxy, paths *scopePaths) {
err := tag.depInfoExtractor(paths, ctx, dep)
if err != nil {
ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error())
@@ -697,7 +699,7 @@ type scopePaths struct {
latestRemovedApiPaths android.Paths
}
-func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.ModuleProxy) error {
if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
@@ -711,7 +713,7 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.Modul
}
}
-func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.ModuleProxy) error {
if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
paths.stubsHeaderPath = lib.HeaderJars
if !ctx.Config().ReleaseHiddenApiExportableStubs() {
@@ -726,7 +728,7 @@ func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx and
}
}
-func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.ModuleProxy) error {
if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
if ctx.Config().ReleaseHiddenApiExportableStubs() {
paths.stubsImplPath = lib.ImplementationJars
@@ -740,7 +742,7 @@ func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx and
}
}
-func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, dep android.Module,
+func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, dep android.ModuleProxy,
action func(*DroidStubsInfo, *StubsSrcInfo) error) error {
apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider)
if !ok {
@@ -755,7 +757,7 @@ func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, d
}
func (paths *scopePaths) treatDepAsApiStubsSrcProvider(
- ctx android.ModuleContext, dep android.Module, action func(provider *StubsSrcInfo) error) error {
+ ctx android.ModuleContext, dep android.ModuleProxy, action func(provider *StubsSrcInfo) error) error {
if apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider); ok {
err := action(&apiStubsProvider)
if err != nil {
@@ -797,7 +799,7 @@ func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider *S
return err
}
-func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.ModuleProxy) error {
stubsType := Everything
if ctx.Config().ReleaseHiddenApiExportableStubs() {
stubsType = Exportable
@@ -807,7 +809,7 @@ func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext
})
}
-func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.ModuleProxy) error {
stubsType := Everything
if ctx.Config().ReleaseHiddenApiExportableStubs() {
stubsType = Exportable
@@ -819,7 +821,7 @@ func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx an
})
}
-func extractOutputPaths(ctx android.ModuleContext, dep android.Module) (android.Paths, error) {
+func extractOutputPaths(ctx android.ModuleContext, dep android.ModuleProxy) (android.Paths, error) {
var paths android.Paths
if sourceFileProducer, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok {
paths = sourceFileProducer.Srcs
@@ -829,13 +831,13 @@ func extractOutputPaths(ctx android.ModuleContext, dep android.Module) (android.
}
}
-func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.ModuleProxy) error {
outputPaths, err := extractOutputPaths(ctx, dep)
paths.latestApiPaths = outputPaths
return err
}
-func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error {
+func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.ModuleProxy) error {
outputPaths, err := extractOutputPaths(ctx, dep)
paths.latestRemovedApiPaths = outputPaths
return err
@@ -1022,6 +1024,12 @@ func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.Mod
ExportableStubDexJarPaths: exportableStubPaths,
RemovedTxtFiles: removedApiFilePaths,
SharedLibrary: c.sharedLibrary(),
+ DoctagPaths: c.doctagPaths,
+ OnBootclasspathSince: c.commonSdkLibraryProperties.On_bootclasspath_since,
+ OnBootclasspathBefore: c.commonSdkLibraryProperties.On_bootclasspath_before,
+ MinDeviceSdk: c.commonSdkLibraryProperties.Min_device_sdk,
+ MaxDeviceSdk: c.commonSdkLibraryProperties.Max_device_sdk,
+ ImplLibProfileGuided: c.implLibraryInfo != nil && c.implLibraryInfo.ProfileGuided,
}
}
@@ -1166,13 +1174,13 @@ func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.M
module.AddProperties(&e.sdkLibraryComponentProperties)
}
-// to satisfy SdkLibraryComponentDependency
func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
return e.sdkLibraryComponentProperties.SdkLibraryName
}
-// to satisfy SdkLibraryComponentDependency
-func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string {
+var SdkLibraryComponentDependencyInfoProvider = blueprint.NewMutatorProvider[SdkLibraryComponentDependencyInfo]("deps")
+
+type SdkLibraryComponentDependencyInfo struct {
// For shared libraries, this is the same as the SDK library name. If a Java library or app
// depends on a component library (e.g. a stub library) it still needs to know the name of the
// run-time library and the corresponding module that provides the implementation. This name is
@@ -1181,28 +1189,29 @@ func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *stri
//
// For non-shared SDK (component or not) libraries this returns `nil`, as they are not
// <uses-library> and should not be added to the manifest or to CLC.
- return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
+ OptionalSdkLibraryImplementation *string
+ // The name of the java_sdk_library/_import module if this module was created by one.
+ SdkLibraryName *string
}
-// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
-// (including the java_sdk_library) itself.
-type SdkLibraryComponentDependency interface {
- UsesLibraryDependency
-
- // SdkLibraryName returns the name of the java_sdk_library/_import module.
- SdkLibraryName() *string
+func (e *EmbeddableSdkLibraryComponent) setComponentDependencyInfoProvider(ctx android.BottomUpMutatorContext) {
+ android.SetProvider(ctx, SdkLibraryComponentDependencyInfoProvider, SdkLibraryComponentDependencyInfo{
+ OptionalSdkLibraryImplementation: e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack,
+ SdkLibraryName: e.sdkLibraryComponentProperties.SdkLibraryName,
+ })
+}
- // The name of the implementation library for the optional SDK library or nil, if there isn't one.
- OptionalSdkLibraryImplementation() *string
+type ApiScopePathsInfo struct {
+ StubsImplPath android.Paths
+ CurrentApiFilePath android.OptionalPath
+ RemovedApiFilePath android.OptionalPath
+ StubsSrcJar android.OptionalPath
+ AnnotationsZip android.OptionalPath
}
-// Make sure that all the module types that are components of java_sdk_library/_import
-// and which can be referenced (directly or indirectly) from an android app implement
-// the SdkLibraryComponentDependency interface.
-var _ SdkLibraryComponentDependency = (*Library)(nil)
-var _ SdkLibraryComponentDependency = (*Import)(nil)
-var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
-var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
+type ApiScopePropsInfo struct {
+ SdkVersion *string
+}
type SdkLibraryInfo struct {
// GeneratingLibs is the names of the library modules that this sdk library
@@ -1224,7 +1233,16 @@ type SdkLibraryInfo struct {
// Whether if this can be used as a shared library.
SharedLibrary bool
- Prebuilt bool
+ Prebuilt bool
+ DistStem string
+ DoctagPaths android.Paths
+ OnBootclasspathSince *string
+ OnBootclasspathBefore *string
+ MinDeviceSdk *string
+ MaxDeviceSdk *string
+ ImplLibProfileGuided bool
+ ApiScopePaths map[string]ApiScopePathsInfo
+ ApiScopeProps map[string]ApiScopePropsInfo
}
var SdkLibraryInfoProvider = blueprint.NewProvider[SdkLibraryInfo]()
@@ -1445,6 +1463,13 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these."
ctx.ModuleErrorf(m)
}
+
+ module.usesLibrary.deps(ctx, false)
+
+ module.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
+ libDeps := ctx.AddVariationDependencies(nil, usesLibStagingTag, module.properties.Libs...)
+ libDeps = append(libDeps, ctx.AddVariationDependencies(nil, usesLibStagingTag, module.sdkLibraryProperties.Impl_only_libs...)...)
+ module.usesLibrary.depsFromLibs(ctx, libDeps)
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1505,6 +1530,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
module.bootDexJarPath = module.implLibraryInfo.BootDexJarPath
module.uncompressDexState = module.implLibraryInfo.UncompressDexState
module.active = module.implLibraryInfo.Active
+ module.classLoaderContexts = module.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
}
module.outputFile = module.implLibraryInfo.OutputFile
@@ -1519,7 +1545,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
// Properties required for Library.AndroidMkEntries
module.logtagsSrcs = module.implLibraryInfo.LogtagsSrcs
module.dexpreopter.builtInstalled = module.implLibraryInfo.BuiltInstalled
- module.jacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile
+ module.jacocoInfo = module.implLibraryInfo.JacocoInfo
module.dexer.proguardDictionary = module.implLibraryInfo.ProguardDictionary
module.dexer.proguardUsageZip = module.implLibraryInfo.ProguardUsageZip
module.linter.reports = module.implLibraryInfo.LinterReports
@@ -1532,9 +1558,9 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
module.hostdexInstallFile = module.implLibraryInfo.HostdexInstallFile
}
- if installFilesInfo, ok := android.OtherModuleProvider(ctx, implLib, android.InstallFilesProvider); ok {
- if installFilesInfo.CheckbuildTarget != nil {
- ctx.CheckbuildFile(installFilesInfo.CheckbuildTarget)
+ if buildTargetsInfo, ok := android.OtherModuleProvider(ctx, implLib, android.ModuleBuildTargetsProvider); ok {
+ if buildTargetsInfo.CheckbuildTarget != nil {
+ ctx.CheckbuildFile(buildTargetsInfo.CheckbuildTarget)
}
}
}
@@ -1581,14 +1607,47 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
}
javaInfo := &JavaInfo{
- JacocoReportClassesFile: module.jacocoReportClassesFile,
+ JacocoInfo: module.jacocoInfo,
+ CompileDex: module.dexProperties.Compile_dex,
}
setExtraJavaInfo(ctx, ctx.Module(), javaInfo)
android.SetProvider(ctx, JavaInfoProvider, javaInfo)
sdkLibInfo.GeneratingLibs = generatingLibs
sdkLibInfo.Prebuilt = false
+ sdkLibInfo.DistStem = module.distStem()
+ if module.scopePaths != nil {
+ sdkLibInfo.ApiScopePaths = make(map[string]ApiScopePathsInfo)
+ for k, v := range module.scopePaths {
+ sdkLibInfo.ApiScopePaths[k.name] = ApiScopePathsInfo{
+ StubsImplPath: v.stubsImplPath,
+ CurrentApiFilePath: v.currentApiFilePath,
+ RemovedApiFilePath: v.removedApiFilePath,
+ StubsSrcJar: v.stubsSrcJar,
+ AnnotationsZip: v.annotationsZip,
+ }
+ }
+ }
+ if module.scopeToProperties != nil {
+ sdkLibInfo.ApiScopeProps = make(map[string]ApiScopePropsInfo)
+ for k, v := range module.scopeToProperties {
+ sdkLibInfo.ApiScopeProps[k.name] = ApiScopePropsInfo{
+ SdkVersion: v.Sdk_version,
+ }
+ }
+ }
android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo)
+
+ android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{
+ PermittedPackages: module.PermittedPackagesForUpdatableBootJars(),
+ })
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if module.implementationAndResourcesJar != nil {
+ moduleInfoJSON.ClassesJar = []string{module.implementationAndResourcesJar.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func setOutputFilesFromJavaInfo(ctx android.ModuleContext, info *JavaInfo) {
@@ -1630,12 +1689,17 @@ func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
// Get the sdk version for use when compiling the stubs library.
func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string {
- scopeProperties := module.scopeToProperties[apiScope]
- if scopeProperties.Sdk_version != nil {
- return proptools.String(scopeProperties.Sdk_version)
+ return getSdkVersionForStubsLibrary(mctx, apiScope, module.scopeToProperties[apiScope].Sdk_version,
+ android.SdkContext(&module.Library))
+}
+
+func getSdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope,
+ sdkVersion *string, sdkContext SdkVersionContext) string {
+ if sdkVersion != nil {
+ return proptools.String(sdkVersion)
}
- sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
+ sdkDep := decodeSdkDep(mctx, sdkContext)
if sdkDep.hasStandardLibs() {
// If building against a standard sdk then use the sdk version appropriate for the scope.
return apiScope.sdkVersion
@@ -1797,11 +1861,17 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
panic(fmt.Sprintf("script file %s doesn't exist", script))
}
+ env_msg := ""
+ if mctx.Config().GetBuildFlagBool("RELEASE_SRC_DIR_IS_READ_ONLY") {
+ env_msg = "BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true "
+ }
+
mctx.ModuleErrorf("One or more current api files are missing. "+
"You can update them by:\n"+
- "%s %q %s && m update-api",
+ "%s %q %s && %sm update-api",
script, filepath.Join(mctx.ModuleDir(), apiDir),
- strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
+ strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "),
+ env_msg)
return
}
@@ -2076,6 +2146,12 @@ func (module *SdkLibraryImport) BaseModuleName() string {
return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
}
+func (module *SdkLibraryImport) sortedApiScopes() []*apiScope {
+ return slices.SortedFunc(maps.Keys(module.scopeProperties), func(a, b *apiScope) int {
+ return strings.Compare(a.name, b.name)
+ })
+}
+
func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
@@ -2083,7 +2159,8 @@ func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHo
module.prebuilt.ForcePrefer()
}
- for apiScope, scopeProperties := range module.scopeProperties {
+ for _, apiScope := range module.sortedApiScopes() {
+ scopeProperties := module.scopeProperties[apiScope]
if len(scopeProperties.Jars) == 0 {
continue
}
@@ -2108,7 +2185,8 @@ func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHo
// Add the dependencies on the child module in the component deps mutator so that it
// creates references to the prebuilt and not the source modules.
func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
- for apiScope, scopeProperties := range module.scopeProperties {
+ for _, apiScope := range module.sortedApiScopes() {
+ scopeProperties := module.scopeProperties[apiScope]
if len(scopeProperties.Jars) == 0 {
continue
}
@@ -2136,6 +2214,8 @@ func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext)
ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName)
}
}
+
+ module.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)
}
var _ android.ApexModule = (*SdkLibraryImport)(nil)
@@ -2202,7 +2282,8 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
sdkLibInfo := module.generateCommonBuildActions(ctx)
// Populate the scope paths with information from the properties.
- for apiScope, scopeProperties := range module.scopeProperties {
+ for _, apiScope := range module.sortedApiScopes() {
+ scopeProperties := module.scopeProperties[apiScope]
if len(scopeProperties.Jars) == 0 {
continue
}
@@ -2243,7 +2324,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
javaInfo := &JavaInfo{}
if module.implLibraryInfo != nil {
- javaInfo.JacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile
+ javaInfo.JacocoInfo = module.implLibraryInfo.JacocoInfo
}
setExtraJavaInfo(ctx, ctx.Module(), javaInfo)
@@ -2283,16 +2364,7 @@ func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderConte
return nil
}
-// to satisfy apex.javaDependency interface
-func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
- if module.implLibraryInfo == nil {
- return nil
- } else {
- return module.implLibraryInfo.JacocoReportClassesFile
- }
-}
-
-// to satisfy apex.javaDependency interface
+// to satisfy apex.javaModule interface
func (module *SdkLibraryImport) Stem() string {
return module.BaseModuleName()
}
@@ -2341,9 +2413,9 @@ func (s *sdkLibrarySdkMemberType) AddDependencies(ctx android.SdkDependencyConte
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*SdkLibrary)
- return ok
+func (s *sdkLibrarySdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ info, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider)
+ return ok && !info.Prebuilt
}
func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
@@ -2436,49 +2508,70 @@ type scopeProperties struct {
SdkVersion string
}
-func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- sdk := variant.(*SdkLibrary)
+type SdkVersionContext interface {
+ SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
+ SystemModules() string
+}
+
+type SdkVersionContextProviderImpl struct {
+ javaInfo *JavaInfo
+}
+
+func (s *SdkVersionContextProviderImpl) SdkVersion(_ android.EarlyModuleContext) android.SdkSpec {
+ return s.javaInfo.SdkVersion
+}
+func (s *SdkVersionContextProviderImpl) SystemModules() string {
+ return s.javaInfo.SystemModules
+}
+
+func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ mctx := ctx.SdkModuleContext()
+ javaInfo := android.OtherModulePointerProviderOrDefault(mctx, variant, JavaInfoProvider)
+ libraryInfo := android.OtherModuleProviderOrDefault(mctx, variant, JavaLibraryInfoProvider)
+ sdkInfo := android.OtherModuleProviderOrDefault(mctx, variant, SdkLibraryInfoProvider)
// Copy the stem name for files in the sdk snapshot.
- s.Stem = sdk.distStem()
+ s.Stem = sdkInfo.DistStem
s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range AllApiScopes {
- paths := sdk.findScopePaths(apiScope)
- if paths == nil {
+ paths, ok := sdkInfo.ApiScopePaths[apiScope.name]
+ if !ok {
continue
}
- jars := paths.stubsImplPath
+ jars := paths.StubsImplPath
if len(jars) > 0 {
properties := scopeProperties{}
properties.Jars = jars
- properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope)
- properties.StubsSrcJar = paths.stubsSrcJar.Path()
- if paths.currentApiFilePath.Valid() {
- properties.CurrentApiFile = paths.currentApiFilePath.Path()
+ properties.SdkVersion = getSdkVersionForStubsLibrary(mctx, apiScope, sdkInfo.ApiScopeProps[apiScope.name].SdkVersion,
+ &SdkVersionContextProviderImpl{javaInfo})
+
+ properties.StubsSrcJar = paths.StubsSrcJar.Path()
+ if paths.CurrentApiFilePath.Valid() {
+ properties.CurrentApiFile = paths.CurrentApiFilePath.Path()
}
- if paths.removedApiFilePath.Valid() {
- properties.RemovedApiFile = paths.removedApiFilePath.Path()
+ if paths.RemovedApiFilePath.Valid() {
+ properties.RemovedApiFile = paths.RemovedApiFilePath.Path()
}
// The annotations zip is only available for modules that set annotations_enabled: true.
- if paths.annotationsZip.Valid() {
- properties.AnnotationsZip = paths.annotationsZip.Path()
+ if paths.AnnotationsZip.Valid() {
+ properties.AnnotationsZip = paths.AnnotationsZip.Path()
}
s.Scopes[apiScope] = &properties
}
}
- s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
- s.Compile_dex = sdk.dexProperties.Compile_dex
- s.Doctag_paths = sdk.doctagPaths
- s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars()
- s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since
- s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before
- s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
- s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
+ s.Shared_library = proptools.BoolPtr(sdkInfo.SharedLibrary)
+ s.Compile_dex = javaInfo.CompileDex
+ s.Doctag_paths = sdkInfo.DoctagPaths
+ s.Permitted_packages = libraryInfo.PermittedPackages
+ s.On_bootclasspath_since = sdkInfo.OnBootclasspathSince
+ s.On_bootclasspath_before = sdkInfo.OnBootclasspathBefore
+ s.Min_device_sdk = sdkInfo.MinDeviceSdk
+ s.Max_device_sdk = sdkInfo.MaxDeviceSdk
- if sdk.implLibraryInfo != nil && sdk.implLibraryInfo.ProfileGuided {
+ if sdkInfo.ImplLibProfileGuided {
s.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
}
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
index f5feabeb4..2d27c42f6 100644
--- a/java/sdk_library_internal.go
+++ b/java/sdk_library_internal.go
@@ -20,7 +20,9 @@ import (
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/etc"
+ "android/soong/java/config"
"github.com/google/blueprint/proptools"
)
@@ -168,6 +170,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
&module.dexpreoptProperties,
&module.linter.properties,
&module.overridableProperties,
+ &module.usesLibrary.usesLibraryProperties,
&props,
module.sdkComponentPropertiesForChildLibrary(),
}
@@ -581,7 +584,9 @@ func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
- Uses_libs_dependencies proptools.Configurable[[]string]
+ Uses_libs proptools.Configurable[[]string]
+ Libs []string
+ Impl_only_libs []string
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Enabled: module.EnabledProperty(),
@@ -592,7 +597,9 @@ func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
- Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs.Clone(),
+ Uses_libs: module.usesLibraryProperties.Uses_libs.Clone(),
+ Libs: android.RemoveListFromList(module.properties.Libs, config.FrameworkLibraries),
+ Impl_only_libs: module.sdkLibraryProperties.Impl_only_libs,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -716,6 +723,8 @@ type sdkLibraryXml struct {
installDirPath android.InstallPath
hideApexVariantFromMake bool
+
+ usesLibrary
}
type sdkLibraryXmlProperties struct {
@@ -754,10 +763,11 @@ type sdkLibraryXmlProperties struct {
// This value comes from the ApiLevel of the MinSdkVersion property.
Sdk_library_min_api_level *string
- // Uses-libs dependencies that the shared library requires to work correctly.
- //
- // This will add dependency="foo:bar" to the <library> section.
- Uses_libs_dependencies proptools.Configurable[[]string]
+ // List of java libraries that will be in the classpath.
+ Libs []string `android:"arch_variant"`
+
+ // List of Java libraries that will be in the classpath when building the implementation lib.
+ Impl_only_libs []string `android:"arch_variant"`
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -765,7 +775,7 @@ type sdkLibraryXmlProperties struct {
func sdkLibraryXmlFactory() android.Module {
module := &sdkLibraryXml{}
- module.AddProperties(&module.properties)
+ module.AddProperties(&module.properties, &module.usesLibrary.usesLibraryProperties)
android.InitApexModule(module)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
@@ -801,7 +811,10 @@ func (module *sdkLibraryXml) ApexAvailableFor() []string {
}
func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
- // do nothing
+ module.usesLibrary.deps(ctx, false)
+ libDeps := ctx.AddVariationDependencies(nil, usesLibStagingTag, module.properties.Libs...)
+ libDeps = append(libDeps, ctx.AddVariationDependencies(nil, usesLibStagingTag, module.properties.Impl_only_libs...)...)
+ module.usesLibrary.depsFromLibs(ctx, libDeps)
}
var _ android.ApexModule = (*sdkLibraryXml)(nil)
@@ -865,8 +878,13 @@ func formattedOptionalAttribute(attrName string, value *string) string {
return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
}
-func formattedDependenciesAttribute(dependencies []string) string {
- if dependencies == nil {
+func (module *sdkLibraryXml) formattedDependenciesAttribute(ctx android.ModuleContext) string {
+ classLoaderContexts := module.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+ dependencies := make([]string, 0, len(classLoaderContexts[dexpreopt.AnySdkVersion]))
+ for _, dep := range classLoaderContexts[dexpreopt.AnySdkVersion] {
+ dependencies = append(dependencies, dep.Name)
+ }
+ if len(dependencies) == 0 {
return ""
}
return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
@@ -881,7 +899,7 @@ func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) stri
implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
- dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies.GetOrDefault(ctx, nil))
+ dependenciesAttr := module.formattedDependenciesAttribute(ctx)
// <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
// similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
var libraryTag string
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 6d27e54d0..1f4b57e7d 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -180,11 +180,11 @@ func TestJavaSdkLibrary(t *testing.T) {
fooImplDexJar := result.ModuleForTests(t, "foo.impl", "android_common").Rule("d8")
// tests if kotlinc generated files are NOT excluded from output of foo.impl.
- android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/**/*.kotlin_module")
barImplDexJar := result.ModuleForTests(t, "bar.impl", "android_common").Rule("d8")
// tests if kotlinc generated files are excluded from output of bar.impl.
- android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/**/*.kotlin_module")
}
func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
diff --git a/java/system_modules.go b/java/system_modules.go
index e955aec15..5ced86efc 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -29,6 +29,8 @@ import (
// file will produce the rules necessary to convert each unique set of bootclasspath jars into
// system modules in a runtime image using the jmod and jlink tools.
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
func init() {
RegisterSystemModulesBuildComponents(android.InitRegistrationContext)
@@ -121,6 +123,7 @@ func SystemModulesFactory() android.Module {
return module
}
+// @auto-generate: gob
type SystemModulesProviderInfo struct {
// The aggregated header jars from all jars specified in the libs property.
// Used when system module is added as a dependency to bootclasspath.
@@ -131,6 +134,8 @@ type SystemModulesProviderInfo struct {
// depset of header jars for this module and all transitive static dependencies
TransitiveStaticLibsHeaderJars depset.DepSet[android.Path]
+ Prebuilt bool
+ Libs []string
}
var SystemModulesProvider = blueprint.NewProvider[*SystemModulesProviderInfo]()
@@ -150,11 +155,21 @@ type SystemModulesProperties struct {
Libs []string
}
+func (system *systemModulesImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ info := system.commonBuildActions(ctx)
+ info.Prebuilt = true
+ android.SetProvider(ctx, SystemModulesProvider, info)
+}
+
func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ android.SetProvider(ctx, SystemModulesProvider, system.commonBuildActions(ctx))
+}
+
+func (system *SystemModules) commonBuildActions(ctx android.ModuleContext) *SystemModulesProviderInfo {
var jars android.Paths
var transitiveStaticLibsHeaderJars []depset.DepSet[android.Path]
- ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(systemModulesLibsTag, func(module android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
jars = append(jars, dep.HeaderJars...)
transitiveStaticLibsHeaderJars = append(transitiveStaticLibsHeaderJars, dep.TransitiveStaticLibsHeaderJars)
@@ -163,12 +178,13 @@ func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleConte
system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
- android.SetProvider(ctx, SystemModulesProvider, &SystemModulesProviderInfo{
+ return &SystemModulesProviderInfo{
HeaderJars: jars,
OutputDir: system.outputDir,
OutputDirDeps: system.outputDeps,
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, nil, transitiveStaticLibsHeaderJars),
- })
+ Libs: system.properties.Libs,
+ }
}
// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
@@ -275,12 +291,11 @@ func (mt *systemModulesSdkMemberType) AddDependencies(ctx android.SdkDependencyC
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (mt *systemModulesSdkMemberType) IsInstance(module android.Module) bool {
- if _, ok := module.(*SystemModules); ok {
+func (mt *systemModulesSdkMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ if info, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
// A prebuilt system module cannot be added as a member of an sdk because the source and
// snapshot instances would conflict.
- _, ok := module.(*systemModulesImport)
- return !ok
+ return !info.Prebuilt
}
return false
}
@@ -299,9 +314,8 @@ func (mt *systemModulesSdkMemberType) CreateVariantPropertiesStruct() android.Sd
return &systemModulesInfoProperties{}
}
-func (p *systemModulesInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- systemModule := variant.(*SystemModules)
- p.Libs = systemModule.properties.Libs
+func (p *systemModulesInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ p.Libs = android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, SystemModulesProvider).Libs
}
func (p *systemModulesInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/java/system_modules_gob_enc.go b/java/system_modules_gob_enc.go
new file mode 100644
index 000000000..7585318b4
--- /dev/null
+++ b/java/system_modules_gob_enc.go
@@ -0,0 +1,137 @@
+// Code generated by go run gob_gen.go; DO NOT EDIT.
+
+package java
+
+import (
+ "android/soong/android"
+ "bytes"
+ "github.com/google/blueprint/gobtools"
+)
+
+func init() {
+ SystemModulesProviderInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(SystemModulesProviderInfo) })
+}
+
+func (r SystemModulesProviderInfo) Encode(buf *bytes.Buffer) error {
+ var err error
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.HeaderJars))); err != nil {
+ return err
+ }
+ for val1 := 0; val1 < len(r.HeaderJars); val1++ {
+ if err = gobtools.EncodeInterface(buf, r.HeaderJars[val1]); err != nil {
+ return err
+ }
+ }
+
+ if err = gobtools.EncodeInterface(buf, r.OutputDir); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.OutputDirDeps))); err != nil {
+ return err
+ }
+ for val2 := 0; val2 < len(r.OutputDirDeps); val2++ {
+ if err = gobtools.EncodeInterface(buf, r.OutputDirDeps[val2]); err != nil {
+ return err
+ }
+ }
+
+ if err = r.TransitiveStaticLibsHeaderJars.EncodeInterface(buf); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, r.Prebuilt); err != nil {
+ return err
+ }
+
+ if err = gobtools.EncodeSimple(buf, int32(len(r.Libs))); err != nil {
+ return err
+ }
+ for val3 := 0; val3 < len(r.Libs); val3++ {
+ if err = gobtools.EncodeString(buf, r.Libs[val3]); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func (r *SystemModulesProviderInfo) Decode(buf *bytes.Reader) error {
+ var err error
+
+ var val3 int32
+ err = gobtools.DecodeSimple[int32](buf, &val3)
+ if err != nil {
+ return err
+ }
+ if val3 > 0 {
+ r.HeaderJars = make([]android.Path, val3)
+ for val4 := 0; val4 < int(val3); val4++ {
+ if val6, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val6 == nil {
+ r.HeaderJars[val4] = nil
+ } else {
+ r.HeaderJars[val4] = val6.(android.Path)
+ }
+ }
+ }
+
+ if val8, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val8 == nil {
+ r.OutputDir = nil
+ } else {
+ r.OutputDir = val8.(android.Path)
+ }
+
+ var val11 int32
+ err = gobtools.DecodeSimple[int32](buf, &val11)
+ if err != nil {
+ return err
+ }
+ if val11 > 0 {
+ r.OutputDirDeps = make([]android.Path, val11)
+ for val12 := 0; val12 < int(val11); val12++ {
+ if val14, err := gobtools.DecodeInterface(buf); err != nil {
+ return err
+ } else if val14 == nil {
+ r.OutputDirDeps[val12] = nil
+ } else {
+ r.OutputDirDeps[val12] = val14.(android.Path)
+ }
+ }
+ }
+
+ if err = r.TransitiveStaticLibsHeaderJars.DecodeInterface(buf); err != nil {
+ return err
+ }
+
+ err = gobtools.DecodeSimple[bool](buf, &r.Prebuilt)
+ if err != nil {
+ return err
+ }
+
+ var val18 int32
+ err = gobtools.DecodeSimple[int32](buf, &val18)
+ if err != nil {
+ return err
+ }
+ if val18 > 0 {
+ r.Libs = make([]string, val18)
+ for val19 := 0; val19 < int(val18); val19++ {
+ err = gobtools.DecodeString(buf, &r.Libs[val19])
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return err
+}
+
+var SystemModulesProviderInfoGobRegId int16
+
+func (r SystemModulesProviderInfo) GetTypeId() int16 {
+ return SystemModulesProviderInfoGobRegId
+}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index a60f6b82c..345090067 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -97,6 +97,13 @@ type SystemServerClasspathModule struct {
var _ android.ApexModule = (*SystemServerClasspathModule)(nil)
+type SystemServerClasspathInfo struct {
+ Contents []string
+ StandaloneContents []string
+}
+
+var SystemServerClasspathInfoProvider = blueprint.NewProvider[SystemServerClasspathInfo]()
+
func (m *SystemServerClasspathModule) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
return android.MinApiLevel
}
@@ -139,6 +146,11 @@ func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.Mo
classpathJars = append(classpathJars, standaloneClasspathJars...)
s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
s.setPartitionInfoOfLibraries(ctx)
+
+ android.SetProvider(ctx, SystemServerClasspathInfoProvider, SystemServerClasspathInfo{
+ Contents: s.properties.Contents.GetOrDefault(ctx, nil),
+ StandaloneContents: s.properties.Standalone_contents.GetOrDefault(ctx, nil),
+ })
}
// Map of java library name to their install partition.
@@ -152,8 +164,9 @@ var LibraryNameToPartitionInfoProvider = blueprint.NewProvider[LibraryNameToPart
func (s *SystemServerClasspathModule) setPartitionInfoOfLibraries(ctx android.ModuleContext) {
libraryNameToPartition := map[string]string{}
- ctx.VisitDirectDepsWithTag(systemServerClasspathFragmentContentDepTag, func(m android.Module) {
- libraryNameToPartition[m.Name()] = m.PartitionTag(ctx.DeviceConfig())
+ ctx.VisitDirectDepsProxyWithTag(systemServerClasspathFragmentContentDepTag, func(m android.ModuleProxy) {
+ info := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ libraryNameToPartition[m.Name()] = info.PartitionTag
})
android.SetProvider(ctx, LibraryNameToPartitionInfoProvider, LibraryNameToPartitionInfo{
LibraryNameToPartition: libraryNameToPartition,
@@ -214,10 +227,10 @@ func (systemServerClasspathFragmentContentDependencyTag) ReplaceSourceWithPrebui
// SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if
// they were specified using java_systemserver_libs or java_sdk_libs.
-func (b systemServerClasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+func (b systemServerClasspathFragmentContentDependencyTag) SdkMemberType(ctx android.ModuleContext, child android.ModuleProxy) android.SdkMemberType {
// If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs
// property, otherwise treat if it was specified in the java_systemserver_libs property.
- if javaSdkLibrarySdkMemberType.IsInstance(child) {
+ if javaSdkLibrarySdkMemberType.IsInstance(ctx, child) {
return javaSdkLibrarySdkMemberType
}
@@ -278,8 +291,8 @@ func (s *systemServerClasspathFragmentMemberType) AddDependencies(ctx android.Sd
ctx.AddVariationDependencies(nil, dependencyTag, names...)
}
-func (s *systemServerClasspathFragmentMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*SystemServerClasspathModule)
+func (s *systemServerClasspathFragmentMemberType) IsInstance(ctx android.ModuleContext, module android.ModuleProxy) bool {
+ _, ok := android.OtherModuleProvider(ctx, module, SystemServerClasspathInfoProvider)
return ok
}
@@ -305,11 +318,11 @@ type systemServerClasspathFragmentSdkMemberProperties struct {
Standalone_contents []string
}
-func (s *systemServerClasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- module := variant.(*SystemServerClasspathModule)
+func (s *systemServerClasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ module := android.OtherModuleProviderOrDefault(ctx.SdkModuleContext(), variant, SystemServerClasspathInfoProvider)
- s.Contents = module.properties.Contents.GetOrDefault(ctx.SdkModuleContext(), nil)
- s.Standalone_contents = module.properties.Standalone_contents.GetOrDefault(ctx.SdkModuleContext(), nil)
+ s.Contents = module.Contents
+ s.Standalone_contents = module.StandaloneContents
}
func (s *systemServerClasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/java/testing.go b/java/testing.go
index c5a0ef390..3989d1987 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -588,7 +588,7 @@ func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant
t.Helper()
module := ctx.ModuleForTests(t, name, variant).Module()
deps := []string{}
- ctx.VisitDirectDeps(module, func(m blueprint.Module) {
+ ctx.VisitDirectDepsProxies(module, func(m android.ModuleProxy) {
deps = append(deps, m.Name())
})
return android.SortedUniqueStrings(deps)
@@ -654,9 +654,9 @@ func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *androi
func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests(t, name, variant).Module().(*platformBootclasspathModule)
- modules := []android.Module{}
- ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) {
- modules = append(modules, m.(android.Module))
+ modules := []android.ModuleProxy{}
+ ctx.VisitDirectDepsProxies(platformBootclasspath, func(m android.ModuleProxy) {
+ modules = append(modules, m)
})
pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex)
@@ -664,7 +664,7 @@ func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestConte
}
// apexNamePairsFromModules returns the apex:module pair for the supplied modules.
-func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string {
+func apexNamePairsFromModules(ctx *android.TestContext, modules []android.ModuleProxy, modulesToApex map[android.ModuleProxy]string) []string {
pairs := []string{}
for _, module := range modules {
pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex))
@@ -673,7 +673,7 @@ func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module
}
// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments.
-func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string {
+func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.ModuleProxy, apexNameToFragment map[string]android.ModuleProxy) []string {
pairs := []string{}
for _, fragment := range fragments {
found := false
@@ -690,7 +690,7 @@ func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.
return pairs
}
-func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string {
+func apexNamePairFromModule(ctx *android.TestContext, module android.ModuleProxy, modulesToApex map[android.ModuleProxy]string) string {
name := module.Name()
apex := modulesToApex[module]
if apex == "" {
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 1225da0f2..1ba4f8889 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -47,6 +47,11 @@ type prebuiltKernelModulesProperties struct {
// List or filegroup of prebuilt kernel module files. Should have .ko suffix.
Srcs []string `android:"path,arch_variant"`
+ // List or filegroup of prebuilt kernel module files for 16k. Should have .ko suffix.
+ // These files will be installed in lib/modules/16k-mode/
+ // These files are ONLY loaded during the Second Boot Stage when the device is in 16k mode.
+ Srcs_16k []string `android:"path,arch_variant"`
+
// List of system_dlkm kernel modules that the local kernel modules depend on.
// The deps will be assembled into intermediates directory for running depmod
// but will not be added to the current module's installed files.
@@ -120,45 +125,76 @@ func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.Module
installDir = installDir.Join(ctx, pkm.KernelVersion())
}
+ dests := []string{}
for _, m := range modules {
- ctx.InstallFile(installDir, filepath.Base(m.String()), m)
+ installPath := ctx.InstallFile(installDir, filepath.Base(m.String()), m)
+ dests = append(dests, installPath.String())
+ }
+ installDir16k := installDir.Join(ctx, "16k-mode")
+ for _, m := range android.PathsForModuleSrc(ctx, pkm.properties.Srcs_16k) {
+ installPath := ctx.InstallFile(installDir16k, filepath.Base(m.String()), m)
+ dests = append(dests, installPath.String())
}
- ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad)
- ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep)
- ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep)
- ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias)
- pkm.installBlocklistFile(ctx, installDir)
- pkm.installOptionsFile(ctx, installDir)
+ srcs := android.PathsForModuleSrc(ctx, pkm.properties.Srcs).Strings()
+ srcs = append(srcs, android.PathsForModuleSrc(ctx, pkm.properties.Srcs_16k).Strings()...)
+ // Use ANDROID-GEN to identify the source of module.* files which are generated in the build process.
+ // See the use of ANDROID-GEN in build/make/core/Makefile
+ androidGen := "ANDROID-GEN"
+ // Add ANDROID-GEN four time to match the number of "modules.*" files installed below.
+ srcs = append(srcs, androidGen, androidGen, androidGen, androidGen)
+ installPath := ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad)
+ dests = append(dests, installPath.String())
+ installPath = ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep)
+ dests = append(dests, installPath.String())
+ installPath = ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep)
+ dests = append(dests, installPath.String())
+ installPath = ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias)
+ dests = append(dests, installPath.String())
+
+ pkm.installBlocklistFile(ctx, installDir, &srcs, &dests)
+ pkm.installOptionsFile(ctx, installDir, &srcs, &dests)
ctx.SetOutputFiles(modules, ".modules")
+
+ android.SetProvider(ctx, android.PrebuiltKernelModulesComplianceMetadataProvider,
+ android.PrebuiltKernelModulesComplianceMetadata{
+ Srcs: srcs,
+ Dests: dests,
+ })
}
-func (pkm *prebuiltKernelModules) installBlocklistFile(ctx android.ModuleContext, installDir android.InstallPath) {
+func (pkm *prebuiltKernelModules) installBlocklistFile(ctx android.ModuleContext, installDir android.InstallPath, srcs *[]string, dests *[]string) {
if pkm.properties.Blocklist_file == nil {
return
}
blocklistOut := android.PathForModuleOut(ctx, "modules.blocklist")
+ src := android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Blocklist_file))
+ *srcs = append(*srcs, src.String())
ctx.Build(pctx, android.BuildParams{
Rule: processBlocklistFile,
- Input: android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Blocklist_file)),
+ Input: src,
Output: blocklistOut,
})
- ctx.InstallFile(installDir, "modules.blocklist", blocklistOut)
+ installPath := ctx.InstallFile(installDir, "modules.blocklist", blocklistOut)
+ *dests = append(*dests, installPath.String())
}
-func (pkm *prebuiltKernelModules) installOptionsFile(ctx android.ModuleContext, installDir android.InstallPath) {
+func (pkm *prebuiltKernelModules) installOptionsFile(ctx android.ModuleContext, installDir android.InstallPath, srcs *[]string, dests *[]string) {
if pkm.properties.Options_file == nil {
return
}
optionsOut := android.PathForModuleOut(ctx, "modules.options")
+ src := android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Options_file))
+ *srcs = append(*srcs, src.String())
ctx.Build(pctx, android.BuildParams{
Rule: processOptionsFile,
- Input: android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Options_file)),
+ Input: src,
Output: optionsOut,
})
- ctx.InstallFile(installDir, "modules.options", optionsOut)
+ installPath := ctx.InstallFile(installDir, "modules.options", optionsOut)
+ *dests = append(*dests, installPath.String())
}
var (
diff --git a/licenses/Android.bp b/licenses/Android.bp
index f420110dd..4a0e5059a 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -31,6 +31,11 @@ license {
license_text: ["LICENSE"],
}
+license {
+ name: "opensourcerequest",
+ license_text: ["opensourcerequest"],
+}
+
license_kind {
name: "BSD-Binary-Only",
conditions: [
@@ -219,6 +224,12 @@ license_kind {
}
license_kind {
+ name: "SPDX-license-identifier-blessing",
+ conditions: ["unencumbered"],
+ url: "https://spdx.org/licenses/blessing.html",
+}
+
+license_kind {
name: "SPDX-license-identifier-BSD",
conditions: ["notice"],
}
diff --git a/licenses/opensourcerequest b/licenses/opensourcerequest
new file mode 100644
index 000000000..af27fcffa
--- /dev/null
+++ b/licenses/opensourcerequest
@@ -0,0 +1 @@
+To obtain the source code for third-party components where the open source license grants you the right to receive the source go to https://source.android.com/opensourcerequest \ No newline at end of file
diff --git a/phony/phony.go b/phony/phony.go
index e75f4c809..5c2273ee1 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -57,7 +57,7 @@ func (p *phony) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
- ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(android.RequiredDepTag, func(dep android.ModuleProxy) {
if o, ok := android.OtherModuleProvider(ctx, dep, android.OutputFilesProvider); ok {
p.outputDeps = append(p.outputDeps, o.DefaultOutputFiles...)
}
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
index c1bc1c75c..ca42ebe38 100644
--- a/provenance/provenance_singleton.go
+++ b/provenance/provenance_singleton.go
@@ -45,10 +45,12 @@ var (
})
)
-type ProvenanceMetadata interface {
- ProvenanceMetaDataFile() android.Path
+type ProvenanceMetadataInfo struct {
+ ProvenanceMetaDataFile android.Path
}
+var ProvenanceMetadataInfoProvider = blueprint.NewProvider[ProvenanceMetadataInfo]()
+
func init() {
RegisterProvenanceSingleton(android.InitRegistrationContext)
}
@@ -69,18 +71,14 @@ type provenanceInfoSingleton struct {
func (p *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
allMetaDataFiles := make([]android.Path, 0)
- moduleFilter := func(module android.Module) bool {
- if !module.Enabled(context) || module.IsSkipInstall() {
- return false
- }
- if p, ok := module.(ProvenanceMetadata); ok {
- return p.ProvenanceMetaDataFile() != nil
+ context.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ commonInfo := android.OtherModulePointerProviderOrDefault(context, module, android.CommonModuleInfoProvider)
+ if !commonInfo.Enabled || commonInfo.SkipInstall {
+ return
}
- return false
- }
- context.VisitAllModulesIf(moduleFilter, func(module android.Module) {
- if p, ok := module.(ProvenanceMetadata); ok {
- allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile())
+
+ if p, ok := android.OtherModuleProvider(context, module, ProvenanceMetadataInfoProvider); ok {
+ allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile)
}
})
p.mergedMetaDataFile = android.PathForOutput(context, "provenance_metadata.textproto")
@@ -102,7 +100,7 @@ func (p *provenanceInfoSingleton) GenerateBuildActions(context android.Singleton
context.DistForGoal("droidcore", p.mergedMetaDataFile)
}
-func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.Path {
+func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) {
onDevicePathOfInstalledFile := android.InstallPathToOnDevicePath(ctx, installedFile)
artifactMetaDataFile := android.PathForIntermediates(ctx, "provenance_metadata", ctx.ModuleDir(), ctx.ModuleName(), "provenance_metadata.textproto")
ctx.Build(pctx, android.BuildParams{
@@ -115,5 +113,7 @@ func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath
"install_path": onDevicePathOfInstalledFile,
}})
- return artifactMetaDataFile
+ android.SetProvider(ctx, ProvenanceMetadataInfoProvider, ProvenanceMetadataInfo{
+ ProvenanceMetaDataFile: artifactMetaDataFile,
+ })
}
diff --git a/python/binary.go b/python/binary.go
index f894299f9..fc38b157a 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -115,6 +115,12 @@ func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleConte
ctx.SetOutputFiles(android.Paths{p.installSource}, "")
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: p.binaryProperties.Test_suites,
+ MainFile: p.installSource,
+ MainFileStem: p.installSource.Base(),
+ })
+
moduleInfoJSON := ctx.ModuleInfoJSON()
moduleInfoJSON.Class = []string{"EXECUTABLES"}
moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, p.androidMkSharedLibs...)
@@ -166,8 +172,11 @@ func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
}
p.androidMkSharedLibs = sharedLibs
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: p.binaryProperties.Test_suites,
+ android.SetProvider(ctx, android.TestSuiteSharedLibsInfoProvider, android.TestSuiteSharedLibsInfo{
+ MakeNames: p.androidMkSharedLibs,
+ })
+ android.SetProvider(ctx, android.MakeNameInfoProvider, android.MakeNameInfo{
+ Name: ctx.ModuleName(),
})
}
diff --git a/python/python.go b/python/python.go
index de21e39bd..7af8d9d18 100644
--- a/python/python.go
+++ b/python/python.go
@@ -108,7 +108,6 @@ type BaseProperties struct {
// list of the Python libraries compatible both with Python2 and Python3.
Libs []string `android:"arch_variant"`
- // TODO: b/403060602 - add unit tests for this property and related code
// list of shared libraries that should be packaged with the python code for this module.
Shared_libs []string `android:"arch_variant"`
@@ -681,7 +680,7 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC
destToPyData[path.dest] = path.src.String()
}
- seen := make(map[android.Module]bool)
+ seen := make(map[android.ModuleProxy]bool)
var result android.Paths
@@ -727,7 +726,7 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC
}
func (p *PythonLibraryModule) collectSharedLibDeps(ctx android.ModuleContext) android.Paths {
- seen := make(map[android.Module]bool)
+ seen := make(map[android.ModuleProxy]bool)
var result android.Paths
diff --git a/python/python_test.go b/python/python_test.go
index 5f971cdd1..696c27ff1 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -23,8 +23,6 @@ import (
"android/soong/android"
"android/soong/cc"
-
- "github.com/google/blueprint"
)
type pyModule struct {
@@ -37,7 +35,7 @@ type pyModule struct {
var (
buildNamePrefix = "soong_python_test"
- moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*": `
+ moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_\-]*": `
pkgPathErrTemplate = moduleVariantErrTemplate +
"pkg_path: %q must be a relative path contained in par file."
badIdentifierErrTemplate = moduleVariantErrTemplate +
@@ -46,9 +44,11 @@ var (
"found two files to be placed at the same location within zip %q." +
" First file: in module %s at path %q." +
" Second file: in module %s at path %q."
- badSrcFileExtErr = moduleVariantErrTemplate + `srcs: found non \(.py\|.proto\) file: %q!`
- badDataFileExtErr = moduleVariantErrTemplate + `data: found \(.py\) file: %q!`
- bpFile = "Android.bp"
+ badSrcFileExtErr = moduleVariantErrTemplate + `srcs: found non \(.py\|.proto\) file: %q!`
+ badDataFileExtErr = moduleVariantErrTemplate + `data: found \(.py\) file: %q!`
+ sharedLibErrTemplate = moduleVariantErrTemplate +
+ "shared_libs: shared_libs is not supported for device builds"
+ bpFile = "Android.bp"
data = []struct {
desc string
@@ -206,6 +206,27 @@ var (
"lib1", "dir/c/file1.py"),
},
},
+ {
+ desc: "device module with shared libs",
+ mockFiles: map[string][]byte{
+ filepath.Join("dir", bpFile): []byte(
+ `python_library {
+ name: "lib1",
+ srcs: [
+ "file1.py",
+ ],
+ shared_libs: [
+ "clib1",
+ ],
+ }`,
+ ),
+ "dir/file1.py": nil,
+ },
+ errors: []string{
+ fmt.Sprintf(sharedLibErrTemplate,
+ "dir/Android.bp:6:18", "lib1"),
+ },
+ },
}
)
@@ -268,7 +289,7 @@ func TestTestOnlyProvider(t *testing.T) {
// marked as test-only are marked as test-only.
actualTestOnly := []string{}
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m android.Module) {
if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
if provider.TestOnly {
actualTestOnly = append(actualTestOnly, m.Name())
@@ -312,6 +333,68 @@ func TestInvalidTestOnlyTargets(t *testing.T) {
}
}
+func TestSharedLib(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ android.PrepareForTestWithDefaults,
+ android.PrepareForTestWithArchMutator,
+ android.PrepareForTestWithAllowMissingDependencies,
+ cc.PrepareForTestWithCcDefaultModules,
+ PrepareForTestWithPythonBuildComponents,
+ ).RunTestWithBp(
+ t,
+ `python_library_host {
+ name: "py-lib-host",
+ srcs: ["py-lib-host.py"],
+ shared_libs: ["clib-host"],
+ }
+
+ cc_library_shared {
+ name: "clib-host",
+ host_supported: true,
+ shared_libs: ["clib-host-2"],
+ }
+
+ cc_library_shared {
+ name: "clib-host-2",
+ host_supported: true,
+ }`,
+ )
+ if len(ctx.Errs) > 0 {
+ t.Errorf("Expected got: %s, want: 0 errs", ctx.Errs)
+ }
+
+ mod, modOk := ctx.ModuleForTests(t, "py-lib-host", ctx.Config.BuildOSTarget.String()).Module().(*PythonLibraryModule)
+ if !modOk {
+ t.Fatalf("py-lib-host is not Python library!")
+ }
+ // ensure the shared lib is included in the data path mappings
+ dataPathMappings := mod.getDataPathMappings()
+ if len(dataPathMappings) != 1 {
+ t.Fatalf("expected 1 data file, got: %d", len(dataPathMappings))
+ }
+ android.AssertStringMatches(
+ t,
+ "data path included shared lib",
+ dataPathMappings[0].dest,
+ "clib-host(.so|.dylib)",
+ )
+ // ensure any dependencies of the shared lib are included in the bundle shared
+ // libs
+ android.AssertStringMatches(
+ t,
+ "shared libs",
+ mod.getBundleSharedLibs()[0].String(),
+ "clib-host-2(.so|.dylib)$",
+ )
+ android.AssertStringMatches(
+ t,
+ "shared libs",
+ mod.getBundleSharedLibs()[1].String(),
+ "libc\\+\\+(.so|.dylib)$",
+ )
+
+}
+
func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles []string) {
module := ctx.ModuleForTests(t, name, variant)
diff --git a/python/scripts/main.py b/python/scripts/main.py
index 35cdfc47e..a3d8f65a2 100644
--- a/python/scripts/main.py
+++ b/python/scripts/main.py
@@ -1,48 +1,52 @@
+# It's important that we use a function here, as any global variables we make in this script will
+# also be available in the real entrypoint run by runpy._run_module_as_main.
+def _soong_main():
+ import os
+ import runpy
+ import shutil
+ import sys
+ import tempfile
+ import zipfile
-import os
-import runpy
-import shutil
-import sys
-import tempfile
-import zipfile
+ from pathlib import PurePath
-from pathlib import PurePath
+ sys.argv[0] = __loader__.archive
+ # Set sys.executable to None. The real executable is available as
+ # sys.argv[0], and too many things assume sys.executable is a regular Python
+ # binary, which isn't available. By setting it to None we get clear errors
+ # when people try to use it.
+ sys.executable = None
-sys.argv[0] = __loader__.archive
-
-# Set sys.executable to None. The real executable is available as
-# sys.argv[0], and too many things assume sys.executable is a regular Python
-# binary, which isn't available. By setting it to None we get clear errors
-# when people try to use it.
-sys.executable = None
-
-# Extract the shared libraries from the zip file into a temporary directory.
-# This works around the limitations of dynamic linker. Some Python libraries
-# reference the .so files relatively and so extracting only the .so files
-# does not work, so we extract the entire parent directory of the .so files to a
-# tempdir and then add that to sys.path.
-tempdir = None
-with zipfile.ZipFile(__loader__.archive) as z:
- # any root so files or root directories that contain so files will be
- # extracted to the tempdir so the linker load them, this minimizes the
- # number of files that need to be extracted to a tempdir
- extract_paths = {}
- for member in z.infolist():
- if member.filename.endswith('.so'):
- extract_paths[PurePath(member.filename).parts[0]] = member.filename
- if extract_paths:
- tempdir = tempfile.mkdtemp()
+ # Extract the shared libraries from the zip file into a temporary directory.
+ # This works around the limitations of dynamic linker. Some Python libraries
+ # reference the .so files relatively and so extracting only the .so files
+ # does not work, so we extract the entire parent directory of the .so files to a
+ # tempdir and then add that to sys.path.
+ tempdir = None
+ with zipfile.ZipFile(__loader__.archive) as z:
+ # any root so files or root directories that contain so files will be
+ # extracted to the tempdir so the linker load them, this minimizes the
+ # number of files that need to be extracted to a tempdir
+ extract_paths = {}
for member in z.infolist():
- if not PurePath(member.filename).parts[0] in extract_paths.keys():
- continue
- if member.is_dir():
- os.makedirs(os.path.join(tempdir, member.filename))
- else:
- z.extract(member, tempdir)
- sys.path.insert(0, tempdir)
-try:
- runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
-finally:
- if tempdir is not None:
- shutil.rmtree(tempdir)
+ if member.filename.endswith('.so'):
+ extract_paths[PurePath(member.filename).parts[0]] = member.filename
+ if extract_paths:
+ tempdir = tempfile.mkdtemp()
+ for member in z.infolist():
+ if not PurePath(member.filename).parts[0] in extract_paths.keys():
+ continue
+ if member.is_dir():
+ os.makedirs(os.path.join(tempdir, member.filename))
+ else:
+ z.extract(member, tempdir)
+ sys.path.insert(0, tempdir)
+ try:
+ runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
+ finally:
+ if tempdir is not None:
+ shutil.rmtree(tempdir)
+
+if __name__ == "__main__":
+ _soong_main()
diff --git a/python/test.go b/python/test.go
index df62ab794..d6670c3c4 100644
--- a/python/test.go
+++ b/python/test.go
@@ -215,25 +215,21 @@ func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext
installedData := ctx.InstallTestData(installDir, p.data)
p.installedDest = ctx.InstallFile(installDir, p.installSource.Base(), p.installSource, installedData...)
- // TODO: Remove the special case for kati
- if !ctx.Config().KatiEnabled() {
- // Install the test config in testcases/ directory for atest.
- // Install configs in the root of $PRODUCT_OUT/testcases/$module
- testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName())
- if ctx.PrimaryArch() {
- if p.testConfig != nil {
- ctx.InstallFile(testCases, ctx.ModuleName()+".config", p.testConfig)
- }
- dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
- if dynamicConfig.Valid() {
- ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
- }
- }
- // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
- testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
- installedData := ctx.InstallTestData(testCases, p.data)
- ctx.InstallFile(testCases, p.installSource.Base(), p.installSource, installedData...)
+ configFileSuffix := ""
+ // ATS 2.0 is the test harness for mobly tests and the test config is for ATS 2.0.
+ // Add "v2" suffix to test config name to distinguish it from the config for TF.
+ if proptools.String(p.testProperties.Test_options.Runner) == "mobly" {
+ configFileSuffix = "v2"
}
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: p.binaryProperties.Test_suites,
+ MainFile: p.installSource,
+ MainFileStem: p.installSource.Base(),
+ ConfigFile: p.testConfig,
+ ConfigFileSuffix: configFileSuffix,
+ Data: p.data,
+ NeedsArchFolder: true,
+ })
moduleInfoJSON := ctx.ModuleInfoJSON()
moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
diff --git a/rust/Android.bp b/rust/Android.bp
index 54ba9d49c..d8f7b9d47 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -27,6 +27,7 @@ bootstrap_go_package {
"fuzz.go",
"image.go",
"library.go",
+ "object.go",
"prebuilt.go",
"proc_macro.go",
"project_json.go",
@@ -38,6 +39,7 @@ bootstrap_go_package {
"test.go",
"testing.go",
"toolchain_library.go",
+ "toolchain_object.go",
],
testSrcs: [
"afdo_test.go",
@@ -51,6 +53,7 @@ bootstrap_go_package {
"fuzz_test.go",
"image_test.go",
"library_test.go",
+ "object_test.go",
"proc_macro_test.go",
"project_json_test.go",
"protobuf_test.go",
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 98946844d..bdd316c02 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -95,6 +95,12 @@ func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.Andr
ret.Class = "EXECUTABLES"
}
+func (object *objectDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
+ ctx.SubAndroidMk(ret, object.baseCompiler)
+
+ ret.Class = "STATIC_LIBRARIES"
+}
+
func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, test.binaryDecorator)
@@ -203,8 +209,5 @@ func (fuzz *fuzzDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidM
ret.ExtraEntries = append(ret.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
- if fuzz.installedSharedDeps != nil {
- entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
- }
})
}
diff --git a/rust/benchmark.go b/rust/benchmark.go
index 3aa2f1779..85aa6a52e 100644
--- a/rust/benchmark.go
+++ b/rust/benchmark.go
@@ -129,6 +129,15 @@ func (benchmark *benchmarkDecorator) install(ctx ModuleContext) {
}
benchmark.binaryDecorator.install(ctx)
+
+ mainFile := ctx.RustModule().OutputFile().Path()
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: benchmark.Properties.Test_suites,
+ MainFile: mainFile,
+ MainFileExt: mainFile.Ext(),
+ ConfigFile: benchmark.testConfig,
+ NeedsArchFolder: true,
+ })
}
func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
@@ -146,8 +155,4 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf
} else {
moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
}
-
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: benchmark.Properties.Test_suites,
- })
}
diff --git a/rust/binary.go b/rust/binary.go
index 5a03d91c2..7ef357910 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -15,6 +15,9 @@
package rust
import (
+ "github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
)
@@ -69,6 +72,24 @@ func NewRustBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator
return module, binary
}
+func (binary *binaryDecorator) begin(ctx BaseModuleContext) {
+ binary.baseCompiler.begin(ctx)
+
+ if ctx.Os().Linux() && ctx.Host() && ctx.toolchain().Musl() {
+ // Unless explicitly specified otherwise, host static binaries are built statically
+ // if HostStaticBinaries is true for the product configuration.
+ // In Rust however this is only supported for musl targets.
+ if binary.Properties.Static_executable == nil && ctx.Config().HostStaticBinaries() {
+ binary.Properties.Static_executable = proptools.BoolPtr(true)
+ }
+ }
+
+ if ctx.Darwin() || ctx.Windows() || (ctx.Os().Linux() && ctx.Host() && ctx.toolchain().Glibc()) {
+ // Static executables are not supported on Darwin, Linux glibc, or Windows
+ binary.Properties.Static_executable = nil
+ }
+}
+
func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseCompiler.compilerFlags(ctx, flags)
@@ -79,11 +100,11 @@ func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Fla
"-Wl,--gc-sections",
"-Wl,-z,nocopyreloc",
"-Wl,--no-undefined-version")
+ }
- if Bool(binary.Properties.Static_executable) {
- flags.LinkFlags = append(flags.LinkFlags, "-static")
- flags.RustFlags = append(flags.RustFlags, "-C relocation-model=static")
- }
+ if Bool(binary.Properties.Static_executable) {
+ flags.LinkFlags = append(flags.LinkFlags, "-static")
+ flags.RustFlags = append(flags.RustFlags, "-C relocation-model=static")
}
return flags
@@ -109,8 +130,10 @@ func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic"}
}
deps.CrtEnd = []string{"libc_musl_crtend"}
+ } else if ctx.Os() == android.Windows {
+ deps.CrtBegin = []string{"rsbegin.rust_sysroot"}
+ deps.CrtEnd = []string{"rsend.rust_sysroot"}
}
-
return deps
}
@@ -132,7 +155,10 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path
fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix()
outputFile := android.PathForModuleOut(ctx, fileName)
ret := buildOutput{outputFile: outputFile}
- crateRootPath := crateRootPath(ctx, binary)
+ crateRootPath := binary.crateRootPath(ctx)
+
+ deps.SrcFiles = append(deps.SrcFiles, crateRootPath)
+ deps.SrcFiles = append(deps.SrcFiles, binary.crateSources(ctx)...)
// Ensure link dirs are not duplicated
deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs)
@@ -140,10 +166,20 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...)
- flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...)
flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...)
+ if ctx.Windows() {
+ for _, lib := range deps.sharedLibObjects {
+ // Windows uses the .lib import library at link-time and at runtime
+ // uses the .dll library, so we need to make sure we're passing the
+ // import library to the linker.
+ flags.LinkFlags = append(flags.LinkFlags, pathtools.ReplaceExtension(lib, "lib"))
+ }
+ } else {
+ flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
+ }
+
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 2f84168bd..873828206 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@ var (
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r530567"
+ bindgenClangVersion = "clang-r547379"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
@@ -300,6 +300,10 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
// it cannot recognize. Turn off unknown warning flags warning.
cflags = append(cflags, "-Wno-unknown-warning-option")
+ // The main file for bindgen usually is header where #pragma once is actually best practice.
+ // Don't pollute the build log with unnecessary warnings.
+ cflags = append(cflags, "-Wno-pragma-once-outside-header")
+
// Suppress warnings while testing a new compiler.
if ctx.Config().IsEnvTrue("LLVM_NEXT") {
cflags = append(cflags, "-Wno-everything")
diff --git a/rust/builder.go b/rust/builder.go
index 1b6a6c117..1c0d31f1d 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -19,31 +19,52 @@ import (
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/depset"
"android/soong/android"
"android/soong/cc"
+ "android/soong/remoteexec"
"android/soong/rust/config"
)
var (
- _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
- rustc = pctx.AndroidStaticRule("rustc",
+ _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
+
+ rustc, rustcRbe = pctx.RemoteStaticRules("rustc",
blueprint.RuleParams{
- Command: "$envVars $rustcCmd " +
- "-C linker=${RustcLinkerCmd} " +
- "-C link-args=\"--android-clang-bin=${config.ClangCmd} ${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
- "--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
+ Command: "$relPwd $reTemplate/usr/bin/env $envVars ${rustcCmd} " +
+ "-C linker=${RustcLinkerCmd} -C link-args=\"--android-clang-bin=${config.ClangCmd} ${linkerScriptFlags}\" " +
+ "-C link-args=@${out}.clang.rsp " +
+ "--emit ${emitType} -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
+ // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
+ // Rustc emits unneeded dependency lines for the .d and input .rs files.
+ // Those extra lines cause ninja warning:
+ // "warning: depfile has multiple output paths"
+ // For ninja, we keep/grep only the dependency rule for the rust $out file.
" && grep ^$out: $out.d.raw > $out.d",
- CommandDeps: []string{"$rustcCmd", "${RustcLinkerCmd}", "${config.ClangCmd}"},
- // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
- // Rustc emits unneeded dependency lines for the .d and input .rs files.
- // Those extra lines cause ninja warning:
- // "warning: depfile has multiple output paths"
- // For ninja, we keep/grep only the dependency rule for the rust $out file.
- Deps: blueprint.DepsGCC,
- Depfile: "$out.d",
+ CommandDeps: []string{"$rustcCmd", "${RustcLinkerCmd}", "${config.ClangCmd}"},
+ Rspfile: "${out}.clang.rsp",
+ RspfileContent: "${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}",
+ Deps: blueprint.DepsGCC,
+ Depfile: "$out.d",
+ }, &remoteexec.REParams{
+ // Until there's a "rust" tool, use clang. This interprets "-L" flags
+ // to help identify potential build dependencies.
+ Labels: map[string]string{"type": "link", "tool": "clang"},
+ Inputs: []string{"${out}.clang.rsp"},
+ RSPFiles: []string{"$rbeRspFile"},
+ OutputFiles: []string{"${out}.d", "${out}.d.raw", "${out}"},
+ ExecStrategy: "${config.RERustExecStrategy}",
+ ToolchainInputs: []string{
+ "${rustcCmd}",
+ "${RustcLinkerCmd}",
+ "${config.ClangCmd}",
+ "${config.LlvmDlltool}",
+ },
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RERustPool}"},
},
- "rustcFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
+ []string{"rustcFlags", "linkerScriptFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "emitType", "envVars"},
+ []string{"rbeRspFile"})
_ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
rustdoc = pctx.AndroidStaticRule("rustdoc",
@@ -84,32 +105,6 @@ var (
RspfileContent: "$in",
},
"outDir")
-
- // Cross-referencing:
- _ = pctx.SourcePathVariable("rustExtractor",
- "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/rust_extractor")
- _ = pctx.VariableFunc("kytheCorpus",
- func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
- _ = pctx.VariableFunc("kytheCuEncoding",
- func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
- _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
- kytheExtract = pctx.AndroidStaticRule("kythe",
- blueprint.RuleParams{
- Command: `KYTHE_CORPUS=${kytheCorpus} ` +
- `KYTHE_OUTPUT_FILE=$out ` +
- `KYTHE_VNAMES=$kytheVnames ` +
- `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
- `KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
- `$rustExtractor $envVars ` +
- `$rustcCmd ` +
- `-C linker=${RustcLinkerCmd} ` +
- `-C link-args="--android-clang-bin=${config.ClangCmd} ${crtBegin} ${linkFlags} ${crtEnd}" ` +
- `$in ${libFlags} $rustcFlags`,
- CommandDeps: []string{"$rustExtractor", "$kytheVnames", "${RustcLinkerCmd}", "${config.ClangCmd}"},
- Rspfile: "${out}.rsp",
- RspfileContent: "$in",
- },
- "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
)
type buildOutput struct {
@@ -120,6 +115,8 @@ type buildOutput struct {
func init() {
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
pctx.HostBinToolVariable("RustcLinkerCmd", "rustc_linker")
+ pctx.StaticVariable("relPwd", cc.PwdPrefix())
+
cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
}
@@ -134,6 +131,7 @@ type transformProperties struct {
cargoOutDir android.OptionalPath
synthetic bool
crateType string
+ emitType string
}
// Populates a standard transformProperties struct for Rust modules
@@ -147,13 +145,15 @@ func getTransformProperties(ctx ModuleContext, crateType string) transformProper
inRecovery: module.InRecovery(),
inRamdisk: module.InRamdisk(),
inVendorRamdisk: module.InVendorRamdisk(),
- cargoOutDir: module.compiler.cargoOutDir(),
+ cargoOutDir: module.compiler.cargoOutDir(ctx),
// crateType indicates what type of crate to build
crateType: crateType,
// synthetic indicates whether this is an actual Rust module or not
synthetic: false,
+
+ emitType: module.compiler.emitType(),
}
}
@@ -166,6 +166,13 @@ func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
}
+func TransformSrcToObject(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+ outputFile android.WritablePath) buildOutput {
+
+ // There's no "obj" crate-type since it doesn't get linked, so don't define one.
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, ""))
+}
+
func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
@@ -199,6 +206,7 @@ func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path,
inRecovery: mod.InRecovery(),
inRamdisk: mod.InRamdisk(),
inVendorRamdisk: mod.InVendorRamdisk(),
+ emitType: "link",
// crateType indicates what type of crate to build
crateType: "staticlib",
@@ -277,14 +285,22 @@ func makeLibFlags(deps PathDeps) []string {
return libFlags
}
-func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
- var envVars []string
+func rustStringifyEnvVars(envVars map[string]string) string {
+ envVarStrings := []string{}
+ for _, key := range android.SortedKeys(envVars) {
+ envVarStrings = append(envVarStrings, key+"="+envVars[key])
+ }
+ return strings.Join(envVarStrings, " ")
+}
+
+func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) map[string]string {
+ envVars := make(map[string]string)
// libstd requires a specific environment variable to be set. This is
// not officially documented and may be removed in the future. See
// https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
if crateName == "std" {
- envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
+ envVars["STD_ENV_ARCH"] = config.StdEnvArch[ctx.Arch().ArchType]
}
if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
@@ -299,41 +315,39 @@ func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, car
// If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
outDirPrefix = ""
}
- envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
+ envVars["OUT_DIR"] = filepath.Join(outDirPrefix, moduleGenDir.String())
} else {
// TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
- envVars = append(envVars, "OUT_DIR=out")
+ envVars["OUT_DIR"] = "out"
}
-
- envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
+ envVars["ANDROID_RUST_VERSION"] = config.GetRustVersion(ctx)
if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
// We only emulate cargo environment variables for 3p code, which is only ever built
// by defining a Rust module, so we only need to set these for true Rust modules.
if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
- envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
+ envVars["CARGO_BIN_NAME"] = bin.getStem(ctx)
}
- envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
- envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
+ envVars["CARGO_CRATE_NAME"] = crateName
+ envVars["CARGO_PKG_NAME"] = crateName
pkgVersion := rustMod.compiler.cargoPkgVersion()
if pkgVersion != "" {
- envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
-
+ envVars["CARGO_PKG_VERSION"] = pkgVersion
// Ensure the version is in the form of "x.y.z" (approximately semver compliant).
//
// For our purposes, we don't care to enforce that these are integers since they may
// include other characters at times (e.g. sometimes the patch version is more than an integer).
if strings.Count(pkgVersion, ".") == 2 {
var semver_parts = strings.Split(pkgVersion, ".")
- envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
- envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
- envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
+ envVars["CARGO_PKG_VERSION_MAJOR"] = semver_parts[0]
+ envVars["CARGO_PKG_VERSION_MINOR"] = semver_parts[1]
+ envVars["CARGO_PKG_VERSION_PATCH"] = semver_parts[2]
}
}
}
if ctx.Darwin() {
- envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
+ envVars["ANDROID_RUST_DARWIN"] = "true"
}
return envVars
@@ -346,7 +360,7 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
var implicits android.Paths
var orderOnly android.Paths
var output buildOutput
- var rustcFlags, linkFlags []string
+ var linkerScriptFlags, rustcFlags, linkFlags []string
var earlyLinkFlags string
output.outputFile = outputFile
@@ -358,7 +372,9 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
// Collect rustc flags
rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
rustcFlags = append(rustcFlags, flags.RustFlags...)
- rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
+ if t.crateType != "" {
+ rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
+ }
if t.crateName != "" {
rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
}
@@ -375,6 +391,8 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
incrementalPath := android.PathForOutput(ctx, "rustc").String()
rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
+ } else if ctx.Config().Eng() {
+ rustcFlags = append(rustcFlags, "-C codegen-units=16")
} else {
rustcFlags = append(rustcFlags, "-C codegen-units=1")
}
@@ -392,6 +410,7 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
linkFlags = append(linkFlags, flags.LinkFlags...)
+ linkerScriptFlags = append(linkerScriptFlags, flags.LinkerScriptFlags...)
// Check if this module needs to use the bootstrap linker
if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
@@ -450,6 +469,21 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
implicits = append(implicits, outputs.Paths()...)
}
}
+ var implicitOutputs android.WritablePaths
+
+ if ctx.Windows() && (t.crateType == "cdylib" || t.crateType == "dylib") {
+ // On windows, an additional .lib file is produced for dynamic linkages.
+ importLibraryPath := android.PathForModuleOut(ctx, outputFile.ReplaceExtension(ctx, "lib").Base())
+ linkFlags = append(linkFlags, "-Wl,--out-implib="+importLibraryPath.String())
+ implicitOutputs = append(implicitOutputs, importLibraryPath)
+
+ // On Windows, we always generate a PDB file
+ // --strip-debug is needed to also keep COFF symbols which are needed when
+ // we patch binaries with symbol_inject.
+ pdb := outputFile.ReplaceExtension(ctx, "pdb")
+ linkFlags = append(linkFlags, " -Wl,--strip-debug -Wl,--pdb="+pdb.String()+" ")
+ implicitOutputs = append(implicitOutputs, pdb)
+ }
if !t.synthetic {
// Only worry about clippy for actual Rust modules.
@@ -468,7 +502,7 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"clippyFlags": strings.Join(flags.ClippyFlags, " "),
- "envVars": strings.Join(envVars, " "),
+ "envVars": rustStringifyEnvVars(envVars),
},
})
// Declare the clippy build as an implicit dependency of the original crate.
@@ -476,47 +510,52 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
}
}
+ rule := rustc
+ args := map[string]string{
+ "rustcFlags": strings.Join(rustcFlags, " "),
+ "linkerScriptFlags": strings.Join(linkerScriptFlags, " "),
+ "earlyLinkFlags": earlyLinkFlags,
+ "linkFlags": strings.Join(linkFlags, " "),
+ "libFlags": strings.Join(libFlags, " "),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
+ "envVars": rustStringifyEnvVars(envVars),
+ "emitType": t.emitType,
+ }
+
+ // If SrcFiles populating is ever tied to some other property being set
+ // (e.g. crate_root), a check against whether its populated should be added here.
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_RUST") {
+ rule = rustcRbe
+ rbeInputs := android.Paths{}
+ rbeInputs = append(rbeInputs, implicits...)
+ rbeInputs = append(rbeInputs, deps.SrcDeps...)
+ rbeInputs = append(rbeInputs, deps.srcProviderFiles...)
+ rbeInputs = append(rbeInputs, main)
+ rbeInputs = append(rbeInputs, depset.New(depset.PREORDER, deps.directApexImplementationDeps, deps.transitiveApexImplementationDeps).ToList()...)
+ rbeInputs = append(rbeInputs, depset.New(depset.PREORDER, deps.directNonApexImplementationDeps, deps.transitiveNonApexImplementationDeps).ToList()...)
+ rbeInputs = append(rbeInputs, deps.SrcFiles...)
+ rbeInputs = android.FirstUniquePaths(rbeInputs)
+
+ // Produce an rsp file for RBE as the inputs list can easily grow too large.
+ rbeRustRspFile := android.PathForModuleOut(ctx, "", outputFile.Base()+".rbe.rsp")
+ android.WriteFileRule(ctx, rbeRustRspFile, strings.Join(rbeInputs.Strings(), "\n"))
+ implicits = append(implicits, rbeRustRspFile)
+
+ args["rbeRspFile"] = rbeRustRspFile.String()
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: rustc,
- Description: "rustc " + main.Rel(),
- Output: outputFile,
- Inputs: inputs,
- Implicits: implicits,
- OrderOnly: orderOnly,
- Args: map[string]string{
- "rustcFlags": strings.Join(rustcFlags, " "),
- "earlyLinkFlags": earlyLinkFlags,
- "linkFlags": strings.Join(linkFlags, " "),
- "libFlags": strings.Join(libFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
- "envVars": strings.Join(envVars, " "),
- },
+ Rule: rule,
+ Description: "rustc " + main.Rel(),
+ Output: outputFile,
+ Inputs: inputs,
+ Implicits: implicits,
+ ImplicitOutputs: implicitOutputs,
+ OrderOnly: orderOnly,
+ Args: args,
})
- if !t.synthetic {
- // Only emit xrefs for true Rust modules.
- if flags.EmitXrefs {
- kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
- ctx.Build(pctx, android.BuildParams{
- Rule: kytheExtract,
- Description: "Xref Rust extractor " + main.Rel(),
- Output: kytheFile,
- Inputs: inputs,
- Implicits: implicits,
- OrderOnly: orderOnly,
- Args: map[string]string{
- "rustcFlags": strings.Join(rustcFlags, " "),
- "linkFlags": strings.Join(linkFlags, " "),
- "libFlags": strings.Join(libFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
- "envVars": strings.Join(envVars, " "),
- },
- })
- output.kytheFile = kytheFile
- }
- }
return output
}
@@ -559,16 +598,22 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
// https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
docDir := android.PathForOutput(ctx, "rustdoc")
+ var implicits android.Paths
+ implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
+ implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
+ implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
+ envVars := rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir(ctx))
ctx.Build(pctx, android.BuildParams{
Rule: rustdoc,
Description: "rustdoc " + main.Rel(),
Output: docTimestampFile,
Input: main,
Implicit: ctx.RustModule().UnstrippedOutputFile(),
+ Implicits: implicits,
Args: map[string]string{
"rustdocFlags": strings.Join(rustdocFlags, " "),
"outDir": docDir.String(),
- "envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
+ "envVars": rustStringifyEnvVars(envVars),
},
})
diff --git a/rust/builder_test.go b/rust/builder_test.go
index 7d6b56ac9..95d17b23e 100644
--- a/rust/builder_test.go
+++ b/rust/builder_test.go
@@ -87,6 +87,8 @@ func TestCompilationOutputFiles(t *testing.T) {
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/unstripped/libfizz_buzz.dylib.so",
"out/target/product/test_device/system/lib64/libfizz_buzz.dylib.so",
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/meta_lic",
+ "out/target/product/test_device/obj/PACKAGING/elf_symbol_mapping_intermediates/system/lib64/libfizz_buzz.dylib.so.textproto",
+ "out/target/product/test_device/symbols/system/lib64/libfizz_buzz.dylib.so",
},
},
{
@@ -120,6 +122,8 @@ func TestCompilationOutputFiles(t *testing.T) {
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/unstripped/fizz_buzz",
"out/target/product/test_device/system/bin/fizz_buzz",
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/meta_lic",
+ "out/target/product/test_device/obj/PACKAGING/elf_symbol_mapping_intermediates/system/bin/fizz_buzz.textproto",
+ "out/target/product/test_device/symbols/system/bin/fizz_buzz",
},
},
{
@@ -155,6 +159,8 @@ func TestCompilationOutputFiles(t *testing.T) {
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/meta_lic",
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/rustdoc.timestamp",
"out/target/product/test_device/system/lib64/librust_ffi.so",
+ "out/target/product/test_device/obj/PACKAGING/elf_symbol_mapping_intermediates/system/lib64/librust_ffi.so.textproto",
+ "out/target/product/test_device/symbols/system/lib64/librust_ffi.so",
},
},
}
diff --git a/rust/compiler.go b/rust/compiler.go
index c3bc937da..dd1f6fc63 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -15,12 +15,12 @@
package rust
import (
- "android/soong/cc"
- "errors"
"fmt"
"path/filepath"
"strings"
+ "android/soong/cc"
+
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -35,23 +35,23 @@ const (
)
type compiler interface {
- initialize(ctx ModuleContext)
compilerFlags(ctx ModuleContext, flags Flags) Flags
cfgFlags(ctx ModuleContext, flags Flags) Flags
- featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags
+ featureFlags(ctx ModuleContext, flags Flags) Flags
baseCompilerProps() BaseCompilerProperties
compilerProps() []interface{}
compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
compilerDeps(ctx DepsContext, deps Deps) Deps
crateName() string
edition() string
- features(ctx android.ConfigurableEvaluatorContext, module *Module) []string
+ features(ctx ModuleContext) []string
rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
Thinlto() bool
+ begin(ctx BaseModuleContext)
// Output directory in which source-generated code from dependencies is
// copied. This is equivalent to Cargo's OUT_DIR variable.
- cargoOutDir() android.OptionalPath
+ cargoOutDir(ctx ModuleContext) android.OptionalPath
// cargoPkgVersion returns the value of the Cargo_pkg_version property.
cargoPkgVersion() string
@@ -75,11 +75,14 @@ type compiler interface {
unstrippedOutputFilePath() android.Path
strippedOutputFilePath() android.OptionalPath
- checkedCrateRootPath() (android.Path, error)
+ crateRootPath(ctx ModuleContext) android.Path
+ crateSources(ctx ModuleContext) android.Paths
Aliases() map[string]string
moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
+
+ emitType() string
}
func (compiler *baseCompiler) edition() string {
@@ -108,9 +111,9 @@ type installLocation int
const (
InstallInSystem installLocation = 0
InstallInData = iota
+ NoInstall = iota
- incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
- genSubDir = "out/"
+ genSubDir = "out/"
)
type BaseCompilerProperties struct {
@@ -243,6 +246,12 @@ type BaseCompilerProperties struct {
// be enabled for production builds unless there's a clear need to disable it.
Thin *bool `android:"arch_variant"`
} `android:"arch_variant"`
+
+ // Set this to true to use an expansive default set of source file requirements
+ // (all .rs, .h, .xml, and .md files in the module tree).
+ // This is primarily for tracking sources for RBE purposes. Currently defaults
+ // to true, though this may change in the future.
+ Use_expansive_default_srcs *bool
}
type baseCompiler struct {
@@ -264,21 +273,10 @@ type baseCompiler struct {
// stripped output file.
strippedOutputFile android.OptionalPath
-
- // If a crate has a source-generated dependency, a copy of the source file
- // will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
- // This is stored internally because it may not be available during
- // singleton-generation passes like rustdoc/rust_project.json, but should
- // be stashed during initial generation.
- cachedCargoOutDir android.ModuleOutPath
- // Calculated crate root cached internally because ModuleContext is not
- // available to singleton targets like rustdoc/rust_project.json
- cachedCrateRootPath android.Path
- // If cachedCrateRootPath is nil after initialization, this will contain
- // an explanation of why
- cachedCrateRootError error
}
+func (compiler *baseCompiler) begin(ctx BaseModuleContext) {}
+
func (compiler *baseCompiler) Disabled() bool {
return false
}
@@ -353,6 +351,7 @@ func (compiler *baseCompiler) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *
}
var _ compiler = (*baseCompiler)(nil)
+var _ autoDeppable = (*baseCompiler)(nil)
func (compiler *baseCompiler) inData() bool {
return compiler.location == InstallInData
@@ -375,23 +374,22 @@ func cfgsToFlags(cfgs []string) []string {
return flags
}
-func (compiler *baseCompiler) features(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
- eval := module.ConfigurableEvaluator(ctx)
- return compiler.Properties.Features.GetOrDefault(eval, nil)
+func (compiler *baseCompiler) features(ctx ModuleContext) []string {
+ return compiler.Properties.Features.GetOrDefault(ctx, nil)
}
-func (compiler *baseCompiler) featuresToFlags(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
+func (compiler *baseCompiler) featuresToFlags(ctx ModuleContext) []string {
flags := []string{}
- for _, feature := range compiler.features(ctx, module) {
+ for _, feature := range compiler.features(ctx) {
flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
}
return flags
}
-func (compiler *baseCompiler) featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags {
- flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(ctx, module)...)
- flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags(ctx, module)...)
+func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags {
+ flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(ctx)...)
+ flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags(ctx)...)
return flags
}
@@ -435,6 +433,7 @@ func CommonDefaultFlags(ctx android.ModuleContext, toolchain config.Toolchain, f
if ctx.Os() == android.Linux {
// Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match
// the default behavior of device builds.
+ flags.RustFlags = append(flags.RustFlags, config.LinuxHostGlobalRustFlags...)
flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...)
} else if ctx.Os() == android.Darwin {
// Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default
@@ -494,18 +493,8 @@ func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags,
return android.OptionalPath{}
}
-func (compiler *baseCompiler) initialize(ctx ModuleContext) {
- compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir)
- if compiler.Properties.Crate_root == nil {
- compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs)
- } else {
- compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root)
- compiler.cachedCrateRootError = nil
- }
-}
-
-func (compiler *baseCompiler) cargoOutDir() android.OptionalPath {
- return android.OptionalPathForPath(compiler.cachedCargoOutDir)
+func (compiler *baseCompiler) cargoOutDir(ctx ModuleContext) android.OptionalPath {
+ return android.OptionalPathForPath(android.PathForModuleOut(ctx, genSubDir))
}
func (compiler *baseCompiler) cargoEnvCompat() bool {
@@ -543,6 +532,13 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps.Stdlibs = append(deps.Stdlibs, stdlib)
}
}
+
+ if ctx.Windows() {
+ if ctx.ModuleName() != "libwinpthread" {
+ deps.StaticLibs = append(deps.StaticLibs, "libwinpthread")
+ }
+ }
+
return deps
}
@@ -647,20 +643,40 @@ func (compiler *baseCompiler) relativeInstallPath() string {
return String(compiler.Properties.Relative_install_path)
}
-func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) {
- return compiler.cachedCrateRootPath, compiler.cachedCrateRootError
+func (compiler *baseCompiler) crateRootPath(ctx ModuleContext) android.Path {
+ if compiler.Properties.Crate_root == nil {
+ return srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs)
+ } else {
+ return android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root)
+ }
}
-func crateRootPath(ctx ModuleContext, compiler compiler) android.Path {
- root, err := compiler.checkedCrateRootPath()
- if err != nil {
- ctx.PropertyErrorf("srcs", err.Error())
+func (compiler *baseCompiler) crateSources(ctx ModuleContext) android.Paths {
+ crateSources := android.PathsForModuleSrc(ctx, compiler.Properties.Srcs)
+
+ // By default use an expansive set of required sources.
+ // Check for UseRBE here since this isn't necessary for local builds and can
+ // break some tests as the MockFS doesn't support globbing in all instances.
+ if BoolDefault(compiler.Properties.Use_expansive_default_srcs, true) && ctx.Config().IsEnvTrue("RBE_RUST") {
+ crateSources = append(crateSources, android.PathsForModuleSrc(ctx,
+ []string{
+ "*.md",
+ "**/*.md",
+ "*.rs",
+ "**/*.rs",
+ "*.proto",
+ "**/*.proto",
+ "*.xml",
+ "**/*.xml",
+ "*.h",
+ "**/*.h"})...)
}
- return root
+
+ return crateSources
}
// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
-func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) {
+func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path {
// The srcs can contain strings with prefix ":".
// They are dependent modules of this module, with android.SourceDepTag.
// They are not the main source file compiled by rustc.
@@ -673,22 +689,35 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, erro
}
}
if numSrcs > 1 {
- return nil, errors.New(incorrectSourcesError)
+ ctx.PropertyErrorf("srcs", "srcs can only contain one path for a rust file and source providers prefixed by \":\"")
+ return nil
}
// If a main source file is not provided we expect only a single SourceProvider module to be defined
// within srcs, with the expectation that the first source it provides is the entry point.
if srcIndex != 0 {
- return nil, errors.New("main source file must be the first in srcs")
+ ctx.PropertyErrorf("srcs", "main source file must be the first in srcs")
+ return nil
} else if numSrcs > 1 {
- return nil, errors.New("only a single generated source module can be defined without a main source file.")
+ ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.")
+ return nil
}
// TODO: b/297264540 - once all modules are sandboxed, we need to select the proper
// entry point file from Srcs rather than taking the first one
paths := android.PathsForModuleSrc(ctx, srcs)
if len(paths) == 0 {
- return nil, errors.New("srcs must not be empty")
+ ctx.PropertyErrorf("srcs", "srcs must not be empty")
+ return nil
}
- return paths[srcIndex], nil
+ return paths[srcIndex]
+}
+
+// Returns an emit type corresponding to the `--emit=` rustc flag.
+func (compiler *baseCompiler) emitType() string {
+ return "link"
+}
+
+func (compiler *baseCompiler) autoDep(ctx android.BottomUpMutatorContext) autoDep {
+ panic("baseCompiler does not implement autoDep()")
}
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 8805d15eb..381c03909 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -24,7 +24,7 @@ import (
// Test that feature flags are being correctly generated.
func TestFeaturesToFlags(t *testing.T) {
ctx := testRust(t, `
- rust_library_host_dylib {
+ rust_library_dylib {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -34,7 +34,7 @@ func TestFeaturesToFlags(t *testing.T) {
],
}`)
- libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") ||
!strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") {
@@ -45,7 +45,7 @@ func TestFeaturesToFlags(t *testing.T) {
// Test that cfgs flags are being correctly generated.
func TestCfgsToFlags(t *testing.T) {
ctx := testRust(t, `
- rust_library_host {
+ rust_library {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -55,7 +55,7 @@ func TestCfgsToFlags(t *testing.T) {
],
}`)
- libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") ||
!strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") {
@@ -65,7 +65,7 @@ func TestCfgsToFlags(t *testing.T) {
func TestLtoFlag(t *testing.T) {
ctx := testRust(t, `
- rust_library_host {
+ rust_library {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -74,15 +74,15 @@ func TestLtoFlag(t *testing.T) {
}
}
- rust_library_host {
+ rust_library {
name: "libfoo_lto",
srcs: ["foo.rs"],
crate_name: "foo",
}
`)
- libfoo := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
- libfooLto := ctx.ModuleForTests(t, "libfoo_lto", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Rule("rustc")
+ libfooLto := ctx.ModuleForTests(t, "libfoo_lto", "android_arm64_armv8-a_dylib").Rule("rustc")
if strings.Contains(libfoo.Args["rustcFlags"], "-C lto=thin") {
t.Fatalf("libfoo expected to disable lto -- rustcFlags: %#v", libfoo.Args["rustcFlags"])
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 25f7580d0..f527f6785 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -8,6 +8,7 @@ bootstrap_go_package {
deps: [
"soong-android",
"soong-cc-config",
+ "soong-remoteexec",
],
srcs: [
"arm_device.go",
@@ -22,6 +23,7 @@ bootstrap_go_package {
"x86_linux_host.go",
"x86_device.go",
"x86_64_device.go",
+ "x86_windows_host.go",
"arm64_linux_host.go",
],
visibility: [
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 7875eea55..ba7458e94 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -18,42 +18,78 @@ import (
"strings"
"android/soong/android"
-
- cc_config "android/soong/cc/config"
)
var (
Arm64RustFlags = []string{
"-C force-frame-pointers=y",
}
- Arm64ArchFeatureRustFlags = map[string][]string{}
- Arm64LinkFlags = []string{}
+ Arm64ArchFeatureRustFlags = map[string][]string{
+ // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
+ "branchprot": {
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
+ }
+ Arm64LinkFlags = []string{}
+
+ // We could simply pass "-C target-feature=+v8.2a" and similar, but "v8.2a" and the other
+ // architecture version target-features are marked unstable and spam warnings in the build log,
+ // even though they're just aliases for groups of other features, most of which are stable.
+ // As a workaround, we'll simply look at this file and enable the constituent features:
+ // https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_target/target_features.rs.html
+
+ // Mandatory extensions from ARMv8.1-A and ARMv8.2-A
+ armv82aFeatures = "-C target-feature=+crc,+lse,+rdm,+pan,+lor,+vh,+ras,+dpb"
+ // Mandatory extensions from ARMv8.3-A, ARMv8.4-A and ARMv8.5-A
+ armv85aFeatures = "-C target-feature=+rcpc,+paca,+pacg,+jsconv,+dotprod,+dit,+flagm,+ssbs,+sb,+dpb2,+bti"
+ // Mandatory extensions from ARMv8.6-A and ARMv8.7-A
+ // "wfxt" is marked unstable, so we don't include it yet.
+ armv87aFeatures = "-C target-feature=+bf16,+i8mm"
Arm64ArchVariantRustFlags = map[string][]string{
- "armv8-a": []string{},
- "armv8-a-branchprot": []string{
- // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
- "-Z branch-protection=bti,pac-ret",
+ "armv8-a": {},
+ "armv8-a-branchprot": {},
+ "armv8-2a": {
+ armv82aFeatures,
+ },
+ "armv8-2a-dotprod": {
+ armv82aFeatures,
+ "-C target-feature=+dotprod",
+ },
+ "armv8-5a": {
+ armv82aFeatures,
+ armv85aFeatures,
+ },
+ "armv8-7a": {
+ armv82aFeatures,
+ armv85aFeatures,
+ armv87aFeatures,
},
- "armv8-2a": []string{},
- "armv8-2a-dotprod": []string{},
- // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
- "armv9-a": []string{
- "-Z branch-protection=bti,pac-ret",
- "-Z stack-protector=none",
+ // All of the Armv9 entries below should have "-C target-feature=+sve2",
+ // but a large subset of Rust code runs in VMs that are incompatible with SVE.
+ // TODO: b/409859765 - apply a solution similar to cc_baremetal_defaults.
+ "armv9-a": {
+ armv82aFeatures,
+ armv85aFeatures,
},
- "armv9-2a": []string{
- "-Z branch-protection=bti,pac-ret",
- "-Z stack-protector=none",
+ "armv9-2a": {
+ armv82aFeatures,
+ armv85aFeatures,
+ armv87aFeatures,
},
- "armv9-3a": []string{
- "-Z branch-protection=bti,pac-ret",
- "-Z stack-protector=none",
+ // ARMv9.3-A adds +hbc,+mops but they're both unstable
+ "armv9-3a": {
+ armv82aFeatures,
+ armv85aFeatures,
+ armv87aFeatures,
},
- "armv9-4a": []string{
- "-Z branch-protection=bti,pac-ret",
- "-Z stack-protector=none",
+ // ARMv9.4-A adds +cssc but it's unstable
+ "armv9-4a": {
+ armv82aFeatures,
+ armv85aFeatures,
+ armv87aFeatures,
},
}
)
@@ -65,8 +101,12 @@ func init() {
pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " "))
for variant, rustFlags := range Arm64ArchVariantRustFlags {
- pctx.StaticVariable("Arm64"+variant+"VariantRustFlags",
- strings.Join(rustFlags, " "))
+ pctx.VariableFunc("Arm64"+variant+"VariantRustFlags", func(ctx android.PackageVarContext) string {
+ if ctx.Config().ReleaseRustUseArmTargetArchVariant() {
+ return strings.Join(rustFlags, " ")
+ }
+ return ""
+ })
}
pctx.StaticVariable("DEVICE_ARM64_RUSTC_FLAGS", strings.Join(Arm64RustFlags, " "))
@@ -75,7 +115,6 @@ func init() {
type toolchainArm64 struct {
toolchain64Bit
toolchainRustFlags string
- lldflags string
}
func (t *toolchainArm64) RustTriple() string {
@@ -84,7 +123,7 @@ func (t *toolchainArm64) RustTriple() string {
func (t *toolchainArm64) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${config.DeviceGlobalLinkFlags} " + t.lldflags + " ${config.Arm64ToolchainLinkFlags}"
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.Arm64Ldflags} ${config.Arm64ToolchainLinkFlags}"
}
func (t *toolchainArm64) ToolchainRustFlags() string {
@@ -122,10 +161,7 @@ func Arm64ToolchainFactory(arch android.Arch) Toolchain {
toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...)
}
- cc_toolchain := cc_config.FindToolchain(android.Android, arch)
-
return &toolchainArm64{
toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
- lldflags: strings.ReplaceAll(cc_toolchain.Lldflags(), "${config.", "${cc_config."),
}
}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
index 4446587a2..ce6fb7f34 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -18,8 +18,6 @@ import (
"strings"
"android/soong/android"
-
- cc_config "android/soong/cc/config"
)
var (
@@ -52,7 +50,6 @@ func init() {
type toolchainArm struct {
toolchain32Bit
toolchainRustFlags string
- lldflags string
}
func (t *toolchainArm) RustTriple() string {
@@ -61,7 +58,7 @@ func (t *toolchainArm) RustTriple() string {
func (t *toolchainArm) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${config.DeviceGlobalLinkFlags} " + t.lldflags + " ${config.ArmToolchainLinkFlags}"
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.ArmLdflags} ${config.ArmToolchainLinkFlags}"
}
func (t *toolchainArm) ToolchainRustFlags() string {
@@ -92,10 +89,7 @@ func ArmToolchainFactory(arch android.Arch) Toolchain {
toolchainRustFlags = append(toolchainRustFlags, ArmArchFeatureRustFlags[feature]...)
}
- cc_toolchain := cc_config.FindToolchain(android.Android, arch)
-
return &toolchainArm{
toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
- lldflags: strings.ReplaceAll(cc_toolchain.Lldflags(), "${config.", "${cc_config."),
}
}
diff --git a/rust/config/arm_linux_host.go b/rust/config/arm_linux_host.go
index 22bdaee3e..6e7593204 100644
--- a/rust/config/arm_linux_host.go
+++ b/rust/config/arm_linux_host.go
@@ -56,7 +56,7 @@ func (t *toolchainLinuxArm64) Name() string {
func (t *toolchainLinuxArm64) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.LinuxLldflags} ${cc_config.LinuxArm64Lldflags} " +
+ return "${cc_config.LinuxLdflags} ${cc_config.LinuxArm64Ldflags} " +
"${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainArm64LinkFlags}"
}
@@ -113,7 +113,7 @@ func (toolchainLinuxArm64) LibclangRuntimeLibraryArch() string {
func (t *toolchainLinuxArm) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.LinuxLldflags} ${cc_config.LinuxArmLldflags} " +
+ return "${cc_config.LinuxLdflags} ${cc_config.LinuxArmLdflags} " +
"${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainArmLinkFlags}"
}
diff --git a/rust/config/darwin_host.go b/rust/config/darwin_host.go
index df8c6ac5a..986621053 100644
--- a/rust/config/darwin_host.go
+++ b/rust/config/darwin_host.go
@@ -104,7 +104,7 @@ func (t *toolchainDarwin) ProcMacroSuffix() string {
func (t *toolchainDarwinArm64) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainArm64LinkFlags}"
+ return "${cc_config.DarwinLdflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainArm64LinkFlags}"
}
func (t *toolchainDarwinArm64) ToolchainRustFlags() string {
@@ -113,7 +113,7 @@ func (t *toolchainDarwinArm64) ToolchainRustFlags() string {
func (t *toolchainDarwinX8664) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}"
+ return "${cc_config.DarwinLdflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}"
}
func (t *toolchainDarwinX8664) ToolchainRustFlags() string {
diff --git a/rust/config/global.go b/rust/config/global.go
index 907316fab..93667ab6a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -20,12 +20,13 @@ import (
"android/soong/android"
_ "android/soong/cc/config"
+ "android/soong/remoteexec"
)
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- RustDefaultVersion = "1.83.0"
+ RustDefaultVersion = "1.84.1"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -48,7 +49,6 @@ var (
"-Z remap-cwd-prefix=.",
"-C debuginfo=2",
"-C opt-level=3",
- "-C relocation-model=pic",
"-C overflow-checks=on",
"-C force-unwind-tables=yes",
// Use v0 mangling to distinguish from C++ symbols
@@ -60,7 +60,9 @@ var (
// cfg flag to indicate that we are building in AOSP with Soong
"--cfg soong",
}
-
+ LinuxHostGlobalRustFlags = []string{
+ "-C relocation-model=pic",
+ }
LinuxHostGlobalLinkFlags = []string{
"-lc",
"-lrt",
@@ -77,11 +79,12 @@ var (
"-Z debug-info-for-profiling",
// Android has ELF TLS on platform
"-Z tls-model=global-dynamic",
+ "-C relocation-model=pic",
}
deviceGlobalLinkFlags = []string{
// Prepend the lld flags from cc_config so we stay in sync with cc
- "${cc_config.DeviceGlobalLldflags}",
+ "${cc_config.DeviceGlobalLdflags}",
// Override cc's --no-undefined-version to allow rustc's generated alloc functions
"-Wl,--undefined-version",
@@ -124,20 +127,40 @@ func init() {
pctx.ImportAs("cc_config", "android/soong/cc/config")
pctx.StaticVariable("ClangCmd", "${cc_config.ClangBin}/clang++")
+ pctx.StaticVariable("LlvmDlltool", "${cc_config.ClangBin}/llvm-dlltool")
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
pctx.StaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
pctx.StaticVariable("GLOBAL_RUSTC_FLAGS", strings.Join(GlobalRustFlags, " "))
pctx.StaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", strings.Join(LinuxHostGlobalLinkFlags, " "))
+ pctx.StaticVariable("LINUX_HOST_GLOBAL_RUST_FLAGS", strings.Join(LinuxHostGlobalRustFlags, " "))
pctx.StaticVariable("DEVICE_GLOBAL_RUSTC_FLAGS", strings.Join(deviceGlobalRustFlags, " "))
pctx.StaticVariable("DEVICE_GLOBAL_LINK_FLAGS",
strings.Join(android.RemoveListFromList(deviceGlobalLinkFlags, []string{
// The cc_config flags are retrieved from cc_toolchain by rust rules.
- "${cc_config.DeviceGlobalLldflags}",
+ "${cc_config.DeviceGlobalLdflags}",
"-B${cc_config.ClangBin}",
}), " "))
+
+ pctx.VariableFunc("RERustPool", func(ctx android.PackageVarContext) string {
+ var defaultPool, overrideEnv string
+ if ctx.Config().Eng() {
+ // eng uses codegen-units=16, which can take advantage of the larger java16 machines.
+ defaultPool = "java16"
+ overrideEnv = "RBE_RUST_ENG_POOL"
+ } else {
+ defaultPool = "default"
+ overrideEnv = "RBE_RUST_POOL"
+ }
+ if override := ctx.Config().Getenv(overrideEnv); override != "" {
+ return override
+ }
+ return defaultPool
+ })
+ pctx.StaticVariableWithEnvOverride("RERustExecStrategy", "RBE_RUST_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+
}
func HostPrebuiltTag(config android.Config) string {
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
index 295cac5d9..a8a0990ae 100644
--- a/rust/config/riscv64_device.go
+++ b/rust/config/riscv64_device.go
@@ -18,8 +18,6 @@ import (
"strings"
"android/soong/android"
-
- cc_config "android/soong/cc/config"
)
var (
@@ -52,7 +50,6 @@ func init() {
type toolchainRiscv64 struct {
toolchain64Bit
toolchainRustFlags string
- lldflags string
}
func (t *toolchainRiscv64) RustTriple() string {
@@ -61,7 +58,7 @@ func (t *toolchainRiscv64) RustTriple() string {
func (t *toolchainRiscv64) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${config.DeviceGlobalLinkFlags} " + t.lldflags + " ${config.Riscv64ToolchainLinkFlags}"
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.Riscv64Ldflags} ${config.Riscv64ToolchainLinkFlags}"
}
func (t *toolchainRiscv64) ToolchainRustFlags() string {
@@ -94,10 +91,7 @@ func Riscv64ToolchainFactory(arch android.Arch) Toolchain {
toolchainRustFlags = append(toolchainRustFlags, Riscv64ArchFeatureRustFlags[feature]...)
}
- cc_toolchain := cc_config.FindToolchain(android.Android, arch)
-
return &toolchainRiscv64{
toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
- lldflags: strings.ReplaceAll(cc_toolchain.Lldflags(), "${config.", "${cc_config."),
}
}
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index 9c9d5724a..3b3923008 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -34,6 +34,8 @@ type Toolchain interface {
Supported() bool
Bionic() bool
+ Musl() bool
+ Glibc() bool
LibclangRuntimeLibraryArch() string
}
@@ -61,6 +63,14 @@ func (toolchainBase) Bionic() bool {
return true
}
+func (toolchainBase) Musl() bool {
+ return false
+}
+
+func (toolchainBase) Glibc() bool {
+ return false
+}
+
type toolchain64Bit struct {
toolchainBase
}
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index eae325718..457908005 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -18,8 +18,6 @@ import (
"strings"
"android/soong/android"
-
- cc_config "android/soong/cc/config"
)
var (
@@ -63,7 +61,6 @@ func init() {
type toolchainX86_64 struct {
toolchain64Bit
toolchainRustFlags string
- lldflags string
}
func (t *toolchainX86_64) RustTriple() string {
@@ -72,7 +69,7 @@ func (t *toolchainX86_64) RustTriple() string {
func (t *toolchainX86_64) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${config.DeviceGlobalLinkFlags} " + t.lldflags + " ${config.X86_64ToolchainLinkFlags}"
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.X86_64Ldflags} ${config.X86_64ToolchainLinkFlags}"
}
func (t *toolchainX86_64) ToolchainRustFlags() string {
@@ -103,10 +100,7 @@ func x86_64ToolchainFactory(arch android.Arch) Toolchain {
toolchainRustFlags = append(toolchainRustFlags, x86_64ArchFeatureRustFlags[feature]...)
}
- cc_toolchain := cc_config.FindToolchain(android.Android, arch)
-
return &toolchainX86_64{
toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
- lldflags: strings.ReplaceAll(cc_toolchain.Lldflags(), "${config.", "${cc_config."),
}
}
diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go
index 9820603e3..9d3382bde 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -18,8 +18,6 @@ import (
"strings"
"android/soong/android"
-
- cc_config "android/soong/cc/config"
)
var (
@@ -65,7 +63,6 @@ func init() {
type toolchainX86 struct {
toolchain32Bit
toolchainRustFlags string
- lldflags string
}
func (t *toolchainX86) RustTriple() string {
@@ -74,7 +71,7 @@ func (t *toolchainX86) RustTriple() string {
func (t *toolchainX86) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${config.DeviceGlobalLinkFlags} " + t.lldflags + " ${config.X86ToolchainLinkFlags}"
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.X86Ldflags} ${config.X86ToolchainLinkFlags}"
}
func (t *toolchainX86) ToolchainRustFlags() string {
@@ -105,10 +102,7 @@ func x86ToolchainFactory(arch android.Arch) Toolchain {
toolchainRustFlags = append(toolchainRustFlags, x86ArchFeatureRustFlags[feature]...)
}
- cc_toolchain := cc_config.FindToolchain(android.Android, arch)
-
return &toolchainX86{
toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
- lldflags: strings.ReplaceAll(cc_toolchain.Lldflags(), "${config.", "${cc_config."),
}
}
diff --git a/rust/config/x86_linux_bionic_host.go b/rust/config/x86_linux_bionic_host.go
index 79c40ce41..495ab20ab 100644
--- a/rust/config/x86_linux_bionic_host.go
+++ b/rust/config/x86_linux_bionic_host.go
@@ -61,7 +61,7 @@ func (t *toolchainLinuxBionicX8664) RustTriple() string {
func (t *toolchainLinuxBionicX8664) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.LinuxBionicLldflags} ${config.LinuxBionicToolchainLinkFlags}"
+ return "${cc_config.LinuxBionicLdflags} ${config.LinuxBionicToolchainLinkFlags}"
}
func (t *toolchainLinuxBionicX8664) ToolchainRustFlags() string {
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index 4d7c42219..f1e7eff0d 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -21,7 +21,13 @@ import (
)
var (
- LinuxRustFlags = []string{}
+ LinuxRustFlags = []string{
+ // These flags are no strictly necessary but included so RBE can discover dependencies.
+ "-L${cc_config.LinuxGccRoot}/${cc_config.LinuxGccTriple}/lib32",
+ "-L${cc_config.LinuxGccRoot}/${cc_config.LinuxGccTriple}/lib64",
+ "-L${cc_config.LinuxGccRoot}/lib/gcc/${cc_config.LinuxGccTriple}/${cc_config.LinuxGccVersion}",
+ "-L${cc_config.LinuxGccRoot}/sysroot/usr/lib",
+ }
LinuxMuslRustFlags = []string{
// disable rustc's builtin fallbacks for crt objects
"-C link_self_contained=no",
@@ -87,7 +93,7 @@ func (t *toolchainLinuxX8664) Name() string {
func (t *toolchainLinuxX8664) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.LinuxLldflags} ${cc_config.LinuxX8664Lldflags} " +
+ return "${cc_config.LinuxLdflags} ${cc_config.LinuxX8664Ldflags} " +
"${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainX8664LinkFlags}"
}
@@ -105,6 +111,10 @@ func (t *toolchainLinuxX8664) RustTriple() string {
return "x86_64-unknown-linux-gnu"
}
+func (t *toolchainLinuxGlibcX8664) Glibc() bool {
+ return true
+}
+
func (t *toolchainLinuxGlibcX8664) ToolchainLinkFlags() string {
return t.toolchainLinuxX8664.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
}
@@ -135,6 +145,10 @@ func linuxMuslX8664ToolchainFactory(arch android.Arch) Toolchain {
return toolchainLinuxMuslX8664Singleton
}
+func (t *toolchainLinuxMuslX8664) Musl() bool {
+ return true
+}
+
// Base 32-bit linux rust toolchain
type toolchainLinuxX86 struct {
toolchain32Bit
@@ -162,7 +176,7 @@ func (toolchainLinuxX8664) LibclangRuntimeLibraryArch() string {
func (t *toolchainLinuxX86) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
- return "${cc_config.LinuxLldflags} ${cc_config.LinuxX86Lldflags} " +
+ return "${cc_config.LinuxLdflags} ${cc_config.LinuxX86Ldflags} " +
"${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainX86LinkFlags}"
}
@@ -180,6 +194,10 @@ func (t *toolchainLinuxGlibcX86) RustTriple() string {
return "i686-unknown-linux-gnu"
}
+func (t *toolchainLinuxGlibcX86) Glibc() bool {
+ return true
+}
+
func (t *toolchainLinuxGlibcX86) ToolchainLinkFlags() string {
return t.toolchainLinuxX86.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
}
@@ -206,6 +224,10 @@ func (t *toolchainLinuxMuslX86) ToolchainRustFlags() string {
return t.toolchainLinuxX86.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
}
+func (t *toolchainLinuxMuslX86) Musl() bool {
+ return true
+}
+
func linuxMuslX86ToolchainFactory(arch android.Arch) Toolchain {
return toolchainLinuxMuslX86Singleton
}
diff --git a/rust/config/x86_windows_host.go b/rust/config/x86_windows_host.go
new file mode 100644
index 000000000..2199b341c
--- /dev/null
+++ b/rust/config/x86_windows_host.go
@@ -0,0 +1,193 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ // Common Windows Rust flags
+ windowsRustFlags = []string{
+ "-C dlltool=${cc_config.ClangBin}/llvm-dlltool",
+ "-C split-debuginfo=packed",
+ "-C link-self-contained=no",
+ "-C panic=abort",
+ }
+ // Common Windows linker flags for Rust
+ windowsRustLinkFlags = []string{
+ "--sysroot ${cc_config.WindowsGccRoot}/${cc_config.WindowsGccTriple}",
+ "-fuse-ld=lld",
+ }
+
+ // x86 specific flags
+ windowsX86RustFlags = []string{}
+ windowsX8664RustFlags = []string{}
+
+ // x86_64 specific flags
+ windowsX86RustLinkFlags = []string{}
+ windowsX8664RustLinkFlags = []string{}
+)
+
+func init() {
+ registerToolchainFactory(android.Windows, android.X86, windowsX86ToolchainFactory)
+ registerToolchainFactory(android.Windows, android.X86_64, windowsX8664ToolchainFactory)
+
+ pctx.StaticVariable("WindowsToolchainRustFlags", strings.Join(windowsRustFlags, " "))
+ pctx.StaticVariable("WindowsToolchainRustLinkFlags", strings.Join(windowsRustLinkFlags, " "))
+
+ pctx.StaticVariable("WindowsX86ToolchainRustFlags", strings.Join(windowsX86RustFlags, " "))
+ pctx.StaticVariable("WindowsX86ToolchainRustLinkFlags", strings.Join(windowsX86RustLinkFlags, " "))
+ pctx.StaticVariable("WindowsX8664ToolchainRustFlags", strings.Join(windowsX8664RustFlags, " "))
+ pctx.StaticVariable("WindowsX8664ToolchainRustLinkFlags", strings.Join(windowsX8664RustLinkFlags, " "))
+}
+
+type toolchainWindowsX86 struct {
+ toolchainBase
+}
+
+func (t *toolchainWindowsX86) Is64Bit() bool {
+ return false
+}
+
+func (t *toolchainWindowsX86) LibclangRuntimeLibraryArch() string {
+ return "i686"
+}
+
+func (t *toolchainWindowsX86) RlibSuffix() string {
+ return ".rlib"
+}
+
+// Windows x86
+func (t *toolchainWindowsX86) Name() string {
+ return "x86"
+}
+
+func (t *toolchainWindowsX86) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${cc_config.WindowsLdflags} ${cc_config.WindowsX86Ldflags} ${cc_config.WindowsAvailableLibraries} " +
+ "${config.WindowsToolchainRustLinkFlags} ${config.WindowsX86ToolchainRustLinkFlags}"
+}
+
+func (t *toolchainWindowsX86) ToolchainRustFlags() string {
+ return "${config.WindowsToolchainRustFlags} ${config.WindowsX86ToolchainRustFlags}"
+}
+
+func (t *toolchainWindowsX86) RustTriple() string {
+ return "i686-pc-windows-gnu"
+}
+
+func windowsX86ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainWindowsX86Singleton
+}
+
+func (toolchainWindowsX86) Supported() bool {
+ return true
+}
+
+func (toolchainWindowsX86) Bionic() bool {
+ return false
+}
+
+func (toolchainWindowsX86) StaticLibSuffix() string {
+ return ".a"
+}
+
+func (toolchainWindowsX86) SharedLibSuffix() string {
+ return ".dll"
+}
+
+func (toolchainWindowsX86) ExecutableSuffix() string {
+ return ".exe"
+}
+
+func (toolchainWindowsX86) DylibSuffix() string {
+ return ".dylib.dll"
+}
+
+func (toolchainWindowsX86) ProcMacroSuffix() string {
+ return ".dylib.dll"
+}
+
+// Windows x86_64
+type toolchainWindowsX8664 struct {
+ toolchainBase
+}
+
+func (t *toolchainWindowsX8664) Is64Bit() bool {
+ return true
+}
+
+func (t *toolchainWindowsX8664) LibclangRuntimeLibraryArch() string {
+ return "x86_64"
+}
+
+func (t *toolchainWindowsX8664) RlibSuffix() string {
+ return ".rlib"
+}
+
+func (t *toolchainWindowsX8664) Name() string {
+ return "x86_64"
+}
+
+func (t *toolchainWindowsX8664) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${cc_config.WindowsLdflags} ${cc_config.WindowsX8664Ldflags} ${cc_config.WindowsAvailableLibraries} " +
+ "${config.WindowsToolchainRustLinkFlags} ${config.WindowsX8664ToolchainRustLinkFlags}"
+}
+
+func (t *toolchainWindowsX8664) ToolchainRustFlags() string {
+ return "${config.WindowsToolchainRustFlags} ${config.WindowsX8664ToolchainRustFlags}"
+}
+
+func (t *toolchainWindowsX8664) RustTriple() string {
+ return "x86_64-pc-windows-gnu"
+}
+func windowsX8664ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainWindowsX8664Singleton
+}
+
+func (toolchainWindowsX8664) Supported() bool {
+ return true
+}
+
+func (toolchainWindowsX8664) Bionic() bool {
+ return false
+}
+
+func (toolchainWindowsX8664) StaticLibSuffix() string {
+ return ".a"
+}
+
+func (toolchainWindowsX8664) SharedLibSuffix() string {
+ return ".dll"
+}
+
+func (toolchainWindowsX8664) ExecutableSuffix() string {
+ return ".exe"
+}
+
+func (toolchainWindowsX8664) DylibSuffix() string {
+ return ".dylib.dll"
+}
+
+func (toolchainWindowsX8664) ProcMacroSuffix() string {
+ return ".dylib.dll"
+}
+
+var toolchainWindowsX8664Singleton Toolchain = &toolchainWindowsX8664{}
+var toolchainWindowsX86Singleton Toolchain = &toolchainWindowsX86{}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 9e8efd754..54ee00cdb 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -30,9 +30,8 @@ func init() {
type fuzzDecorator struct {
*binaryDecorator
- fuzzPackagedModule fuzz.FuzzPackagedModule
- sharedLibraries android.RuleBuilderInstalls
- installedSharedDeps []string
+ fuzzPackagedModule fuzz.FuzzPackagedModule
+ sharedLibraries cc.InstallPairs
}
var _ compiler = (*fuzzDecorator)(nil)
@@ -132,23 +131,14 @@ func (fuzzer *fuzzDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep
func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule)
- installBase := "fuzz"
-
// Grab the list of required shared libraries.
fuzz.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
- for _, ruleBuilderInstall := range fuzz.sharedLibraries {
- install := ruleBuilderInstall.To
-
- fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
- cc.SharedLibraryInstallLocation(
- install, ctx.Host(), ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
-
- // Also add the dependency on the shared library symbols dir.
- if !ctx.Host() {
- fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
- cc.SharedLibrarySymbolsInstallLocation(install, ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
- }
+ for _, sharedLib := range fuzz.sharedLibraries {
+ fuzz.binaryDecorator.installDeps = append(
+ fuzz.binaryDecorator.installDeps,
+ sharedLib.Dst,
+ )
}
var fuzzData []android.DataPath
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index bdcfbbba1..ab99b72c0 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -95,11 +95,15 @@ func TestRustFuzzDepBundling(t *testing.T) {
fuzz_libtest := ctx.ModuleForTests(t, "fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
- if !strings.Contains(fuzz_libtest.FuzzSharedLibraries().String(), ":libcc_direct_dep.so") {
- t.Errorf("rust_fuzz does not contain the expected bundled direct shared libs ('libcc_direct_dep'): %#v", fuzz_libtest.FuzzSharedLibraries().String())
+ var fuzzLibInstalls []string
+ for _, install := range fuzz_libtest.FuzzSharedLibraries() {
+ fuzzLibInstalls = append(fuzzLibInstalls, install.Dst.Base())
}
- if !strings.Contains(fuzz_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("rust_fuzz does not contain the expected bundled transitive shared libs ('libcc_transitive_dep'): %#v", fuzz_libtest.FuzzSharedLibraries().String())
+ if !android.InList("libcc_direct_dep.so", fuzzLibInstalls) {
+ t.Errorf("rust_fuzz does not contain the expected bundled direct shared libs ('libcc_direct_dep'): %#v", fuzzLibInstalls)
+ }
+ if !android.InList("libcc_transitive_dep.so", fuzzLibInstalls) {
+ t.Errorf("rust_fuzz does not contain the expected bundled transitive shared libs ('libcc_transitive_dep'): %#v", fuzzLibInstalls)
}
}
@@ -134,17 +138,27 @@ func TestCCFuzzDepBundling(t *testing.T) {
}
`)
- fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
- fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
- fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+ fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module()
+ fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module()
+ fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module()
+
+ fuzzSharedLibraries := func(module android.Module) []string {
+ var allLibs []string
+ if info, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ for _, install := range info.FuzzSharedLibraries {
+ allLibs = append(allLibs, install.Dst.String())
+ }
+ }
+ return allLibs
+ }
- if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
+ if libs := fuzzSharedLibraries(fuzz_shared_libtest); !android.SubstringInList(libs, "libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", libs)
}
- if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
+ if libs := fuzzSharedLibraries(fuzz_static_libtest); !android.SubstringInList(libs, "libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
}
- if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
+ if libs := fuzzSharedLibraries(fuzz_staticffi_libtest); !android.SubstringInList(libs, "libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
}
}
diff --git a/rust/library.go b/rust/library.go
index 415785a16..8e471599f 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,13 +15,13 @@
package rust
import (
- "errors"
"fmt"
"regexp"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/depset"
+ "github.com/google/blueprint/pathtools"
"android/soong/android"
"android/soong/cc"
@@ -311,6 +311,8 @@ func (library *libraryDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
} else if library.baseCompiler.preferRlib() {
return RlibLinkage
+ } else if !device {
+ return RlibLinkage
}
return DylibLinkage
}
@@ -624,7 +626,9 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
"-install_name @rpath/"+library.sharedLibFilename(ctx),
)
} else {
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ if !ctx.Windows() {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ }
}
}
@@ -635,7 +639,10 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
var outputFile android.ModuleOutPath
var ret buildOutput
var fileName string
- crateRootPath := crateRootPath(ctx, library)
+ crateRootPath := library.crateRootPath(ctx)
+
+ deps.SrcFiles = append(deps.SrcFiles, crateRootPath)
+ deps.SrcFiles = append(deps.SrcFiles, library.crateSources(ctx)...)
if library.sourceProvider != nil {
deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
@@ -675,10 +682,20 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...)
- flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...)
flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...)
+ if ctx.Windows() {
+ for _, lib := range deps.sharedLibObjects {
+ // Windows uses the .lib import library at link-time and at runtime
+ // uses the .dll library, so we need to make sure we're passing the
+ // import library to the linker.
+ flags.LinkFlags = append(flags.LinkFlags, pathtools.ReplaceExtension(lib, "lib"))
+ }
+ } else {
+ flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
+ }
+
if String(library.Properties.Version_script) != "" {
if String(library.Properties.Extra_exported_symbols) != "" {
ctx.ModuleErrorf("version_script and extra_exported_symbols cannot both be set.")
@@ -687,7 +704,8 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
if library.shared() {
// "-Wl,--android-version-script" signals to the rustcLinker script
// that the default version script should be removed.
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,--android-version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Version_script)).String())
+ flags.LinkerScriptFlags = append(flags.LinkerScriptFlags,
+ "-Wl,--android-version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Version_script)).String())
deps.LinkerDeps = append(deps.LinkerDeps, android.PathForModuleSrc(ctx, String(library.Properties.Version_script)))
} else if !library.static() && !library.rlib() {
// We include rlibs here because rust_ffi produces rlib variants
@@ -785,16 +803,17 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
return ret
}
-func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) {
+func (library *libraryDecorator) crateRootPath(ctx ModuleContext) android.Path {
if library.sourceProvider != nil {
srcs := library.sourceProvider.Srcs()
if len(srcs) == 0 {
- return nil, errors.New("Source provider generated 0 sources")
+ ctx.PropertyErrorf("srcs", "Source provider generated 0 sources")
+ return nil
}
// Assume the first source from the source provider is the library entry point.
- return srcs[0], nil
+ return srcs[0]
} else {
- return library.baseCompiler.checkedCrateRootPath()
+ return library.baseCompiler.crateRootPath(ctx)
}
}
@@ -809,7 +828,7 @@ func (library *libraryDecorator) getApiStubsCcFlags(ctx ModuleContext) cc.Flags
minSdkVersion := cc.MinSdkVersion(ctx.RustModule(), cc.CtxIsForPlatform(ctx), ctx.Device(), platformSdkVersion)
// Collect common CC compilation flags
- ccFlags = cc.CommonLinkerFlags(ctx, ccFlags, true, toolchain, false)
+ ccFlags = cc.CommonLinkerFlags(ctx, ccFlags, toolchain, false)
ccFlags = cc.CommonLibraryLinkerFlags(ctx, ccFlags, toolchain, library.getStem(ctx))
ccFlags = cc.AddStubLibraryCompilerFlags(ccFlags)
ccFlags = cc.AddTargetFlags(ctx, ccFlags, toolchain, minSdkVersion, false)
@@ -856,7 +875,7 @@ func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
return android.OptionalPath{}
}
- return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library),
+ return android.OptionalPathForPath(Rustdoc(ctx, library.crateRootPath(ctx),
deps, flags))
}
@@ -942,7 +961,8 @@ func (libraryTransitionMutator) Split(ctx android.BaseModuleContext) []string {
if library.buildRlib() {
variants = append(variants, rlibVariation)
}
- if library.buildDylib() {
+ if library.buildDylib() && !ctx.Host() {
+ // Hosts do not produce dylib variants.
variants = append(variants, dylibVariation)
}
@@ -1039,6 +1059,10 @@ func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string {
// Only create a variant if a library is actually being built.
if library, ok := m.compiler.(libraryInterface); ok {
if library.rlib() && !library.sysroot() {
+ if ctx.Host() {
+ // Hosts do not produce dylib variants, so there's only one std option.
+ return []string{"rlib-std"}
+ }
return []string{"rlib-std", "dylib-std"}
}
}
diff --git a/rust/library_test.go b/rust/library_test.go
index 6cc4f2517..09874897f 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -25,27 +25,27 @@ import (
func TestLibraryVariants(t *testing.T) {
ctx := testRust(t, `
- rust_library_host {
+ rust_library {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
}
- rust_ffi_host {
+ rust_ffi {
name: "libfoo.ffi",
srcs: ["foo.rs"],
crate_name: "foo"
}
- rust_ffi_host_static {
+ rust_ffi_static {
name: "libfoo.ffi_static",
srcs: ["foo.rs"],
crate_name: "foo"
}`)
// Test all variants are being built.
- libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
- libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
- libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
- libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc")
+ libfooRlib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Rule("rustc")
+ libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
+ libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "android_arm64_armv8-a_shared").Rule("rustc")
rlibCrateType := "rlib"
dylibCrateType := "dylib"
@@ -76,13 +76,13 @@ func TestLibraryVariants(t *testing.T) {
// Test that dylibs are not statically linking the standard library.
func TestDylibPreferDynamic(t *testing.T) {
ctx := testRust(t, `
- rust_library_host_dylib {
+ rust_library_dylib {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
}`)
- libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") {
t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
@@ -247,17 +247,17 @@ func TestNativeDependencyOfRlib(t *testing.T) {
func TestAutoDeps(t *testing.T) {
ctx := testRust(t, `
- rust_library_host {
+ rust_library {
name: "libbar",
srcs: ["bar.rs"],
crate_name: "bar",
}
- rust_library_host_rlib {
+ rust_library_rlib {
name: "librlib_only",
srcs: ["bar.rs"],
crate_name: "rlib_only",
}
- rust_library_host {
+ rust_library {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -266,7 +266,7 @@ func TestAutoDeps(t *testing.T) {
"librlib_only",
],
}
- rust_ffi_host {
+ rust_ffi {
name: "libfoo.ffi",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -275,7 +275,7 @@ func TestAutoDeps(t *testing.T) {
"librlib_only",
],
}
- rust_ffi_host_static {
+ rust_ffi_static {
name: "libfoo.ffi.static",
srcs: ["foo.rs"],
crate_name: "foo",
@@ -285,10 +285,10 @@ func TestAutoDeps(t *testing.T) {
],
}`)
- libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std")
- libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib")
- libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
- libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared")
+ libfooRlib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib")
+ libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "android_arm64_armv8-a_rlib_rlib-std")
+ libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "android_arm64_armv8-a_shared")
for _, static := range []android.TestingModule{libfooRlib, libfooFFIRlib} {
if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
@@ -489,14 +489,14 @@ func TestRustVersionScript(t *testing.T) {
t.Errorf("missing expected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v",
librs.Args["linkFlags"])
}
- if strings.Contains(librs.Args["linkFlags"], "-Wl,--android-version-script=librs.map.txt") {
+ if strings.Contains(librs.Args["linkerScriptFlags"], "-Wl,--android-version-script=librs.map.txt") {
t.Errorf("unexpected -Wl,--android-version-script= linker flag for libextended shared lib, linkFlags: %#v",
- librs.Args["linkFlags"])
+ librs.Args["linkerScriptFlags"])
}
- if !strings.Contains(libffi.Args["linkFlags"], "-Wl,--android-version-script=libffi.map.txt") {
+ if !strings.Contains(libffi.Args["linkerScriptFlags"], "-Wl,--android-version-script=libffi.map.txt") {
t.Errorf("missing -Wl,--android-version-script= linker flag for libreplaced shared lib, linkFlags: %#v",
- libffi.Args["linkFlags"])
+ libffi.Args["linkerScriptFlags"])
}
if strings.Contains(libffi.Args["linkFlags"], "-Wl,--version-script=libffi.map.txt") {
t.Errorf("unexpected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v",
diff --git a/rust/object.go b/rust/object.go
new file mode 100644
index 000000000..b2123c4a9
--- /dev/null
+++ b/rust/object.go
@@ -0,0 +1,125 @@
+// Copyright 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "android/soong/android"
+)
+
+func init() {
+ // Rust objects are object files built with --emit=obj.
+ android.RegisterModuleType("rust_object", RustObjectFactory)
+ android.RegisterModuleType("rust_object_host", RustObjectHostFactory)
+}
+
+type ObjectProperties struct {
+ // Indicates that this module is a CRT object. CRT objects will be split
+ // into a variant per-API level between min_sdk_version and current.
+ Crt *bool
+}
+
+type objectDecorator struct {
+ *baseCompiler
+ Properties ObjectProperties
+}
+
+type objectInterface interface {
+ crt() bool
+}
+
+var _ objectInterface = (*objectDecorator)(nil)
+var _ compiler = (*objectDecorator)(nil)
+
+// rust_object produces an object file.
+func RustObjectFactory() android.Module {
+ module, _ := NewRustObject(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// rust_object_host produces an object file for host only.
+func RustObjectHostFactory() android.Module {
+ module, _ := NewRustObject(android.HostSupported)
+ return module.Init()
+}
+
+func NewRustObject(hod android.HostOrDeviceSupported) (*Module, *objectDecorator) {
+ module := newModule(hod, android.MultilibFirst)
+
+ object := &objectDecorator{
+ baseCompiler: NewBaseCompiler("", "", NoInstall),
+ }
+
+ module.compiler = object
+
+ return module, object
+}
+
+func (object *objectDecorator) begin(ctx BaseModuleContext) {
+ object.baseCompiler.begin(ctx)
+}
+
+func (object *objectDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+ flags = object.baseCompiler.compilerFlags(ctx, flags)
+ return flags
+}
+
+func (object *objectDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ deps = object.baseCompiler.compilerDeps(ctx, deps)
+ return deps
+}
+
+func (object *objectDecorator) crt() bool {
+ return Bool(object.Properties.Crt)
+}
+
+func (object *objectDecorator) compilerProps() []interface{} {
+ return append(object.baseCompiler.compilerProps(),
+ &object.Properties)
+}
+
+func (object *objectDecorator) nativeCoverage() bool {
+ return true
+}
+
+func (object *objectDecorator) emitType() string {
+ return "obj"
+}
+
+func (object *objectDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
+ fileName := object.getStem(ctx) + ".o"
+ outputFile := android.PathForModuleOut(ctx, fileName)
+ ret := buildOutput{outputFile: outputFile}
+ crateRootPath := object.crateRootPath(ctx)
+
+ flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+ object.baseCompiler.unstrippedOutputFile = outputFile
+
+ ret.kytheFile = TransformSrcToObject(ctx, crateRootPath, deps, flags, outputFile).kytheFile
+ return ret
+}
+
+func (object *objectDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
+ // rust_objects are not linked so selecting deps for them doesn't make sense.
+ panic("rust_objects should not declare rustlibs dependencies")
+}
+
+func (object *objectDecorator) install(ctx ModuleContext) {
+ // Objects aren't installable, so do nothing.
+}
+
+func (object *objectDecorator) everInstallable() bool {
+ // Objects aren't installable.
+ return false
+}
diff --git a/rust/object_test.go b/rust/object_test.go
new file mode 100644
index 000000000..3c07ed1da
--- /dev/null
+++ b/rust/object_test.go
@@ -0,0 +1,35 @@
+// Copyright 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "strings"
+ "testing"
+)
+
+// Smoke test rust_object_host and also check the emit type is correct.
+func TestObjectEmitType(t *testing.T) {
+ ctx := testRust(t, `
+ rust_object_host {
+ name: "foors",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ libfooRlib := ctx.ModuleForTests(t, "foors", "linux_glibc_x86_64").Rule("rustc")
+ if !strings.Contains(libfooRlib.Args["emitType"], "obj") {
+ t.Errorf("rust_object_host not emitting type obj")
+ }
+}
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 7c92dda1e..a3537e9b4 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -197,6 +197,14 @@ func (prebuilt *prebuiltLibraryDecorator) prebuilt() *android.Prebuilt {
return &prebuilt.Prebuilt
}
+func (prebuilt *prebuiltLibraryDecorator) crateRootPath(ctx ModuleContext) android.Path {
+ if prebuilt.baseCompiler.Properties.Crate_root == nil {
+ return srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
+ } else {
+ return android.PathForModuleSrc(ctx, *prebuilt.baseCompiler.Properties.Crate_root)
+ }
+}
+
func (prebuilt *prebuiltProcMacroDecorator) prebuiltSrcs() []string {
srcs := prebuilt.Properties.Srcs
return srcs
@@ -233,3 +241,11 @@ func (prebuilt *prebuiltProcMacroDecorator) compilerDeps(ctx DepsContext, deps D
func (prebuilt *prebuiltProcMacroDecorator) nativeCoverage() bool {
return false
}
+
+func (prebuilt *prebuiltProcMacroDecorator) crateRootPath(ctx ModuleContext) android.Path {
+ if prebuilt.baseCompiler.Properties.Crate_root == nil {
+ return srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
+ } else {
+ return android.PathForModuleSrc(ctx, *prebuilt.baseCompiler.Properties.Crate_root)
+ }
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 837e1a6c8..568f82faf 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -74,7 +74,11 @@ func (procMacro *procMacroDecorator) compilerFlags(ctx ModuleContext, flags Flag
func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix()
outputFile := android.PathForModuleOut(ctx, fileName)
- srcPath := crateRootPath(ctx, procMacro)
+ srcPath := procMacro.crateRootPath(ctx)
+
+ deps.SrcFiles = append(deps.SrcFiles, srcPath)
+ deps.SrcFiles = append(deps.SrcFiles, procMacro.crateSources(ctx)...)
+
ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile)
procMacro.baseCompiler.unstrippedOutputFile = outputFile
diff --git a/rust/project_json.go b/rust/project_json.go
index 6e8cebeed..be1bb9c75 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -18,6 +18,8 @@ import (
"encoding/json"
"fmt"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/rust/config"
)
@@ -33,6 +35,7 @@ import (
const (
// Environment variables used to control the behavior of this singleton.
envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
+ envVariableUseKythe = "XREF_CORPUS"
rustProjectJsonFileName = "rust-project.json"
)
@@ -83,23 +86,23 @@ func init() {
// mergeDependencies visits all the dependencies for module and updates crate and deps
// with any new dependency.
func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
- module *Module, crate *rustProjectCrate, deps map[string]int) {
+ module android.ModuleProxy, crate *rustProjectCrate, deps map[string]int) {
- ctx.VisitDirectDeps(module, func(child android.Module) {
+ ctx.VisitDirectDepsProxies(module, func(child android.ModuleProxy) {
// Skip intra-module dependencies (i.e., generated-source library depending on the source variant).
if module.Name() == child.Name() {
return
}
// Skip unsupported modules.
- rChild, ok := isModuleSupported(ctx, child)
+ rustInfo, commonInfo, ok := isModuleSupported(ctx, child)
if !ok {
return
}
// For unknown dependency, add it first.
var childId int
- cInfo, known := singleton.knownCrates[rChild.Name()]
+ cInfo, known := singleton.knownCrates[child.Name()]
if !known {
- childId, ok = singleton.addCrate(ctx, rChild)
+ childId, ok = singleton.addCrate(ctx, child, rustInfo, commonInfo)
if !ok {
return
}
@@ -110,44 +113,43 @@ func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.Single
if _, ok = deps[child.Name()]; ok {
return
}
- crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: rChild.CrateName()})
+ crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: rustInfo.CompilerInfo.CrateName})
deps[child.Name()] = childId
})
}
// isModuleSupported returns the RustModule if the module
// should be considered for inclusion in rust-project.json.
-func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, bool) {
- rModule, ok := module.(*Module)
+func isModuleSupported(ctx android.SingletonContext, module android.ModuleProxy) (*RustInfo, *android.CommonModuleInfo, bool) {
+ info, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider)
if !ok {
- return nil, false
+ return nil, nil, false
}
- if !rModule.Enabled(ctx) {
- return nil, false
+ commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ if !commonInfo.Enabled {
+ return nil, nil, false
}
- return rModule, true
+ return info, commonInfo, true
}
// addCrate adds a crate to singleton.project.Crates ensuring that required
// dependencies are also added. It returns the index of the new crate in
// singleton.project.Crates
-func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module) (int, bool) {
+func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, module android.ModuleProxy, rustInfo *RustInfo,
+ commonInfo *android.CommonModuleInfo) (int, bool) {
+
deps := make(map[string]int)
- rootModule, err := rModule.compiler.checkedCrateRootPath()
- if err != nil {
- return 0, false
- }
var procMacroDylib *string = nil
- if procDec, procMacro := rModule.compiler.(*procMacroDecorator); procMacro {
- procMacroDylib = new(string)
- *procMacroDylib = procDec.baseCompiler.unstrippedOutputFilePath().String()
+
+ if procMacro := rustInfo.ProcMacroInfo; procMacro != nil {
+ procMacroDylib = proptools.StringPtr(procMacro.Dylib.String())
}
crate := rustProjectCrate{
- DisplayName: rModule.Name(),
- RootModule: rootModule.String(),
- Edition: rModule.compiler.edition(),
+ DisplayName: module.Name(),
+ RootModule: rustInfo.CompilerInfo.CrateRootPath.String(),
+ Edition: rustInfo.CompilerInfo.Edition,
Deps: make([]rustProjectDep, 0),
Cfg: make([]string, 0),
Env: make(map[string]string),
@@ -155,60 +157,60 @@ func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContex
ProcMacroDylib: procMacroDylib,
}
- if rModule.compiler.cargoOutDir().Valid() {
- crate.Env["OUT_DIR"] = rModule.compiler.cargoOutDir().String()
+ if cargoOutDir := rustInfo.CompilerInfo.CargoOutDir; cargoOutDir.Valid() {
+ crate.Env["OUT_DIR"] = cargoOutDir.String()
}
- for _, feature := range rModule.compiler.features(ctx, rModule) {
+ for _, feature := range rustInfo.CompilerInfo.Features {
crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
}
- singleton.mergeDependencies(ctx, rModule, &crate, deps)
+ singleton.mergeDependencies(ctx, module, &crate, deps)
var idx int
- if cInfo, ok := singleton.knownCrates[rModule.Name()]; ok {
+ if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
idx = cInfo.Idx
singleton.project.Crates[idx] = crate
} else {
idx = len(singleton.project.Crates)
singleton.project.Crates = append(singleton.project.Crates, crate)
}
- singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps, Device: rModule.Device()}
+ singleton.knownCrates[module.Name()] = crateInfo{Idx: idx, Deps: deps, Device: commonInfo.Target.Os.Class == android.Device}
return idx, true
}
// appendCrateAndDependencies creates a rustProjectCrate for the module argument and appends it to singleton.project.
// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the
// current module is already in singleton.knownCrates, its dependencies are merged.
-func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.Module) {
- rModule, ok := isModuleSupported(ctx, module)
+func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.ModuleProxy) {
+ rustInfo, commonInfo, ok := isModuleSupported(ctx, module)
if !ok {
return
}
// If we have seen this crate already; merge any new dependencies.
if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
// If we have a new device variant, override the old one
- if !cInfo.Device && rModule.Device() {
- singleton.addCrate(ctx, rModule)
+ if !cInfo.Device && commonInfo.Target.Os.Class == android.Device {
+ singleton.addCrate(ctx, module, rustInfo, commonInfo)
return
}
crate := singleton.project.Crates[cInfo.Idx]
- singleton.mergeDependencies(ctx, rModule, &crate, cInfo.Deps)
+ singleton.mergeDependencies(ctx, module, &crate, cInfo.Deps)
singleton.project.Crates[cInfo.Idx] = crate
return
}
- singleton.addCrate(ctx, rModule)
+ singleton.addCrate(ctx, module, rustInfo, commonInfo)
}
func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
+ if !(ctx.Config().IsEnvTrue(envVariableCollectRustDeps) || ctx.Config().Getenv(envVariableUseKythe) != "") {
return
}
singleton.project.Sysroot = config.RustPath(ctx)
singleton.knownCrates = make(map[string]crateInfo)
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
singleton.appendCrateAndDependencies(ctx, module)
})
@@ -217,6 +219,21 @@ func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.Sin
if err != nil {
ctx.Errorf(err.Error())
}
+ if ctx.Config().XrefCorpusName() != "" {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ jsonPath := android.PathForOutput(ctx, "rust-project.json")
+ kzipPath := android.PathForOutput(ctx, "rust-project.kzip")
+ vnames := android.PathForSource(ctx, "build/soong/vnames.json")
+ rule.Command().PrebuiltBuildTool(ctx, "rust_project_to_kzip").
+ FlagWithInput("-project_json ", jsonPath).
+ FlagWithOutput("-output ", kzipPath).
+ FlagWithArg("-corpus ", ctx.Config().XrefCorpusName()).
+ FlagWithArg("-root ", "$PWD").
+ FlagWithInput("-vnames_json_path ", vnames)
+ ruleName := "rust3-extraction"
+ rule.Build(ruleName, "Turning Rust project into kzips")
+ ctx.Phony("xref_rust", kzipPath)
+ }
}
func createJsonFile(project rustProjectJson, rustProjectPath android.WritablePath) error {
diff --git a/rust/protobuf.go b/rust/protobuf.go
index fab5259a5..b2ce4d867 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -227,6 +227,9 @@ func (proto *protobufDecorator) genModFileContents() string {
lines,
"pub mod empty {",
" pub use protobuf::well_known_types::empty::Empty;",
+ "}",
+ "pub mod wrappers {",
+ " pub use protobuf::well_known_types::wrappers::*;",
"}")
}
diff --git a/rust/rust.go b/rust/rust.go
index 54b5d92e3..65849a3f9 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -16,6 +16,7 @@ package rust
import (
"fmt"
+ "path/filepath"
"strconv"
"strings"
@@ -43,6 +44,11 @@ type CompilerInfo struct {
StdLinkageForDevice RustLinkage
StdLinkageForNonDevice RustLinkage
NoStdlibs bool
+ CrateName string
+ Edition string
+ CargoOutDir android.OptionalPath
+ Features []string
+ CrateRootPath android.Path
LibraryInfo *LibraryInfo
}
@@ -53,6 +59,10 @@ type SourceProviderInfo struct {
ProtobufDecoratorInfo *ProtobufDecoratorInfo
}
+type ProcMacroInfo struct {
+ Dylib android.Path
+}
+
type RustInfo struct {
AndroidMkSuffix string
RustSubName string
@@ -60,6 +70,7 @@ type RustInfo struct {
CompilerInfo *CompilerInfo
SnapshotInfo *cc.SnapshotInfo
SourceProviderInfo *SourceProviderInfo
+ ProcMacroInfo *ProcMacroInfo
XrefRustFiles android.Paths
DocTimestampFile android.OptionalPath
}
@@ -73,7 +84,6 @@ func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/rust/config")
pctx.ImportAs("cc_config", "android/soong/cc/config")
- android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory)
}
func registerPreDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -87,16 +97,17 @@ func registerPostDepsMutators(ctx android.RegisterMutatorsContext) {
}
type Flags struct {
- GlobalRustFlags []string // Flags that apply globally to rust
- GlobalLinkFlags []string // Flags that apply globally to linker
- RustFlags []string // Flags that apply to rust
- LinkFlags []string // Flags that apply to linker
- ClippyFlags []string // Flags that apply to clippy-driver, during the linting
- RustdocFlags []string // Flags that apply to rustdoc
- Toolchain config.Toolchain
- Coverage bool
- Clippy bool
- EmitXrefs bool // If true, emit rules to aid cross-referencing
+ GlobalRustFlags []string // Flags that apply globally to rust
+ GlobalLinkFlags []string // Flags that apply globally to linker
+ RustFlags []string // Flags that apply to rust
+ LinkFlags []string // Flags that apply to linker
+ LinkerScriptFlags []string // Flags that should be visible to the android linker script
+ ClippyFlags []string // Flags that apply to clippy-driver, during the linting
+ RustdocFlags []string // Flags that apply to rustdoc
+ Toolchain config.Toolchain
+ Coverage bool
+ Clippy bool
+ EmitXrefs bool // If true, emit rules to aid cross-referencing
}
type BaseProperties struct {
@@ -524,12 +535,16 @@ type PathDeps struct {
CrtBegin android.Paths
CrtEnd android.Paths
+ SrcFiles android.Paths
+
// Paths to generated source files
SrcDeps android.Paths
srcProviderFiles android.Paths
- directImplementationDeps android.Paths
- transitiveImplementationDeps []depset.DepSet[android.Path]
+ directApexImplementationDeps android.Paths
+ transitiveApexImplementationDeps []depset.DepSet[android.Path]
+ directNonApexImplementationDeps android.Paths
+ transitiveNonApexImplementationDeps []depset.DepSet[android.Path]
}
type RustLibraries []RustLibrary
@@ -663,6 +678,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
&BenchmarkProperties{},
&BindgenProperties{},
&BaseCompilerProperties{},
+ &ObjectProperties{},
&BinaryCompilerProperties{},
&LibraryCompilerProperties{},
&ProcMacroCompilerProperties{},
@@ -731,7 +747,7 @@ func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName()))
}
-func (mod *Module) FuzzSharedLibraries() android.RuleBuilderInstalls {
+func (mod *Module) FuzzSharedLibraries() cc.InstallPairs {
if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
return fuzzer.sharedLibraries
}
@@ -812,6 +828,10 @@ func (mod *Module) CoverageOutputFile() android.OptionalPath {
return android.OptionalPath{}
}
+func (c *Module) LinkCoverage() bool {
+ return false
+}
+
func (mod *Module) IsNdk(config android.Config) bool {
return false
}
@@ -860,7 +880,9 @@ func (mod *Module) Multilib() string {
}
func (mod *Module) IsCrt() bool {
- // Rust does not currently provide any crt modules.
+ if obj, ok := mod.compiler.(objectInterface); ok {
+ return obj.crt()
+ }
return false
}
@@ -1081,7 +1103,7 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if mod.compiler != nil {
flags = mod.compiler.compilerFlags(ctx, flags)
flags = mod.compiler.cfgFlags(ctx, flags)
- flags = mod.compiler.featureFlags(ctx, mod, flags)
+ flags = mod.compiler.featureFlags(ctx, flags)
}
if mod.coverage != nil {
flags, deps = mod.coverage.flags(ctx, flags, deps)
@@ -1111,7 +1133,6 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
}
if mod.compiler != nil && !mod.compiler.Disabled() {
- mod.compiler.initialize(ctx)
buildOutput := mod.compiler.compile(ctx, flags, deps)
if ctx.Failed() {
return
@@ -1121,7 +1142,13 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if buildOutput.kytheFile != nil {
mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile)
}
- bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath()))
+ if _, ok := mod.compiler.(*objectDecorator); !ok && !ctx.Windows() {
+ // Bloaty doesn't recognize Windows object files.
+ // Since objects are inputs to other binaries, if there's bloat
+ // in one it should be reflected in the outputs which take them
+ // as inputs, so skipping this check for them should be fine.
+ bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath()))
+ }
mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)
@@ -1152,7 +1179,10 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
}
android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{
- ImplementationDeps: depset.New(depset.PREORDER, deps.directImplementationDeps, deps.transitiveImplementationDeps),
+ ImplementationDeps: depset.New(depset.PREORDER, deps.directApexImplementationDeps, deps.transitiveApexImplementationDeps),
+ })
+ android.SetProvider(ctx, RustImplementationDepInfoProvider, &RustImplementationDepInfo{
+ NonApexImplementationDeps: depset.New(depset.PREORDER, deps.directNonApexImplementationDeps, deps.transitiveNonApexImplementationDeps),
})
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
@@ -1179,6 +1209,11 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if mod.compiler != nil {
rustInfo.CompilerInfo = &CompilerInfo{
NoStdlibs: mod.compiler.noStdlibs(),
+ CrateName: mod.compiler.crateName(),
+ Edition: mod.compiler.edition(),
+ CargoOutDir: mod.compiler.cargoOutDir(ctx),
+ Features: mod.compiler.features(ctx),
+ CrateRootPath: mod.compiler.crateRootPath(ctx),
StdLinkageForDevice: mod.compiler.stdLinkage(true),
StdLinkageForNonDevice: mod.compiler.stdLinkage(false),
}
@@ -1202,6 +1237,11 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
rustInfo.SourceProviderInfo.ProtobufDecoratorInfo = &ProtobufDecoratorInfo{}
}
}
+ if _, ok := mod.compiler.(*procMacroDecorator); ok {
+ rustInfo.ProcMacroInfo = &ProcMacroInfo{
+ Dylib: mod.compiler.unstrippedOutputFilePath(),
+ }
+ }
android.SetProvider(ctx, RustInfoProvider, rustInfo)
ccInfo := &cc.CcInfo{
@@ -1220,6 +1260,15 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
android.SetProvider(ctx, cc.CcInfoProvider, ccInfo)
+ // TODO: Refactor rustMakeLibName so we don't have to fake CommonModuleInfo like this
+ myCommonInfo := android.CommonModuleInfo{
+ BaseModuleName: mod.BaseModuleName(),
+ Target: ctx.Target(),
+ }
+ android.SetProvider(ctx, android.MakeNameInfoProvider, android.MakeNameInfo{
+ Name: rustMakeLibName(rustInfo, linkableInfo, &myCommonInfo, ctx.ModuleName()),
+ })
+
mod.setOutputFiles(ctx)
buildComplianceMetadataInfo(ctx, mod, deps)
@@ -1228,6 +1277,75 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if mod.compiler != nil {
mod.compiler.moduleInfoJSON(ctx, moduleInfoJSON)
}
+
+ mod.setSymbolsInfoProvider(ctx)
+}
+
+func (mod *Module) baseSymbolInfo(ctx android.ModuleContext) *cc.SymbolInfo {
+ return &cc.SymbolInfo{
+ Name: mod.BaseModuleName() + mod.Properties.SubName,
+ ModuleDir: ctx.ModuleDir(),
+ Uninstallable: mod.IsSkipInstall() || !proptools.BoolDefault(mod.Properties.Installable, true) || mod.NoFullInstall(),
+ }
+}
+
+func (mod *Module) getSymbolInfo(ctx android.ModuleContext, t any, info *cc.SymbolInfo) *cc.SymbolInfo {
+ switch tt := t.(type) {
+ case *binaryDecorator:
+ mod.getSymbolInfo(ctx, tt.baseCompiler, info)
+ case *testDecorator:
+ mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ case *benchmarkDecorator:
+ mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ case *libraryDecorator:
+ mod.getSymbolInfo(ctx, tt.baseCompiler, info)
+ case *procMacroDecorator:
+ mod.getSymbolInfo(ctx, tt.baseCompiler, info)
+ case *BaseSourceProvider:
+ outFile := tt.OutputFiles[0]
+ _, file := filepath.Split(outFile.String())
+ stem, suffix, _ := android.SplitFileExt(file)
+ info.Suffix = suffix
+ info.Stem = stem
+ info.Uninstallable = true
+ case *bindgenDecorator:
+ mod.getSymbolInfo(ctx, tt.BaseSourceProvider, info)
+ case *protobufDecorator:
+ mod.getSymbolInfo(ctx, tt.BaseSourceProvider, info)
+ case *baseCompiler:
+ if tt.path != (android.InstallPath{}) {
+ info.UnstrippedBinaryPath = tt.unstrippedOutputFile
+ path, file := filepath.Split(tt.path.String())
+ stem, suffix, _ := android.SplitFileExt(file)
+ info.Suffix = suffix
+ info.ModuleDir = path
+ info.Stem = stem
+ }
+ case *fuzzDecorator:
+ mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
+ case *prebuiltLibraryDecorator:
+ mod.getSymbolInfo(ctx, tt.baseCompiler, info)
+ case *toolchainLibraryDecorator:
+ mod.getSymbolInfo(ctx, tt.baseCompiler, info)
+ }
+ return info
+}
+
+func (mod *Module) setSymbolsInfoProvider(ctx android.ModuleContext) {
+ if !mod.Properties.HideFromMake && !mod.hideApexVariantFromMake {
+ infos := &cc.SymbolInfos{}
+ if mod.compiler != nil && !mod.compiler.Disabled() {
+ infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.compiler, mod.baseSymbolInfo(ctx)))
+ } else if mod.sourceProvider != nil {
+ infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.sourceProvider, mod.baseSymbolInfo(ctx)))
+ }
+
+ if mod.sanitize != nil {
+ infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.sanitize, mod.baseSymbolInfo(ctx)))
+ }
+
+ cc.CopySymbolsAndSetSymbolsInfoProvider(ctx, infos)
+ }
}
func (mod *Module) setOutputFiles(ctx ModuleContext) {
@@ -1386,6 +1504,9 @@ func (mod *Module) begin(ctx BaseModuleContext) {
if mod.sanitize != nil {
mod.sanitize.begin(ctx)
}
+ if mod.compiler != nil {
+ mod.compiler.begin(ctx)
+ }
if mod.UseSdk() && mod.IsSdkVariant() {
sdkVersion := ""
@@ -1496,9 +1617,12 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
- depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
+ depPaths.directApexImplementationDeps = append(depPaths.directApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
- depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
+ }
+ if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
+ depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
}
if !rustInfo.CompilerInfo.NoStdlibs {
@@ -1527,9 +1651,13 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
- // rlibs are not installed, so don't add the output file to directImplementationDeps
+ // rlibs are not installed, so don't add the output file to apexDirectImplementationDeps. Track them for RBE however.
+ depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
- depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
+ }
+ if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
+ depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
}
if !rustInfo.CompilerInfo.NoStdlibs {
@@ -1556,6 +1684,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// proc_macro link dirs need to be exported, so collect those here.
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
+ depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
+ if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
+ depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
+ }
+
case depTag == sourceDepTag:
if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
collectIncludedProtos(mod, rustInfo, linkableInfo)
@@ -1714,9 +1847,9 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
if !sharedLibraryInfo.IsStubs {
// TODO(b/362509506): remove this additional check once all apex_exclude uses are switched to stubs.
if !linkableInfo.RustApexExclude {
- depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
+ depPaths.directApexImplementationDeps = append(depPaths.directApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
- depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
}
}
}
@@ -1768,7 +1901,9 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
switch {
case depTag == cc.CrtBeginDepTag:
depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
+ depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
case depTag == cc.CrtEndDepTag:
+ depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, ""))
}
}
@@ -1781,7 +1916,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
})
- mod.transitiveAndroidMkSharedLibs = depset.New[string](depset.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)
+ mod.transitiveAndroidMkSharedLibs = depset.New(depset.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)
+
+ android.SetProvider(ctx, android.TestSuiteSharedLibsInfoProvider, android.TestSuiteSharedLibsInfo{
+ MakeNames: append(mod.transitiveAndroidMkSharedLibs.ToList(), mod.Properties.AndroidMkDylibs...),
+ })
var rlibDepFiles RustLibraries
aliases := mod.compiler.Aliases()
@@ -2231,28 +2370,15 @@ func libNameFromFilePath(filepath android.Path) (string, bool) {
return "", false
}
-func kytheExtractRustFactory() android.Singleton {
- return &kytheExtractRustSingleton{}
-}
-
-type kytheExtractRustSingleton struct {
+func (c *Module) Partition() string {
+ return ""
}
-func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var xrefTargets android.Paths
- ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
- if rustModule, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok {
- xrefTargets = append(xrefTargets, rustModule.XrefRustFiles...)
- }
- })
- if len(xrefTargets) > 0 {
- ctx.Phony("xref_rust", xrefTargets...)
- }
+type RustImplementationDepInfo struct {
+ NonApexImplementationDeps depset.DepSet[android.Path]
}
-func (c *Module) Partition() string {
- return ""
-}
+var RustImplementationDepInfoProvider = blueprint.NewProvider[*RustImplementationDepInfo]()
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
diff --git a/rust/test.go b/rust/test.go
index cedced260..9ca295b25 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -204,29 +204,17 @@ func (test *testDecorator) install(ctx ModuleContext) {
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
- if !ctx.Config().KatiEnabled() { // TODO(spandandas): Remove the special case for kati
- // Install the test config in testcases/ directory for atest.
- r, ok := ctx.Module().(*Module)
- if !ok {
- ctx.ModuleErrorf("Not a rust test module")
- }
- // Install configs in the root of $PRODUCT_OUT/testcases/$module
- testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName()+r.SubName())
- if ctx.PrimaryArch() {
- if test.testConfig != nil {
- ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
- }
- dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
- if dynamicConfig.Valid() {
- ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
- }
- }
- // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
- testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
- ctx.InstallTestData(testCases, test.data)
- testPath := ctx.RustModule().OutputFile().Path()
- ctx.InstallFile(testCases, testPath.Base(), testPath)
- }
+ // Install the test config in testcases/ directory for atest.
+ mainFile := ctx.RustModule().OutputFile().Path()
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ NameSuffix: ctx.RustModule().SubName(),
+ TestSuites: test.Properties.Test_suites,
+ MainFile: mainFile,
+ MainFileStem: mainFile.Base(),
+ ConfigFile: test.testConfig,
+ Data: test.data,
+ NeedsArchFolder: true,
+ })
test.binaryDecorator.installTestData(ctx, test.data)
test.binaryDecorator.install(ctx)
@@ -267,12 +255,22 @@ func RustTestFactory() android.Module {
// rustTestHostMultilib load hook to set MultilibFirst for the
// host target.
android.AddLoadHook(module, rustTestHostMultilib)
+
+ // Windows tests are currently unsupported, so disable them.
+ // To support Windows test modules, we likely need to switch
+ // to panic=unwind.
+ android.AddLoadHook(module, rustTestDisableWindows)
module.testModule = true
return module.Init()
}
func RustTestHostFactory() android.Module {
module, _ := NewRustTest(android.HostSupported)
+
+ // Windows tests are unsupported, so disable them.
+ // To support Windows test modules, we likely need to switch
+ // to panic=unwind.
+ android.AddLoadHook(module, rustTestDisableWindows)
module.testModule = true
return module.Init()
}
@@ -320,10 +318,6 @@ func (test *testDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *and
} else {
moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
}
-
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: test.Properties.Test_suites,
- })
}
func rustTestHostMultilib(ctx android.LoadHookContext) {
@@ -338,3 +332,16 @@ func rustTestHostMultilib(ctx android.LoadHookContext) {
p.Target.Host.Compile_multilib = proptools.StringPtr("first")
ctx.AppendProperties(p)
}
+
+func rustTestDisableWindows(ctx android.LoadHookContext) {
+ type props struct {
+ Target struct {
+ Windows struct {
+ Enabled bool
+ }
+ }
+ }
+ p := &props{}
+ p.Target.Windows.Enabled = false
+ ctx.AppendProperties(p)
+}
diff --git a/rust/testing.go b/rust/testing.go
index 2082b524e..10fa93aeb 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -190,6 +190,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
ctx.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
ctx.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
+ ctx.RegisterModuleType("rust_object", RustObjectFactory)
+ ctx.RegisterModuleType("rust_object_host", RustObjectHostFactory)
ctx.RegisterModuleType("rust_fuzz", RustFuzzFactory)
ctx.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
@@ -206,6 +208,5 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
ctx.PreDepsMutators(registerPreDepsMutators)
ctx.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
- ctx.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory)
ctx.PostDepsMutators(registerPostDepsMutators)
}
diff --git a/rust/toolchain_library.go b/rust/toolchain_library.go
index 054104ccc..b174daf28 100644
--- a/rust/toolchain_library.go
+++ b/rust/toolchain_library.go
@@ -52,6 +52,16 @@ type toolchainLibraryDecorator struct {
Properties toolchainLibraryProperties
}
+// toolchainCrateRoot implements toolchainCompiler.
+func (t *toolchainLibraryDecorator) toolchainCrateRoot() *string {
+ return t.Properties.Toolchain_crate_root
+}
+
+// toolchainSrcs implements toolchainCompiler.
+func (t *toolchainLibraryDecorator) toolchainSrcs() []string {
+ return t.Properties.Toolchain_srcs
+}
+
// rust_toolchain_library produces all rust variants.
func rustToolchainLibraryFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
@@ -87,12 +97,19 @@ func initToolchainLibrary(module *Module, library *libraryDecorator) android.Mod
return module.Init()
}
+type toolchainCompiler interface {
+ toolchainCrateRoot() *string
+ toolchainSrcs() []string
+}
+
+var _ toolchainCompiler = (*toolchainLibraryDecorator)(nil)
+
func rustSetToolchainSource(ctx android.LoadHookContext) {
- if toolchainLib, ok := ctx.Module().(*Module).compiler.(*toolchainLibraryDecorator); ok {
+ if toolchainLib, ok := ctx.Module().(*Module).compiler.(toolchainCompiler); ok {
prefix := filepath.Join("linux-x86", GetRustPrebuiltVersion(ctx))
- versionedCrateRoot := path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_crate_root))
- versionedSrcs := make([]string, len(toolchainLib.Properties.Toolchain_srcs))
- for i, src := range toolchainLib.Properties.Toolchain_srcs {
+ versionedCrateRoot := path.Join(prefix, android.String(toolchainLib.toolchainCrateRoot()))
+ versionedSrcs := make([]string, len(toolchainLib.toolchainSrcs()))
+ for i, src := range toolchainLib.toolchainSrcs() {
versionedSrcs[i] = path.Join(prefix, src)
}
@@ -105,7 +122,7 @@ func rustSetToolchainSource(ctx android.LoadHookContext) {
p.Srcs = versionedSrcs
ctx.AppendProperties(p)
} else {
- ctx.ModuleErrorf("Called rustSetToolchainSource on a non-Rust Module.")
+ ctx.ModuleErrorf("Called rustSetToolchainSource on a non-Toolchain Module.")
}
}
diff --git a/rust/toolchain_object.go b/rust/toolchain_object.go
new file mode 100644
index 000000000..ac16483a1
--- /dev/null
+++ b/rust/toolchain_object.go
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package rust
+
+import (
+ "android/soong/android"
+)
+
+// This module is used to compile the rust toolchain objects
+// When RUST_PREBUILTS_VERSION is set, the object will generated
+// from the given Rust version.
+func init() {
+ android.RegisterModuleType("rust_toolchain_object",
+ rustToolchainObjectFactory)
+ android.RegisterModuleType("rust_toolchain_object_host",
+ rustToolchainObjectHostFactory)
+}
+
+type toolchainObjectProperties struct {
+ // path to the toolchain object crate root, relative to the top of the toolchain source
+ Toolchain_crate_root *string `android:"arch_variant"`
+ // path to the rest of the toolchain srcs, relative to the top of the toolchain source
+ Toolchain_srcs []string `android:"arch_variant"`
+}
+
+type toolchainObjectDecorator struct {
+ *objectDecorator
+ Properties toolchainObjectProperties
+}
+
+// toolchainCrateRoot implements toolchainCompiler.
+func (t *toolchainObjectDecorator) toolchainCrateRoot() *string {
+ return t.Properties.Toolchain_crate_root
+}
+
+// toolchainSrcs implements toolchainCompiler.
+func (t *toolchainObjectDecorator) toolchainSrcs() []string {
+ return t.Properties.Toolchain_srcs
+}
+
+// rust_toolchain_library produces all rust variants.
+func rustToolchainObjectFactory() android.Module {
+ module, object := NewRustObject(android.HostAndDeviceSupported)
+ return initToolchainObject(module, object)
+}
+
+// rust_toolchain_library produces all rust variants.
+func rustToolchainObjectHostFactory() android.Module {
+ module, object := NewRustObject(android.HostSupported)
+ return initToolchainObject(module, object)
+}
+
+func initToolchainObject(module *Module, object *objectDecorator) android.Module {
+ toolchainObject := &toolchainObjectDecorator{
+ objectDecorator: object,
+ }
+ module.compiler = toolchainObject
+ module.AddProperties(&toolchainObject.Properties)
+
+ android.AddLoadHook(module, rustSetToolchainSource)
+
+ return module.Init()
+}
+
+func (t *toolchainObjectDecorator) compilerProps() []interface{} {
+ return append(t.objectDecorator.compilerProps(), &t.Properties)
+}
+
+func (t *toolchainObjectDecorator) crt() bool {
+ return t.objectDecorator.crt()
+}
+
+func (t *toolchainObjectDecorator) install(ctx ModuleContext) {
+ // Objects aren't installable, so do nothing.
+}
+
+func (t *toolchainObjectDecorator) everInstallable() bool {
+ // Objects aren't installable.
+ return false
+}
+
+var _ toolchainCompiler = (*toolchainObjectDecorator)(nil)
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index 983650039..0ca5c9973 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -75,6 +75,7 @@ javax\.xml\.xpath
jdk\.internal
jdk\.internal\.access
jdk\.internal\.event
+jdk\.internal\.invoke
jdk\.internal\.math
jdk\.internal\.misc
jdk\.internal\.ref
diff --git a/scripts/disk_usage.py b/scripts/disk_usage.py
new file mode 100644
index 000000000..940cea73a
--- /dev/null
+++ b/scripts/disk_usage.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+"""Calculates the disk size of each repository managed by 'repo'.
+
+This script invokes 'repo forall ...' to get the disk usage
+for each project repository and prints the combined output as a CSV.
+"""
+
+import os
+import re
+import subprocess
+import sys
+
+
+def get_repo_disk_usage() -> dict[str, int]:
+ """Invokes 'repo forall -p -c du -s .' and parses the output into a dictionary.
+
+ Returns:
+ A dictionary mapping project paths (str) to their disk size in bytes (int).
+ Returns an empty dictionary if the input is empty or malformed.
+
+ Raises:
+ subprocess.CalledProcessError: If the command returns a non-zero exit
+ code.
+ FileNotFoundError: If the 'repo' command is not found.
+ """
+ output = subprocess.check_output(
+ ["repo", "forall", "-p", "-c", "du", "-s", "-b", "."],
+ text=True,
+ )
+
+ project_sizes: dict[str, int] = {}
+ lines = output.strip().split("\n")
+ current_project_name = None
+
+ for line in lines:
+ line = line.strip()
+ if not line:
+ continue # Skip empty lines
+
+ if line.startswith("project "):
+ # Extract project name: remove "project " prefix and trailing "/"
+ current_project_name = line.removeprefix("project ").removesuffix("/")
+ elif current_project_name is not None:
+ match = re.match(r"^(\d+)\s+\.$", line)
+ if not match:
+ continue
+ size_str = match.group(1)
+ project_sizes[current_project_name] = int(size_str)
+ current_project_name = None # Reset for the next project
+
+ return project_sizes
+
+
+def get_dot_repo_size() -> int:
+ """Gets the disk usage of the '.repo' directory in bytes.
+
+ Returns:
+ The size of the '.repo' directory in bytes. Returns 0 if the command
+ fails or the directory doesn't exist (du returns 0).
+
+ Raises:
+ FileNotFoundError: If the 'du' command is not found.
+ # Note: subprocess.CalledProcessError is not explicitly raised on failure
+ # because we want to return 0 in that case.
+ """
+
+ result = subprocess.check_output(["du", "-s", "-b", ".repo"], text=True)
+ size_str = result.split()[0]
+ return int(size_str)
+
+
+def main():
+ if not os.path.isdir(".repo"):
+ sys.exit("Error: .repo directory not found, run inside a repo root.")
+
+ project_sizes = get_repo_disk_usage()
+ dot_repo_size = get_dot_repo_size()
+
+ print("project_name,size_bytes")
+ print(f".repo,{dot_repo_size}")
+ for name, size_bytes in sorted(project_sizes.items()):
+ print(f"{name},{size_bytes}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
index 16507bb11..901df4b5a 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -477,9 +477,6 @@ def append_additional_vendor_props(args):
if config["ShippingApiLevel"]:
props.append(f"ro.product.first_api_level={config['ShippingApiLevel']}")
- if config["ShippingVendorApiLevel"]:
- props.append(f"ro.vendor.api_level={config['ShippingVendorApiLevel']}")
-
if config["BuildVariant"] != "user" and config["BuildDebugfsRestrictionsEnabled"]:
props.append(f"ro.product.debugfs_restrictions.enabled=true")
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 96dc5a6ce..975709e72 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -80,6 +80,13 @@ def parse_args():
dest='dexpreopt_configs',
action='append',
help='a paths to a dexpreopt.config of some library')
+ parser.add_argument(
+ '--bootclasspath-libs',
+ dest='bootclasspath_libs',
+ action='append',
+ help='jars in the bootclasspath, which should be ignored by the uses '
+ 'libraries check',
+ default=[])
parser.add_argument('--aapt', dest='aapt', help='path to aapt executable')
parser.add_argument(
'--output', '-o', dest='output', help='output AndroidManifest.xml file')
@@ -94,7 +101,8 @@ C_OFF = "\033[0m"
C_BOLD = "\033[1m"
-def enforce_uses_libraries(manifest, required, optional, missing_optional, relax, is_apk, path):
+def enforce_uses_libraries(manifest, required, optional, missing_optional, relax, is_apk, path,
+ bootclasspath_libs):
"""Verify that the <uses-library> tags in the manifest match those provided
by the build system.
@@ -113,6 +121,10 @@ def enforce_uses_libraries(manifest, required, optional, missing_optional, relax
manifest_required, manifest_optional, tags = extract_uses_libs_xml(
manifest)
+ # Filter out bootclasspath libs from the manifest to ignore them in the check.
+ manifest_required = [lib for lib in manifest_required if lib not in bootclasspath_libs]
+ manifest_optional = [lib for lib in manifest_optional if lib not in bootclasspath_libs]
+
# Trim namespace component. Normally Soong does that automatically when it
# handles module names specified in Android.bp properties. However not all
# <uses-library> entries in the manifest correspond to real modules: some of
@@ -361,7 +373,8 @@ def main():
# script was passed a special parameter to suppress exceptions.
errmsg = enforce_uses_libraries(manifest, required, optional,
args.missing_optional_uses_libraries,
- args.enforce_uses_libraries_relax, is_apk, args.input)
+ args.enforce_uses_libraries_relax, is_apk, args.input,
+ args.bootclasspath_libs)
# Create a status file that is empty on success, or contains an
# error message on failure. When exceptions are suppressed,
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index abe0d8b0e..eedce18b6 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -45,18 +45,17 @@ class EnforceUsesLibrariesTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
def run_test(self, xml, apk, uses_libraries=(), optional_uses_libraries=(),
- missing_optional_uses_libraries=()): #pylint: disable=dangerous-default-value
+ missing_optional_uses_libraries=(),
+ bootclasspath_libs=()): #pylint: disable=dangerous-default-value
doc = minidom.parseString(xml)
try:
relax = False
manifest_check.enforce_uses_libraries(
doc, uses_libraries, optional_uses_libraries, missing_optional_uses_libraries,
- relax, False, 'path/to/X/AndroidManifest.xml')
- manifest_check.enforce_uses_libraries(apk, uses_libraries,
- optional_uses_libraries,
- missing_optional_uses_libraries,
- relax, True,
- 'path/to/X/X.apk')
+ relax, False, 'path/to/X/AndroidManifest.xml', bootclasspath_libs)
+ manifest_check.enforce_uses_libraries(
+ apk, uses_libraries, optional_uses_libraries, missing_optional_uses_libraries,
+ relax, True, 'path/to/X/X.apk', bootclasspath_libs)
return True
except manifest_check.ManifestMismatchError:
return False
@@ -260,6 +259,15 @@ class EnforceUsesLibrariesTest(unittest.TestCase):
optional_uses_libraries=['//x/y/z:bar', '//x/y/z:qux'])
self.assertTrue(matches)
+ def test_ignore_bootclasspath_libs(self):
+ xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True)))
+ apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True)))
+ xml = self.xml_tmpl % (uses_library_xml('bar', required_xml(False)))
+ apk = self.apk_tmpl % (uses_library_apk('bar', required_apk(False)))
+ matches = self.run_test(xml, apk, uses_libraries=[], optional_uses_libraries=[],
+ bootclasspath_libs=['foo', 'bar'])
+ self.assertTrue(matches)
+
class ExtractTargetSdkVersionTest(unittest.TestCase):
diff --git a/scripts/rustc_linker.py b/scripts/rustc_linker.py
index 3f60708e2..c9c4a1515 100755
--- a/scripts/rustc_linker.py
+++ b/scripts/rustc_linker.py
@@ -31,27 +31,40 @@ replacementVersionScript = None
argparser = argparse.ArgumentParser()
argparser.add_argument('--android-clang-bin', required=True)
args = argparser.parse_known_args()
-clang_args = [args[0].android_clang_bin] + args[1]
+old_clang_args = [args[0].android_clang_bin] + args[1]
+new_clang_args = list()
-for i, arg in enumerate(clang_args):
+# Add/remove args
+for i, arg in enumerate(old_clang_args):
+ # Record and remove the custom android-version-script arg
if arg.startswith('-Wl,--android-version-script='):
replacementVersionScript = arg.split("=")[1]
- del clang_args[i]
- break
+ continue
+ # Remove object files rustc emits for Windows target
+ # We provide these as an rlib.
+ if arg == "rsend.o":
+ continue
+ if arg == "rsbegin.o":
+ continue
+
+ # Keep the arg
+ new_clang_args.append(old_clang_args[i])
+
+# Modify args
if replacementVersionScript:
versionScriptFound = False
- for i, arg in enumerate(clang_args):
+ for i, arg in enumerate(new_clang_args):
if arg.startswith('-Wl,--version-script='):
- clang_args[i] ='-Wl,--version-script=' + replacementVersionScript
+ new_clang_args[i] ='-Wl,--version-script=' + replacementVersionScript
versionScriptFound = True
break
if not versionScriptFound:
# If rustc did not emit a version script, just append the arg
- clang_args.append('-Wl,--version-script=' + replacementVersionScript)
+ new_clang_args.append('-Wl,--version-script=' + replacementVersionScript)
try:
- subprocess.run(clang_args, encoding='utf-8', check=True)
+ subprocess.run(new_clang_args, encoding='utf-8', check=True)
except subprocess.CalledProcessError as e:
sys.exit(-1)
diff --git a/scripts/soong_only_diff_test.py b/scripts/soong_only_diff_test.py
new file mode 100755
index 000000000..f72b88d2e
--- /dev/null
+++ b/scripts/soong_only_diff_test.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python3
+#
+# Copyright 2025 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+import os
+import shutil
+import stat
+import struct
+import subprocess
+import sys
+import zipfile
+
+from ninja_determinism_test import Product, get_top, transitively_included_ninja_files
+
+def run_build_target_files_zip(product: Product, soong_only: bool) -> bool:
+ """Runs a build and returns if it succeeded or not."""
+ soong_only_arg = '--no-soong-only'
+ if soong_only:
+ soong_only_arg = '--soong-only'
+
+ out_dir = os.getenv('OUT_DIR', 'out')
+
+ if not os.path.exists(out_dir):
+ os.mkdir(out_dir)
+
+ with open(os.path.join(out_dir, 'build.log'), 'wb') as f:
+ result = subprocess.run([
+ 'build/soong/soong_ui.bash',
+ '--make-mode',
+ 'USE_RBE=true',
+ 'BUILD_DATETIME=1',
+ 'USE_FIXED_TIMESTAMP_IMG_FILES=true',
+ 'DISABLE_NOTICE_XML_GENERATION=true',
+ f'TARGET_PRODUCT={product.product}',
+ f'TARGET_RELEASE={product.release}',
+ f'TARGET_BUILD_VARIANT={product.variant}',
+ 'target-files-package',
+ 'dist',
+ soong_only_arg,
+ ], stdout=f, stderr=subprocess.STDOUT, env=os.environ)
+ return result.returncode == 0
+
+# These values are defined in build/soong/zip/zip.go
+SHA_256_HEADER_ID = 0x4967
+SHA_256_HEADER_SIGNATURE = 0x9514
+
+def get_local_file_sha256_fields(zip_filepath: os.PathLike) -> dict[str, bytes]:
+ if not os.path.exists(zip_filepath):
+ print(f"Error: File not found at {zip_filepath}", file=sys.stderr)
+ return None
+
+ sha256_checksums: dict[str, bytes] = {}
+
+ with zipfile.ZipFile(zip_filepath, 'r') as zip_ref:
+ infolist = zip_ref.infolist()
+
+ for member_info in infolist:
+ # Skip if the entry is a directory or does not contain the sha256 value, which
+ # is included in the extra field.
+ if member_info.is_dir() or len(member_info.extra) == 0:
+ continue
+
+ local_extra_data = member_info.extra
+
+ i = 0
+ found_sha_in_file = None
+ while i + 4 <= len(local_extra_data): # Need at least 4 (header ID + data size)
+ block_header_id, block_data_size = struct.unpack('<HH', local_extra_data[i:i+4])
+
+ current_block_end = i + 4 + block_data_size
+
+ # Check if the block is SHA256 block
+ if block_header_id == SHA_256_HEADER_ID:
+ if block_data_size >= 2:
+ data_bytes = local_extra_data[i+4 : current_block_end]
+
+ # Check internal signature
+ internal_sig = struct.unpack('<H', data_bytes[0:2])[0]
+ if internal_sig == SHA_256_HEADER_SIGNATURE:
+ found_sha_in_file = data_bytes[2:]
+ break
+
+ i += (4 + block_data_size)
+
+ if found_sha_in_file:
+ sha256_checksums[member_info.filename] = found_sha_in_file
+ elif member_info.external_attr != 0:
+ # Upper 16 bits of external_attr are UNIX permissions.
+ # If the file is a symlink then add its target as the value of the map.
+ mode = (member_info.external_attr >> 16) & 0xFFFF
+ if stat.S_ISLNK(mode):
+ target = zip_ref.read(member_info.filename)
+ sha256_checksums[member_info.filename] = target
+ else:
+ print(f"{member_info.filename} sha not found", file=sys.stderr)
+
+ return sha256_checksums
+
+def find_build_id() -> str | None:
+ tag_file_path = os.path.join(os.getenv('OUT_DIR', 'out'), 'file_name_tag.txt')
+ build_id = None
+
+ with open(tag_file_path, 'r', encoding='utf-8') as f:
+ build_id = f.read().strip()
+
+ return build_id
+
+def zip_ninja_files(subdistdir: str, product: Product):
+ out_dir = os.getenv('OUT_DIR', 'out')
+ root_dir = os.path.dirname(out_dir)
+ files_to_zip = transitively_included_ninja_files(out_dir, os.path.join(out_dir, f'combined-{product.product}.ninja'), {})
+
+ zip_filename = os.path.join(subdistdir, "ninja_files.zip")
+ with zipfile.ZipFile(zip_filename, 'w', compression=zipfile.ZIP_DEFLATED) as zipf:
+ for file in files_to_zip:
+ zipf.write(filename=file, arcname=os.path.relpath(file, root_dir))
+
+def move_artifacts_to_subfolder(product: Product, soong_only: bool):
+ subdir = "soong_only" if soong_only else "soong_plus_make"
+
+ out_dir = os.getenv('OUT_DIR', 'out')
+ dist_dir = os.getenv('DIST_DIR', os.path.join(out_dir, 'dist'))
+ subdistdir = os.path.join(dist_dir, subdir)
+ if os.path.exists(subdistdir):
+ shutil.rmtree(subdistdir)
+ os.makedirs(subdistdir)
+ zip_ninja_files(subdistdir, product)
+
+ build_id = find_build_id()
+
+ files_to_move = [
+ os.path.join(dist_dir, f'{product.product}-target_files-{build_id}.zip'), # target_files.zip
+ os.path.join(out_dir, 'build.log'),
+ ]
+
+ for file in files_to_move:
+ shutil.move(file, subdistdir)
+
+SHA_DIFF_ALLOWLIST = {
+ "IMAGES/system.img",
+ "IMAGES/system_ext.img", # TODO: b/406045340 - Remove from the allowlist once it's fixed
+ "IMAGES/userdata.img",
+ "IMAGES/vbmeta_system.img",
+ "META/misc_info.txt",
+ "META/vbmeta_digest.txt",
+ "SYSTEM_EXT/etc/vm/trusty_vm/trusty_security_vm.elf", # TODO: b/406045340 - Remove from the allowlist once it's fixed
+ "SYSTEM/apex/com.android.resolv.capex", # TODO: b/411514418 - Remove once nondeterminism is fixed
+}
+
+def compare_sha_maps(soong_only_map: dict[str, bytes], soong_plus_make_map: dict[str, bytes]) -> bool:
+ """Compares two sha maps and reports any missing or different entries."""
+
+ all_keys = list(soong_only_map.keys() | soong_plus_make_map.keys())
+ all_identical = True
+ for key in all_keys:
+ allowlisted = key in SHA_DIFF_ALLOWLIST
+ allowlisted_str = "ALLOWLISTED" if allowlisted else "NOT ALLOWLISTED"
+ file = None if allowlisted else sys.stderr
+ if key not in soong_only_map:
+ print(f'{key} not found in soong only build target_files.zip ({allowlisted_str})', file=file)
+ all_identical = all_identical and allowlisted
+ elif key not in soong_plus_make_map:
+ print(f'{key} not found in soong plus make build target_files.zip ({allowlisted_str})', file=file)
+ all_identical = all_identical and allowlisted
+ elif soong_only_map[key] != soong_plus_make_map[key]:
+ print(f'{key} sha value differ between soong only build and soong plus make build ({allowlisted_str})', file=file)
+ all_identical = all_identical and allowlisted
+
+ return all_identical
+
+def get_zip_sha_map(product: Product, soong_only: bool) -> dict[str, bytes]:
+ """Runs the build and returns the map of entries to its SHA256 values of target_files.zip."""
+
+ out_dir = os.getenv('OUT_DIR', 'out')
+
+ build_type = "soong only" if soong_only else "soong plus make"
+
+ build_success = run_build_target_files_zip(product, soong_only)
+ if not build_success:
+ with open(os.path.join(out_dir, 'build.log'), 'r') as f:
+ print(f.read(), file=sys.stderr)
+ sys.exit(f'{build_type} build failed')
+
+ build_id = find_build_id()
+ dist_dir = os.getenv('DIST_DIR', os.path.join(out_dir, 'dist'))
+ target_files_zip = os.path.join(dist_dir, f'{product.product}-target_files-{build_id}.zip')
+ zip_sha_map = get_local_file_sha256_fields(target_files_zip)
+ if zip_sha_map is None:
+ sys.exit("Could not construct sha map for target_files.zip entries for soong only build")
+
+ return zip_sha_map
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("product", help="target product name")
+ return parser.parse_args()
+
+def main():
+ os.chdir(get_top())
+
+ args = parse_args()
+
+ product = Product(
+ args.product,
+ 'trunk_staging',
+ 'userdebug',
+ )
+
+ soong_only = True
+ soong_only_zip_sha_map = get_zip_sha_map(product, soong_only)
+ move_artifacts_to_subfolder(product, soong_only)
+
+ soong_only = False
+ soong_plus_make_zip_sha_map = get_zip_sha_map(product, soong_only)
+ move_artifacts_to_subfolder(product, soong_only)
+
+ if not compare_sha_maps(soong_only_zip_sha_map, soong_plus_make_zip_sha_map):
+ sys.exit("target_files.zip differ between soong only build and soong plus make build")
+
+ print("target_files.zip are identical between soong only build and soong plus make build")
+
+if __name__ == "__main__":
+ main()
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 80ced00bf..8986efd48 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -21,6 +21,7 @@ import (
"testing"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java"
)
@@ -91,6 +92,8 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(
"com.android.art", "art-bootclasspath-fragment", java.ApexBootJarFragmentsForPlatformBootclasspath),
+ dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
+
java.PrepareForBootImageConfigTest,
java.PrepareApexBootJarConfigsAndModules,
android.FixtureWithRootAndroidBp(`
diff --git a/sdk/member_trait_test.go b/sdk/member_trait_test.go
index 9b41e9b7a..6bcc5b110 100644
--- a/sdk/member_trait_test.go
+++ b/sdk/member_trait_test.go
@@ -45,7 +45,7 @@ func (t *fakeMemberType) AddDependencies(ctx android.SdkDependencyContext, depen
}
}
-func (t *fakeMemberType) IsInstance(module android.Module) bool {
+func (t *fakeMemberType) IsInstance(_ android.ModuleContext, _ android.ModuleProxy) bool {
return true
}
@@ -67,8 +67,8 @@ type fakeMemberTypeProperties struct {
path android.Path
}
-func (t *fakeMemberTypeProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- headerJars := variant.(java.ApexDependency).HeaderJars()
+func (t *fakeMemberTypeProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.ModuleProxy) {
+ headerJars := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, java.JavaInfoProvider).HeaderJars
if len(headerJars) != 1 {
panic(fmt.Errorf("there must be only one header jar from %q", variant.Name()))
}
diff --git a/sdk/sdk.go b/sdk/sdk.go
index ab50659cd..46f7d27a7 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -186,6 +186,9 @@ func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.SetOutputFiles([]android.Path{s.snapshotFile.Path()}, "")
ctx.SetOutputFiles([]android.Path{s.snapshotFile.Path(), s.infoFile.Path()}, android.DefaultDistTag)
}
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"FAKE"}
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/sdk/update.go b/sdk/update.go
index 00352cb1d..684598270 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -115,10 +115,10 @@ func (gc *generatedContents) UnindentedPrintf(format string, args ...interface{}
// multilibs (32/64/both) are used by this sdk variant.
func (s *sdk) collectMembers(ctx android.ModuleContext) {
s.multilibUsages = multilibNone
- ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
tag := ctx.OtherModuleDependencyTag(child)
if memberTag, ok := tag.(android.SdkMemberDependencyTag); ok {
- memberType := memberTag.SdkMemberType(child)
+ memberType := memberTag.SdkMemberType(ctx, child)
// If a nil SdkMemberType was returned then this module should not be added to the sdk.
if memberType == nil {
@@ -126,32 +126,31 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) {
}
// Make sure that the resolved module is allowed in the member list property.
- if !memberType.IsInstance(child) {
+ if !memberType.IsInstance(ctx, child) {
ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())
}
// Keep track of which multilib variants are used by the sdk.
- s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider)
+ s.multilibUsages = s.multilibUsages.addArchType(commonInfo.Target.Arch.ArchType)
exportedComponentsInfo, _ := android.OtherModuleProvider(ctx, child, android.ExportedComponentsInfoProvider)
- var container android.Module
- if parent != ctx.Module() {
- container = parent
- }
-
- minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child)
-
+ minApiLevel := android.MinApiLevelForSdkSnapshot(commonInfo)
export := memberTag.ExportMember()
- s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
+ vd := sdkMemberVariantDep{
sdkVariant: s,
memberType: memberType,
variant: child,
minApiLevel: minApiLevel,
- container: container,
export: export,
exportedComponentsInfo: exportedComponentsInfo,
- })
+ }
+ if !android.EqualModules(parent, ctx.Module()) {
+ container := parent
+ vd.container = &container
+ }
+ s.memberVariantDeps = append(s.memberVariantDeps, vd)
// Recurse down into the member's dependencies as it may have dependencies that need to be
// automatically added to the sdk.
@@ -198,7 +197,7 @@ func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, tar
if err != nil {
targetApiLevel = android.FutureApiLevel
}
- if lastApiLevel, exists := ignoreHostModuleVariantsAboveDessert[name]; exists && targetApiLevel.GreaterThan(lastApiLevel) && memberVariantDep.Host() {
+ if lastApiLevel, exists := ignoreHostModuleVariantsAboveDessert[name]; exists && targetApiLevel.GreaterThan(lastApiLevel) && memberVariantDep.Host(ctx) {
// ignore host variant of this module if the targetApiLevel is V and above.
continue
}
@@ -255,7 +254,7 @@ func isMemberTypeSupportedByTargetBuildRelease(memberType android.SdkMemberType,
return supportedByTargetBuildRelease
}
-func appendUniqueVariants(variants []android.Module, newVariant android.Module) []android.Module {
+func appendUniqueVariants(variants []android.ModuleProxy, newVariant android.ModuleProxy) []android.ModuleProxy {
for _, v := range variants {
if v == newVariant {
return variants
@@ -346,7 +345,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) {
// Always include host variants (e.g. host tools) in the snapshot.
// Host variants should not be guarded by a min_sdk_version check. In fact, host variants
// do not have a `min_sdk_version`.
- if memberVariantDep.Host() {
+ if memberVariantDep.Host(ctx) {
exclude = false
}
@@ -623,7 +622,7 @@ func (s *sdk) generateInfoData(ctx android.ModuleContext, memberVariantDeps []sd
modules = append(modules, &sdkInfo)
name2Info := map[string]*moduleInfo{}
- getModuleInfo := func(module android.Module) *moduleInfo {
+ getModuleInfo := func(module android.ModuleProxy) *moduleInfo {
name := module.Name()
info := name2Info[name]
if info == nil {
@@ -655,7 +654,7 @@ func (s *sdk) generateInfoData(ctx android.ModuleContext, memberVariantDeps []sd
sdkInfo.memberSpecific[propertyName] = android.SortedUniqueStrings(list)
if memberVariantDep.container != nil {
- containerInfo := getModuleInfo(memberVariantDep.container)
+ containerInfo := getModuleInfo(*memberVariantDep.container)
containerInfo.deps = android.SortedUniqueStrings(append(containerInfo.deps, memberName))
}
@@ -1129,8 +1128,8 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType
}
// Where available copy apex_available properties from the member.
- if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
- apexAvailable := apexAware.ApexAvailable()
+ if info, ok := android.OtherModuleProvider(s.ctx, variant, android.CommonModuleInfoProvider); ok && info.IsApexModule {
+ apexAvailable := info.ApexAvailable
if len(apexAvailable) == 0 {
// //apex_available:platform is the default.
apexAvailable = []string{android.AvailableToPlatform}
@@ -1154,7 +1153,7 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType
hostSupported := false
for _, variant := range member.Variants() {
- osClass := variant.Target().Os.Class
+ osClass := android.OtherModulePointerProviderOrDefault(mctx, variant, android.CommonModuleInfoProvider).Target.Os.Class
if osClass == android.Host {
hostSupported = true
} else if osClass == android.Device {
@@ -1250,12 +1249,12 @@ type sdkMemberVariantDep struct {
memberType android.SdkMemberType
// The variant that is added to the sdk.
- variant android.Module
+ variant android.ModuleProxy
// The optional container of this member, i.e. the module that is depended upon by the sdk
// (possibly transitively) and whose dependency on this module is why it was added to the sdk.
// Is nil if this a direct dependency of the sdk.
- container android.Module
+ container *android.ModuleProxy
// True if the member should be exported, i.e. accessible, from outside the sdk.
export bool
@@ -1268,8 +1267,8 @@ type sdkMemberVariantDep struct {
}
// Host returns true if the sdk member is a host variant (e.g. host tool)
-func (s *sdkMemberVariantDep) Host() bool {
- return s.variant.Target().Os.Class == android.Host
+func (s *sdkMemberVariantDep) Host(ctx android.ModuleContext) bool {
+ return android.OtherModulePointerProviderOrDefault(ctx, s.variant, android.CommonModuleInfoProvider).Host
}
var _ android.SdkMember = (*sdkMember)(nil)
@@ -1279,14 +1278,14 @@ var _ android.SdkMember = (*sdkMember)(nil)
type sdkMember struct {
memberType android.SdkMemberType
name string
- variants []android.Module
+ variants []android.ModuleProxy
}
func (m *sdkMember) Name() string {
return m.name
}
-func (m *sdkMember) Variants() []android.Module {
+func (m *sdkMember) Variants() []android.ModuleProxy {
return m.variants
}
@@ -1344,15 +1343,16 @@ type variantCoordinate struct {
linkType string
}
-func getVariantCoordinate(ctx *memberContext, variant android.Module) variantCoordinate {
+func getVariantCoordinate(ctx *memberContext, variant android.ModuleProxy) variantCoordinate {
linkType := ""
if len(ctx.MemberType().SupportedLinkages()) > 0 {
- linkType = getLinkType(variant)
+ linkType = getLinkType(ctx.sdkMemberContext, variant)
}
+ info := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider)
return variantCoordinate{
- osType: variant.Target().Os,
- archId: archIdFromTarget(variant.Target()),
- image: variant.ImageVariation().Variation,
+ osType: info.Target.Os,
+ archId: archIdFromTarget(info.Target),
+ image: info.ImageVariation.Variation,
linkType: linkType,
}
}
@@ -1371,24 +1371,24 @@ func getVariantCoordinate(ctx *memberContext, variant android.Module) variantCoo
// by apex variant, where one is the default/platform variant and one is the APEX variant. In that
// case it picks the APEX variant. It picks the APEX variant because that is the behavior that would
// be expected
-func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.Module) []android.Module {
+func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.ModuleProxy) []android.ModuleProxy {
moduleCtx := ctx.sdkMemberContext
// Group the variants by coordinates.
- variantsByCoord := make(map[variantCoordinate][]android.Module)
+ variantsByCoord := make(map[variantCoordinate][]android.ModuleProxy)
for _, variant := range variants {
coord := getVariantCoordinate(ctx, variant)
variantsByCoord[coord] = append(variantsByCoord[coord], variant)
}
- toDiscard := make(map[android.Module]struct{})
+ toDiscard := make(map[android.ModuleProxy]struct{})
for coord, list := range variantsByCoord {
count := len(list)
if count == 1 {
continue
}
- variantsByApex := make(map[string]android.Module)
+ variantsByApex := make(map[string]android.ModuleProxy)
conflictDetected := false
for _, variant := range list {
apexInfo, _ := android.OtherModuleProvider(moduleCtx, variant, android.ApexInfoProvider)
@@ -1430,7 +1430,7 @@ func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.Mod
// If there are any variants to discard then remove them from the list of variants, while
// preserving the order.
if len(toDiscard) > 0 {
- filtered := []android.Module{}
+ filtered := []android.ModuleProxy{}
for _, variant := range variants {
if _, ok := toDiscard[variant]; !ok {
filtered = append(filtered, variant)
@@ -1469,7 +1469,7 @@ type variantPropertiesFactoryFunc func() android.SdkMemberProperties
// Create a new osTypeSpecificInfo for the specified os type and its properties
// structures populated with information from the variants.
-func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, osTypeVariants []android.Module) *osTypeSpecificInfo {
+func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, osTypeVariants []android.ModuleProxy) *osTypeSpecificInfo {
osInfo := &osTypeSpecificInfo{
osType: osType,
}
@@ -1485,10 +1485,10 @@ func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType,
osInfo.Properties = osSpecificVariantPropertiesFactory()
// Group the variants by arch type.
- var variantsByArchId = make(map[archId][]android.Module)
+ var variantsByArchId = make(map[archId][]android.ModuleProxy)
var archIds []archId
for _, variant := range osTypeVariants {
- target := variant.Target()
+ target := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider).Target
id := archIdFromTarget(target)
if _, ok := variantsByArchId[id]; !ok {
archIds = append(archIds, id)
@@ -1695,7 +1695,7 @@ var _ propertiesContainer = (*archTypeSpecificInfo)(nil)
// Create a new archTypeSpecificInfo for the specified arch type and its properties
// structures populated with information from the variants.
-func newArchSpecificInfo(ctx android.SdkMemberContext, archId archId, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.Module) *archTypeSpecificInfo {
+func newArchSpecificInfo(ctx android.SdkMemberContext, archId archId, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.ModuleProxy) *archTypeSpecificInfo {
// Create an arch specific info into which the variant properties can be copied.
archInfo := &archTypeSpecificInfo{archId: archId, osType: osType}
@@ -1710,9 +1710,9 @@ func newArchSpecificInfo(ctx android.SdkMemberContext, archId archId, osType and
archInfo.Properties.PopulateFromVariant(ctx, archVariants[0])
} else {
// Group the variants by image type.
- variantsByImage := make(map[string][]android.Module)
+ variantsByImage := make(map[string][]android.ModuleProxy)
for _, variant := range archVariants {
- image := variant.ImageVariation().Variation
+ image := android.OtherModulePointerProviderOrDefault(ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider).ImageVariation.Variation
variantsByImage[image] = append(variantsByImage[image], variant)
}
@@ -1730,14 +1730,14 @@ func newArchSpecificInfo(ctx android.SdkMemberContext, archId archId, osType and
//
// If the variant is not differentiated by link type then it returns "",
// otherwise it returns one of "static" or "shared".
-func getLinkType(variant android.Module) string {
+func getLinkType(ctx android.ModuleContext, variant android.ModuleProxy) string {
linkType := ""
- if linkable, ok := variant.(cc.LinkableInterface); ok {
- if linkable.Shared() && linkable.Static() {
+ if linkable, ok := android.OtherModuleProvider(ctx, variant, cc.LinkableInfoProvider); ok {
+ if linkable.Shared && linkable.Static {
panic(fmt.Errorf("expected variant %q to be either static or shared but was both", variant.String()))
- } else if linkable.Shared() {
+ } else if linkable.Shared {
linkType = "shared"
- } else if linkable.Static() {
+ } else if linkable.Static {
linkType = "static"
} else {
panic(fmt.Errorf("expected variant %q to be either static or shared but was neither", variant.String()))
@@ -1825,7 +1825,7 @@ type imageVariantSpecificInfo struct {
linkInfos []*linkTypeSpecificInfo
}
-func newImageVariantSpecificInfo(ctx android.SdkMemberContext, imageVariant string, variantPropertiesFactory variantPropertiesFactoryFunc, imageVariants []android.Module) *imageVariantSpecificInfo {
+func newImageVariantSpecificInfo(ctx android.SdkMemberContext, imageVariant string, variantPropertiesFactory variantPropertiesFactoryFunc, imageVariants []android.ModuleProxy) *imageVariantSpecificInfo {
// Create an image variant specific info into which the variant properties can be copied.
imageInfo := &imageVariantSpecificInfo{imageVariant: imageVariant}
@@ -1841,7 +1841,7 @@ func newImageVariantSpecificInfo(ctx android.SdkMemberContext, imageVariant stri
// There is more than one variant for this image variant which must be differentiated by link
// type. Or there are multiple supported linkages and we need to nest based on link type.
for _, linkVariant := range imageVariants {
- linkType := getLinkType(linkVariant)
+ linkType := getLinkType(ctx.SdkModuleContext(), linkVariant)
if linkType == "" {
panic(fmt.Errorf("expected one arch specific variant as it is not identified by link type but found %d", len(imageVariants)))
} else {
@@ -1925,7 +1925,7 @@ var _ propertiesContainer = (*linkTypeSpecificInfo)(nil)
// Create a new linkTypeSpecificInfo for the specified link type and its properties
// structures populated with information from the variant.
-func newLinkSpecificInfo(ctx android.SdkMemberContext, linkType string, variantPropertiesFactory variantPropertiesFactoryFunc, linkVariant android.Module) *linkTypeSpecificInfo {
+func newLinkSpecificInfo(ctx android.SdkMemberContext, linkType string, variantPropertiesFactory variantPropertiesFactoryFunc, linkVariant android.ModuleProxy) *linkTypeSpecificInfo {
linkInfo := &linkTypeSpecificInfo{
baseInfo: baseInfo{
// Create the properties into which the link type specific properties will be
@@ -2008,9 +2008,10 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu
variants := selectApexVariantsWhereAvailable(ctx, member.variants)
// Group the variants by os type.
- variantsByOsType := make(map[android.OsType][]android.Module)
+ variantsByOsType := make(map[android.OsType][]android.ModuleProxy)
for _, variant := range variants {
- osType := variant.Target().Os
+ osType := android.OtherModulePointerProviderOrDefault(
+ ctx.SdkModuleContext(), variant, android.CommonModuleInfoProvider).Target.Os
variantsByOsType[osType] = append(variantsByOsType[osType], variant)
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 57f5ad1c7..257d60936 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -540,6 +540,17 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
installedData := ctx.InstallTestData(s.installDir, s.data)
s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath, installedData...)
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: s.testProperties.Test_suites,
+ MainFile: s.outputFilePath,
+ MainFileStem: s.outputFilePath.Base(),
+ ConfigFile: s.testConfig,
+ ExtraConfigs: s.extraTestConfigs,
+ Data: s.data,
+ NeedsArchFolder: true,
+ PerTestcaseDirectory: proptools.Bool(s.testProperties.Per_testcase_directory),
+ })
+
mkEntries := s.AndroidMkEntries()[0]
android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
TestcaseRelDataFiles: addArch(ctx.Arch().ArchType.String(), installedData.Paths()),
@@ -574,10 +585,6 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.testConfig.String())
}
moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.extraTestConfigs.Strings()...)
-
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: s.testProperties.Test_suites,
- })
}
func addArch(archType string, paths android.Paths) []string {
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index a398cbce2..a82bf66de 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -86,14 +86,20 @@ func init() {
pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust")
}
+var SyspropLibraryInfoProvider = blueprint.NewProvider[SyspropLibraryInfo]()
+
+type SyspropLibraryInfo struct {
+ CheckApiFileTimeStamp android.WritablePath
+}
+
// syspropJavaGenRule module generates srcjar containing generated java APIs.
// It also depends on check api rule, so api check has to pass to use sysprop_library.
func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var checkApiFileTimeStamp android.WritablePath
- ctx.VisitDirectDeps(func(dep android.Module) {
- if m, ok := dep.(*syspropLibrary); ok {
- checkApiFileTimeStamp = m.checkApiFileTimeStamp
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
+ if info, ok := android.OtherModuleProvider(ctx, dep, SyspropLibraryInfoProvider); ok {
+ checkApiFileTimeStamp = info.CheckApiFileTimeStamp
}
})
@@ -136,9 +142,9 @@ func syspropJavaGenFactory() android.Module {
func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
var checkApiFileTimeStamp android.WritablePath
- ctx.VisitDirectDeps(func(dep android.Module) {
- if m, ok := dep.(*syspropLibrary); ok {
- checkApiFileTimeStamp = m.checkApiFileTimeStamp
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
+ if info, ok := android.OtherModuleProvider(ctx, dep, SyspropLibraryInfoProvider); ok {
+ checkApiFileTimeStamp = info.CheckApiFileTimeStamp
}
})
@@ -207,8 +213,6 @@ type syspropLibrary struct {
properties syspropLibraryProperties
checkApiFileTimeStamp android.WritablePath
- latestApiFile android.OptionalPath
- currentApiFile android.OptionalPath
dumpedApiFile android.WritablePath
}
@@ -335,10 +339,6 @@ func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name()
}
-func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath {
- return m.currentApiFile
-}
-
// GenerateAndroidBuildActions of sysprop_library handles API dump and API check.
// generated java_library will depend on these API files.
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -357,8 +357,8 @@ func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
apiDirectoryPath := path.Join(ctx.ModuleDir(), "api")
currentApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-current.txt")
latestApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-latest.txt")
- m.currentApiFile = android.ExistentPathForSource(ctx, currentApiFilePath)
- m.latestApiFile = android.ExistentPathForSource(ctx, latestApiFilePath)
+ currentApiFile := android.ExistentPathForSource(ctx, currentApiFilePath)
+ latestApiFile := android.ExistentPathForSource(ctx, latestApiFilePath)
// dump API rule
rule := android.NewRuleBuilder(pctx, ctx)
@@ -379,15 +379,15 @@ func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
// method.
var apiFileList android.Paths
currentApiArgument := os.DevNull
- if m.currentApiFile.Valid() {
- apiFileList = append(apiFileList, m.currentApiFile.Path())
- currentApiArgument = m.currentApiFile.String()
+ if currentApiFile.Valid() {
+ apiFileList = append(apiFileList, currentApiFile.Path())
+ currentApiArgument = currentApiFile.String()
}
latestApiArgument := os.DevNull
- if m.latestApiFile.Valid() {
- apiFileList = append(apiFileList, m.latestApiFile.Path())
- latestApiArgument = m.latestApiFile.String()
+ if latestApiFile.Valid() {
+ apiFileList = append(apiFileList, latestApiFile.Path())
+ latestApiArgument = latestApiFile.String()
}
// 1. compares current.txt to api-dump.txt
@@ -431,6 +431,10 @@ func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
Output(m.checkApiFileTimeStamp)
rule.Build(baseModuleName+"_check_api", baseModuleName+" check api")
+
+ android.SetProvider(ctx, SyspropLibraryInfoProvider, SyspropLibraryInfo{
+ CheckApiFileTimeStamp: m.checkApiFileTimeStamp,
+ })
}
func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
diff --git a/systemfeatures/system_features.go b/systemfeatures/system_features.go
index b8dacfb1f..51f69bbe4 100644
--- a/systemfeatures/system_features.go
+++ b/systemfeatures/system_features.go
@@ -15,6 +15,7 @@ package systemfeatures
import (
"fmt"
+ "path/filepath"
"sort"
"strings"
@@ -44,7 +45,6 @@ type javaSystemFeaturesSrcs struct {
// Whether to generate only a simple metadata class with details about the full API surface.
// This is useful for tools that rely on the mapping from feature names to their generated
// method names, but don't want the fully generated API class (e.g., for linting).
-
Metadata_only *bool
}
outputFiles android.WritablePaths
@@ -74,13 +74,20 @@ func (m *javaSystemFeaturesSrcs) GenerateAndroidBuildActions(ctx android.ModuleC
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().Text("rm -rf").Text(outputDir.String())
rule.Command().Text("mkdir -p").Text(outputDir.String())
- rule.Command().
+ ruleCmd := rule.Command().
BuiltTool("systemfeatures-gen-tool").
Flag(m.properties.Full_class_name).
FlagForEachArg("--feature=", features).
FlagWithArg("--readonly=", fmt.Sprint(ctx.Config().ReleaseUseSystemFeatureBuildFlags())).
- FlagWithArg("--metadata-only=", fmt.Sprint(proptools.Bool(m.properties.Metadata_only))).
- FlagWithOutput(" > ", outputFile)
+ FlagWithArg("--metadata-only=", fmt.Sprint(proptools.Bool(m.properties.Metadata_only)))
+
+ if ctx.Config().ReleaseUseSystemFeatureXmlForUnavailableFeatures() {
+ if featureXmlFiles := uniquePossibleFeatureXmlPaths(ctx); len(featureXmlFiles) > 0 {
+ ruleCmd.FlagWithInputList("--unavailable-feature-xml-files=", featureXmlFiles, ",")
+ }
+ }
+
+ ruleCmd.FlagWithOutput(" > ", outputFile)
rule.Build(ctx.ModuleName(), "Generating systemfeatures srcs filegroup")
m.outputFiles = append(m.outputFiles, outputFile)
@@ -109,3 +116,45 @@ func JavaSystemFeaturesSrcsFactory() android.Module {
android.InitAndroidModule(module)
return module
}
+
+// Generates a list of unique, existent src paths for potential feature XML
+// files, as contained in the configured PRODUCT_COPY_FILES listing.
+func uniquePossibleFeatureXmlPaths(ctx android.ModuleContext) android.Paths {
+ dstPathSeen := make(map[string]bool)
+ var possibleSrcPaths []android.Path
+ for _, copyFilePair := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles {
+ srcDstList := strings.Split(copyFilePair, ":")
+ // The length may be >2 (e.g., "$src:$dst:$owner"), but we only care
+ // that it has at least "$src:$dst".
+ if len(srcDstList) < 2 {
+ ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair)
+ continue
+ }
+ src, dst := srcDstList[0], srcDstList[1]
+
+ // We're only interested in `.xml` files (case-insensitive).
+ if !strings.EqualFold(filepath.Ext(dst), ".xml") {
+ continue
+ }
+
+ // We only care about files directly in `*/etc/permissions/` or
+ // `*/etc/sysconfig` dirs, not any nested subdirs.
+ normalizedDstDir := filepath.ToSlash(filepath.Dir(filepath.Clean(dst)))
+ if !strings.HasSuffix(normalizedDstDir, "/etc/permissions") &&
+ !strings.HasSuffix(normalizedDstDir, "/etc/sysconfig") {
+ continue
+ }
+
+ // The first `dst` entry in the PRODUCT_COPY_FILES `src:dst` pairings
+ // always takes precedence over latter entries.
+ if _, ok := dstPathSeen[dst]; !ok {
+ relSrc := android.ToRelativeSourcePath(ctx, src)
+ if optionalPath := android.ExistentPathForSource(ctx, relSrc); optionalPath.Valid() {
+ dstPathSeen[dst] = true
+ possibleSrcPaths = append(possibleSrcPaths, optionalPath.Path())
+ }
+ }
+ }
+ // A sorted, unique list ensures stability of ninja build command outputs.
+ return android.SortedUniquePaths(possibleSrcPaths)
+}
diff --git a/systemfeatures/system_features_test.go b/systemfeatures/system_features_test.go
index 58e6a0660..3f6060b0a 100644
--- a/systemfeatures/system_features_test.go
+++ b/systemfeatures/system_features_test.go
@@ -44,8 +44,88 @@ java_system_features_srcs {
android.AssertStringDoesContain(t, "Expected TELEVISION feature flag", cmd, "--feature=TELEVISION:UNAVAILABLE ")
android.AssertStringDoesContain(t, "Expected WATCH feature flag", cmd, "--feature=WATCH: ")
android.AssertStringDoesNotContain(t, "Unexpected FOO arg from non-system feature flag", cmd, "FOO")
+ android.AssertStringDoesNotContain(t, "Unexpected feature xml files flag", cmd, "--feature-xml-files")
systemFeaturesModule := module.Module().(*javaSystemFeaturesSrcs)
expectedOutputPath := "out/soong/.intermediates/system-features-srcs/gen/RoSystemFeatures.java"
android.AssertPathsRelativeToTopEquals(t, "Expected output file", []string{expectedOutputPath}, systemFeaturesModule.Srcs())
}
+
+func TestJavaSystemFeaturesSrcsFromXml(t *testing.T) {
+ bp := `
+java_system_features_srcs {
+ name: "system-features-srcs",
+ full_class_name: "com.android.test.RoSystemFeatures",
+}
+`
+
+ res := android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerSystemFeaturesComponents),
+ android.PrepareForTestWithBuildFlag("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS", "true"),
+ android.PrepareForTestWithBuildFlag("RELEASE_USE_SYSTEM_FEATURE_XML_FOR_UNAVAILABLE_FEATURES", "true"),
+ android.PrepareForTestWithBuildFlag("RELEASE_SYSTEM_FEATURE_AUTOMOTIVE", "0"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles = []string{
+ "frameworks/features.xml:system/etc/permissions/features.xml",
+ "frameworks/features.xml:system/etc/permissions/featurescopy.xml",
+ "frameworks/features2.xml:system/etc/sysconfig/features2.xml",
+ "frameworks/featureswithowner.xml:vendor/etc/permissions/featureswithowner.xml:customowner",
+ "frameworks/dstalreadyexists.xml:system/etc/permissions/features.xml",
+ "frameworks/wrongsuffix.notxml:system/etc/permissions/wrongsuffix.notxml",
+ "frameworks/wrongsubdir.xml:system/notsysconfig/wrongsubdir.xml",
+ "frameworks/wrongsubdir.xml:system/notpermissions/wrongsubdir.xml",
+ "frameworks/wrongsubdir.xml:system/etc/permissions/nested/wrongsubdir.xml",
+ "frameworks/wrongsubdir.xml:system/notetc/permissions/wrongsubdir.xml",
+ "frameworks/nonexistent.xml:system/etc/permissions/nonexistent.xml",
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "frameworks/features.xml": nil,
+ "frameworks/features2.xml": nil,
+ "frameworks/featureswithowner.xml": nil,
+ "frameworks/wrongsuffix.notxml": nil,
+ "frameworks/wrongsubdir.xml": nil,
+ "frameworks/dstalreadyexists.xml": nil,
+ // Note that we explicitly omit frameworks/nonexistent.xml.
+ }),
+ ).RunTestWithBp(t, bp)
+
+ module := res.ModuleForTests(t, "system-features-srcs", "")
+ cmd := module.Rule("system-features-srcs").RuleParams.Command
+ android.AssertStringDoesContain(t, "Expected fully class name", cmd, " com.android.test.RoSystemFeatures ")
+ android.AssertStringDoesContain(t, "Expected readonly flag", cmd, "--readonly=true")
+ android.AssertStringDoesContain(t, "Expected AUTOMOTIVE feature flag", cmd, "--feature=AUTOMOTIVE:0 ")
+ android.AssertStringDoesContain(t, "Expected feature xml files flag", cmd, "--unavailable-feature-xml-files=frameworks/features.xml,frameworks/features2.xml,frameworks/featureswithowner.xml")
+ android.AssertStringDoesNotContain(t, "Unexpected feature xml file", cmd, "dstalreadyexists.xml")
+ android.AssertStringDoesNotContain(t, "Unexpected feature xml file", cmd, "nonexistent.xml")
+ android.AssertStringDoesNotContain(t, "Unexpected feature xml file", cmd, "wrongsubdir.xml")
+ android.AssertStringDoesNotContain(t, "Unexpected feature xml file", cmd, "wrongsuffix.notxml")
+
+ systemFeaturesModule := module.Module().(*javaSystemFeaturesSrcs)
+ expectedOutputPath := "out/soong/.intermediates/system-features-srcs/gen/RoSystemFeatures.java"
+ android.AssertPathsRelativeToTopEquals(t, "Expected output file", []string{expectedOutputPath}, systemFeaturesModule.Srcs())
+}
+
+func TestJavaSystemFeaturesSrcsFromInvalidProductFiles(t *testing.T) {
+ bp := `
+java_system_features_srcs {
+ name: "system-features-srcs",
+ full_class_name: "com.android.test.RoSystemFeatures",
+}
+`
+
+ android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerSystemFeaturesComponents),
+ android.PrepareForTestWithBuildFlag("RELEASE_USE_SYSTEM_FEATURE_XML_FOR_UNAVAILABLE_FEATURES", "true"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles = []string{
+ "frameworks/dstmissing.xml",
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "frameworks/dstmissing.xml": nil,
+ }),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: frameworks/dstmissing.xml"),
+ ).RunTestWithBp(t, bp)
+}
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 5a660e979..70d110d93 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -9,7 +9,7 @@ source "$(dirname "$0")/lib.sh"
readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
-readonly target_product="${TARGET_PRODUCT:-aosp_arm}"
+readonly target_product=aosp_arm
function test_smoke {
setup
@@ -62,7 +62,7 @@ EOF
touch a/my_little_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja || fail "module not found"
+ grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".*ninja || fail "module not found"
cat > a/Android.bp <<'EOF'
python_binary_host {
@@ -73,8 +73,8 @@ EOF
touch a/my_great_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja && fail "old module found"
- grep -q "^# Module:.*my_great_binary_host" out/soong/build."${target_product}".ninja || fail "new module not found"
+ grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".*ninja && fail "old module found"
+ grep -q "^# Module:.*my_great_binary_host" out/soong/build."${target_product}".*ninja || fail "new module not found"
}
function test_add_android_bp() {
@@ -97,7 +97,7 @@ EOF
fail "Output Ninja file did not change"
fi
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "New module not in output"
+ grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".*ninja || fail "New module not in output"
run_soong
}
@@ -114,12 +114,12 @@ EOF
touch a/my_little_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "Module not in output"
+ grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".*ninja || fail "Module not in output"
rm a/Android.bp
run_soong
- if grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja; then
+ if grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".*ninja; then
fail "Old module in output"
fi
}
@@ -182,7 +182,7 @@ EOF
fail "Output Ninja file did not change"
fi
- grep -q my_little_library.py out/soong/build."${target_product}".ninja || fail "new file is not in output"
+ grep -q my_little_library.py out/soong/build."${target_product}".*ninja || fail "new file is not in output"
}
function test_soong_build_rerun_iff_environment_changes() {
@@ -288,7 +288,9 @@ function test_create_global_include_directory() {
run_soong
local -r mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime2" = "$mtime3" ]]; then
- fail "Output Ninja file did not change when global include directory created"
+ # TODO(b/422558779): test fails
+ # fail "Output Ninja file did not change when global include directory created"
+ true
fi
}
@@ -363,7 +365,7 @@ EOF
fail "Output Ninja file did not change"
fi
- grep -q "Make it so" out/soong/build."${target_product}".ninja || fail "New action not present"
+ grep -q "Make it so" out/soong/build."${target_product}".*ninja || fail "New action not present"
}
# Tests a glob in a build= statement in an Android.bp file, which is interpreted
@@ -473,9 +475,9 @@ EOF
fail "Output Ninja file did not change"
fi
- grep -q "Engage" out/soong/build."${target_product}".ninja || fail "New action not present"
+ grep -q "Engage" out/soong/build."${target_product}".*ninja || fail "New action not present"
- if grep -q "Make it so" out/soong/build."${target_product}".ninja; then
+ if grep -q "Make it so" out/soong/build."${target_product}".*ninja; then
fail "Original action still present"
fi
}
@@ -529,12 +531,16 @@ EOF
readonly ERROR_HINT_PATTERN="BUILD_BROKEN_SRC_DIR"
# Test in ReadOnly source tree
run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false ${EXPECTED_OUT} &> /dev/null && \
- fail "Write to source tree should not work in a ReadOnly source tree"
+ # TODO(b/422558875): genrules are sandboxed, so they won't write to the source tree
+ # fail "Write to source tree should not work in a ReadOnly source tree"
+ true
if grep -q "${ERROR_MSG}" "${ERROR_LOG}" && grep -q "${ERROR_HINT_PATTERN}" "${ERROR_LOG}" ; then
echo Error message and error hint found in logs >/dev/null
else
- fail "Did not find Read-only error AND error hint in error.log"
+ # TODO(b/422558875): genrules are sandboxed, so they won't write to the source tree
+ # fail "Did not find Read-only error AND error hint in error.log"
+ true
fi
# Test in ReadWrite source tree
@@ -546,37 +552,6 @@ EOF
fi
}
-function test_dump_json_module_graph() {
- setup
- run_soong json-module-graph
- if [[ ! -r "out/soong/module-graph.json" ]]; then
- fail "JSON file was not created"
- fi
-}
-
-function test_json_module_graph_back_and_forth_null_build() {
- setup
-
- run_soong
- local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
-
- run_soong json-module-graph
- local -r json_mtime1=$(stat -c "%y" out/soong/module-graph.json)
-
- run_soong
- local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
- fail "Output Ninja file changed after writing JSON module graph"
- fi
-
- run_soong json-module-graph
- local -r json_mtime2=$(stat -c "%y" out/soong/module-graph.json)
- if [[ "$json_mtime1" != "$json_mtime2" ]]; then
- fail "JSON module graph file changed after writing Ninja file"
- fi
-
-}
-
# This test verifies that adding a new glob to a blueprint file only
# causes build."${target_product}".ninja to be regenerated on the *next* build, and *not*
# the build after. (This is a regression test for a bug where globs
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 0235f2b09..26790b04e 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -6,4 +6,3 @@ TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/androidmk_test.sh"
"$TOP/build/soong/tests/bootstrap_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
-"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 2ef9e374f..81da22e40 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -267,19 +267,17 @@ function test_sbom_unbundled_apex {
out_dir="$(setup)"
# run_soong to build com.android.adbd.apex
- run_soong "${out_dir}" "sbom deapexer" "com.android.adbd"
+ run_soong "${out_dir}" "sbom apex-ls" "com.android.adbd"
- deapexer=${out_dir}/host/linux-x86/bin/deapexer
- debugfs=${out_dir}/host/linux-x86/bin/debugfs_static
+ apex_ls=${out_dir}/host/linux-x86/bin/apex-ls
apex_file=${out_dir}/target/product/module_arm64/system/apex/com.android.adbd.apex
echo "============ Diffing files in $apex_file and SBOM"
set +e
- # deapexer prints the list of all files and directories
- # sed extracts the file/directory names
+ # apex-ls prints the list of all files and directories
# grep removes directories
# sed removes leading ./ in file names
diff -I /system/apex/com.android.adbd.apex -I apex_manifest.pb \
- <($deapexer --debugfs_path=$debugfs list --extents ${apex_file} | sed -E 's#(.*) \[.*\]$#\1#' | grep -v "/$" | sed -E 's#^\./(.*)#\1#' | sort -n) \
+ <(${apex_ls} ${apex_file} | grep -v "/$" | sed -E 's#^\./(.*)#\1#' | sort -n) \
<(grep '"fileName": ' ${apex_file}.spdx.json | sed -E 's/.*"fileName": "(.*)",/\1/' | sort -n )
if [ $? != "0" ]; then
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index e833df293..c9ef551d6 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -179,10 +179,6 @@ func (m *testModuleConfigModule) GenerateAndroidBuildActions(ctx android.ModuleC
moduleInfoJSON.TestConfig = []string{m.testConfig.String()}
moduleInfoJSON.AutoTestConfig = []string{"true"}
moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base)
-
- android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
- SupportFiles: m.supportFiles,
- })
}
// Ensure at least one test_suite is listed. Ideally it should be general-tests
@@ -332,15 +328,21 @@ func (m *testModuleConfigHostModule) DepsMutator(ctx android.BottomUpMutatorCont
func (m *testModuleConfigHostModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
m.validateBase(ctx, &testModuleConfigHostTag, "java_test_host", true)
m.generateManifestAndConfig(ctx)
- android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
- SupportFiles: m.supportFiles,
- })
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, m.tradefedProperties.Test_suites...)
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ moduleInfoJSON.TestConfig = []string{m.testConfig.String()}
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base)
}
// Ensure the base listed is the right type by checking that we get the expected provider data.
// Returns false on errors and the context is updated with an error indicating the baseType expected.
func (m *testModuleConfigModule) validateBase(ctx android.ModuleContext, depTag *dependencyTag, baseType string, baseShouldBeHost bool) {
- ctx.VisitDirectDepsWithTag(*depTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(*depTag, func(dep android.ModuleProxy) {
if provider, ok := android.OtherModuleProvider(ctx, dep, tradefed.BaseTestProviderKey); ok {
if baseShouldBeHost == provider.IsHost {
m.provider = provider
@@ -435,8 +437,19 @@ func (m *testModuleConfigModule) generateManifestAndConfig(ctx android.ModuleCon
IsUnitTest: m.provider.IsUnitTest,
})
- android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
- TestSuites: m.tradefedProperties.Test_suites,
+ mainFileExt := ".apk"
+ if m.provider.MkAppClass == "JAVA_LIBRARIES" {
+ mainFileExt = ".jar"
+ }
+
+ ctx.SetTestSuiteInfo(android.TestSuiteInfo{
+ TestSuites: m.tradefedProperties.Test_suites,
+ MainFile: m.manifest,
+ MainFileStem: fmt.Sprintf("UNUSED-%s", *m.Base),
+ MainFileExt: mainFileExt,
+ ConfigFile: m.testConfig,
+ CompatibilitySupportFiles: m.supportFiles.Paths(),
+ NeedsArchFolder: ctx.Device(),
})
}
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index 302f9a9d5..3a5c3d7f6 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -14,15 +14,14 @@
package tradefed_modules
import (
- "android/soong/android"
- "android/soong/java"
- "android/soong/sh"
"fmt"
"strconv"
"strings"
"testing"
- "github.com/google/blueprint"
+ "android/soong/android"
+ "android/soong/java"
+ "android/soong/sh"
)
const bp = `
@@ -510,7 +509,7 @@ func TestTestOnlyProvider(t *testing.T) {
// marked as test-only are marked as test-only.
actualTestOnly := []string{}
- ctx.VisitAllModules(func(m blueprint.Module) {
+ ctx.VisitAllModules(func(m android.Module) {
if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
if provider.TestOnly {
actualTestOnly = append(actualTestOnly, m.Name())
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index a868d6acb..e118ced90 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -51,6 +51,7 @@ bootstrap_go_package {
srcs: [
"androidmk_denylist.go",
"build.go",
+ "cipd.go",
"cleanbuild.go",
"config.go",
"context.go",
@@ -60,7 +61,6 @@ bootstrap_go_package {
"environment.go",
"exec.go",
"finder.go",
- "goma.go",
"kati.go",
"ninja.go",
"path.go",
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index cf97f1c2f..8537d4553 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -83,6 +83,7 @@ func blockAndroidMks(ctx Context, androidMks []string) {
"vendor/google/build/androidmk/allowlist.txt",
"device/google/clockwork/build/androidmk/allowlist.txt",
"device/google/sdv/androidmk/allowlist.txt",
+ "device/google/harriet/androidmk/allowlist.txt",
"vendor/extra/build/androidmk/allowlist.txt",
}
for _, allowlist_file := range allowlist_files {
diff --git a/ui/build/build.go b/ui/build/build.go
index 7fea863df..1b40f36f8 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -31,7 +31,7 @@ import (
func SetupOutDir(ctx Context, config Config) {
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
- ensureEmptyDirectoriesExist(ctx, config.TempDir())
+ ensureDirectoriesExist(ctx, config.SoongOutDir())
// The ninja_build file is used by our buildbots to understand that the output
// can be parsed as ninja output.
@@ -87,6 +87,11 @@ func SetupOutDir(ctx Context, config Config) {
writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
}
+// SetupTempDir makes sure config.TempDir() exists and is empty.
+func SetupTempDir(ctx Context, config Config) {
+ ensureEmptyDirectoriesExist(ctx, config.TempDir())
+}
+
// SetupKatiEnabledMarker creates or delets a file that tells soong_build if we're running with
// kati.
func SetupKatiEnabledMarker(ctx Context, config Config) {
@@ -300,6 +305,7 @@ func Build(ctx Context, config Config) {
checkRAM(ctx, config)
SetupOutDir(ctx, config)
+ SetupTempDir(ctx, config)
// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
checkCaseSensitivity(ctx, config)
@@ -308,10 +314,6 @@ func Build(ctx Context, config Config) {
what := evaluateWhatToRun(config, ctx.Verboseln)
- if config.StartGoma() {
- startGoma(ctx, config)
- }
-
rbeCh := make(chan bool)
var rbePanic any
if config.StartRBE() {
@@ -329,6 +331,11 @@ func Build(ctx Context, config Config) {
close(rbeCh)
}
+ if config.RunCIPDProxyServer() && shouldRunCIPDProxy(config) {
+ cipdProxy := startCIPDProxyServer(ctx, config)
+ defer cipdProxy.Stop()
+ }
+
if what&RunProductConfig != 0 {
runMakeProductConfig(ctx, config)
@@ -366,7 +373,7 @@ func Build(ctx Context, config Config) {
genKatiSuffix(ctx, config)
if what&RunSoong != 0 {
- runSoong(ctx, config)
+ runSoong(ctx, config, what&RunBuildTests != 0)
}
if what&RunKati != 0 {
diff --git a/ui/build/cipd.go b/ui/build/cipd.go
new file mode 100644
index 000000000..ba7ca3190
--- /dev/null
+++ b/ui/build/cipd.go
@@ -0,0 +1,169 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+)
+
+const (
+ cipdProxyPolicyPath = "build/soong/ui/build/cipd_proxy_policy.txtpb"
+ cipdProxyUrlKey = "CIPD_PROXY_URL"
+)
+
+type cipdProxy struct {
+ cmd *Cmd
+ wg sync.WaitGroup
+ stopping atomic.Bool
+}
+
+func cipdPath(config Config) string {
+ return filepath.Join("prebuilts/cipd", config.HostPrebuiltTag(), "cipd")
+}
+
+func shouldRunCIPDProxy(config Config) bool {
+ cipdPath := cipdPath(config)
+ _, err := os.Stat(cipdPath)
+ return err == nil
+}
+
+func startCIPDProxyServer(ctx Context, config Config) *cipdProxy {
+ ctx.Status.Status("Starting CIPD proxy server...")
+
+ cipdArgs := []string{"proxy", "-proxy-policy", cipdProxyPolicyPath}
+ adcFlagAdded := false
+
+ if config.UseRBE() {
+ // Determine RBE authentication mechanism and propagate to CIPD flags.
+ authType, authValue := config.rbeAuth()
+ switch authType {
+ case "RBE_credential_file":
+ cipdArgs = append(cipdArgs, "-service-account-json", authValue)
+ case "RBE_credentials_helper", "RBE_use_google_prod_creds":
+ helperPath := filepath.Join(config.rbeDir(), "credshelper")
+
+ var credHelperArgsParts []string
+ // RBE_credentials_helper_args contains space-separated arguments for the helper
+ // and need to be formatted as repeated 'args:"..."' for the -credential-helper spec.
+ // e.g. "--f=foo --b=bar" -> 'args:"--f=foo" args:"--b=bar"'.
+ if rbeArgsStr, ok := config.environ.Get("RBE_credentials_helper_args"); ok && rbeArgsStr != "" {
+ argList := strings.Fields(rbeArgsStr)
+ for _, arg := range argList {
+ credHelperArgsParts = append(credHelperArgsParts, fmt.Sprintf("args:%q", arg))
+ }
+ } else {
+ credHelperArgsParts = append(credHelperArgsParts, fmt.Sprintf("args:%q", "--auth_source=automaticAuth"))
+ credHelperArgsParts = append(credHelperArgsParts, fmt.Sprintf("args:%q", "--gcert_refresh_timeout=20"))
+ }
+ helperSpec := fmt.Sprintf("protocol:RECLIENT exec:'%s' %s", helperPath, strings.Join(credHelperArgsParts, " "))
+ cipdArgs = append(cipdArgs, "-credential-helper", helperSpec)
+ case "RBE_use_application_default_credentials", "RBE_use_gce_credentials":
+ fallthrough
+ default:
+ cipdArgs = append(cipdArgs, "-application-default-credentials=always")
+ adcFlagAdded = true
+ }
+ } else {
+ ctx.Printf("No RBE configuration detected. You may need to use application default credentials.")
+ }
+
+ if !adcFlagAdded {
+ // RBE instructions for non-corp machines set both RBE_credentials_helper and
+ // RBE_use_application_default_credentials. Pass that along to CIPD as well.
+ // Even if USE_RBE=false, CIPD can still use ADC.
+ if useAdcStr, ok := config.environ.Get("RBE_use_application_default_credentials"); ok {
+ parsedVal, err := strconv.ParseBool(useAdcStr)
+ if err == nil && parsedVal {
+ cipdArgs = append(cipdArgs, "-application-default-credentials=always")
+ }
+ }
+ }
+
+ cipdCmd := fmt.Sprintf("cipd %s", strings.Join(cipdArgs, " "))
+ ctx.Printf("Starting CIPD proxy server with: %s", cipdCmd)
+
+ cmd := Command(ctx, config, "cipd", cipdPath(config), cipdArgs...)
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ log.Fatal(err)
+ }
+ stderr, err := cmd.StderrPipe()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := cmd.Start(); err != nil {
+ log.Fatal(err)
+ }
+ cp := cipdProxy{cmd: cmd}
+ cp.wg.Add(1)
+ go func() {
+ // Log any error output from cipd until it exits.
+ defer cp.wg.Done()
+
+ bufReader := bufio.NewReader(stderr)
+ for {
+ l, err := bufReader.ReadString('\n')
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ if !cp.stopping.Load() {
+ err := cmd.Wait()
+ ctx.Printf("cipd: unexpected EOF, process exited with %v", err)
+ }
+ break
+ }
+ ctx.Fatalf("cipd: %v %v", l, err)
+ }
+ ctx.Printf("cipd: %v", l)
+ }
+ }()
+
+ bufReader := bufio.NewReader(stdout)
+ for {
+ l, err := bufReader.ReadString('\n')
+ if errors.Is(err, io.EOF) {
+ ctx.Printf("cipd: unexpected EOF: %v\n", l)
+ // The stderr goroutine will handle the EOF
+ cp.wg.Wait()
+ }
+
+ if err != nil {
+ log.Fatalf("Got %v reading from cipd process", err)
+ }
+ if strings.HasPrefix(l, cipdProxyUrlKey) {
+ proxyUrl := strings.TrimSpace(l[len(cipdProxyUrlKey)+1:])
+ config.environ.Set(cipdProxyUrlKey, proxyUrl)
+ ctx.Println("Started CIPD proxy listening on", proxyUrl)
+ break
+ }
+ }
+ return &cp
+}
+
+func (c *cipdProxy) Stop() {
+ c.stopping.Store(true)
+ c.cmd.Process.Kill()
+ c.wg.Wait()
+}
diff --git a/ui/build/cipd_proxy_policy.txtpb b/ui/build/cipd_proxy_policy.txtpb
new file mode 100644
index 000000000..35fcc0dc0
--- /dev/null
+++ b/ui/build/cipd_proxy_policy.txtpb
@@ -0,0 +1,6 @@
+allowed_remotes: "chrome-infra-packages.appspot.com"
+resolve_version {
+ allow_tags: false
+ allow_refs: false
+}
+get_instance_url {}
diff --git a/ui/build/config.go b/ui/build/config.go
index 94b07811d..46b434bc1 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -71,12 +71,14 @@ type Config struct{ *configImpl }
type configImpl struct {
// Some targets that are implemented in soong_build
arguments []string
- goma bool
environ *Environment
distDir string
buildDateTime string
logsPrefix string
+ // Whether this config was generated by NewDumpVarConfig().
+ isDumpVar bool
+
// From the arguments
parallel int
keepGoing int
@@ -90,19 +92,20 @@ type configImpl struct {
// Either the user or product config requested that we skip soong (for the banner). The other
// skip flags tell whether *this* soong_ui invocation will skip kati - which will be true
// during lunch.
- soongOnlyRequested bool
- skipKati bool
- skipKatiControlledByFlags bool
- skipKatiNinja bool
- skipSoong bool
- skipNinja bool
- skipSoongTests bool
- searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
- skipMetricsUpload bool
- buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
- buildFromSourceStub bool
- incrementalBuildActions bool
- ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
+ soongOnlyRequested bool
+ skipKati bool
+ skipKatiControlledByFlags bool
+ skipKatiNinja bool
+ skipSoong bool
+ skipNinja bool
+ skipSoongTests bool
+ skipMetricsUpload bool
+ buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
+ buildFromSourceStub bool
+ incrementalBuildActions bool
+ ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
+ runCIPDProxyServer bool
+ runCIPDProxyServerControlledByFlags bool
// From the product config
katiArgs []string
@@ -138,10 +141,33 @@ type configImpl struct {
// This file is a detailed dump of all soong-defined modules for debugging purposes.
// There's quite a bit of overlap with module-info.json and soong module graph. We
// could consider merging them.
- moduleDebugFile string
+ moduleDebugFile string
+ incrementalDebugFile string
// Which builder are we using
ninjaCommand ninjaCommandType
+
+ // Whether this build has a target that needs to disable SOONG_USE_PARTIAL_COMPILE.
+ disableUsePartialCompile bool
+
+ // Whether the user requested partial compile.
+ partialCompileRequested bool
+}
+
+// Some of the speed optimizations (such as using d8 instead of r8) used in partial
+// compile cause the size of image to become too large. To avoid this, some ninja
+// targets force SOONG_USE_PARTIAL_COMPILE=false.
+// This list is missing a great many targets which could cause the image to be too
+// large. Rather than try to be complete, it only includes targets which we know
+// are commonly used by Java/Kotlin developers.
+//
+// Without this automation, the developer would do an initial build -- which would
+// fail -- and then need to run `SOONG_USE_PARTIAL_COMPILE=false m ...` to rebuild
+// before beginning their inner loop work. See also b/409810224.
+var disableUsePartialCompileArgs = map[string]bool{
+ "droid": true,
+ "sync": true,
+ "systemimage": true,
}
type NinjaWeightListSource uint
@@ -225,11 +251,21 @@ func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
return nil
}
+// NewDumpVarConfig does not parse any arguments.
+func NewDumpVarConfig(ctx Context, args ...string) Config {
+ return newConfig(ctx, true)
+}
+
func NewConfig(ctx Context, args ...string) Config {
+ return newConfig(ctx, false, args...)
+}
+
+func newConfig(ctx Context, isDumpVar bool, args ...string) Config {
ret := &configImpl{
environ: OsEnvironment(),
sandboxConfig: &SandboxConfig{},
ninjaWeightListSource: DEFAULT,
+ isDumpVar: isDumpVar,
}
wd, err := os.Getwd()
if err != nil {
@@ -325,17 +361,42 @@ func NewConfig(ctx Context, args ...string) Config {
ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
}
+ if os.Getenv("GENERATE_INCREMENTAL_DEBUG") == "true" {
+ ret.incrementalDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "incremental-debug-info.json"))
+ }
+
// If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
// This simplifies the generated Ninja rules, so that they only need to check for the empty string.
if value, ok := ret.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
if value == "true" || value == "1" || value == "y" || value == "yes" {
+ ret.partialCompileRequested = true
value = "true"
+ if ret.disableUsePartialCompile {
+ // Allow the user to try using partial compile when we would normally force it off to avoid
+ // superpartition overflow.
+ if ret.environ.IsEnvTrue("SOONG_HONOR_USE_PARTIAL_COMPILE") {
+ ret.disableUsePartialCompile = false
+ } else {
+ value = ""
+ }
+ }
} else {
value = ""
}
ret.environ.Set("SOONG_USE_PARTIAL_COMPILE", value)
}
+ if !ret.runCIPDProxyServerControlledByFlags {
+ if value, ok := ret.environ.Get("SOONG_RUN_CIPD_PROXY_SERVER"); ok {
+ parsedVal, err := strconv.ParseBool(value)
+ if err == nil {
+ ret.runCIPDProxyServer = parsedVal
+ } else {
+ ctx.Verbosef("SOONG_RUN_CIPD_PROXY_SERVER (%q) is not a valid boolean", value)
+ }
+ }
+ }
+
ret.ninjaCommand = NINJA_NINJA
switch os.Getenv("SOONG_NINJA") {
case "n2":
@@ -406,6 +467,7 @@ func NewConfig(ctx Context, args ...string) Config {
// We read it here already, don't let others share in the fun
"GENERATE_SOONG_DEBUG",
+ "INCREMENTAL_SOONG_DEBUG",
// Use config.ninjaCommand instead.
"SOONG_NINJA",
@@ -415,11 +477,6 @@ func NewConfig(ctx Context, args ...string) Config {
"SOONG_ONLY",
)
- if ret.UseGoma() || ret.ForceUseGoma() {
- ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
- ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
- }
-
// Tell python not to spam the source tree with .pyc files.
ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
@@ -634,8 +691,6 @@ func buildConfig(config Config) *smpb.BuildConfig {
ensure().UsePartialCompile = proto.String(value)
}
c := &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(config.ForceUseGoma()),
- UseGoma: proto.Bool(config.UseGoma()),
UseRbe: proto.Bool(config.UseRBE()),
NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
SoongEnvVars: soongEnvVars,
@@ -897,8 +952,6 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
c.skipMetricsUpload = true
} else if arg == "--mk-metrics" {
c.reportMkMetrics = true
- } else if arg == "--search-api-dir" {
- c.searchApiDir = true
} else if strings.HasPrefix(arg, "--ninja_weight_source=") {
source := strings.TrimPrefix(arg, "--ninja_weight_source=")
if source == "ninja_log" {
@@ -943,6 +996,12 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
}
} else if arg == "--ensure-allowlist-integrity" {
c.ensureAllowlistIntegrity = true
+ } else if arg == "--run-cipd-proxy-server" {
+ c.runCIPDProxyServer = true
+ c.runCIPDProxyServerControlledByFlags = true
+ } else if arg == "--no-run-cipd-proxy-server" {
+ c.runCIPDProxyServer = false
+ c.runCIPDProxyServerControlledByFlags = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -983,9 +1042,16 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
if arg == "checkbuild" {
c.checkbuild = true
}
+ if disableUsePartialCompileArgs[arg] {
+ c.disableUsePartialCompile = true
+ }
c.arguments = append(c.arguments, arg)
}
}
+ // The default target needs disableUsePartialCompile.
+ if len(args) == 0 {
+ c.disableUsePartialCompile = true
+ }
}
func validateNinjaWeightList(weightListFilePath string) (err error) {
@@ -1100,7 +1166,7 @@ func (c *configImpl) RealDistDir() string {
}
func (c *configImpl) NinjaArgs() []string {
- if c.skipKati {
+ if c.skipConfig {
return append(c.arguments, c.ninjaArgs...)
}
return c.ninjaArgs
@@ -1110,10 +1176,6 @@ func (c *configImpl) SoongOutDir() string {
return filepath.Join(c.OutDir(), "soong")
}
-func (c *configImpl) ApiSurfacesOutDir() string {
- return filepath.Join(c.OutDir(), "api_surfaces")
-}
-
func (c *configImpl) PrebuiltOS() string {
switch runtime.GOOS {
case "linux":
@@ -1322,42 +1384,6 @@ func (c *configImpl) TotalRAM() uint64 {
return c.totalRAM
}
-// ForceUseGoma determines whether we should override Goma deprecation
-// and use Goma for the current build or not.
-func (c *configImpl) ForceUseGoma() bool {
- if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return true
- }
- }
- return false
-}
-
-func (c *configImpl) UseGoma() bool {
- if v, ok := c.environ.Get("USE_GOMA"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return true
- }
- }
- return false
-}
-
-func (c *configImpl) StartGoma() bool {
- if !c.UseGoma() {
- return false
- }
-
- if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return false
- }
- }
- return true
-}
-
func (c *configImpl) canSupportRBE() bool {
// Only supported on linux
if runtime.GOOS != "linux" {
@@ -1514,6 +1540,7 @@ func (c *configImpl) rbeReproxy() string {
func (c *configImpl) rbeAuth() (string, string) {
credFlags := []string{
+ "credentials_helper",
"use_application_default_credentials",
"use_gce_credentials",
"credential_file",
@@ -1577,7 +1604,7 @@ func (c *configImpl) GoogleProdCredsExist() bool {
// UseRemoteBuild indicates whether to use a remote build acceleration system
// to speed up the build.
func (c *configImpl) UseRemoteBuild() bool {
- return c.UseGoma() || c.UseRBE()
+ return c.UseRBE()
}
// StubbyExists checks whether the stubby binary exists on the machine running
@@ -1590,7 +1617,7 @@ func (c *configImpl) StubbyExists() bool {
}
// RemoteParallel controls how many remote jobs (i.e., commands which contain
-// gomacc) are run in parallel. Note the parallelism of all other jobs is
+// rewrapper) are run in parallel. Note the parallelism of all other jobs is
// still limited by Parallel()
func (c *configImpl) RemoteParallel() int {
if !c.UseRemoteBuild() {
@@ -1852,6 +1879,10 @@ func (c *configImpl) EnsureAllowlistIntegrity() bool {
return c.ensureAllowlistIntegrity
}
+func (c *configImpl) RunCIPDProxyServer() bool {
+ return c.runCIPDProxyServer
+}
+
// Returns a Time object if one was passed via a command-line flag.
// Otherwise returns the passed default.
func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 10de1ad96..3837bf38e 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -1021,29 +1021,31 @@ func TestBuildConfig(t *testing.T) {
name: "none set",
environ: Environment{},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
UseRbe: proto.Bool(false),
NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
- name: "force use goma",
- environ: Environment{"FORCE_USE_GOMA=1"},
+ name: "partial compile not used",
+ environ: Environment{"SOONG_USE_PARTIAL_COMPILE=", "SOONG_PARTIAL_COMPILE=true"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ SoongEnvVars: &smpb.SoongEnvVars{
+ PartialCompile: proto.String("true"),
+ UsePartialCompile: proto.String("false"),
+ },
NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
- name: "use goma",
- environ: Environment{"USE_GOMA=1"},
+ name: "partial compile",
+ environ: Environment{"SOONG_USE_PARTIAL_COMPILE=true", "SOONG_PARTIAL_COMPILE=true"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ SoongEnvVars: &smpb.SoongEnvVars{
+ PartialCompile: proto.String("true"),
+ UsePartialCompile: proto.String("true"),
+ },
NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
@@ -1052,8 +1054,6 @@ func TestBuildConfig(t *testing.T) {
name: "use rbe",
environ: Environment{"USE_RBE=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
UseRbe: proto.Bool(runtime.GOOS == "linux"),
NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
@@ -1068,8 +1068,6 @@ func TestBuildConfig(t *testing.T) {
}
config := Config{c}
actual := buildConfig(config)
- assertEquals(t, "ForceUseGoma", *tc.expectedBuildConfig.ForceUseGoma, *actual.ForceUseGoma)
- assertEquals(t, "UseGoma", *tc.expectedBuildConfig.UseGoma, *actual.UseGoma)
assertEquals(t, "UseRbe", *tc.expectedBuildConfig.UseRbe, *actual.UseRbe)
assertEquals(t, "NinjaWeightListSource", *tc.expectedBuildConfig.NinjaWeightListSource, *actual.NinjaWeightListSource)
})
diff --git a/ui/build/context.go b/ui/build/context.go
index 69e5f96a9..d5d708d26 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -74,7 +74,7 @@ func (c ContextImpl) CompleteTrace(name, desc string, begin, end uint64) {
if c.Metrics != nil {
realTime := end - begin
c.Metrics.SetTimeMetrics(
- soong_metrics_proto.PerfInfo{
+ &soong_metrics_proto.PerfInfo{
Description: &desc,
Name: &name,
StartTime: &begin,
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index dcbd603b8..c19380371 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -189,6 +189,21 @@ func Banner(config Config, make_vars map[string]string) string {
fmt.Fprintf(b, "%s=%s\n", name, make_vars[name])
}
}
+ if config.partialCompileRequested {
+ if partialCompile, ok := config.environ.Get("SOONG_PARTIAL_COMPILE"); ok {
+ // If we are only dumping variables, do not say that partial compile is disabled.
+ if config.disableUsePartialCompile && !config.isDumpVar {
+ fmt.Fprintf(b,
+ "SOONG_PARTIAL_COMPILE=%s # Inactive because of build arguments\n",
+ partialCompile)
+ } else {
+ fmt.Fprintf(b, "SOONG_PARTIAL_COMPILE=%s\n", partialCompile)
+ }
+ }
+ }
+
+ // Normally config.soongOnlyRequested already takes into account PRODUCT_SOONG_ONLY,
+ // except when doing `get_build_var report_config`, which is run during envsetup.
if config.skipKatiControlledByFlags {
fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested)
} else { // default for this product
@@ -295,6 +310,7 @@ func runMakeProductConfig(ctx Context, config Config) {
"BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
"RELEASE_BUILD_EXECUTION_METRICS",
+ "RELEASE_SRC_DIR_IS_READ_ONLY",
}, exportEnvVars...), BannerVars...)
makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
@@ -316,7 +332,15 @@ func runMakeProductConfig(ctx Context, config Config) {
config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
config.SetTargetDevice(makeVars["TARGET_DEVICE"])
config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
- config.sandboxConfig.SetSrcDirIsRO(makeVars["BUILD_BROKEN_SRC_DIR_IS_WRITABLE"] == "false")
+ if makeVars["RELEASE_SRC_DIR_IS_READ_ONLY"] == "true" {
+ // If the release config says source is read-only, then make it read-write only if
+ // BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true.
+ config.sandboxConfig.SetSrcDirIsRO(makeVars["BUILD_BROKEN_SRC_DIR_IS_WRITABLE"] != "true")
+ } else {
+ // If the release config says source is not read-only, then make it read-only only if
+ // BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false.
+ config.sandboxConfig.SetSrcDirIsRO(makeVars["BUILD_BROKEN_SRC_DIR_IS_WRITABLE"] == "false")
+ }
config.sandboxConfig.SetSrcDirRWAllowlist(strings.Fields(makeVars["BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST"]))
config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
@@ -333,6 +357,8 @@ func runMakeProductConfig(ctx Context, config Config) {
}
}
+ ctx.Metrics.SetSoongOnly(config.soongOnlyRequested)
+
// Print the banner like make did
if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
fmt.Fprintln(ctx.Writer, Banner(config, makeVars))
diff --git a/ui/build/finder.go b/ui/build/finder.go
index ff8908b29..8407f6397 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -63,7 +63,7 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
// Set up configuration parameters for the Finder cache.
cacheParams := finder.CacheParams{
WorkingDirectory: dir,
- RootDirs: androidBpSearchDirs(config),
+ RootDirs: []string{"."},
FollowSymlinks: config.environ.IsEnvTrue("ALLOW_BP_UNDER_SYMLINKS"),
ExcludeDirs: []string{".git", ".repo"},
PruneFiles: pruneFiles,
@@ -83,6 +83,10 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
"TEST_MAPPING",
// METADATA file of packages
"METADATA",
+ // Release config contributions.
+ "release_config_map.textproto",
+ // Release config allowed duplicate flag declarations.
+ "duplicate_allowlist.txt",
},
IncludeSuffixes: []string{
// .mk files for product/board configuration.
@@ -102,15 +106,6 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
return f
}
-func androidBpSearchDirs(config Config) []string {
- dirs := []string{"."} // always search from root of source tree.
- if config.searchApiDir {
- // Search in out/api_surfaces
- dirs = append(dirs, config.ApiSurfacesOutDir())
- }
- return dirs
-}
-
func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
@@ -195,6 +190,25 @@ func FindSources(ctx Context, config Config, f *finder.Finder) {
ctx.Fatalf("Could not find METADATA: %v", err)
}
+ // Recursively look for all release_config_map.textproto files.
+ releaseConfigMaps := f.FindNamedAt(".", "release_config_map.textproto")
+ err = dumpListToFile(ctx, config, releaseConfigMaps, filepath.Join(dumpDir, "release_config_map.list"))
+ if err != nil {
+ ctx.Fatalf("Could not find release_config_map.textproto: %v", err)
+ }
+
+ // Recursively look for all duplicate_allowlist.txt files where we found release_config_map.textproto.
+ var duplicateAllowlists []string
+ for _, mapPath := range releaseConfigMaps {
+ // The only `duplicate_allowlist.txt` files we care about are in the same directory
+ // as `release_config_map.textproto`.
+ duplicateAllowlists = append(duplicateAllowlists, f.FindNamedAt(filepath.Dir(mapPath), "duplicate_allowlist.txt")...)
+ }
+ err = dumpListToFile(ctx, config, duplicateAllowlists, filepath.Join(dumpDir, "duplicate_allowlist.list"))
+ if err != nil {
+ ctx.Fatalf("Could not find duplicate_allowlist.txt: %v", err)
+ }
+
// Recursively look for all TEST_MAPPING files.
testMappings := f.FindNamedAt(".", "TEST_MAPPING")
err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
diff --git a/ui/build/goma.go b/ui/build/goma.go
deleted file mode 100644
index ae9b78498..000000000
--- a/ui/build/goma.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package build
-
-import (
- "fmt"
- "math"
- "path/filepath"
- "strconv"
- "strings"
-
- "android/soong/ui/metrics"
-)
-
-const gomaCtlScript = "goma_ctl.py"
-const gomaLeastNProcs = 2500
-const gomaLeastNFiles = 16000
-
-// ulimit returns ulimit result for |opt|.
-// if the resource is unlimited, it returns math.MaxInt32 so that a caller do
-// not need special handling of the returned value.
-//
-// Note that since go syscall package do not have RLIMIT_NPROC constant,
-// we use bash ulimit instead.
-func ulimitOrFatal(ctx Context, config Config, opt string) int {
- commandText := fmt.Sprintf("ulimit %s", opt)
- cmd := Command(ctx, config, commandText, "bash", "-c", commandText)
- output := strings.TrimRight(string(cmd.CombinedOutputOrFatal()), "\n")
- ctx.Verbose(output + "\n")
- ctx.Verbose("done\n")
-
- if output == "unlimited" {
- return math.MaxInt32
- }
- num, err := strconv.Atoi(output)
- if err != nil {
- ctx.Fatalf("ulimit returned unexpected value: %s: %v\n", opt, err)
- }
- return num
-}
-
-func startGoma(ctx Context, config Config) {
- ctx.BeginTrace(metrics.RunSetupTool, "goma_ctl")
- defer ctx.EndTrace()
-
- if u := ulimitOrFatal(ctx, config, "-u"); u < gomaLeastNProcs {
- ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, gomaLeastNProcs)
- }
- if n := ulimitOrFatal(ctx, config, "-n"); n < gomaLeastNFiles {
- ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, gomaLeastNFiles)
- }
-
- var gomaCtl string
- if gomaDir, ok := config.Environment().Get("GOMA_DIR"); ok {
- gomaCtl = filepath.Join(gomaDir, gomaCtlScript)
- } else if home, ok := config.Environment().Get("HOME"); ok {
- gomaCtl = filepath.Join(home, "goma", gomaCtlScript)
- } else {
- ctx.Fatalln("goma_ctl.py not found")
- }
-
- cmd := Command(ctx, config, "goma_ctl.py ensure_start", gomaCtl, "ensure_start")
- cmd.Environment.Set("DIST_DIR", config.DistDir())
-
- if output, err := cmd.CombinedOutput(); err != nil {
- ctx.Fatalf("goma_ctl.py ensure_start failed with: %v\n%s\n", err, output)
- }
-}
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 6519573ac..f4b062a05 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -205,6 +205,11 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF
// fi
cmd.Environment.Unset("SOONG_USE_PARTIAL_COMPILE")
+ // SOONG_HONOR_USE_PARTIAL_COMPILE is used by soong_ui to determine whether or not to force
+ // SOONG_USE_PARTIAL_COMPILE=false for certain ninja targets. It should not be used by anything other
+ // than soong_ui.
+ cmd.Environment.Unset("SOONG_HONOR_USE_PARTIAL_COMPILE")
+
// Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file.
cmd.Environment.Unset("BUILD_HOSTNAME")
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index e2a568fad..47975d11f 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -256,6 +256,9 @@ func runNinja(ctx Context, config Config, ninjaArgs []string) {
// Directory for ExecutionMetrics
"SOONG_METRICS_AGGREGATION_DIR",
+
+ // CIPD proxy
+ "CIPD_PROXY_URL",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 0a0f95628..d4d380f98 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -16,9 +16,11 @@ package build
import (
"fmt"
+ "math"
"os"
"path/filepath"
"runtime"
+ "strconv"
"strings"
"android/soong/remoteexec"
@@ -210,3 +212,26 @@ func PrintOutDirWarning(ctx Context, config Config) {
fmt.Fprintln(ctx.Writer, "")
}
}
+
+// ulimit returns ulimit result for |opt|.
+// if the resource is unlimited, it returns math.MaxInt32 so that a caller do
+// not need special handling of the returned value.
+//
+// Note that since go syscall package do not have RLIMIT_NPROC constant,
+// we use bash ulimit instead.
+func ulimitOrFatal(ctx Context, config Config, opt string) int {
+ commandText := fmt.Sprintf("ulimit %s", opt)
+ cmd := Command(ctx, config, commandText, "bash", "-c", commandText)
+ output := strings.TrimRight(string(cmd.CombinedOutputOrFatal()), "\n")
+ ctx.Verbose(output + "\n")
+ ctx.Verbose("done\n")
+
+ if output == "unlimited" {
+ return math.MaxInt32
+ }
+ num, err := strconv.Atoi(output)
+ if err != nil {
+ ctx.Fatalf("ulimit returned unexpected value: %s: %v\n", opt, err)
+ }
+ return num
+}
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 1edbe2121..ca8e8c2b8 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -16,6 +16,7 @@ package build
import (
"bytes"
+ "encoding/json"
"os"
"os/exec"
"os/user"
@@ -25,8 +26,7 @@ import (
)
type Sandbox struct {
- Enabled bool
- DisableWhenUsingGoma bool
+ Enabled bool
AllowBuildBrokenUsesNetwork bool
}
@@ -41,8 +41,7 @@ var (
katiSandbox = basicSandbox
soongSandbox = basicSandbox
ninjaSandbox = Sandbox{
- Enabled: true,
- DisableWhenUsingGoma: true,
+ Enabled: true,
AllowBuildBrokenUsesNetwork: true,
}
@@ -67,11 +66,6 @@ func (c *Cmd) sandboxSupported() bool {
return false
}
- // Goma is incompatible with PID namespaces and Mount namespaces. b/122767582
- if c.Sandbox.DisableWhenUsingGoma && c.config.UseGoma() {
- return false
- }
-
sandboxConfig.once.Do(func() {
sandboxConfig.group = "nogroup"
if _, err := user.LookupGroup(sandboxConfig.group); err != nil {
@@ -93,19 +87,24 @@ func (c *Cmd) sandboxSupported() bool {
sandboxConfig.distDir = absPath(c.ctx, derefPath)
}
- sandboxArgs := []string{
+ var sandboxArgs []string
+ sandboxArgs = append(sandboxArgs,
"-H", "android-build",
"-e",
"-u", "nobody",
"-g", sandboxConfig.group,
- "-R", "/",
+ )
+ sandboxArgs = append(sandboxArgs,
+ c.readMountArgs()...,
+ )
+ sandboxArgs = append(sandboxArgs,
// Mount tmp before srcDir
// srcDir is /tmp/.* in integration tests, which is a child dir of /tmp
// nsjail throws an error if a child dir is mounted before its parent
"-B", "/tmp",
- c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
- "-B", sandboxConfig.outDir,
- }
+ c.config.sandboxConfig.SrcDirMountFlag(), c.srcDirArg(),
+ "-B", c.outDirArg(),
+ )
if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
//Mount dist dir as read-write if it already exists
@@ -217,6 +216,28 @@ func (c *Cmd) workDir() string {
return abfsSrcDir
}
+func abfsCacheFromMount() (string, error) {
+ wd, _ := os.Getwd()
+ type Config struct {
+ CacheDir string
+ }
+ type MountDetails struct {
+ Config Config
+ }
+ var m MountDetails
+ file, err := os.Open(filepath.Join(wd, ".repo/mount-details"))
+ if err != nil {
+ return "", err
+ }
+ defer file.Close()
+ d := json.NewDecoder(file)
+ if err := d.Decode(&m); err != nil {
+ return "", err
+ }
+
+ return m.Config.CacheDir, nil
+}
+
func (c *Cmd) wrapSandbox() {
wd := c.workDir()
@@ -253,6 +274,10 @@ func (c *Cmd) wrapSandbox() {
"--rlimit_cpu", "soft",
"--rlimit_fsize", "soft",
"--rlimit_nofile", "soft",
+
+ // nsjail defaults to a niceness of 19, the minimum priority. Raise it to 5 so that UI tasks are still
+ // a higher priority, but the build is a higher priority than the other background tasks that are set to 10.
+ "--nice_level", "5",
)
sandboxArgs = append(sandboxArgs,
@@ -277,14 +302,18 @@ func (c *Cmd) wrapSandbox() {
"-q",
)
if c.config.UseABFS() {
- sandboxArgs = append(sandboxArgs, "-B", "{ABFS_DIR}")
+ cacheDir, err := abfsCacheFromMount()
+ if err != nil {
+ c.ctx.Fatalln(err)
+ }
+ sandboxArgs = append(sandboxArgs, "-B", cacheDir)
}
// Mount srcDir RW allowlists as Read-Write
if len(c.config.sandboxConfig.SrcDirRWAllowlist()) > 0 && !c.config.sandboxConfig.SrcDirIsRO() {
errMsg := `Product source tree has been set as ReadWrite, RW allowlist not necessary.
To recover, either
- 1. Unset BUILD_BROKEN_SRC_DIR_IS_WRITABLE #or
+ 1. Set BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false #or
2. Unset BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST`
c.ctx.Fatalln(errMsg)
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 58334a907..f483b291e 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -137,6 +137,10 @@ func (c BlueprintConfig) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderI
return c.primaryBuilderInvocations
}
+func (c BlueprintConfig) IsBootstrap() bool {
+ return true
+}
+
func environmentArgs(config Config, tag string) []string {
return []string{
"--available_env", shared.JoinPath(config.SoongOutDir(), availableEnvFile),
@@ -212,6 +216,11 @@ func (pb PrimaryBuilderFactory) primaryBuilderInvocation(config Config) bootstra
commonArgs = append(commonArgs, pb.config.moduleDebugFile)
}
+ if pb.config.incrementalDebugFile != "" {
+ commonArgs = append(commonArgs, "--incremental-debug-file")
+ commonArgs = append(commonArgs, pb.config.incrementalDebugFile)
+ }
+
commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list"))
invocationEnv := make(map[string]string)
if pb.debugPort != "" {
@@ -554,7 +563,7 @@ func migrateOutputSymlinks(ctx Context, config Config) error {
return fixOutDirSymlinks(ctx, config, outDir)
}
-func runSoong(ctx Context, config Config) {
+func runSoong(ctx Context, config Config, enforceNoSoongOutput bool) {
ctx.BeginTrace(metrics.RunSoong, "soong")
defer ctx.EndTrace()
@@ -575,6 +584,9 @@ func runSoong(ctx Context, config Config) {
soongBuildEnv.Set("TOP", os.Getenv("TOP"))
soongBuildEnv.Set("LOG_DIR", config.LogsDir())
+ // Never pass SOONG_HONOR_USE_PARTIAL_COMPILE to Soong.
+ soongBuildEnv.Unset("SOONG_HONOR_USE_PARTIAL_COMPILE")
+
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
soongBuildEnv.Set("ALLOW_MISSING_DEPENDENCIES", "true")
@@ -606,81 +618,86 @@ func runSoong(ctx Context, config Config) {
fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
- defer nr.Close()
-
- var ninjaCmd string
- var ninjaArgs []string
- switch config.ninjaCommand {
- case NINJA_N2:
- ninjaCmd = config.N2Bin()
- ninjaArgs = []string{
- // TODO: implement these features, or remove them.
- //"-d", "keepdepfile",
- //"-d", "stats",
- //"-o", "usesphonyoutputs=yes",
- //"-o", "preremoveoutputs=yes",
- //"-w", "dupbuild=err",
- //"-w", "outputdir=err",
- //"-w", "missingoutfile=err",
- "-v",
- "-j", strconv.Itoa(config.Parallel()),
- "--frontend-file", fifo,
- "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
- }
- case NINJA_SISO:
- ninjaCmd = config.SisoBin()
- ninjaArgs = []string{
- "ninja",
- // TODO: implement these features, or remove them.
- //"-d", "keepdepfile",
- //"-d", "stats",
- //"-o", "usesphonyoutputs=yes",
- //"-o", "preremoveoutputs=yes",
- //"-w", "dupbuild=err",
- //"-w", "outputdir=err",
- //"-w", "missingoutfile=err",
- "-v",
- "-j", strconv.Itoa(config.Parallel()),
- //"--frontend-file", fifo,
- "--log_dir", config.SoongOutDir(),
- "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ func() {
+ defer nr.Close()
+ var ninjaCmd string
+ var ninjaArgs []string
+ switch config.ninjaCommand {
+ case NINJA_N2:
+ ninjaCmd = config.N2Bin()
+ ninjaArgs = []string{
+ // TODO: implement these features, or remove them.
+ //"-d", "keepdepfile",
+ //"-d", "stats",
+ //"-o", "usesphonyoutputs=yes",
+ //"-o", "preremoveoutputs=yes",
+ //"-w", "dupbuild=err",
+ //"-w", "outputdir=err",
+ //"-w", "missingoutfile=err",
+ "-v",
+ "-j", strconv.Itoa(config.Parallel()),
+ "--frontend-file", fifo,
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
+ case NINJA_SISO:
+ ninjaCmd = config.SisoBin()
+ ninjaArgs = []string{
+ "ninja",
+ // TODO: implement these features, or remove them.
+ //"-d", "keepdepfile",
+ //"-d", "stats",
+ //"-o", "usesphonyoutputs=yes",
+ //"-o", "preremoveoutputs=yes",
+ //"-w", "dupbuild=err",
+ //"-w", "outputdir=err",
+ //"-w", "missingoutfile=err",
+ "-v",
+ "-j", strconv.Itoa(config.Parallel()),
+ //"--frontend-file", fifo,
+ "--log_dir", config.SoongOutDir(),
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
+ default:
+ // NINJA_NINJA is the default.
+ ninjaCmd = config.NinjaBin()
+ ninjaArgs = []string{
+ "-d", "keepdepfile",
+ "-d", "stats",
+ "-o", "usesphonyoutputs=yes",
+ "-o", "preremoveoutputs=yes",
+ "-w", "dupbuild=err",
+ "-w", "outputdir=err",
+ "-w", "missingoutfile=err",
+ "-j", strconv.Itoa(config.Parallel()),
+ "--frontend_file", fifo,
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
}
- default:
- // NINJA_NINJA is the default.
- ninjaCmd = config.NinjaBin()
- ninjaArgs = []string{
- "-d", "keepdepfile",
- "-d", "stats",
- "-o", "usesphonyoutputs=yes",
- "-o", "preremoveoutputs=yes",
- "-w", "dupbuild=err",
- "-w", "outputdir=err",
- "-w", "missingoutfile=err",
- "-j", strconv.Itoa(config.Parallel()),
- "--frontend_file", fifo,
- "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+
+ if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
+ ctx.Printf(`CAUTION: arguments in $SOONG_UI_NINJA_ARGS=%q, e.g. "-n", can make soong_build FAIL or INCORRECT`, extra)
+ ninjaArgs = append(ninjaArgs, strings.Fields(extra)...)
}
- }
- if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
- ctx.Printf(`CAUTION: arguments in $SOONG_UI_NINJA_ARGS=%q, e.g. "-n", can make soong_build FAIL or INCORRECT`, extra)
- ninjaArgs = append(ninjaArgs, strings.Fields(extra)...)
- }
+ ninjaArgs = append(ninjaArgs, targets...)
- ninjaArgs = append(ninjaArgs, targets...)
+ cmd := Command(ctx, config, "soong bootstrap",
+ ninjaCmd, ninjaArgs...)
- cmd := Command(ctx, config, "soong bootstrap",
- ninjaCmd, ninjaArgs...)
+ var ninjaEnv Environment
- var ninjaEnv Environment
+ // This is currently how the command line to invoke soong_build finds the
+ // root of the source tree and the output root
+ ninjaEnv.Set("TOP", os.Getenv("TOP"))
- // This is currently how the command line to invoke soong_build finds the
- // root of the source tree and the output root
- ninjaEnv.Set("TOP", os.Getenv("TOP"))
+ cmd.Environment = &ninjaEnv
+ cmd.Sandbox = soongSandbox
+ cmd.RunAndStreamOrFatal()
+ }()
- cmd.Environment = &ninjaEnv
- cmd.Sandbox = soongSandbox
- cmd.RunAndStreamOrFatal()
+ if enforceNoSoongOutput && nr.HasAnyOutput() {
+ ctx.Fatalf("Soong must not output anything to stdout/stderr on a successful build, please remove the prints")
+ }
}
targets := make([]string, 0, 0)
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 87bec93a2..0d80d8796 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -87,7 +87,7 @@ func testForDanglingRules(ctx Context, config Config) {
// out/target/product/<xxxxx>/build_fingerprint.txt is a source file created in sysprop.mk
// ^out/target/product/[^/]+/build_fingerprint.txt$
- buildFingerPrintFilePattern := regexp.MustCompile("^" + filepath.Join(outDir, "target", "product") + "/[^/]+/build_fingerprint.txt$")
+ buildFingerPrintFilePattern := regexp.MustCompile("^" + filepath.Join(outDir, "target", "product") + "/[^/]+/build_(fingerprint|thumbprint).txt$")
danglingRules := make(map[string]bool)
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index cbdeb2789..65890abfd 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -69,9 +69,9 @@ func newEvent(name, desc string) *event {
}
}
-func (e event) perfInfo() soong_metrics_proto.PerfInfo {
+func (e event) perfInfo() *soong_metrics_proto.PerfInfo {
realTime := uint64(_now().Sub(e.start).Nanoseconds())
- perfInfo := soong_metrics_proto.PerfInfo{
+ perfInfo := &soong_metrics_proto.PerfInfo{
Description: proto.String(e.desc),
Name: proto.String(e.name),
StartTime: proto.Uint64(uint64(e.start.UnixNano())),
@@ -154,6 +154,6 @@ func (t *EventTracer) Begin(name, desc string) {
// End performs post calculations such as duration of the event, aggregates
// the collected performance information into PerfInfo protobuf message.
-func (t *EventTracer) End() soong_metrics_proto.PerfInfo {
+func (t *EventTracer) End() *soong_metrics_proto.PerfInfo {
return t.pop().perfInfo()
}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 8d29cfc2d..458572a1e 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -58,7 +58,6 @@ const (
RunSoong = "soong"
PrimaryNinja = "ninja"
RunKati = "kati"
- RunBazel = "bazel"
// Overall build from building the graph to building the target.
Total = "total"
@@ -102,31 +101,33 @@ func (m *Metrics) SetToplevelMakefiles(total int) {
m.mkMetrics.ToplevelMakefiles = uint32(total)
}
+func (m *Metrics) SetSoongOnly(soongOnly bool) {
+ m.metrics.BuildConfig.SoongOnly = &soongOnly
+}
+
func (m *Metrics) DumpMkMetrics(outPath string) {
shared.Save(&m.mkMetrics, outPath)
}
// SetTimeMetrics stores performance information from an executed block of
// code.
-func (m *Metrics) SetTimeMetrics(perf soong_metrics_proto.PerfInfo) {
+func (m *Metrics) SetTimeMetrics(perf *soong_metrics_proto.PerfInfo) {
switch perf.GetName() {
case RunKati:
- m.metrics.KatiRuns = append(m.metrics.KatiRuns, &perf)
+ m.metrics.KatiRuns = append(m.metrics.KatiRuns, perf)
case RunSoong:
- m.metrics.SoongRuns = append(m.metrics.SoongRuns, &perf)
- case RunBazel:
- m.metrics.BazelRuns = append(m.metrics.BazelRuns, &perf)
+ m.metrics.SoongRuns = append(m.metrics.SoongRuns, perf)
case PrimaryNinja:
- m.metrics.NinjaRuns = append(m.metrics.NinjaRuns, &perf)
+ m.metrics.NinjaRuns = append(m.metrics.NinjaRuns, perf)
case RunSetupTool:
- m.metrics.SetupTools = append(m.metrics.SetupTools, &perf)
+ m.metrics.SetupTools = append(m.metrics.SetupTools, perf)
case Total:
- m.metrics.Total = &perf
+ m.metrics.Total = perf
}
}
-func (m *Metrics) SetCriticalPathInfo(criticalPathInfo soong_metrics_proto.CriticalPathInfo) {
- m.metrics.CriticalPathInfo = &criticalPathInfo
+func (m *Metrics) SetCriticalPathInfo(criticalPathInfo *soong_metrics_proto.CriticalPathInfo) {
+ m.metrics.CriticalPathInfo = criticalPathInfo
}
// SetFatalOrPanicMessage stores a non-zero exit and the relevant message in the latest event if
@@ -254,35 +255,3 @@ func (m *Metrics) Dump(out string) error {
return shared.Save(&m.metrics, out)
}
-
-// SetSoongBuildMetrics sets the metrics collected from the soong_build
-// execution.
-func (m *Metrics) SetSoongBuildMetrics(metrics *soong_metrics_proto.SoongBuildMetrics) {
- m.metrics.SoongBuildMetrics = metrics
-}
-
-// A CriticalUserJourneysMetrics is a struct that contains critical user journey
-// metrics. These critical user journeys are defined under cuj/cuj.go file.
-type CriticalUserJourneysMetrics struct {
- // A list of collected CUJ metrics.
- cujs soong_metrics_proto.CriticalUserJourneysMetrics
-}
-
-// NewCriticalUserJourneyMetrics returns a pointer of CriticalUserJourneyMetrics
-// to capture CUJs metrics.
-func NewCriticalUserJourneysMetrics() *CriticalUserJourneysMetrics {
- return &CriticalUserJourneysMetrics{}
-}
-
-// Add adds a set of collected metrics from an executed critical user journey.
-func (c *CriticalUserJourneysMetrics) Add(name string, metrics *Metrics) {
- c.cujs.Cujs = append(c.cujs.Cujs, &soong_metrics_proto.CriticalUserJourneyMetrics{
- Name: proto.String(name),
- Metrics: &metrics.metrics,
- })
-}
-
-// Dump saves the collected CUJs metrics to the raw protobuf file.
-func (c *CriticalUserJourneysMetrics) Dump(filename string) (err error) {
- return shared.Save(&c.cujs, filename)
-}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 1ebe9115d..6425606aa 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -341,7 +341,7 @@ func (x *ExpConfigFetcher_ConfigStatus) UnmarshalJSON(b []byte) error {
// Deprecated: Use ExpConfigFetcher_ConfigStatus.Descriptor instead.
func (ExpConfigFetcher_ConfigStatus) EnumDescriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{15, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{13, 0}
}
type MetricsBase struct {
@@ -403,8 +403,6 @@ type MetricsBase struct {
SystemResourceInfo *SystemResourceInfo `protobuf:"bytes,25,opt,name=system_resource_info,json=systemResourceInfo" json:"system_resource_info,omitempty"`
// The build command that the user entered to the build system.
BuildCommand *string `protobuf:"bytes,26,opt,name=build_command,json=buildCommand" json:"build_command,omitempty"`
- // The metrics for calling Bazel.
- BazelRuns []*PerfInfo `protobuf:"bytes,27,rep,name=bazel_runs,json=bazelRuns" json:"bazel_runs,omitempty"`
// The metrics of the experiment config fetcher
ExpConfigFetcher *ExpConfigFetcher `protobuf:"bytes,28,opt,name=exp_config_fetcher,json=expConfigFetcher" json:"exp_config_fetcher,omitempty"`
// Whether the build exited with a panic or non-zero exit code, includes both
@@ -654,13 +652,6 @@ func (x *MetricsBase) GetBuildCommand() string {
return ""
}
-func (x *MetricsBase) GetBazelRuns() []*PerfInfo {
- if x != nil {
- return x.BazelRuns
- }
- return nil
-}
-
func (x *MetricsBase) GetExpConfigFetcher() *ExpConfigFetcher {
if x != nil {
return x.ExpConfigFetcher
@@ -729,19 +720,10 @@ type BuildConfig struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"`
- UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
- ForceUseGoma *bool `protobuf:"varint,3,opt,name=force_use_goma,json=forceUseGoma" json:"force_use_goma,omitempty"`
- // Whether the Bazel is acting as the Ninja executor for this build.
- BazelAsNinja *bool `protobuf:"varint,4,opt,name=bazel_as_ninja,json=bazelAsNinja" json:"bazel_as_ninja,omitempty"`
- // Whether build is occurring in a mixed build mode, where Bazel maintains the
- // definition and build of some modules in cooperation with Soong.
- BazelMixedBuild *bool `protobuf:"varint,5,opt,name=bazel_mixed_build,json=bazelMixedBuild" json:"bazel_mixed_build,omitempty"`
+ UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
Targets []string `protobuf:"bytes,6,rep,name=targets" json:"targets,omitempty"`
- // Whether the user explicitly disabled bazel mixed builds for this build.
- ForceDisableBazelMixedBuild *bool `protobuf:"varint,7,opt,name=force_disable_bazel_mixed_build,json=forceDisableBazelMixedBuild" json:"force_disable_bazel_mixed_build,omitempty"`
// NOT_USED - ninja doesn't use weight list.
// NINJA_LOG - ninja uses weight list based on previous builds by ninja log
// EVENLY_DISTRIBUTED - ninja thinks every task has the same weight.
@@ -792,13 +774,6 @@ func (*BuildConfig) Descriptor() ([]byte, []int) {
return file_metrics_proto_rawDescGZIP(), []int{1}
}
-func (x *BuildConfig) GetUseGoma() bool {
- if x != nil && x.UseGoma != nil {
- return *x.UseGoma
- }
- return false
-}
-
func (x *BuildConfig) GetUseRbe() bool {
if x != nil && x.UseRbe != nil {
return *x.UseRbe
@@ -806,27 +781,6 @@ func (x *BuildConfig) GetUseRbe() bool {
return false
}
-func (x *BuildConfig) GetForceUseGoma() bool {
- if x != nil && x.ForceUseGoma != nil {
- return *x.ForceUseGoma
- }
- return false
-}
-
-func (x *BuildConfig) GetBazelAsNinja() bool {
- if x != nil && x.BazelAsNinja != nil {
- return *x.BazelAsNinja
- }
- return false
-}
-
-func (x *BuildConfig) GetBazelMixedBuild() bool {
- if x != nil && x.BazelMixedBuild != nil {
- return *x.BazelMixedBuild
- }
- return false
-}
-
func (x *BuildConfig) GetTargets() []string {
if x != nil {
return x.Targets
@@ -834,13 +788,6 @@ func (x *BuildConfig) GetTargets() []string {
return nil
}
-func (x *BuildConfig) GetForceDisableBazelMixedBuild() bool {
- if x != nil && x.ForceDisableBazelMixedBuild != nil {
- return *x.ForceDisableBazelMixedBuild
- }
- return false
-}
-
func (x *BuildConfig) GetNinjaWeightListSource() BuildConfig_NinjaWeightListSource {
if x != nil && x.NinjaWeightListSource != nil {
return *x.NinjaWeightListSource
@@ -1623,111 +1570,6 @@ func (x *ModuleTypeInfo) GetNumOfModules() uint32 {
return 0
}
-type CriticalUserJourneyMetrics struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // The name of a critical user journey test.
- Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
- // The metrics produced when running the critical user journey test.
- Metrics *MetricsBase `protobuf:"bytes,2,opt,name=metrics" json:"metrics,omitempty"`
-}
-
-func (x *CriticalUserJourneyMetrics) Reset() {
- *x = CriticalUserJourneyMetrics{}
- if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[12]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CriticalUserJourneyMetrics) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CriticalUserJourneyMetrics) ProtoMessage() {}
-
-func (x *CriticalUserJourneyMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[12]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CriticalUserJourneyMetrics.ProtoReflect.Descriptor instead.
-func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{12}
-}
-
-func (x *CriticalUserJourneyMetrics) GetName() string {
- if x != nil && x.Name != nil {
- return *x.Name
- }
- return ""
-}
-
-func (x *CriticalUserJourneyMetrics) GetMetrics() *MetricsBase {
- if x != nil {
- return x.Metrics
- }
- return nil
-}
-
-type CriticalUserJourneysMetrics struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // A set of metrics from a run of the critical user journey tests.
- Cujs []*CriticalUserJourneyMetrics `protobuf:"bytes,1,rep,name=cujs" json:"cujs,omitempty"`
-}
-
-func (x *CriticalUserJourneysMetrics) Reset() {
- *x = CriticalUserJourneysMetrics{}
- if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[13]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CriticalUserJourneysMetrics) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CriticalUserJourneysMetrics) ProtoMessage() {}
-
-func (x *CriticalUserJourneysMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[13]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CriticalUserJourneysMetrics.ProtoReflect.Descriptor instead.
-func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{13}
-}
-
-func (x *CriticalUserJourneysMetrics) GetCujs() []*CriticalUserJourneyMetrics {
- if x != nil {
- return x.Cujs
- }
- return nil
-}
-
type SoongBuildMetrics struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1745,8 +1587,6 @@ type SoongBuildMetrics struct {
MaxHeapSize *uint64 `protobuf:"varint,5,opt,name=max_heap_size,json=maxHeapSize" json:"max_heap_size,omitempty"`
// Runtime metrics for soong_build execution.
Events []*PerfInfo `protobuf:"bytes,6,rep,name=events" json:"events,omitempty"`
- // Mixed Builds information
- MixedBuildsInfo *MixedBuildsInfo `protobuf:"bytes,7,opt,name=mixed_builds_info,json=mixedBuildsInfo" json:"mixed_builds_info,omitempty"`
// Performance during for soong_build execution.
PerfCounters []*PerfCounters `protobuf:"bytes,8,rep,name=perf_counters,json=perfCounters" json:"perf_counters,omitempty"`
}
@@ -1754,7 +1594,7 @@ type SoongBuildMetrics struct {
func (x *SoongBuildMetrics) Reset() {
*x = SoongBuildMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[14]
+ mi := &file_metrics_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1767,7 +1607,7 @@ func (x *SoongBuildMetrics) String() string {
func (*SoongBuildMetrics) ProtoMessage() {}
func (x *SoongBuildMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[14]
+ mi := &file_metrics_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1780,7 +1620,7 @@ func (x *SoongBuildMetrics) ProtoReflect() protoreflect.Message {
// Deprecated: Use SoongBuildMetrics.ProtoReflect.Descriptor instead.
func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{14}
+ return file_metrics_proto_rawDescGZIP(), []int{12}
}
func (x *SoongBuildMetrics) GetModules() uint32 {
@@ -1825,13 +1665,6 @@ func (x *SoongBuildMetrics) GetEvents() []*PerfInfo {
return nil
}
-func (x *SoongBuildMetrics) GetMixedBuildsInfo() *MixedBuildsInfo {
- if x != nil {
- return x.MixedBuildsInfo
- }
- return nil
-}
-
func (x *SoongBuildMetrics) GetPerfCounters() []*PerfCounters {
if x != nil {
return x.PerfCounters
@@ -1858,7 +1691,7 @@ type ExpConfigFetcher struct {
func (x *ExpConfigFetcher) Reset() {
*x = ExpConfigFetcher{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[15]
+ mi := &file_metrics_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1871,7 +1704,7 @@ func (x *ExpConfigFetcher) String() string {
func (*ExpConfigFetcher) ProtoMessage() {}
func (x *ExpConfigFetcher) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[15]
+ mi := &file_metrics_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1884,7 +1717,7 @@ func (x *ExpConfigFetcher) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExpConfigFetcher.ProtoReflect.Descriptor instead.
func (*ExpConfigFetcher) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{15}
+ return file_metrics_proto_rawDescGZIP(), []int{13}
}
func (x *ExpConfigFetcher) GetStatus() ExpConfigFetcher_ConfigStatus {
@@ -1908,63 +1741,6 @@ func (x *ExpConfigFetcher) GetMicros() uint64 {
return 0
}
-type MixedBuildsInfo struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // Modules that are enabled for Mixed Builds.
- MixedBuildEnabledModules []string `protobuf:"bytes,1,rep,name=mixed_build_enabled_modules,json=mixedBuildEnabledModules" json:"mixed_build_enabled_modules,omitempty"`
- // Modules that are not enabled for MixedBuilds
- MixedBuildDisabledModules []string `protobuf:"bytes,2,rep,name=mixed_build_disabled_modules,json=mixedBuildDisabledModules" json:"mixed_build_disabled_modules,omitempty"`
-}
-
-func (x *MixedBuildsInfo) Reset() {
- *x = MixedBuildsInfo{}
- if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[16]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *MixedBuildsInfo) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*MixedBuildsInfo) ProtoMessage() {}
-
-func (x *MixedBuildsInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[16]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use MixedBuildsInfo.ProtoReflect.Descriptor instead.
-func (*MixedBuildsInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{16}
-}
-
-func (x *MixedBuildsInfo) GetMixedBuildEnabledModules() []string {
- if x != nil {
- return x.MixedBuildEnabledModules
- }
- return nil
-}
-
-func (x *MixedBuildsInfo) GetMixedBuildDisabledModules() []string {
- if x != nil {
- return x.MixedBuildDisabledModules
- }
- return nil
-}
-
// CriticalPathInfo contains critical path nodes's information.
// A critical path is a path determining the minimum time needed for the whole build given perfect parallelism.
type CriticalPathInfo struct {
@@ -1985,7 +1761,7 @@ type CriticalPathInfo struct {
func (x *CriticalPathInfo) Reset() {
*x = CriticalPathInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[17]
+ mi := &file_metrics_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1998,7 +1774,7 @@ func (x *CriticalPathInfo) String() string {
func (*CriticalPathInfo) ProtoMessage() {}
func (x *CriticalPathInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[17]
+ mi := &file_metrics_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2011,7 +1787,7 @@ func (x *CriticalPathInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use CriticalPathInfo.ProtoReflect.Descriptor instead.
func (*CriticalPathInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{17}
+ return file_metrics_proto_rawDescGZIP(), []int{14}
}
func (x *CriticalPathInfo) GetElapsedTimeMicros() uint64 {
@@ -2056,7 +1832,7 @@ type JobInfo struct {
func (x *JobInfo) Reset() {
*x = JobInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[18]
+ mi := &file_metrics_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2069,7 +1845,7 @@ func (x *JobInfo) String() string {
func (*JobInfo) ProtoMessage() {}
func (x *JobInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[18]
+ mi := &file_metrics_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2082,7 +1858,7 @@ func (x *JobInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use JobInfo.ProtoReflect.Descriptor instead.
func (*JobInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{18}
+ return file_metrics_proto_rawDescGZIP(), []int{15}
}
func (x *JobInfo) GetElapsedTimeMicros() uint64 {
@@ -2115,7 +1891,7 @@ type OptimizedBuildMetrics struct {
func (x *OptimizedBuildMetrics) Reset() {
*x = OptimizedBuildMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2128,7 +1904,7 @@ func (x *OptimizedBuildMetrics) String() string {
func (*OptimizedBuildMetrics) ProtoMessage() {}
func (x *OptimizedBuildMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2141,7 +1917,7 @@ func (x *OptimizedBuildMetrics) ProtoReflect() protoreflect.Message {
// Deprecated: Use OptimizedBuildMetrics.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{19}
+ return file_metrics_proto_rawDescGZIP(), []int{16}
}
func (x *OptimizedBuildMetrics) GetAnalysisPerf() *PerfInfo {
@@ -2180,7 +1956,7 @@ type ExecutionMetrics struct {
func (x *ExecutionMetrics) Reset() {
*x = ExecutionMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2193,7 +1969,7 @@ func (x *ExecutionMetrics) String() string {
func (*ExecutionMetrics) ProtoMessage() {}
func (x *ExecutionMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2206,7 +1982,7 @@ func (x *ExecutionMetrics) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExecutionMetrics.ProtoReflect.Descriptor instead.
func (*ExecutionMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{20}
+ return file_metrics_proto_rawDescGZIP(), []int{17}
}
func (x *ExecutionMetrics) GetCommandArgs() []string {
@@ -2246,7 +2022,7 @@ type AggregatedFileList struct {
func (x *AggregatedFileList) Reset() {
*x = AggregatedFileList{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[21]
+ mi := &file_metrics_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2259,7 +2035,7 @@ func (x *AggregatedFileList) String() string {
func (*AggregatedFileList) ProtoMessage() {}
func (x *AggregatedFileList) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[21]
+ mi := &file_metrics_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2272,7 +2048,7 @@ func (x *AggregatedFileList) ProtoReflect() protoreflect.Message {
// Deprecated: Use AggregatedFileList.ProtoReflect.Descriptor instead.
func (*AggregatedFileList) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{21}
+ return file_metrics_proto_rawDescGZIP(), []int{18}
}
func (x *AggregatedFileList) GetAdditions() []string {
@@ -2328,7 +2104,7 @@ type FileCount struct {
func (x *FileCount) Reset() {
*x = FileCount{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[22]
+ mi := &file_metrics_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2341,7 +2117,7 @@ func (x *FileCount) String() string {
func (*FileCount) ProtoMessage() {}
func (x *FileCount) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[22]
+ mi := &file_metrics_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2354,7 +2130,7 @@ func (x *FileCount) ProtoReflect() protoreflect.Message {
// Deprecated: Use FileCount.ProtoReflect.Descriptor instead.
func (*FileCount) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{22}
+ return file_metrics_proto_rawDescGZIP(), []int{19}
}
func (x *FileCount) GetExtension() string {
@@ -2406,7 +2182,7 @@ type OptimizedBuildMetrics_TargetOptimizationResult struct {
func (x *OptimizedBuildMetrics_TargetOptimizationResult) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[23]
+ mi := &file_metrics_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2419,7 +2195,7 @@ func (x *OptimizedBuildMetrics_TargetOptimizationResult) String() string {
func (*OptimizedBuildMetrics_TargetOptimizationResult) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[23]
+ mi := &file_metrics_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2432,7 +2208,7 @@ func (x *OptimizedBuildMetrics_TargetOptimizationResult) ProtoReflect() protoref
// Deprecated: Use OptimizedBuildMetrics_TargetOptimizationResult.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics_TargetOptimizationResult) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{19, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{16, 0}
}
func (x *OptimizedBuildMetrics_TargetOptimizationResult) GetName() string {
@@ -2486,7 +2262,7 @@ type OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact struct {
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[24]
+ mi := &file_metrics_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2499,7 +2275,7 @@ func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) String()
func (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[24]
+ mi := &file_metrics_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2512,7 +2288,7 @@ func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoRef
// Deprecated: Use OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{19, 0, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{16, 0, 0}
}
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) GetName() string {
@@ -2541,7 +2317,7 @@ var File_metrics_proto protoreflect.FileDescriptor
var file_metrics_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x22, 0xd7, 0x10, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0x9f, 0x10, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -2632,365 +2408,323 @@ var file_metrics_proto_rawDesc = []byte{
0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f,
- 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x72,
- 0x75, 0x6e, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
- 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x52,
- 0x75, 0x6e, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46,
- 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f,
- 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d,
- 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x1e, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x75, 0x72,
- 0x6c, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73,
- 0x74, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x20,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x53, 0x0a, 0x12,
- 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x69, 0x6e,
- 0x66, 0x6f, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52,
- 0x10, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66,
- 0x6f, 0x12, 0x40, 0x0a, 0x1c, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x76,
- 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
- 0x65, 0x18, 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64,
- 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61,
- 0x62, 0x6c, 0x65, 0x12, 0x62, 0x0a, 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x23,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d,
- 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65,
- 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x30,
- 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08,
- 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52,
- 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02,
- 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
- 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09,
- 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36,
- 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0xf2,
- 0x04, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19,
- 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65,
- 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52,
- 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f,
- 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63,
- 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65,
- 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a,
- 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c,
- 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61,
- 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72,
- 0x67, 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69,
- 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65,
- 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66,
- 0x6f, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c,
- 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x79, 0x0a, 0x18, 0x6e, 0x69,
- 0x6e, 0x6a, 0x61, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x73,
- 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x53, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f,
+ 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23,
+ 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+ 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f,
+ 0x75, 0x72, 0x6c, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x6e, 0x69, 0x66,
+ 0x65, 0x73, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68,
+ 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x53,
+ 0x0a, 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f,
+ 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66,
+ 0x6f, 0x52, 0x10, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49,
+ 0x6e, 0x66, 0x6f, 0x12, 0x40, 0x0a, 0x1c, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x65,
+ 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0x18, 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x62, 0x0a, 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a,
+ 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74,
+ 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69,
+ 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x24, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
+ 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53,
+ 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47,
+ 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e,
+ 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01,
+ 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58,
+ 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04,
+ 0x4a, 0x04, 0x08, 0x1b, 0x10, 0x1c, 0x22, 0xb7, 0x03, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x72, 0x62,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62, 0x65, 0x12,
+ 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x79, 0x0a, 0x18, 0x6e, 0x69, 0x6e,
+ 0x6a, 0x61, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e, 0x69,
+ 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x52, 0x15, 0x6e,
0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x52, 0x15,
- 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x65,
- 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
- 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73,
- 0x52, 0x0c, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x12, 0x1d,
- 0x0a, 0x0a, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0a, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x09, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x74, 0x0a,
- 0x15, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74,
- 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53,
- 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c, 0x4f,
- 0x47, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44, 0x49,
- 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45,
- 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13,
- 0x0a, 0x0f, 0x48, 0x49, 0x4e, 0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f, 0x4e,
- 0x47, 0x10, 0x04, 0x22, 0x67, 0x0a, 0x0c, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56,
- 0x61, 0x72, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63,
- 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61,
- 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x13,
- 0x75, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
- 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x50, 0x61,
- 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x22, 0xed, 0x01, 0x0a,
- 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
- 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79,
- 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61,
- 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c,
- 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x12, 0x3d,
- 0x0a, 0x08, 0x63, 0x70, 0x75, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x63, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a,
- 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7e, 0x0a, 0x0d,
- 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a,
- 0x09, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
- 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75,
- 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x70,
- 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x6c, 0x0a, 0x0d,
- 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a,
- 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65,
- 0x6d, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65,
- 0x6d, 0x46, 0x72, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x61,
- 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x65,
- 0x6d, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50,
- 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a,
- 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09,
- 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d,
- 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18,
- 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17,
- 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
+ 0x75, 0x72, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x65, 0x6e,
+ 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x52,
+ 0x0c, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x09, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x74, 0x0a, 0x15,
+ 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45,
+ 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c, 0x4f, 0x47,
+ 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44, 0x49, 0x53,
+ 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x58,
+ 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a,
+ 0x0f, 0x48, 0x49, 0x4e, 0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x47,
+ 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04,
+ 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04,
+ 0x22, 0x67, 0x0a, 0x0c, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73,
+ 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
+ 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x74, 0x69,
+ 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x75, 0x73, 0x65,
+ 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x50, 0x61, 0x72, 0x74, 0x69,
+ 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x22, 0xed, 0x01, 0x0a, 0x12, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+ 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63,
+ 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
+ 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76,
+ 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x63,
+ 0x70, 0x75, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22,
- 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78,
- 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
- 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72,
- 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x0c, 0x50, 0x65, 0x72, 0x66, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x67,
- 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f,
- 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f,
- 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x64, 0x0a, 0x10, 0x50, 0x65,
- 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12,
+ 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75, 0x49, 0x6e, 0x66,
+ 0x6f, 0x52, 0x07, 0x63, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x08, 0x6d, 0x65,
+ 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f,
+ 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7e, 0x0a, 0x0d, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x65,
+ 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76,
+ 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x64,
+ 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f,
+ 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f,
+ 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x6c, 0x0a, 0x0d, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65,
+ 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d,
+ 0x65, 0x6d, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x66,
+ 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x46, 0x72,
+ 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
+ 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x41, 0x76,
+ 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66,
+ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61,
+ 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65,
+ 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09,
+ 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+ 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x6e,
+ 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12,
+ 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x0c, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75,
+ 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50,
+ 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52,
+ 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x64, 0x0a, 0x10, 0x50, 0x65, 0x72, 0x66, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x3c, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x37, 0x0a,
+ 0x0b, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
- 0x22, 0x37, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12,
- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66,
- 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69,
- 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12,
- 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73,
- 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a,
- 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d,
- 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67,
- 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
- 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75,
- 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f,
- 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75,
- 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
- 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74,
- 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61,
- 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63,
- 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e,
- 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63,
- 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61,
- 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63,
- 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c,
- 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69,
- 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f,
+ 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f,
+ 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73,
+ 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61,
+ 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
+ 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f,
+ 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61,
+ 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61,
+ 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73,
+ 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62,
+ 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72,
+ 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
+ 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
+ 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
+ 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68,
+ 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+ 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e,
+ 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d,
+ 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69,
+ 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
+ 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01,
+ 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0xc8, 0x02, 0x0a, 0x11, 0x53,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61,
+ 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61,
+ 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f,
+ 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d,
+ 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65,
+ 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+ 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x46, 0x0a, 0x0d, 0x70, 0x65, 0x72, 0x66, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21,
0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49,
- 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a,
- 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f,
- 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75,
- 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66,
- 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
- 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b,
- 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55,
- 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e,
- 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a,
- 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75,
- 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61,
- 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
- 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75,
- 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
- 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22,
- 0x94, 0x03, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12,
- 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c,
- 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c,
- 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a,
- 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
- 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61,
- 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18,
- 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11,
- 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66,
- 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69,
- 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d,
- 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46,
- 0x0a, 0x0d, 0x70, 0x65, 0x72, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18,
- 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x4a,
+ 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06,
+ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f,
+ 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e,
+ 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02,
+ 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52,
+ 0x54, 0x10, 0x03, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70,
+ 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69,
+ 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
+ 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
+ 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f,
+ 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72,
+ 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+ 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73,
+ 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65,
+ 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65,
+ 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a,
+ 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x05, 0x0a, 0x15, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a,
+ 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x42,
+ 0x0a, 0x0d, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x66, 0x43, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73,
- 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f,
- 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
- 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
- 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
- 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43,
- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e,
- 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f,
- 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10,
- 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45,
- 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
- 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65,
- 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f,
- 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d,
- 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f,
- 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d,
- 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69,
- 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a,
- 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69,
- 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70,
- 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a,
- 0x19, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x16, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69,
- 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c,
- 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73,
- 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
- 0x67, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f,
- 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65,
- 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65,
- 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
- 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x05, 0x0a, 0x15, 0x4f, 0x70,
- 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f,
- 0x70, 0x65, 0x72, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x50, 0x65,
+ 0x72, 0x66, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f,
+ 0x70, 0x65, 0x72, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f,
0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x61, 0x6e, 0x61, 0x6c, 0x79,
- 0x73, 0x69, 0x73, 0x50, 0x65, 0x72, 0x66, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61,
- 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d,
- 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x68, 0x0a,
- 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d,
- 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65,
- 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0xab, 0x03, 0x0a, 0x18, 0x54, 0x61, 0x72, 0x67,
+ 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61,
+ 0x67, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x68, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x43, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42,
+ 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
- 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x69,
- 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x70, 0x74,
- 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x16, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69,
- 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x12, 0x44, 0x0a,
- 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50,
- 0x65, 0x72, 0x66, 0x12, 0x7b, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x72,
- 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x52, 0x2e, 0x73,
- 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f,
- 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c,
- 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
- 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
- 0x1a, 0x63, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
- 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e,
- 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
- 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f,
- 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
- 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x12, 0x4c, 0x0a,
- 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65,
- 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x12,
- 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69,
- 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
- 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65,
- 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64,
- 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
- 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65,
- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
- 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
- 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65,
- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75,
+ 0x6c, 0x74, 0x1a, 0xab, 0x03, 0x0a, 0x18, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74,
+ 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65,
+ 0x64, 0x12, 0x35, 0x0a, 0x16, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+ 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x7b,
+ 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+ 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x52, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70,
+ 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69,
+ 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4f, 0x75, 0x74,
+ 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0e, 0x6f, 0x75, 0x74,
+ 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x1a, 0x63, 0x0a, 0x0e, 0x4f,
+ 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
+ 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+ 0x22, 0x83, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x27, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
+ 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
+ 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, 0x65,
+ 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x0a,
+ 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63,
+ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44,
+ 0x65, 0x6c, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x06,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x4a, 0x04, 0x08, 0x01,
+ 0x10, 0x02, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c,
+ 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0d,
+ 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
+ 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -3006,7 +2740,7 @@ func file_metrics_proto_rawDescGZIP() []byte {
}
var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
var file_metrics_proto_goTypes = []interface{}{
(MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
(MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
@@ -3025,19 +2759,16 @@ var file_metrics_proto_goTypes = []interface{}{
(*PerfCounter)(nil), // 14: soong_build_metrics.PerfCounter
(*ProcessResourceInfo)(nil), // 15: soong_build_metrics.ProcessResourceInfo
(*ModuleTypeInfo)(nil), // 16: soong_build_metrics.ModuleTypeInfo
- (*CriticalUserJourneyMetrics)(nil), // 17: soong_build_metrics.CriticalUserJourneyMetrics
- (*CriticalUserJourneysMetrics)(nil), // 18: soong_build_metrics.CriticalUserJourneysMetrics
- (*SoongBuildMetrics)(nil), // 19: soong_build_metrics.SoongBuildMetrics
- (*ExpConfigFetcher)(nil), // 20: soong_build_metrics.ExpConfigFetcher
- (*MixedBuildsInfo)(nil), // 21: soong_build_metrics.MixedBuildsInfo
- (*CriticalPathInfo)(nil), // 22: soong_build_metrics.CriticalPathInfo
- (*JobInfo)(nil), // 23: soong_build_metrics.JobInfo
- (*OptimizedBuildMetrics)(nil), // 24: soong_build_metrics.OptimizedBuildMetrics
- (*ExecutionMetrics)(nil), // 25: soong_build_metrics.ExecutionMetrics
- (*AggregatedFileList)(nil), // 26: soong_build_metrics.AggregatedFileList
- (*FileCount)(nil), // 27: soong_build_metrics.FileCount
- (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 28: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 29: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ (*SoongBuildMetrics)(nil), // 17: soong_build_metrics.SoongBuildMetrics
+ (*ExpConfigFetcher)(nil), // 18: soong_build_metrics.ExpConfigFetcher
+ (*CriticalPathInfo)(nil), // 19: soong_build_metrics.CriticalPathInfo
+ (*JobInfo)(nil), // 20: soong_build_metrics.JobInfo
+ (*OptimizedBuildMetrics)(nil), // 21: soong_build_metrics.OptimizedBuildMetrics
+ (*ExecutionMetrics)(nil), // 22: soong_build_metrics.ExecutionMetrics
+ (*AggregatedFileList)(nil), // 23: soong_build_metrics.AggregatedFileList
+ (*FileCount)(nil), // 24: soong_build_metrics.FileCount
+ (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 25: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 26: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
@@ -3049,41 +2780,37 @@ var file_metrics_proto_depIdxs = []int32{
11, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
11, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
11, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
- 19, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
+ 17, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
6, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
8, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
- 11, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
- 20, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
- 22, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
- 24, // 15: soong_build_metrics.MetricsBase.optimized_build_metrics:type_name -> soong_build_metrics.OptimizedBuildMetrics
- 2, // 16: soong_build_metrics.BuildConfig.ninja_weight_list_source:type_name -> soong_build_metrics.BuildConfig.NinjaWeightListSource
- 7, // 17: soong_build_metrics.BuildConfig.soong_env_vars:type_name -> soong_build_metrics.SoongEnvVars
- 9, // 18: soong_build_metrics.SystemResourceInfo.cpu_info:type_name -> soong_build_metrics.SystemCpuInfo
- 10, // 19: soong_build_metrics.SystemResourceInfo.mem_info:type_name -> soong_build_metrics.SystemMemInfo
- 15, // 20: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
- 13, // 21: soong_build_metrics.PerfCounters.groups:type_name -> soong_build_metrics.PerfCounterGroup
- 14, // 22: soong_build_metrics.PerfCounterGroup.counters:type_name -> soong_build_metrics.PerfCounter
- 3, // 23: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
- 5, // 24: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
- 17, // 25: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
- 11, // 26: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
- 21, // 27: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
- 12, // 28: soong_build_metrics.SoongBuildMetrics.perf_counters:type_name -> soong_build_metrics.PerfCounters
- 4, // 29: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
- 23, // 30: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
- 23, // 31: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
- 11, // 32: soong_build_metrics.OptimizedBuildMetrics.analysis_perf:type_name -> soong_build_metrics.PerfInfo
- 11, // 33: soong_build_metrics.OptimizedBuildMetrics.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 28, // 34: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- 26, // 35: soong_build_metrics.ExecutionMetrics.changed_files:type_name -> soong_build_metrics.AggregatedFileList
- 27, // 36: soong_build_metrics.AggregatedFileList.counts:type_name -> soong_build_metrics.FileCount
- 11, // 37: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 29, // 38: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
- 39, // [39:39] is the sub-list for method output_type
- 39, // [39:39] is the sub-list for method input_type
- 39, // [39:39] is the sub-list for extension type_name
- 39, // [39:39] is the sub-list for extension extendee
- 0, // [0:39] is the sub-list for field type_name
+ 18, // 12: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
+ 19, // 13: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
+ 21, // 14: soong_build_metrics.MetricsBase.optimized_build_metrics:type_name -> soong_build_metrics.OptimizedBuildMetrics
+ 2, // 15: soong_build_metrics.BuildConfig.ninja_weight_list_source:type_name -> soong_build_metrics.BuildConfig.NinjaWeightListSource
+ 7, // 16: soong_build_metrics.BuildConfig.soong_env_vars:type_name -> soong_build_metrics.SoongEnvVars
+ 9, // 17: soong_build_metrics.SystemResourceInfo.cpu_info:type_name -> soong_build_metrics.SystemCpuInfo
+ 10, // 18: soong_build_metrics.SystemResourceInfo.mem_info:type_name -> soong_build_metrics.SystemMemInfo
+ 15, // 19: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
+ 13, // 20: soong_build_metrics.PerfCounters.groups:type_name -> soong_build_metrics.PerfCounterGroup
+ 14, // 21: soong_build_metrics.PerfCounterGroup.counters:type_name -> soong_build_metrics.PerfCounter
+ 3, // 22: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
+ 11, // 23: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
+ 12, // 24: soong_build_metrics.SoongBuildMetrics.perf_counters:type_name -> soong_build_metrics.PerfCounters
+ 4, // 25: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ 20, // 26: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
+ 20, // 27: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
+ 11, // 28: soong_build_metrics.OptimizedBuildMetrics.analysis_perf:type_name -> soong_build_metrics.PerfInfo
+ 11, // 29: soong_build_metrics.OptimizedBuildMetrics.packaging_perf:type_name -> soong_build_metrics.PerfInfo
+ 25, // 30: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ 23, // 31: soong_build_metrics.ExecutionMetrics.changed_files:type_name -> soong_build_metrics.AggregatedFileList
+ 24, // 32: soong_build_metrics.AggregatedFileList.counts:type_name -> soong_build_metrics.FileCount
+ 11, // 33: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
+ 26, // 34: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ 35, // [35:35] is the sub-list for method output_type
+ 35, // [35:35] is the sub-list for method input_type
+ 35, // [35:35] is the sub-list for extension type_name
+ 35, // [35:35] is the sub-list for extension extendee
+ 0, // [0:35] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -3237,30 +2964,6 @@ func file_metrics_proto_init() {
}
}
file_metrics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneyMetrics); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_metrics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneysMetrics); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_metrics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SoongBuildMetrics); i {
case 0:
return &v.state
@@ -3272,7 +2975,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExpConfigFetcher); i {
case 0:
return &v.state
@@ -3284,19 +2987,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*MixedBuildsInfo); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_metrics_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CriticalPathInfo); i {
case 0:
return &v.state
@@ -3308,7 +2999,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*JobInfo); i {
case 0:
return &v.state
@@ -3320,7 +3011,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OptimizedBuildMetrics); i {
case 0:
return &v.state
@@ -3332,7 +3023,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExecutionMetrics); i {
case 0:
return &v.state
@@ -3344,7 +3035,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AggregatedFileList); i {
case 0:
return &v.state
@@ -3356,7 +3047,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FileCount); i {
case 0:
return &v.state
@@ -3368,7 +3059,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult); i {
case 0:
return &v.state
@@ -3380,7 +3071,7 @@ func file_metrics_proto_init() {
return nil
}
}
- file_metrics_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ file_metrics_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact); i {
case 0:
return &v.state
@@ -3399,7 +3090,7 @@ func file_metrics_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
NumEnums: 5,
- NumMessages: 25,
+ NumMessages: 22,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 7ff389acb..80fe30d24 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -108,8 +108,7 @@ message MetricsBase {
// The build command that the user entered to the build system.
optional string build_command = 26;
- // The metrics for calling Bazel.
- repeated PerfInfo bazel_runs = 27;
+ reserved 27;
// The metrics of the experiment config fetcher
optional ExpConfigFetcher exp_config_fetcher = 28;
@@ -154,25 +153,18 @@ message BuildConfig {
HINT_FROM_SOONG = 4;
}
- optional bool use_goma = 1;
optional bool use_rbe = 2;
- optional bool force_use_goma = 3;
+ reserved 4;
- // Whether the Bazel is acting as the Ninja executor for this build.
- optional bool bazel_as_ninja = 4;
-
- // Whether build is occurring in a mixed build mode, where Bazel maintains the
- // definition and build of some modules in cooperation with Soong.
- optional bool bazel_mixed_build = 5;
+ reserved 5;
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
repeated string targets = 6;
- // Whether the user explicitly disabled bazel mixed builds for this build.
- optional bool force_disable_bazel_mixed_build = 7;
+ reserved 7;
// NOT_USED - ninja doesn't use weight list.
// NINJA_LOG - ninja uses weight list based on previous builds by ninja log
@@ -187,6 +179,9 @@ message BuildConfig {
// Whether this build uses soong-only (no kati) mode (either via environment variable,
// command line flag or product config.
optional bool soong_only = 10;
+
+ reserved 1;
+ reserved 3;
}
message SoongEnvVars {
@@ -337,19 +332,6 @@ message ModuleTypeInfo {
optional uint32 num_of_modules = 3;
}
-message CriticalUserJourneyMetrics {
- // The name of a critical user journey test.
- optional string name = 1;
-
- // The metrics produced when running the critical user journey test.
- optional MetricsBase metrics = 2;
-}
-
-message CriticalUserJourneysMetrics {
- // A set of metrics from a run of the critical user journey tests.
- repeated CriticalUserJourneyMetrics cujs = 1;
-}
-
message SoongBuildMetrics {
// The number of modules handled by soong_build.
optional uint32 modules = 1;
@@ -369,8 +351,7 @@ message SoongBuildMetrics {
// Runtime metrics for soong_build execution.
repeated PerfInfo events = 6;
- // Mixed Builds information
- optional MixedBuildsInfo mixed_builds_info = 7;
+ reserved 7;
// Performance during for soong_build execution.
repeated PerfCounters perf_counters = 8;
@@ -396,28 +377,6 @@ message ExpConfigFetcher {
optional uint64 micros = 3;
}
-message MixedBuildsInfo{
- // Modules may be listed below as both enabled for Mixed Builds
- // and disabled for Mixed Builds. This implies that some variants
- // of the module are handled by Bazel in a Mixed Build, and other
- // variants of the same module are handled by Soong.
-
- // Modules that are enabled for Mixed Builds.
- repeated string mixed_build_enabled_modules = 1;
-
- // Modules that are not currently eligible to be handled
- // by Bazel in a Mixed Build.
- // Note that not all modules exempt from Bazel handling are
- // listed. This list includes only modules which are of a
- // Mixed-Build supported module type but are nevertheless not
- // handled by Bazel. This may occur due to being present in
- // the mixed build denylist, or as part of an unsupported
- // mixed build variant type such as Windows.
-
- // Modules that are not enabled for MixedBuilds
- repeated string mixed_build_disabled_modules = 2;
-}
-
// CriticalPathInfo contains critical path nodes's information.
// A critical path is a path determining the minimum time needed for the whole build given perfect parallelism.
message CriticalPathInfo {
diff --git a/ui/status/critical_path.go b/ui/status/critical_path.go
index bf32c589f..1d2728f05 100644
--- a/ui/status/critical_path.go
+++ b/ui/status/critical_path.go
@@ -153,5 +153,5 @@ func (cp *CriticalPath) WriteToMetrics(met *metrics.Metrics) {
criticalPathInfo.CriticalPathTimeMicros = proto.Uint64(uint64(criticalTime.Microseconds()))
addJobInfos(&criticalPathInfo.LongRunningJobs, cp.longRunningJobs())
addJobInfos(&criticalPathInfo.CriticalPath, path)
- met.SetCriticalPathInfo(criticalPathInfo)
+ met.SetCriticalPathInfo(&criticalPathInfo)
}
diff --git a/ui/status/kati.go b/ui/status/kati.go
index dbb0ce3df..9103515ed 100644
--- a/ui/status/kati.go
+++ b/ui/status/kati.go
@@ -24,7 +24,7 @@ import (
)
var katiError = regexp.MustCompile(`^(\033\[1m)?[^ ]+:[0-9]+: (\033\[31m)?error:`)
-var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including [^ ]+|initializing (legacy Make module parser|packaging system)|finishing (legacy Make module parsing|packaging rules)|writing (legacy Make module|packaging) rules) ...)$`)
+var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including|initializing|finishing|writing) .*?)( \.\.\.)?$`)
var katiLogRe = regexp.MustCompile(`^\*kati\*: `)
var katiNinjaMissing = regexp.MustCompile("^[^ ]+ is missing, regenerating...$")
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 73edbf625..ba9f0f9d7 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -55,12 +55,13 @@ func NewNinjaReader(ctx logger.Logger, status ToolStatus, fifo string) *NinjaRea
}
type NinjaReader struct {
- status ToolStatus
- fifo string
- forceClose chan bool
- done chan bool
- cancelOpen chan bool
- running map[uint32]*Action
+ status ToolStatus
+ fifo string
+ forceClose chan bool
+ done chan bool
+ cancelOpen chan bool
+ running map[uint32]*Action
+ hasAnyOutput bool
}
const NINJA_READER_CLOSE_TIMEOUT = 5 * time.Second
@@ -240,7 +241,8 @@ func (n *NinjaReader) run() {
err = fmt.Errorf("exited with code: %d", exitCode)
}
- outputWithErrorHint := errorHintGenerator.GetOutputWithErrorHint(msg.EdgeFinished.GetOutput(), exitCode)
+ rawOutput := msg.EdgeFinished.GetOutput()
+ outputWithErrorHint := errorHintGenerator.GetOutputWithErrorHint(rawOutput, exitCode)
n.status.FinishAction(ActionResult{
Action: started,
Output: outputWithErrorHint,
@@ -258,6 +260,8 @@ func (n *NinjaReader) run() {
Tags: msg.EdgeFinished.GetTags(),
},
})
+
+ n.hasAnyOutput = n.hasAnyOutput || len(rawOutput) > 0
}
}
if msg.Message != nil {
@@ -281,6 +285,12 @@ func (n *NinjaReader) run() {
}
}
+// Returns true if any command run by ninja had any output to stdout/stderr. Be sure to only
+// call this after close() to ensure all commands have been seen.
+func (n *NinjaReader) HasAnyOutput() bool {
+ return n.hasAnyOutput
+}
+
func readVarInt(r *bufio.Reader) (int, error) {
ret := 0
shift := uint(0)
diff --git a/unbundled/Android.bp b/unbundled/Android.bp
new file mode 100644
index 000000000..f0dd4a4e5
--- /dev/null
+++ b/unbundled/Android.bp
@@ -0,0 +1,28 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-unbundled",
+ pkgPath: "android/soong/unbundled",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-java",
+ "soong-filesystem",
+ ],
+ srcs: [
+ "unbundled.go",
+ ],
+ testSrcs: [
+ "unbundled_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
+unbundled_builder {
+ name: "unbundled_builder",
+}
diff --git a/unbundled/unbundled.go b/unbundled/unbundled.go
new file mode 100644
index 000000000..c3c3394b5
--- /dev/null
+++ b/unbundled/unbundled.go
@@ -0,0 +1,218 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package unbundled
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/filesystem"
+ "android/soong/java"
+ "fmt"
+ "slices"
+
+ "github.com/google/blueprint"
+)
+
+var pctx = android.NewPackageContext("android/soong/unbundled")
+
+func init() {
+ pctx.Import("android/soong/android")
+ registerUnbundledBuilder(android.InitRegistrationContext)
+}
+
+func registerUnbundledBuilder(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("unbundled_builder", unbundledBuilderFactory)
+}
+
+func unbundledBuilderFactory() android.Module {
+ m := &unbundledBuilder{}
+ android.InitAndroidModule(m)
+ return m
+}
+
+// unbundledBuilder handles building and disting certain artifacts for "unbundled builds".
+// unbundled builds are builds that aren't for a specific device, such as when you just want to
+// build an app or an apex.
+type unbundledBuilder struct {
+ android.ModuleBase
+}
+
+type unbundledDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+func (unbundledDepTagType) ExcludeFromVisibilityEnforcement() {}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = unbundledDepTagType{}
+
+func (unbundledDepTagType) UsesUnbundledVariant() {}
+
+var _ android.UsesUnbundledVariantDepTag = unbundledDepTagType{}
+
+var unbundledDepTag = unbundledDepTagType{}
+
+// We need to implement IsNativeCoverageNeeded so that in coverage builds we depend on the coverage
+// variants of the unbundled apps. Only the coverage variants export symbols info.
+func (p *unbundledBuilder) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
+ return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
+// Return "false" for UseGenericConfig() to read the DeviceProduct().
+// Even though unbundledBuilder is not for a specific device, do we need "targetProductPrefix"?
+func (p *unbundledBuilder) UseGenericConfig() bool {
+ return false
+}
+
+var _ cc.UseCoverage = (*unbundledBuilder)(nil)
+
+func (*unbundledBuilder) DepsMutator(ctx android.BottomUpMutatorContext) {
+ apps := ctx.Config().UnbundledBuildApps()
+ apps = slices.Clone(apps)
+ slices.Sort(apps)
+
+ for _, app := range apps {
+ // Add a dependency on the app so we can get its providers later.
+ // unbundledDepTag implements android.UsesUnbundledVariantDepTag, which causes the
+ // os, arch, and sdk mutators to pick the most appropriate variants to use for unbundled
+ // builds. unbundledBuilder itself also implements cc.UseCoverage, which forces coverage
+ // variants of deps.
+ ctx.AddDependency(ctx.Module(), unbundledDepTag, app)
+ }
+}
+
+func (*unbundledBuilder) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ctx.Module().HideFromMake()
+ if ctx.ModuleDir() != "build/soong/unbundled" {
+ ctx.ModuleErrorf("There can only be 1 unbundled_builder in build/soong/unbundled")
+ return
+ }
+ if !ctx.Config().HasUnbundledBuildApps() {
+ return
+ }
+
+ var appModules []android.ModuleOrProxy
+ ctx.VisitDirectDepsProxyWithTag(unbundledDepTag, func(m android.ModuleProxy) {
+ appModules = append(appModules, m)
+ })
+
+ targetProductPrefix := ""
+ if ctx.Config().HasDeviceProduct() {
+ targetProductPrefix = ctx.Config().DeviceProduct()
+ if ctx.Config().BuildType() == "debug" {
+ targetProductPrefix += "_debug"
+ }
+ targetProductPrefix += "-"
+ }
+
+ // Dist installed files, bundles, and AARs
+ for _, app := range appModules {
+ name := android.OtherModuleNameWithPossibleOverride(ctx, app)
+ if bundleInfo, ok := android.OtherModuleProvider(ctx, app, java.BundleProvider); ok {
+ ctx.DistForGoalWithFilename("apps_only", bundleInfo.Bundle, name+"-base.zip")
+ }
+ if info, ok := android.OtherModuleProvider(ctx, app, android.InstallFilesProvider); ok {
+ for _, file := range info.InstallFiles {
+ // The "apex" partition is a fake partition just to create files in
+ // out/target/product/<device>/apex. Including it leads to duplicate rule errors as
+ // there are multiple apexes with files installed at the same location within them.
+ if file.Partition() == "apex" {
+ continue
+ }
+
+ ctx.DistForGoal("apps_only", file)
+ }
+ if len(info.InstallFiles) == 0 {
+ outputFiles, err := android.OutputFilesForModuleOrErr(ctx, app, "")
+ // OutputFilesForModuleOrErr can error out when the module doesn't provide any
+ // output files. We don't care about that, just dist files when they're provided.
+ if err == nil {
+ for _, file := range outputFiles {
+ ctx.DistForGoal("apps_only", file)
+ }
+ }
+ if aarInfo, ok := android.OtherModuleProvider(ctx, app, java.AARProvider); ok {
+ ctx.DistForGoal("apps_only", aarInfo.Aar)
+ }
+ }
+ }
+ }
+
+ // Dist apexkeys.txt
+ apexKeysFile := android.PathForModuleOut(ctx, "apexkeys.txt")
+ apexKeysRuleBuilder := android.NewRuleBuilder(pctx, ctx)
+ apexKeysRuleBuilder.Command().Textf("rm -f %s && touch ", apexKeysFile.String()).Output(apexKeysFile)
+ for _, app := range appModules {
+ if info, ok := android.OtherModuleProvider(ctx, app, filesystem.ApexKeyPathInfoProvider); ok {
+ apexKeysRuleBuilder.Command().Text("cat ").Input(info.ApexKeyPath).Text(" >> ").Output(apexKeysFile)
+ }
+ }
+ apexKeysRuleBuilder.Build("unbundled_apexkeys.txt", "Unbundled apexkeys.txt")
+ ctx.DistForGoal("apps_only", apexKeysFile)
+ ctx.Phony("apexkeys.txt", apexKeysFile)
+
+ // Dist symbols.zip
+ symbolsZip := android.PathForOutput(ctx, "unbundled_singleton", targetProductPrefix+"symbols.zip")
+ symbolsMapping := android.PathForOutput(ctx, "unbundled_singleton", targetProductPrefix+"symbols-mapping.textproto")
+ android.BuildSymbolsZip(ctx, appModules, symbolsZip, symbolsMapping)
+ ctx.DistForGoalWithFilenameTag("apps_only", symbolsZip, symbolsZip.Base())
+ ctx.DistForGoalWithFilenameTag("apps_only", symbolsMapping, symbolsMapping.Base())
+
+ // Dist lint reports
+ var reportFiles android.Paths
+ for _, app := range appModules {
+ name := android.OtherModuleNameWithPossibleOverride(ctx, app)
+ if info, ok := android.OtherModuleProvider(ctx, app, java.ModuleLintReportZipsProvider); ok {
+ reports := info.AllReports()
+ for _, report := range reports {
+ ctx.DistForGoalWithFilename("lint-check", report, fmt.Sprintf("%s-%s", name, report.Base()))
+ }
+ reportFiles = append(reportFiles, reports...)
+ }
+ }
+ ctx.Phony("lint-check", reportFiles...)
+
+ // Dist proguard zips
+ proguardZips := java.BuildProguardZips(ctx, appModules)
+ ctx.DistForGoalWithFilenameTag("apps_only", proguardZips.DictZip, targetProductPrefix+proguardZips.DictZip.Base())
+ ctx.DistForGoalWithFilenameTag("apps_only", proguardZips.DictMapping, targetProductPrefix+proguardZips.DictMapping.Base())
+ ctx.DistForGoalWithFilenameTag("apps_only", proguardZips.UsageZip, targetProductPrefix+proguardZips.UsageZip.Base())
+
+ // Dist jacoco report jar
+ if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") {
+ jacocoZip := android.PathForModuleOut(ctx, "jacoco-report-classes-all.jar")
+ jacocoZipWithoutDeviceTests := android.PathForModuleOut(ctx, "jacoco-report-classes-all-without-device-tests.jar")
+ java.BuildJacocoZip(ctx, appModules, jacocoZipWithoutDeviceTests)
+ if ctx.Config().IsEnvTrue("JACOCO_PACKAGING_INCLUDE_DEVICE_TESTS") {
+ deviceTestsJacocoZip := java.DeviceTestsJacocoReportZip(ctx)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.MergeZips,
+ Output: jacocoZip,
+ Inputs: []android.Path{
+ jacocoZipWithoutDeviceTests,
+ deviceTestsJacocoZip,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: jacocoZip,
+ Input: jacocoZipWithoutDeviceTests,
+ })
+ }
+ ctx.DistForGoal("apps_only", jacocoZip)
+ }
+
+ ctx.DistForGoal("apps_only", java.ApkCertsFile(ctx))
+}
diff --git a/unbundled/unbundled_test.go b/unbundled/unbundled_test.go
new file mode 100644
index 000000000..bd5cae2af
--- /dev/null
+++ b/unbundled/unbundled_test.go
@@ -0,0 +1,72 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package unbundled
+
+import (
+ "android/soong/android"
+ "android/soong/java"
+ "strings"
+ "testing"
+)
+
+func TestProguardZipWithOverrideApp(t *testing.T) {
+ t.Parallel()
+ testResult := android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerUnbundledBuilder),
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.Unbundled_build_apps = []string{"foo", "fooOverride"}
+ }),
+ android.FixtureAddTextFile("build/soong/unbundled/Android.bp", `
+ unbundled_builder {
+ name: "unbundled_builder",
+ }
+ `),
+ android.FixtureAddTextFile("build/soong/Android.bp", `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ optimize: {
+ enabled: true,
+ },
+ srcs: ["foo.java"],
+ }
+ override_android_app {
+ name: "fooOverride",
+ base: "foo",
+ }
+ `),
+ android.FixtureAddTextFile("build/soong/foo.java", ""),
+ ).RunTest(t)
+
+ m := testResult.ModuleForTests(t, "unbundled_builder", "")
+ rule := m.Rule("proguard_dict_zip")
+
+ // Test that foo and fooOverride get placed in different locations in the zip
+ expected := strings.Join([]string{
+ "-e out/target/common/obj/APPS/foo_intermediates/proguard_dictionary",
+ "-f out/soong/.intermediates/build/soong/foo/android_common/proguard_dictionary",
+ "-e out/target/common/obj/APPS/foo_intermediates/classes.jar",
+ "-f out/soong/.intermediates/build/soong/foo/android_common/combined/foo.jar",
+ "-e out/target/common/obj/APPS/fooOverride_intermediates/proguard_dictionary",
+ "-f out/soong/.intermediates/build/soong/foo/android_common_fooOverride/proguard_dictionary",
+ "-e out/target/common/obj/APPS/fooOverride_intermediates/classes.jar",
+ "-f out/soong/.intermediates/build/soong/foo/android_common_fooOverride/combined/foo.jar",
+ }, " ")
+
+ if !strings.Contains(rule.RuleParams.Command, expected) {
+ t.Fatalf("Expected command to contain:\n %s\nBut was actually:\n %s\n", expected, rule.RuleParams.Command)
+ }
+}
diff --git a/xml/xml.go b/xml/xml.go
index c28107847..4997507f8 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -77,8 +77,6 @@ func (p *prebuiltEtcXml) timestampFilePath(ctx android.ModuleContext) android.Wr
}
func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.PrebuiltEtc.GenerateAndroidBuildActions(ctx)
-
if p.properties.Schema != nil {
schema := android.PathForModuleSrc(ctx, proptools.String(p.properties.Schema))
@@ -94,7 +92,6 @@ func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext)
"dtd": schema.String(),
},
})
- break
case ".xsd":
ctx.Build(pctx, android.BuildParams{
Rule: xmllintXsd,
@@ -106,7 +103,6 @@ func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext)
"xsd": schema.String(),
},
})
- break
default:
ctx.PropertyErrorf("schema", "not supported extension: %q", schema.Ext())
}
@@ -121,6 +117,8 @@ func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext)
}
p.SetAdditionalDependencies([]android.Path{p.timestampFilePath(ctx)})
+
+ p.PrebuiltEtc.GenerateAndroidBuildActions(ctx)
}
func PrebuiltEtcXmlFactory() android.Module {