diff options
Diffstat (limited to 'rules')
32 files changed, 781 insertions, 503 deletions
diff --git a/rules/abi/abi_dump.bzl b/rules/abi/abi_dump.bzl index 745a9c0b..f1e47618 100644 --- a/rules/abi/abi_dump.bzl +++ b/rules/abi/abi_dump.bzl @@ -19,7 +19,7 @@ load( "CPP_COMPILE_ACTION_NAME", "C_COMPILE_ACTION_NAME", ) -load("@soong_injection//product_config:product_variables.bzl", "product_vars") +load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") load("//build/bazel/platforms:platform_utils.bzl", "platforms") load( "//build/bazel/rules/cc:cc_library_common.bzl", @@ -219,10 +219,10 @@ def create_linked_abi_dump(ctx, dump_files): return output def find_abi_config(_ctx): - sdk_version = str(product_vars["Platform_sdk_version"]) + sdk_version = str(platform_versions.platform_sdk_version) prev_version = int(parse_apex_sdk_version(sdk_version)) version = "current" - if product_vars["Platform_sdk_final"]: + if platform_versions.platform_sdk_final: prev_version -= 1 version = sdk_version @@ -238,7 +238,7 @@ def create_abi_diff(ctx, dump_file): # The logic below comes from: # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/library.go;l=1891;drc=c645853ab73ac8c5889b42f4ce7dc9353ee8fd35 abi_reference_file = None - if not product_vars["Platform_sdk_final"]: + if not platform_versions.platform_sdk_final: abi_reference_file = _find_abi_ref_file(ctx, prev_version, arch, bitness, abi_class, dump_file.basename) if not abi_reference_file: prev_version -= 1 diff --git a/rules/aidl/aidl_interface.bzl b/rules/aidl/aidl_interface.bzl index 2944f1ca..da2cd669 100644 --- a/rules/aidl/aidl_interface.bzl +++ b/rules/aidl/aidl_interface.bzl @@ -13,9 +13,7 @@ # limitations under the License. load("//build/bazel/rules/aidl:aidl_library.bzl", "aidl_library") -load("//build/bazel/rules/cc:cc_aidl_code_gen.bzl", "cc_aidl_code_gen") -load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") -load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") +load("//build/bazel/rules/cc:cc_aidl_library.bzl", "cc_aidl_library") load("//build/bazel/rules/java:java_aidl_library.bzl", "java_aidl_library") JAVA = "java" @@ -26,19 +24,6 @@ NDK = "ndk" def _hash_file(name, version): return "aidl_api/{}/{}/.hash".format(name, version) -def _check_versions(versions): - sorted_versions = sorted([int(i) for i in versions]) # ensure that all versions are ints - - for i, v in enumerate(sorted_versions): - if i > 0: - if v == sorted_versions[i - 1]: - fail("duplicate version found:", v) - if v < sorted_versions[i - 1]: - fail("versions should be sorted") - if v <= 0: - fail("all versions should be > 0, but found version:", v) - return [str(i) for i in sorted_versions] - def _check_versions_with_info(versions_with_info): for version_with_info in versions_with_info: for dep in version_with_info.get("deps", []): @@ -46,6 +31,26 @@ def _check_versions_with_info(versions_with_info): if len(parts) < 2 or not parts[-1].isdigit(): fail("deps in versions_with_info must specify its version, but", dep) + versions = [] + + # ensure that all versions are ints + for info in versions_with_info: + version = info["version"] + if version.isdigit() == False: + fail("version %s is not an integer".format(version)) + + versions.append(int(version)) + + if versions != sorted(versions): + fail("versions should be sorted") + + for i, v in enumerate(versions): + if i > 0: + if v == versions[i - 1]: + fail("duplicate version found:", v) + if v <= 0: + fail("all versions should be > 0, but found version:", v) + def _create_latest_version_aliases(name, last_version_name, backend_configs, **kwargs): latest_name = name + "-latest" native.alias( @@ -68,14 +73,14 @@ def _versioned_name(name, version): return name + "-V" + version # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=782-799;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 -def _next_version(versions, unstable): +def _next_version(versions_with_info, unstable): if unstable: return "" - if versions == None or len(versions) == 0: + if versions_with_info == None or len(versions_with_info) == 0: return "1" - return str(int(versions[-1]) + 1) + return str(int(versions_with_info[-1]["version"]) + 1) def _is_config_enabled(config): if config == None: @@ -89,7 +94,7 @@ def _is_config_enabled(config): def aidl_interface( name, - deps = None, + deps = [], strip_import_prefix = "", srcs = None, flags = None, @@ -97,10 +102,7 @@ def aidl_interface( cpp_config = None, ndk_config = None, stability = None, - # TODO: Remove versions after aidl_interface module type deprecates - # versions prop in favor of versions_with_info prop - versions = None, - versions_with_info = None, + versions_with_info = [], unstable = False, tags = [], # TODO(b/261208761): Support frozen attr @@ -116,7 +118,6 @@ def aidl_interface( Arguments: name: string, base name of generated targets: <module-name>-V<version number>-<language-type> - versions: List[str], list of version labels with associated source directories deps: List[AidlGenInfo], a list of other aidl_libraries that all versions of this interface depend on strip_import_prefix: str, a local directory to pass to the AIDL compiler to satisfy imports srcs: List[file], a list of files to include in the development (unversioned) version of the aidl_interface @@ -130,12 +131,12 @@ def aidl_interface( # When versions_with_info is set, versions is no-op. # TODO(b/244349745): Modify bp2build to skip convert versions if versions_with_info is set - if (versions == None and versions_with_info == None and srcs == None): - fail("must specify at least versions, versions_with_info, or srcs") + if (len(versions_with_info) == 0 and srcs == None): + fail("must specify at least versions_with_info or srcs") - if versions == None and versions_with_info == None: + if len(versions_with_info) == 0: if frozen == True: - fail("frozen cannot be set without versions or versions_with_info attr being set") + fail("frozen cannot be set without versions_with_info attr being set") elif unstable == True: # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=872;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 fail("cannot have versions for unstable interface") @@ -170,59 +171,32 @@ def aidl_interface( # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=791?q=system%2Ftools%2Faidl%2Fbuild%2Faidl_interface.go next_version = None - # versions will be deprecated after all migrated to versions_with_info - if versions_with_info != None and len(versions_with_info) > 0: - versions = _check_versions([ - version_with_info["version"] - for version_with_info in versions_with_info - ]) + if len(versions_with_info) > 0: _check_versions_with_info(versions_with_info) - next_version = _next_version(versions, False) + next_version = _next_version(versions_with_info, False) + for version_with_info in versions_with_info: - hash_file = _hash_file(name, version_with_info["version"]) + deps_for_version = version_with_info.get("deps", []) + create_aidl_binding_for_backends( name = name, version = version_with_info["version"], - hash_file = hash_file, - deps = version_with_info.get("deps"), - aidl_flags = aidl_flags, - backend_configs = enabled_backend_configs, - tags = tags, - **kwargs - ) - if len(versions_with_info) > 0: - _create_latest_version_aliases( - name, - _versioned_name(name, versions[-1]), - enabled_backend_configs, - tags = tags, - **kwargs - ) - elif versions != None and len(versions) > 0: - versions = _check_versions(versions) - next_version = _next_version(versions, False) - for version in versions: - hash_file = _hash_file(name, version) - create_aidl_binding_for_backends( - name = name, - version = version, - hash_file = hash_file, - deps = deps, + deps = deps_for_version, aidl_flags = aidl_flags, backend_configs = enabled_backend_configs, tags = tags, **kwargs ) - if len(versions) > 0: - _create_latest_version_aliases( - name, - _versioned_name(name, versions[-1]), - enabled_backend_configs, - tags = tags, - **kwargs - ) + + _create_latest_version_aliases( + name, + _versioned_name(name, versions_with_info[-1]["version"]), + enabled_backend_configs, + tags = tags, + **kwargs + ) else: - next_version = _next_version(None, unstable) + next_version = _next_version(versions_with_info, unstable) # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=941;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 # Create aidl binding for next_version with srcs @@ -242,7 +216,6 @@ def aidl_interface( def create_aidl_binding_for_backends( name, version = None, - hash_file = None, srcs = None, strip_import_prefix = "", deps = None, @@ -272,16 +245,20 @@ def create_aidl_binding_for_backends( if version != "": aidl_flags = aidl_flags + ["--version=" + version] + hash_file = None + if srcs == None: if version == "": fail("need srcs for unversioned interface") strip_import_prefix = "aidl_api/{}/{}".format(name, version) srcs = native.glob([strip_import_prefix + "/**/*.aidl"]) + hash_file = _hash_file(name, version) aidl_library( name = aidl_library_name, deps = deps, hash_file = hash_file, + version = version, strip_import_prefix = strip_import_prefix, srcs = srcs, flags = aidl_flags, @@ -329,90 +306,26 @@ def create_aidl_binding_for_backends( # https://source.corp.google.com/android/system/tools/aidl/build/aidl_interface_backends.go;l=120;rcl=18dd931bde35b502545b7a52987e2363042c151c cppflags = ["-DBINDER_STABILITY_SUPPORT"] - _cc_aidl_libraries( + if hasattr(kwargs, "tidy_checks_as_errors"): + fail("tidy_checks_as_errors cannot be overriden for aidl_interface cc_libraries") + tidy_checks_as_errors = [ + "*", + "-clang-analyzer-deadcode.DeadStores", # b/253079031 + "-clang-analyzer-cplusplus.NewDeleteLeaks", # b/253079031 + "-clang-analyzer-optin.performance.Padding", # b/253079031 + ] + + cc_aidl_library( name = "{}-{}".format(aidl_library_name, lang), - aidl_library = ":" + aidl_library_name, + make_shared = True, + cppflags = cppflags, + deps = [":" + aidl_library_name], dynamic_deps = dynamic_deps, lang = lang, min_sdk_version = min_sdk_version, + tidy = "local", + tidy_checks_as_errors = tidy_checks_as_errors, + tidy_gen_header_filter = True, tags = tags + config.get("tags", []), - cppflags = cppflags, **kwargs ) - -# _cc_aidl_libraries is slightly different from cc_aidl_library macro provided -# from //bazel/bulid/rules/cc:cc_aidl_libray.bzl. -# -# Instead of creating one cc_library_static target, _cc_aidl_libraries creates -# both static and shared variants of cc library so that the upstream modules -# can reference the aidl interface with ndk or cpp backend as either static -# or shared lib -def _cc_aidl_libraries( - name, - aidl_library = None, - implementation_deps = [], - dynamic_deps = [], - lang = None, - min_sdk_version = "", - tags = [], - cppflags = [], - **kwargs): - """ - Generate AIDL stub code for cpp or ndk backend and wrap it in cc libraries (both shared and static variant) - - Args: - name: (String) name of the cc_library_static target - aidl_library: (AidlGenInfo) aidl_library that this cc_aidl_library depends on - implementation_deps: (list[CcInfo]) internal cpp/ndk dependencies of the created cc_library_static target - dynamic_deps: (list[CcInfo]) dynamic dependencies of the created cc_library_static and cc_library_shared targets - lang: (String) lang to be passed into --lang flag of aidl generator - **kwargs: extra arguments that will be passesd to cc_aidl_code_gen and cc library rules. - """ - - if lang == None: - fail("lang must be set") - if lang != "cpp" and lang != "ndk": - fail("lang {} is unsupported. Allowed lang: ndk, cpp.") - - aidl_code_gen = name + "_aidl_code_gen" - - cc_aidl_code_gen( - name = aidl_code_gen, - deps = [aidl_library], - lang = lang, - min_sdk_version = min_sdk_version, - tags = tags, - **kwargs - ) - - if hasattr(kwargs, "tidy_checks_as_errors"): - fail("tidy_checks_as_errors cannot be overriden for aidl_interface cc_libraries") - tidy_checks_as_errors = [ - "*", - "-clang-analyzer-deadcode.DeadStores", # b/253079031 - "-clang-analyzer-cplusplus.NewDeleteLeaks", # b/253079031 - "-clang-analyzer-optin.performance.Padding", # b/253079031 - ] - - shared_arguments_with_kwargs = dict( - kwargs, - srcs = [":" + aidl_code_gen], - implementation_deps = implementation_deps, - deps = [aidl_code_gen], - dynamic_deps = dynamic_deps, - min_sdk_version = min_sdk_version, - tidy = "local", - tidy_checks_as_errors = tidy_checks_as_errors, - tidy_gen_header_filter = True, - tags = tags, - cppflags = cppflags, - ) - - cc_library_shared( - name = name, - **shared_arguments_with_kwargs - ) - cc_library_static( - name = name + "_bp2build_cc_library_static", - **shared_arguments_with_kwargs - ) diff --git a/rules/aidl/aidl_interface_test.bzl b/rules/aidl/aidl_interface_test.bzl index 22d7c5a9..538ad79b 100644 --- a/rules/aidl/aidl_interface_test.bzl +++ b/rules/aidl/aidl_interface_test.bzl @@ -19,6 +19,7 @@ load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//build/bazel/rules/aidl:aidl_interface.bzl", "aidl_interface") load("//build/bazel/rules/aidl:aidl_library.bzl", "AidlGenInfo") load("//build/bazel/rules/test_common:rules.bzl", "target_under_test_exist_test") +load("//build/bazel/rules/test_common:flags.bzl", "action_flags_present_only_for_mnemonic_test_with_config_settings") def _ndk_backend_test_impl(ctx): env = analysistest.begin(ctx) @@ -168,7 +169,14 @@ def _test_aidl_interface_passes_flags_to_aidl_libraries(): name = name, srcs = ["Foo.aidl"], tags = ["manual"], - versions = ["1", "2"], + versions_with_info = [ + { + "version": "1", + }, + { + "version": "2", + }, + ], ) target_v1_test_name = name + "_test-V1" @@ -230,7 +238,14 @@ def _next_version_for_versioned_stable_interface_test(): aidl_interface( name = name, - versions = ["1", "2"], + versions_with_info = [ + { + "version": "1", + }, + { + "version": "2", + }, + ], srcs = ["Foo.aidl"], tags = ["manual"], ) @@ -327,6 +342,50 @@ def _test_aidl_interface_generated_header_filter(): static_test_name, ] +_action_flags_present_with_tidy_test = action_flags_present_only_for_mnemonic_test_with_config_settings({ + "@//build/bazel/flags/cc/tidy:allow_local_tidy_true": True, +}) + +def _test_aidl_interface_generated_cc_library_has_correct_tidy_checks_as_errors(): + name = "aidl_interface_generated_cc_library_has_correct_tidy_checks_as_errors" + test_name = name + "_test" + aidl_library_target = name + "-cpp" + shared_target_under_test = aidl_library_target + "__internal_root" + shared_test_name = test_name + "_shared" + static_target_under_test = aidl_library_target + "_bp2build_cc_library_static" + static_test_name = test_name + "_static" + + aidl_interface( + name = name, + cpp_config = { + "enabled": True, + }, + unstable = True, + srcs = ["a/b/Foo.aidl"], + tags = ["manual"], + ) + + _action_flags_present_with_tidy_test( + name = shared_test_name, + target_under_test = shared_target_under_test, + mnemonics = ["ClangTidy"], + expected_flags = [ + "-warnings-as-errors=*,-clang-analyzer-deadcode.DeadStores,-clang-analyzer-cplusplus.NewDeleteLeaks,-clang-analyzer-optin.performance.Padding,-bugprone-assignment-in-if-condition,-bugprone-branch-clone,-bugprone-signed-char-misuse,-misc-const-correctness", + ], + ) + _action_flags_present_with_tidy_test( + name = static_test_name, + target_under_test = static_target_under_test, + mnemonics = ["ClangTidy"], + expected_flags = [ + "-warnings-as-errors=*,-clang-analyzer-deadcode.DeadStores,-clang-analyzer-cplusplus.NewDeleteLeaks,-clang-analyzer-optin.performance.Padding,-bugprone-assignment-in-if-condition,-bugprone-branch-clone,-bugprone-signed-char-misuse,-misc-const-correctness", + ], + ) + return [ + shared_test_name, + static_test_name, + ] + def _cc_library_has_flags_test_impl(ctx): env = analysistest.begin(ctx) target = analysistest.target_under_test(env) @@ -406,6 +465,7 @@ def aidl_interface_test_suite(name): ] + _test_aidl_interface_generated_header_filter() + _test_aidl_interface_passes_flags_to_aidl_libraries() + - _test_aidl_interface_sets_flags_to_cc_libraries() + _test_aidl_interface_sets_flags_to_cc_libraries() + + _test_aidl_interface_generated_cc_library_has_correct_tidy_checks_as_errors() ), ) diff --git a/rules/aidl/aidl_library.bzl b/rules/aidl/aidl_library.bzl index f960c770..5e0ee45b 100644 --- a/rules/aidl/aidl_library.bzl +++ b/rules/aidl/aidl_library.bzl @@ -48,10 +48,69 @@ def _symlink_aidl_srcs(ctx, srcs, strip_import_prefix): direct_srcs.append(virtual_src) return include_path, direct_srcs +# https://cs.android.com/android/platform/system/tools/aidl/+/master:build/aidl_api.go;l=718-724;drc=87bcb923b4ed9cf6e6837f4cc02d954f211c0b12 +def _version_for_hash_gen(version): + if int(version) > 1: + return int(version) - 1 + return "latest-version" + +def _get_aidl_interface_name(versioned_name): + parts = versioned_name.split("-V") + if len(parts) == 1 or not parts[-1].isdigit(): + fail("{}'s version is not parsable", versioned_name) + + return parts[0] + +def _verify_hash_file(ctx): + timestamp = ctx.actions.declare_file(ctx.label.name + "_checkhash_" + ctx.attr.version + ".timestamp") + + api_dir = "{package_dir}/aidl_api/{aidl_interface_name}/{version}".format( + package_dir = paths.dirname(ctx.build_file_path), + aidl_interface_name = _get_aidl_interface_name(ctx.label.name), + version = ctx.attr.version, + ) + + shell_command = """ + cd {api_dir} + aidl_files_checksums=$(find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo {version}) + cd - + + if [[ $(echo "$aidl_files_checksums" | sha1sum | cut -d " " -f 1) = $(tail -1 {hash_file}) ]]; then + touch {timestamp}; + else + cat "{message_check_equality}" + exit 1; + fi; + """.format( + api_dir = api_dir, + aidl_files = " ".join([src.path for src in ctx.files.srcs]), + version = _version_for_hash_gen(ctx.attr.version), + hash_file = ctx.file.hash_file.path, + timestamp = timestamp.path, + message_check_equality = ctx.file._message_check_equality.path, + ) + + ctx.actions.run_shell( + inputs = ctx.files.srcs + [ctx.file.hash_file, ctx.file._message_check_equality], + outputs = [timestamp], + command = shell_command, + mnemonic = "AidlHashValidation", + progress_message = "Validating AIDL .hash file", + ) + + return timestamp + def _aidl_library_rule_impl(ctx): transitive_srcs = [] transitive_include_dirs = [] + validation_output = [] + + if ctx.attr.hash_file and ctx.attr.version: + # if the aidl_library represents an aidl_interface frozen version, + # hash_file and version attributes are set + validation_output.append(_verify_hash_file(ctx)) + aidl_import_infos = [d[AidlGenInfo] for d in ctx.attr.deps] for info in aidl_import_infos: transitive_srcs.append(info.transitive_srcs) @@ -62,6 +121,9 @@ def _aidl_library_rule_impl(ctx): return [ DefaultInfo(files = depset(ctx.files.srcs)), + OutputGroupInfo( + _validation = depset(direct = validation_output), + ), AidlGenInfo( srcs = depset(srcs), hdrs = depset(hdrs), @@ -96,9 +158,18 @@ aidl_library = rule( " AIDL defintions. These files cannot be compiled to language" + " bindings, but can be referenced by other AIDL sources.", ), + "version": attr.string( + doc = "The version of the upstream aidl_interface that" + + " the aidl_library is created for", + ), "hash_file": attr.label( + doc = "The .hash file in the api directory of an aidl_interface frozen version", allow_single_file = [".hash"], ), + "_message_check_equality": attr.label( + allow_single_file = [".txt"], + default = "//system/tools/aidl/build:message_check_equality.txt", + ), "deps": attr.label_list( providers = [AidlGenInfo], doc = "Targets listed here provide AIDL sources referenced" + diff --git a/rules/aidl/testing/BUILD b/rules/aidl/testing/BUILD index 8e254f41..cf65e84d 100644 --- a/rules/aidl/testing/BUILD +++ b/rules/aidl/testing/BUILD @@ -15,7 +15,6 @@ limitations under the License. """ load("//build/bazel/rules/aidl:aidl_interface.bzl", "aidl_interface") -load("//build/bazel/rules/aidl:aidl_library.bzl", "aidl_library") test_scope = [ "//build/bazel/rules/aidl/testing:aidl_interface_test-java", @@ -27,8 +26,8 @@ test_scope = [ "//build/bazel/rules/aidl/testing:aidl_interface_test-latest-java", ] -aidl_library( - name = "aidl_library_test", +aidl_interface( + name = "foo", srcs = ["Test.aidl"], tags = ["manual"], ) @@ -39,11 +38,16 @@ aidl_interface( "enabled": True, }, tags = ["manual"], - versions = [ - "1", - "2", + versions_with_info = [ + { + "version": "1", + "deps": [":foo-V1"], + }, + { + "version": "2", + "deps": [":foo-V1"], + }, ], - deps = [":aidl_library_test"], ) genquery( diff --git a/rules/aidl/testing/generated_targets_have_correct_srcs.sh b/rules/aidl/testing/generated_targets_have_correct_srcs.sh index 917fdcea..d6b93917 100755 --- a/rules/aidl/testing/generated_targets_have_correct_srcs.sh +++ b/rules/aidl/testing/generated_targets_have_correct_srcs.sh @@ -23,11 +23,13 @@ readonly expected_query_v1="\ //build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/1/.hash //build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/1/android/net/Test.aidl //build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/1/android/net/Test2.aidl -//build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/1/android/net/Test3.aidl" +//build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/1/android/net/Test3.aidl +//system/tools/aidl/build:message_check_equality.txt" readonly expected_query_v2="\ //build/bazel/rules/aidl/testing:Test.aidl //build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/2/.hash -//build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/2/Test2Only.aidl" +//build/bazel/rules/aidl/testing:aidl_api/aidl_interface_test/2/Test2Only.aidl +//system/tools/aidl/build:message_check_equality.txt" readonly query_path_v1="__main__/build/bazel/rules/aidl/testing/generated_target_V1_has_correct_srcs_query" readonly query_path_v2="__main__/build/bazel/rules/aidl/testing/generated_target_V2_has_correct_srcs_query" diff --git a/rules/android/android_app_certificate.bzl b/rules/android/android_app_certificate.bzl index 8ffa0055..84ab819f 100644 --- a/rules/android/android_app_certificate.bzl +++ b/rules/android/android_app_certificate.bzl @@ -13,7 +13,8 @@ # limitations under the License. load("@bazel_skylib//lib:paths.bzl", "paths") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesDepsInfo", "ProductVariablesInfo") AndroidAppCertificateInfo = provider( "Info needed for Android app certificates", @@ -24,9 +25,59 @@ AndroidAppCertificateInfo = provider( }, ) +def _search_cert_files(cert_name, cert_files_to_search): + pk8 = None + pem = None + for file in cert_files_to_search: + if file.basename == cert_name + ".pk8": + pk8 = file + elif file.basename == cert_name + ".x509.pem": + pem = file + if not pk8 or not pem: + fail("Could not find .x509.pem and/or .pk8 file with name '%s' in the following files: %s" % (cert_name, cert_files_to_search)) + return pk8, pem + +def _maybe_override(ctx, cert_name): + if not cert_name: + fail("cert_name cannot be None") + + cert_overrides = ctx.attr._product_variables[ProductVariablesInfo].CertificateOverrides + if not cert_overrides: + return cert_name, False + + apex_name = ctx.attr._apex_name[BuildSettingInfo].value + if not apex_name: + # Only override in the apex configuration, because the apex module name is used as the key for overriding + return cert_name, False + + matches = [o for o in cert_overrides if o.split(":")[0] == apex_name] + + if not matches: + # no matches, no override. + return cert_name, False + + if len(matches) > 1: + fail("unexpected multiple certificate overrides for %s in: %s" % (apex_name, matches)) + + # e.g. test1_com.android.tzdata:com.google.android.tzdata5.certificate + new_cert_name = matches[0].split(":")[1] + return new_cert_name.removesuffix(".certificate"), True + def _android_app_certificate_rule_impl(ctx): + cert_name = ctx.attr.certificate + pk8 = ctx.file.pk8 + pem = ctx.file.pem + + # Only override if the override mapping exists, otherwise we wouldn't be + # able to find the new certs. + overridden_cert_name, overridden = _maybe_override(ctx, cert_name) + if overridden: + cert_name = overridden_cert_name + cert_files_to_search = ctx.attr._product_variables[ProductVariablesDepsInfo].OverridingCertificateFiles + pk8, pem = _search_cert_files(cert_name, cert_files_to_search) + return [ - AndroidAppCertificateInfo(pem = ctx.file.pem, pk8 = ctx.file.pk8, key_name = ctx.attr.certificate), + AndroidAppCertificateInfo(pem = pem, pk8 = pk8, key_name = cert_name), ] _android_app_certificate = rule( @@ -35,6 +86,13 @@ _android_app_certificate = rule( "pem": attr.label(mandatory = True, allow_single_file = [".pem"]), "pk8": attr.label(mandatory = True, allow_single_file = [".pk8"]), "certificate": attr.string(mandatory = True), + "_apex_name": attr.label(default = "//build/bazel/rules/apex:apex_name"), + "_product_variables": attr.label( + default = "//build/bazel/product_config:product_vars", + ), + "_hardcoded_certs": attr.label( + default = "//build/make/target/product/security:android_certificate_directory", + ), }, ) @@ -53,46 +111,71 @@ def android_app_certificate( ) default_cert_directory = "build/make/target/product/security" -_default_cert_package = "//" + default_cert_directory -# Set up the android_app_certificate dependency pointing to the .pk8 and -# .x509.pem files in the source tree. -# -# Every caller who use this function will have their own android_app_certificate -# target, even if the underlying certs are shared by many. -# -# If cert_name is used, then it will be looked up from the app certificate -# package as determined by the DefaultAppCertificate variable, or the hardcoded -# directory. -# -# Otherwise, if the DefaultAppCertificate variable is used, then an -# android_app_certificate target will be created to point to the path value, and -# the .pk8 and .x509.pem suffixes are added automatically. -# -# Finally (cert_name not used AND DefaultAppCertificate not specified), use the -# testkey. -def android_app_certificate_with_default_cert(name, cert_name = None): - default_cert = product_vars.get("DefaultAppCertificate") +def _android_app_certificate_with_default_cert_impl(ctx): + product_var_cert = ctx.attr._product_variables[ProductVariablesInfo].DefaultAppCertificate - if cert_name and default_cert: - certificate = "".join(["//", paths.dirname(default_cert), ":", cert_name]) + cert_name = ctx.attr.cert_name + + if cert_name and product_var_cert: + cert_dir = paths.dirname(product_var_cert) elif cert_name: - # if a specific certificate name is given, check the default directory - # for that certificate. - certificate = _default_cert_package + ":" + cert_name - elif default_cert: - # This assumes that there is a BUILD file marking the directory of - # the default cert as a package. - certificate = "".join([ - "//", - paths.dirname(default_cert), - ":", - paths.basename(default_cert), - ]) + cert_dir = default_cert_directory + elif product_var_cert: + cert_name = paths.basename(product_var_cert) + cert_dir = paths.dirname(product_var_cert) else: - certificate = _default_cert_package + ":testkey" + cert_name = "testkey" + cert_dir = default_cert_directory - android_app_certificate( - name = name, - certificate = certificate, - ) + if cert_dir != default_cert_directory: + cert_files_to_search = ctx.attr._product_variables[ProductVariablesDepsInfo].DefaultAppCertificateFiles + else: + cert_files_to_search = ctx.files._hardcoded_certs + + cert_name, overridden = _maybe_override(ctx, cert_name) + if overridden: + cert_files_to_search = ctx.attr._product_variables[ProductVariablesDepsInfo].OverridingCertificateFiles + pk8, pem = _search_cert_files(cert_name, cert_files_to_search) + + return [ + AndroidAppCertificateInfo( + pk8 = pk8, + pem = pem, + key_name = "//" + cert_dir + ":" + cert_name, + ), + ] + +android_app_certificate_with_default_cert = rule( + doc = """ + This rule is the equivalent of an android_app_certificate, but uses the + certificate with the given name from a certain folder, or the default + certificate. + + Modules can give a simple name of a certificate instead of a full label to + an android_app_certificate. This certificate will be looked for either in + the package determined by the DefaultAppCertificate product config variable, + or the hardcoded default directory. (build/make/target/product/security) + + If a name is not given, it will fall back to using the certificate termined + by DefaultAppCertificate. (DefaultAppCertificate can function as both the + default certificate to use if none is specified, and the folder to look for + certificates in) + + If neither the name nor DefaultAppCertificate is given, + build/make/target/product/security/testkey.{pem,pk8} will be used. + + Since this rule is intended to be used from other macros, it's common to have + multiple android_app_certificate targets pointing to the same pem/pk8 files. + """, + implementation = _android_app_certificate_with_default_cert_impl, + attrs = { + "cert_name": attr.string(), + "_product_variables": attr.label( + default = "//build/bazel/product_config:product_vars", + ), + "_hardcoded_certs": attr.label( + default = "//build/make/target/product/security:android_certificate_directory", + ), + }, +) diff --git a/rules/android/android_binary.bzl b/rules/android/android_binary.bzl index 262973b3..64465a15 100644 --- a/rules/android/android_binary.bzl +++ b/rules/android/android_binary.bzl @@ -84,7 +84,10 @@ def android_binary( if certificate or certificate_name: if certificate_name: app_cert_name = name + "_app_certificate" - android_app_certificate_with_default_cert(app_cert_name, certificate_name) + android_app_certificate_with_default_cert( + name = app_cert_name, + cert_name = certificate_name, + ) certificate = ":" + app_cert_name app_keystore_name = name + "_keystore" diff --git a/rules/apex/BUILD b/rules/apex/BUILD index d094d3e6..61bacae8 100644 --- a/rules/apex/BUILD +++ b/rules/apex/BUILD @@ -1,5 +1,6 @@ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "bool_setting", "string_list_setting", "string_setting") load("@env//:env.bzl", "env") +load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") load("@soong_injection//product_config:product_variables.bzl", "product_vars") load("//build/bazel/flags:common.bzl", "is_env_true") load("//build/bazel/product_variables:constants.bzl", "constants") @@ -135,24 +136,9 @@ bool_flag( visibility = ["//visibility:public"], ) -bool_setting( - name = "unbundled_build", - # TODO(b/269577299): Make this read from //build/bazel/product_config:product_vars instead. - build_setting_default = product_vars.get("Unbundled_build", False), - visibility = ["//visibility:public"], -) - -bool_setting( - name = "always_use_prebuilt_sdks", - # TODO(b/269577299): Make this read from //build/bazel/product_config:product_vars instead. - build_setting_default = product_vars.get("Always_use_prebuilt_sdks", False), - visibility = ["//visibility:public"], -) - string_setting( name = "platform_sdk_codename", - # TODO(b/269577299): Make this read from //build/bazel/product_config:product_vars instead. - build_setting_default = product_vars.get("Platform_sdk_codename", ""), + build_setting_default = platform_versions.platform_sdk_codename, visibility = ["//visibility:public"], ) diff --git a/rules/apex/apex.bzl b/rules/apex/apex.bzl index 7bebca4b..cc679cea 100644 --- a/rules/apex/apex.bzl +++ b/rules/apex/apex.bzl @@ -15,7 +15,6 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("@soong_injection//apex_toolchain:constants.bzl", "default_manifest_version") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") load("//build/bazel/platforms:platform_utils.bzl", "platforms") load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesInfo") load("//build/bazel/rules:common.bzl", "get_dep_targets") @@ -390,9 +389,10 @@ def _generate_notices(ctx, apex_toolchain): return notice_file def _use_api_fingerprint(ctx): - if not ctx.attr._unbundled_build[BuildSettingInfo].value: + product_vars = ctx.attr._product_variables[ProductVariablesInfo] + if not product_vars.Unbundled_build: return False - if ctx.attr._always_use_prebuilt_sdks[BuildSettingInfo].value: + if product_vars.Always_use_prebuilt_sdks: return False if not ctx.attr._unbundled_build_target_sdk_with_api_fingerprint[BuildSettingInfo].value: return False @@ -451,6 +451,10 @@ def _run_apexer(ctx, apex_toolchain): # Override the package name, if it's expicitly specified if ctx.attr.package_name: args.add_all(["--override_apk_package_name", ctx.attr.package_name]) + else: + override_package_name = _override_manifest_package_name(ctx) + if override_package_name: + args.add_all(["--override_apk_package_name", override_package_name]) if ctx.attr.logging_parent: args.add_all(["--logging_parent", ctx.attr.logging_parent]) @@ -582,6 +586,24 @@ def _run_signapk(ctx, unsigned_file, signed_file, private_key, public_key, mnemo return signed_file +# See also getOverrideManifestPackageName +# https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/builder.go;l=1000;drc=241e738c7156d928e9a993b15993cb3297face45 +def _override_manifest_package_name(ctx): + apex_name = ctx.attr.name + overrides = ctx.attr._product_variables[ProductVariablesInfo].ManifestPackageNameOverrides + if not overrides: + return None + + matches = [o for o in overrides if o.split(":")[0] == apex_name] + + if not matches: + return None + + if len(matches) > 1: + fail("unexpected multiple manifest package overrides for %s, %s" % (apex_name, matches)) + + return matches[0].split(":")[1] + # https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;drc=5ca657189aac546af0aafaba11bbc9c5d889eab3;l=1501 # In Soong, we don't check whether the current apex is part of Unbundled_apps. # Hence, we might simplify the logic by just checking product_vars["Unbundled_build"] @@ -738,7 +760,7 @@ def _apex_rule_impl(ctx): apexer_outputs = _run_apexer(ctx, apex_toolchain) unsigned_apex = apexer_outputs.unsigned_apex - apex_cert_info = ctx.attr.certificate[AndroidAppCertificateInfo] + apex_cert_info = ctx.attr.certificate[0][AndroidAppCertificateInfo] private_key = apex_cert_info.pk8 public_key = apex_cert_info.pem @@ -842,6 +864,7 @@ file mode, and cap is hexadecimal value for the capability.""", "certificate": attr.label( providers = [AndroidAppCertificateInfo], mandatory = True, + cfg = apex_transition, ), "min_sdk_version": attr.string( default = "current", @@ -950,12 +973,6 @@ APEX is truly updatable. To be updatable, min_sdk_version should be set as well. ), # Api_fingerprint - "_unbundled_build": attr.label( - default = "//build/bazel/rules/apex:unbundled_build", - ), - "_always_use_prebuilt_sdks": attr.label( - default = "//build/bazel/rules/apex:always_use_prebuilt_sdks", - ), "_unbundled_build_target_sdk_with_api_fingerprint": attr.label( default = "//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint", ), @@ -1014,13 +1031,16 @@ def apex( app_cert_name = name + "_app_certificate" if certificate_name: # use the name key in the default cert dir - android_app_certificate_with_default_cert(app_cert_name, certificate_name) + android_app_certificate_with_default_cert( + name = app_cert_name, + cert_name = certificate_name, + ) certificate_label = ":" + app_cert_name elif certificate: certificate_label = certificate else: # use the default testkey - android_app_certificate_with_default_cert(app_cert_name) + android_app_certificate_with_default_cert(name = app_cert_name) certificate_label = ":" + app_cert_name target_compatible_with = select({ diff --git a/rules/apex/apex_key.bzl b/rules/apex/apex_key.bzl index 36723c99..45e83f01 100644 --- a/rules/apex/apex_key.bzl +++ b/rules/apex/apex_key.bzl @@ -13,8 +13,7 @@ # limitations under the License. load("@bazel_skylib//lib:paths.bzl", "paths") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") -load("//build/bazel/rules/android:android_app_certificate.bzl", "default_cert_directory") +load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesDepsInfo", "ProductVariablesInfo") ApexKeyInfo = provider( "Info needed to sign APEX bundles", @@ -28,6 +27,18 @@ def _apex_key_rule_impl(ctx): public_key = ctx.file.public_key private_key = ctx.file.private_key + # If the DefaultAppCertificate directory is specified, then look for this + # key in that directory instead, with the exact same basenames for both the + # avbpubkey and pem files. + product_var_cert = ctx.attr._product_variables[ProductVariablesInfo].DefaultAppCertificate + cert_files_to_search = ctx.attr._product_variables[ProductVariablesDepsInfo].DefaultAppCertificateFiles + if product_var_cert and cert_files_to_search: + for f in cert_files_to_search: + if f.basename == ctx.file.public_key.basename: + public_key = f + elif f.basename == ctx.file.private_key.basename: + private_key = f + public_keyname = paths.split_extension(public_key.basename)[0] private_keyname = paths.split_extension(private_key.basename)[0] if public_keyname != private_keyname: @@ -39,7 +50,10 @@ def _apex_key_rule_impl(ctx): )) return [ - ApexKeyInfo(public_key = ctx.file.public_key, private_key = ctx.file.private_key), + ApexKeyInfo( + public_key = public_key, + private_key = private_key, + ), ] _apex_key = rule( @@ -47,12 +61,13 @@ _apex_key = rule( attrs = { "private_key": attr.label(mandatory = True, allow_single_file = True), "public_key": attr.label(mandatory = True, allow_single_file = True), + "_product_variables": attr.label( + default = "//build/bazel/product_config:product_vars", + ), }, ) -# Keep consistent with the ApexKeyDir product config lookup: -# https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;l=831-841;drc=652335ea7c2f8f281a1b93a1e1558960b6ad1b6f -def _get_key_label(label, name, default_cert): +def _get_key_label(label, name): if label and name: fail("Cannot use both {public,private}_key_name and {public,private}_key attributes together. " + "Use only one of them.") @@ -60,11 +75,8 @@ def _get_key_label(label, name, default_cert): if label: return label - if not default_cert or paths.dirname(default_cert) == default_cert_directory: - # Use the package_name of the macro callsite of this function. - return "//" + native.package_name() + ":" + name - - return "//" + paths.dirname(default_cert) + ":" + name + # Ensure that the name references the calling package's local BUILD target + return ":" + name def apex_key( name, @@ -72,22 +84,12 @@ def apex_key( private_key = None, public_key_name = None, private_key_name = None, - - # Product var dependency injection, for testing only. - # DefaultAppCertificate is lifted into a parameter to make it testable in - # analysis tests. - _DefaultAppCertificate = product_vars.get("DefaultAppCertificate"), # path/to/some/cert **kwargs): - # Ensure that only tests can set _DefaultAppCertificate. - if native.package_name() != "build/bazel/rules/apex" and \ - _DefaultAppCertificate != product_vars.get("DefaultAppCertificate"): - fail("Only Bazel's own tests can set apex_key._DefaultAppCertificate.") - # The keys are labels that point to either a file, or a target that provides # a single file (e.g. a filegroup or rule that provides the key itself only). _apex_key( name = name, - public_key = _get_key_label(public_key, public_key_name, _DefaultAppCertificate), - private_key = _get_key_label(private_key, private_key_name, _DefaultAppCertificate), + public_key = _get_key_label(public_key, public_key_name), + private_key = _get_key_label(private_key, private_key_name), **kwargs ) diff --git a/rules/apex/apex_key_test.bzl b/rules/apex/apex_key_test.bzl index 086cee25..fdd31a1b 100644 --- a/rules/apex/apex_key_test.bzl +++ b/rules/apex/apex_key_test.bzl @@ -38,11 +38,24 @@ apex_key_test = analysistest.make( }, ) +apex_key_with_default_app_cert_test = analysistest.make( + _apex_key_test, + attrs = { + "expected_private_key_short_path": attr.string(mandatory = True), + "expected_public_key_short_path": attr.string(mandatory = True), + }, + config_settings = { + # This product sets DefaultAppCertificate to build/bazel/rules/apex/testdata/devkey, + # so we expect the apex_key to look for key_name in build/bazel/rules/apex/testdata. + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_with_overrides_and_app_cert", + }, +) + def _test_apex_key_file_targets_with_key_name_attribute(): name = "apex_key_file_targets_with_key_name_attribute" test_name = name + "_test" - private_key = name + ".priv" - public_key = name + ".pub" + private_key = name + ".pem" + public_key = name + ".avbpubkey" apex_key( name = name, @@ -62,22 +75,16 @@ def _test_apex_key_file_targets_with_key_name_attribute(): def _test_apex_key_file_targets_with_key_name_attribute_with_default_app_cert(): name = "apex_key_file_targets_with_key_attribute_with_default_app_cert" test_name = name + "_test" - private_key = "devkey.priv" - public_key = "devkey.pub" + private_key = "devkey.pem" + public_key = "devkey.avbpubkey" apex_key( name = name, private_key_name = private_key, public_key_name = public_key, - - # Corresponds to the DefaultAppCertificate soong variable. - # This is icky, but there's no simpler/better way to - # inject a different value for a product var loaded from - # @soong_injection and accessed within a macro. - _DefaultAppCertificate = "build/bazel/rules/apex/testdata/some_cert", ) - apex_key_test( + apex_key_with_default_app_cert_test( name = test_name, target_under_test = name, expected_private_key_short_path = "build/bazel/rules/apex/testdata/" + private_key, @@ -89,8 +96,8 @@ def _test_apex_key_file_targets_with_key_name_attribute_with_default_app_cert(): def _test_apex_key_file_targets_with_key_attribute(): name = "apex_key_file_targets_with_key_attribute" test_name = name + "_test" - private_key = name + ".priv" - public_key = name + ".pub" + private_key = name + ".pem" + public_key = name + ".avbpubkey" apex_key( name = name, @@ -112,8 +119,8 @@ def _test_apex_key_file_targets_with_key_attribute(): def _test_apex_key_generated_keys(): name = "apex_key_generated_keys" test_name = name + "_test" - private_key = name + ".priv" - public_key = name + ".pub" + private_key = name + ".pem" + public_key = name + ".avbpubkey" native.genrule( name = private_key, diff --git a/rules/apex/apex_test.bzl b/rules/apex/apex_test.bzl index 4a23162d..f714a599 100644 --- a/rules/apex/apex_test.bzl +++ b/rules/apex/apex_test.bzl @@ -1063,6 +1063,53 @@ def _test_default_apex_manifest_version(): return test_name +action_args_with_overrides_test = analysistest.make( + _action_args_test, + attrs = _action_args_test_attrs, + config_settings = { + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_with_overrides_and_app_cert", + }, +) + +def _test_package_name(): + name = "package_name" + test_name = name + "_test" + + test_apex( + name = name, + package_name = "my.package.name", + ) + + action_args_test( + name = test_name, + target_under_test = name, + action_mnemonic = "Apexer", + expected_args = [ + "--override_apk_package_name", + "my.package.name", + ], + ) + + return test_name + +def _test_package_name_override_from_config(): + name = "package_name_override_from_config" + test_name = name + "_test" + + test_apex(name = name) + + action_args_with_overrides_test( + name = test_name, + target_under_test = name, + action_mnemonic = "Apexer", + expected_args = [ + "--override_apk_package_name", + "another.package", + ], + ) + + return test_name + action_args_with_override_apex_manifest_default_version_test = analysistest.make( _action_args_test, attrs = _action_args_test_attrs, @@ -1235,6 +1282,17 @@ apex_certificate_test = analysistest.make( }, ) +apex_certificate_with_overrides_test = analysistest.make( + _apex_certificate_test, + attrs = { + "expected_pem_path": attr.string(), + "expected_pk8_path": attr.string(), + }, + config_settings = { + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_with_overrides_and_app_cert", + }, +) + def _test_apex_certificate_none(): name = "apex_certificate_none" test_name = name + "_test" @@ -1296,6 +1354,30 @@ def _test_apex_certificate_label(): return test_name +def _test_apex_certificate_label_with_overrides(): + name = "apex_certificate_label_with_overrides" + test_name = name + "_test" + + android_app_certificate( + name = name + "_cert", + certificate = name, + tags = ["manual"], + ) + + test_apex( + name = name, + certificate = name + "_cert", + ) + + apex_certificate_with_overrides_test( + name = test_name, + target_under_test = name, + expected_pem_path = "build/bazel/rules/apex/testdata/another.x509.pem", + expected_pk8_path = "build/bazel/rules/apex/testdata/another.pk8", + ) + + return test_name + def _min_sdk_version_apex_inherit_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) @@ -2327,7 +2409,7 @@ def _apex_in_unbundled_build_test(ctx): apex_in_unbundled_build_test = analysistest.make( _apex_in_unbundled_build_test, config_settings = { - "@//build/bazel/rules/apex:unbundled_build": True, + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_unbundled_build", }, ) @@ -2378,7 +2460,7 @@ def _apex_in_bundled_build_test(ctx): apex_in_bundled_build_test = analysistest.make( _apex_in_bundled_build_test, config_settings = { - "@//build/bazel/rules/apex:unbundled_build": False, + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing", }, ) @@ -2542,8 +2624,7 @@ min_target_sdk_version_api_fingerprint_test = analysistest.make( ), }, config_settings = { - "@//build/bazel/rules/apex:unbundled_build": True, - "@//build/bazel/rules/apex:always_use_prebuilt_sdks": False, + "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_unbundled_build", "@//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint": True, "@//build/bazel/rules/apex:platform_sdk_codename": "123", }, @@ -2606,6 +2687,8 @@ def apex_test_suite(name): _test_apex_manifest_dependencies_selfcontained(), _test_apex_manifest_dependencies_cc_binary(), _test_logging_parent_flag(), + _test_package_name(), + _test_package_name_override_from_config(), _test_generate_file_contexts(), _test_default_apex_manifest_version(), _test_override_apex_manifest_version(), @@ -2614,6 +2697,7 @@ def apex_test_suite(name): _test_apex_certificate_none(), _test_apex_certificate_name(), _test_apex_certificate_label(), + _test_apex_certificate_label_with_overrides(), _test_min_sdk_version_apex_inherit(), _test_min_sdk_version_apex_inherit_override_min_sdk_tiramisu(), _test_apex_testonly_with_manifest(), diff --git a/rules/apex/cc.bzl b/rules/apex/cc.bzl index db3d971d..98f9b7b5 100644 --- a/rules/apex/cc.bzl +++ b/rules/apex/cc.bzl @@ -13,6 +13,7 @@ # limitations under the License. load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesInfo") load("//build/bazel/rules/cc:cc_library_common.bzl", "parse_apex_sdk_version") load("//build/bazel/rules/cc:cc_library_shared.bzl", "CcSharedLibraryOutputInfo", "CcStubLibrariesInfo") load("//build/bazel/rules/cc:cc_stub_library.bzl", "CcStubLibrarySharedInfo") @@ -185,7 +186,7 @@ def _apex_cc_aspect_impl(target, ctx): # If a stub library is in the "provides" of the apex, it doesn't need to be in the "requires" if not is_apex_direct_dep(source_library_label, ctx): requires.append(source_library_label) - if not ctx.attr._unbundled_build[BuildSettingInfo].value and not _installed_to_bootstrap(source_library_label): + if not ctx.attr._product_variables[ProductVariablesInfo].Unbundled_build and not _installed_to_bootstrap(source_library_label): # It's sufficient to pass the make module name, not the fully qualified bazel label. make_modules_to_install.append(source_library_label.name) @@ -292,7 +293,7 @@ apex_cc_aspect = aspect( "_apex_direct_deps": attr.label(default = "//build/bazel/rules/apex:apex_direct_deps"), "_apex_name": attr.label(default = "//build/bazel/rules/apex:apex_name"), "_min_sdk_version": attr.label(default = "//build/bazel/rules/apex:min_sdk_version"), - "_unbundled_build": attr.label(default = "//build/bazel/rules/apex:unbundled_build"), + "_product_variables": attr.label(default = "//build/bazel/product_config:product_vars"), }, attr_aspects = CC_ATTR_ASPECTS, # TODO: Have this aspect also propagate along attributes of native_shared_libs? diff --git a/rules/apex/testdata/BUILD b/rules/apex/testdata/BUILD index 488d96df..88dc8ea4 100644 --- a/rules/apex/testdata/BUILD +++ b/rules/apex/testdata/BUILD @@ -4,6 +4,16 @@ exports_files([ ]) filegroup( + name = "android_certificate_directory", + srcs = glob([ + "*.pk8", + "*.pem", + "*.avbpubkey", + ]), + visibility = ["//build/bazel:__subpackages__"], +) + +filegroup( name = "dev-keystore", srcs = ["devkey.keystore"], visibility = ["//visibility:public"], diff --git a/rules/apex/testdata/another.pk8 b/rules/apex/testdata/another.pk8 new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rules/apex/testdata/another.pk8 diff --git a/rules/apex/testdata/another.x509.pem b/rules/apex/testdata/another.x509.pem new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rules/apex/testdata/another.x509.pem diff --git a/rules/apex/testdata/devkey.avbpubkey b/rules/apex/testdata/devkey.avbpubkey new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rules/apex/testdata/devkey.avbpubkey diff --git a/rules/apex/testdata/devkey.pem b/rules/apex/testdata/devkey.pem new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rules/apex/testdata/devkey.pem diff --git a/rules/cc/cc_aidl_library.bzl b/rules/cc/cc_aidl_library.bzl index e2a8f5bb..c9b7d21a 100644 --- a/rules/cc/cc_aidl_library.bzl +++ b/rules/cc/cc_aidl_library.bzl @@ -14,43 +14,53 @@ load("//build/bazel/rules/cc:cc_aidl_code_gen.bzl", "cc_aidl_code_gen") load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") +load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") def cc_aidl_library( name, deps = [], - implementation_deps = [], - implementation_dynamic_deps = [], - tags = [], - min_sdk_version = None, + lang = "cpp", + make_shared = False, **kwargs): """ Generate AIDL stub code for C++ and wrap it in a cc_library_static target Args: - name: (String) name of the cc_library_static target - deps: (list[AidlGenInfo]) list of all aidl_libraries that this cc_aidl_library depends on - implementation_deps: (list[CcInfo]) list of cc_library_static needed to compile the created cc_library_static target - implementation_dynamic_deps: (list[CcInfo]) list of cc_library_shared needed to compile the created cc_library_static target - **kwargs: extra arguments that will be passesd to cc_aidl_code_gen and cc_library_static. + name (str): name of the cc_library_static target + deps (list[AidlGenInfo]): list of all aidl_libraries that this cc_aidl_library depends on + make_shared (bool): if true, `name` will refer to a cc_library_shared, + and an additional cc_library_static will be created + if false, `name` will refer to a cc_library_static + **kwargs: extra arguments that will be passesd to cc_library_{static,shared}. """ - aidl_code_gen = name + "_aidl_code_gen" + if lang not in ["cpp", "ndk"]: + fail("lang {} is unsupported. Allowed lang: ndk, cpp.".format(lang)) + aidl_code_gen = name + "_aidl_code_gen" cc_aidl_code_gen( name = aidl_code_gen, deps = deps, - lang = "cpp", - tags = tags + ["manual"], - **kwargs + lang = lang, + min_sdk_version = kwargs.get("min_sdk_version", None), + tags = kwargs.get("tags", []) + ["manual"], ) - cc_library_static( - name = name, + arguments_with_kwargs = dict( + kwargs, srcs = [":" + aidl_code_gen], - implementation_deps = implementation_deps, - implementation_dynamic_deps = implementation_dynamic_deps, deps = [aidl_code_gen], - tags = tags, - min_sdk_version = min_sdk_version, - **kwargs + ) + + static_name = name + if make_shared: + cc_library_shared( + name = name, + **arguments_with_kwargs + ) + static_name = name + "_bp2build_cc_library_static" + + cc_library_static( + name = static_name, + **arguments_with_kwargs ) diff --git a/rules/cc/cc_aidl_library_test.bzl b/rules/cc/cc_aidl_library_test.bzl index af63713d..74605f80 100644 --- a/rules/cc/cc_aidl_library_test.bzl +++ b/rules/cc/cc_aidl_library_test.bzl @@ -17,10 +17,7 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//build/bazel/rules/aidl:aidl_library.bzl", "aidl_library") load("//build/bazel/rules/cc:cc_aidl_library.bzl", "cc_aidl_library") -load( - "//build/bazel/rules/test_common:flags.bzl", - "action_flags_present_only_for_mnemonic_test", -) +load("//build/bazel/rules/test_common:flags.bzl", "action_flags_present_only_for_mnemonic_test") aidl_library_label_name = "foo_aidl_library" aidl_files = [ @@ -100,7 +97,7 @@ cc_aidl_code_gen_test = analysistest.make( def _cc_aidl_code_gen_test(): name = "foo" aidl_code_gen_name = name + "_aidl_code_gen" - test_name = aidl_code_gen_name + "_test" + code_gen_test_name = aidl_code_gen_name + "_test" aidl_library( name = aidl_library_label_name, @@ -113,11 +110,24 @@ def _cc_aidl_code_gen_test(): tags = ["manual"], ) cc_aidl_code_gen_test( - name = test_name, + name = code_gen_test_name, target_under_test = aidl_code_gen_name, ) - return test_name + action_flags_present_test_name = name + "_test_action_flags_present" + action_flags_present_only_for_mnemonic_test( + name = action_flags_present_test_name, + target_under_test = name + "_cpp", + mnemonics = ["CppCompile"], + expected_flags = [ + "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", + ], + ) + + return [ + code_gen_test_name, + action_flags_present_test_name, + ] def _cc_aidl_hash_notfrozen(): aidl_library_name = "cc_aidl_hash_notfrozen" @@ -176,8 +186,7 @@ def cc_aidl_library_test_suite(name): native.test_suite( name = name, tests = [ - _cc_aidl_code_gen_test(), _cc_aidl_hash_notfrozen(), _cc_aidl_hash_flag_with_hash_file(), - ], + ] + _cc_aidl_code_gen_test(), ) diff --git a/rules/cc/cc_library_common.bzl b/rules/cc/cc_library_common.bzl index 164d6629..bd861c50 100644 --- a/rules/cc/cc_library_common.bzl +++ b/rules/cc/cc_library_common.bzl @@ -14,7 +14,7 @@ load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load("@soong_injection//android:constants.bzl", android_constants = "constants") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") +load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") load("//build/bazel/rules:common.bzl", "strip_bp2build_label_suffix") load("//build/bazel/rules/common:api.bzl", "api") @@ -237,10 +237,10 @@ def parse_apex_sdk_version(version): version = int(version) if version in api.api_levels.values(): return version - elif version == product_vars["Platform_sdk_version"]: + elif version == platform_versions.platform_sdk_version: # For internal branch states, support parsing a finalized version number # that's also still in - # product_vars["Platform_version_active_codenames"], but not api.api_levels. + # platform_versions.platform_version_active_codenames, but not api.api_levels. # # This happens a few months each year on internal branches where the # internal master branch has a finalized API, but is not released yet, diff --git a/rules/cc/cc_library_shared_test.bzl b/rules/cc/cc_library_shared_test.bzl index ffdc4559..041c3dfb 100644 --- a/rules/cc/cc_library_shared_test.bzl +++ b/rules/cc/cc_library_shared_test.bzl @@ -12,11 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") load("//build/bazel/rules/cc:cc_stub_library.bzl", "cc_stub_suite") +load( + "//build/bazel/rules/cc/testing:transitions.bzl", + "ActionArgsInfo", + "compile_action_argv_aspect_generator", +) load("//build/bazel/rules/test_common:flags.bzl", "action_flags_present_only_for_mnemonic_test") load("//build/bazel/rules/test_common:paths.bzl", "get_package_dir_based_path") load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test") @@ -323,75 +327,6 @@ def _cc_library_shared_does_not_propagate_implementation_dynamic_deps(): return test_name -ActionArgsInfo = provider( - fields = { - "argv_map": "A dict with compile action arguments keyed by the target label", - }, -) - -def _compile_action_argv_aspect_impl(target, ctx): - argv_map = {} - if ctx.rule.kind == "cc_library": - cpp_compile_commands_args = [] - for action in target.actions: - if action.mnemonic == "CppCompile": - cpp_compile_commands_args.extend(action.argv) - - if len(cpp_compile_commands_args): - argv_map = dicts.add( - argv_map, - { - target.label.name: cpp_compile_commands_args, - }, - ) - elif ctx.rule.kind == "_cc_library_combiner": - # propagate compile actions flags from [implementation_]whole_archive_deps upstream - for dep in ctx.rule.attr.deps: - argv_map = dicts.add( - argv_map, - dep[ActionArgsInfo].argv_map, - ) - - # propagate compile actions flags from roots (e.g. _cpp) upstream - for root in ctx.rule.attr.roots: - argv_map = dicts.add( - argv_map, - root[ActionArgsInfo].argv_map, - ) - - # propagate action flags from locals and exports - for include in ctx.rule.attr.includes: - argv_map = dicts.add( - argv_map, - include[ActionArgsInfo].argv_map, - ) - elif ctx.rule.kind == "_cc_includes": - for dep in ctx.rule.attr.deps: - argv_map = dicts.add( - argv_map, - dep[ActionArgsInfo].argv_map, - ) - elif ctx.rule.kind == "_cc_library_shared_proxy": - # propagate compile actions flags from root upstream - argv_map = dicts.add( - argv_map, - ctx.rule.attr.deps[0][ActionArgsInfo].argv_map, - ) - return ActionArgsInfo( - argv_map = argv_map, - ) - -# _compile_action_argv_aspect is used to examine compile action from static deps -# as the result of the fdo transition attached to the cc_library_shared's deps -# and __internal_root_cpp which have cc compile actions. -# Checking the deps directly using their names give us the info before -# transition takes effect. -_compile_action_argv_aspect = aspect( - implementation = _compile_action_argv_aspect_impl, - attr_aspects = ["root", "roots", "deps", "includes"], - provides = [ActionArgsInfo], -) - def _cc_library_shared_propagating_fdo_profile_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) @@ -429,6 +364,12 @@ def _cc_library_shared_propagating_fdo_profile_test_impl(ctx): return analysistest.end(env) +_compile_action_argv_aspect = compile_action_argv_aspect_generator({ + "_cc_library_combiner": ["deps", "roots", "includes"], + "_cc_includes": ["deps"], + "_cc_library_shared_proxy": ["deps"], +}) + cc_library_shared_propagating_fdo_profile_test = analysistest.make( _cc_library_shared_propagating_fdo_profile_test_impl, attrs = { diff --git a/rules/cc/cc_library_static.bzl b/rules/cc/cc_library_static.bzl index e81a1fe3..757f943e 100644 --- a/rules/cc/cc_library_static.bzl +++ b/rules/cc/cc_library_static.bzl @@ -35,6 +35,13 @@ load(":clang_tidy.bzl", "ClangTidyInfo", "clang_tidy_for_dir", "generate_clang_t load(":lto_transitions.bzl", "lto_deps_transition") load(":stl.bzl", "stl_info_from_attr") +_ALLOWED_MANUAL_INTERFACE_PATHS = [ + "vendor/", + "hardware/", + # for testing + "build/bazel/rules/cc", +] + CcStaticLibraryInfo = provider(fields = ["root_static_archive", "objects"]) def cc_library_static( @@ -116,6 +123,11 @@ def cc_library_static( if c_std: toolchain_features += [c_std, "-c_std_default"] + for path in _ALLOWED_MANUAL_INTERFACE_PATHS: + if native.package_name().startswith(path): + toolchain_features += ["do_not_check_manual_binder_interfaces"] + break + if min_sdk_version: toolchain_features += parse_sdk_version(min_sdk_version) + ["-sdk_version_default"] toolchain_features += features @@ -599,6 +611,9 @@ _cc_library_combiner = rule( "_allowlist_function_transition": attr.label( default = "@bazel_tools//tools/allowlists/function_transition_allowlist", ), + "_product_variables": attr.label( + default = "//build/bazel/product_config:product_vars", + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], provides = [CcInfo, CcAndroidMkInfo], diff --git a/rules/cc/cc_library_static_test.bzl b/rules/cc/cc_library_static_test.bzl index c3a37262..64dda437 100644 --- a/rules/cc/cc_library_static_test.bzl +++ b/rules/cc/cc_library_static_test.bzl @@ -533,6 +533,52 @@ def _cc_library_static_link_action_should_not_have_arch_cflags(): cpp_link_test_name, ] +def _cc_library_static_defines_do_not_check_manual_binder_interfaces(): + name = "_cc_library_static_defines_do_not_check_manual_binder_interfaces" + cpp_lib_name = name + "_cpp" + cpp_test_name = cpp_lib_name + "_test" + c_lib_name = name + "_c" + c_test_name = c_lib_name + "_test" + + cc_library_static( + name = name, + srcs = ["a.cpp"], + srcs_c = ["b.c"], + tags = ["manual"], + ) + action_flags_present_only_for_mnemonic_test( + name = cpp_test_name, + target_under_test = cpp_lib_name, + mnemonics = ["CppCompile"], + expected_flags = [ + "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", + ], + ) + action_flags_present_only_for_mnemonic_test( + name = c_test_name, + target_under_test = c_lib_name, + mnemonics = ["CppCompile"], + expected_flags = [ + "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", + ], + ) + + non_allowlisted_package_cpp_name = name + "_non_allowlisted_package_cpp" + action_flags_absent_for_mnemonic_test( + name = non_allowlisted_package_cpp_name, + target_under_test = "//build/bazel/examples/cc:foo_static_cpp", + mnemonics = ["CppCompile"], + expected_absent_flags = [ + "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", + ], + ) + + return [ + cpp_test_name, + c_test_name, + non_allowlisted_package_cpp_name, + ] + def cc_library_static_test_suite(name): native.genrule(name = "hdr", cmd = "null", outs = ["f.h"], tags = ["manual"]) @@ -550,6 +596,7 @@ def cc_library_static_test_suite(name): ] + ( _cc_rules_do_not_allow_absolute_includes() + _cc_library_static_provides_androidmk_info() + - _cc_library_static_link_action_should_not_have_arch_cflags() + _cc_library_static_link_action_should_not_have_arch_cflags() + + _cc_library_static_defines_do_not_check_manual_binder_interfaces() ), ) diff --git a/rules/cc/clang_tidy.bzl b/rules/cc/clang_tidy.bzl index a3b8425a..7386a566 100644 --- a/rules/cc/clang_tidy.bzl +++ b/rules/cc/clang_tidy.bzl @@ -21,7 +21,7 @@ load( ) load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load("@soong_injection//cc_toolchain:config_constants.bzl", "constants") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") +load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesInfo") load("//build/bazel/rules:common.bzl", "get_dep_targets") load(":cc_library_common.bzl", "get_compilation_args") @@ -34,7 +34,6 @@ ClangTidyInfo = provider( }, ) -_PRODUCT_VARIABLE_TIDY_CHECKS = product_vars["TidyChecks"].split(",") if "TidyChecks" in product_vars else [] _TIDY_GLOBAL_NO_CHECKS = constants.TidyGlobalNoChecks.split(",") _TIDY_GLOBAL_NO_ERROR_CHECKS = constants.TidyGlobalNoErrorChecks.split(",") _TIDY_DEFAULT_GLOBAL_CHECKS = constants.TidyDefaultGlobalChecks.split(",") @@ -99,8 +98,8 @@ def _add_header_filter(ctx, tidy_flags): def _add_extra_arg_flags(tidy_flags): return tidy_flags + ["-extra-arg-before=" + f for f in _TIDY_EXTRA_ARG_FLAGS] -def _add_quiet_if_not_global_tidy(tidy_flags): - if len(_PRODUCT_VARIABLE_TIDY_CHECKS) == 0: +def _add_quiet_if_not_global_tidy(ctx, tidy_flags): + if not ctx.attr._product_variables[ProductVariablesInfo].TidyChecks: return tidy_flags + [ "-quiet", "-extra-arg-before=-fno-caret-diagnostics", @@ -154,9 +153,10 @@ def _add_checks_for_dir(directory): return _TIDY_DEFAULT_GLOBAL_CHECKS def _add_global_tidy_checks(ctx, local_checks, input_file): + tidy_checks = ctx.attr._product_variables[ProductVariablesInfo].TidyChecks global_tidy_checks = [] - if product_vars["TidyChecks"]: - global_tidy_checks = _PRODUCT_VARIABLE_TIDY_CHECKS + if tidy_checks: + global_tidy_checks = tidy_checks elif not input_file.is_source: # don't run clang-tidy for generated files global_tidy_checks = _TIDY_DEFAULT_GLOBAL_CHECKS_NO_ANALYZER @@ -191,7 +191,7 @@ def _create_clang_tidy_action( tidy_flags = _add_with_tidy_flags(ctx, tidy_flags) tidy_flags = _add_header_filter(ctx, tidy_flags) tidy_flags = _add_extra_arg_flags(tidy_flags) - tidy_flags = _add_quiet_if_not_global_tidy(tidy_flags) + tidy_flags = _add_quiet_if_not_global_tidy(ctx, tidy_flags) tidy_checks = _add_global_tidy_checks(ctx, tidy_checks, input_file) tidy_checks_as_errors = _add_global_tidy_checks_as_errors(tidy_checks_as_errors) diff --git a/rules/cc/clang_tidy_test.bzl b/rules/cc/clang_tidy_test.bzl index 0372355d..ad9163f9 100644 --- a/rules/cc/clang_tidy_test.bzl +++ b/rules/cc/clang_tidy_test.bzl @@ -138,6 +138,9 @@ _clang_tidy = rule( "_tidy_timeout": attr.label( default = "//build/bazel/flags/cc/tidy:tidy_timeout", ), + "_product_variables": attr.label( + default = "//build/bazel/product_config:product_vars", + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], diff --git a/rules/cc/lto_transitions_test.bzl b/rules/cc/lto_transitions_test.bzl index 937e3c16..e6916b91 100644 --- a/rules/cc/lto_transitions_test.bzl +++ b/rules/cc/lto_transitions_test.bzl @@ -12,87 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary") load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") - -# TODO(b/270583469): Extract this and the equivalent logic for FDO -ActionArgsInfo = provider( - fields = { - "argv_map": "A dict with compile action arguments keyed by the target label", - }, -) - -def _compile_action_argv_aspect_impl(target, ctx): - argv_map = {} - if ctx.rule.kind == "cc_library": - cpp_compile_commands_args = [] - for action in target.actions: - if action.mnemonic == "CppCompile": - cpp_compile_commands_args.extend(action.argv) - - if len(cpp_compile_commands_args): - argv_map = dicts.add( - argv_map, - { - target.label.name: cpp_compile_commands_args, - }, - ) - elif ctx.rule.kind == "_cc_library_combiner": - # propagate compile actions flags from [implementation_]whole_archive_deps upstream - for dep in ctx.rule.attr.deps: - argv_map = dicts.add( - argv_map, - dep[ActionArgsInfo].argv_map, - ) - - # propagate compile actions flags from roots (e.g. _cpp) upstream - for root in ctx.rule.attr.roots: - argv_map = dicts.add( - argv_map, - root[ActionArgsInfo].argv_map, - ) - - # propagate action flags from locals and exports - for include in ctx.rule.attr.includes: - argv_map = dicts.add( - argv_map, - include[ActionArgsInfo].argv_map, - ) - elif ctx.rule.kind == "_cc_includes": - for dep in ctx.rule.attr.deps: - argv_map = dicts.add( - argv_map, - dep[ActionArgsInfo].argv_map, - ) - elif ctx.rule.kind == "_cc_library_shared_proxy": - # propagate compile actions flags from root upstream - argv_map = dicts.add( - argv_map, - ctx.rule.attr.deps[0][ActionArgsInfo].argv_map, - ) - elif ctx.rule.kind == "stripped_binary": - # Checking `androidmk_deps` because that contains the root library - # where ths sources for the binary are ultimately compiled - argv_map = dicts.add( - argv_map, - ctx.rule.attr.androidmk_deps[0][ActionArgsInfo].argv_map, - ) - return ActionArgsInfo( - argv_map = argv_map, - ) - -# _compile_action_argv_aspect is used to examine compile action from static deps -# as the result of the fdo transition attached to the cc_library_shared's deps -# and __internal_root_cpp which have cc compile actions. -# Checking the deps directly using their names give us the info before -# transition takes effect. -_compile_action_argv_aspect = aspect( - implementation = _compile_action_argv_aspect_impl, - attr_aspects = ["root", "roots", "deps", "includes", "androidmk_deps"], - provides = [ActionArgsInfo], +load( + "//build/bazel/rules/cc/testing:transitions.bzl", + "ActionArgsInfo", + "compile_action_argv_aspect_generator", ) lto_flag = "-flto=thin" @@ -111,30 +38,39 @@ def _lto_deps_test_impl(ctx): target in argv_map, "can't find {} in argv map".format(target), ) - argv = argv_map[target] - asserts.true( - env, - lto_flag in argv, - "Compile action of {} didn't have LTO but it was expected".format( - target, - ), - ) + if target in argv_map: + argv = argv_map[target] + asserts.true( + env, + lto_flag in argv, + "Compile action of {} didn't have LTO but it was expected".format( + target, + ), + ) for target in ctx.attr.targets_without_lto: asserts.true( env, target in argv_map, "can't find {} in argv map".format(target), ) - argv = argv_map[target] - asserts.true( - env, - lto_flag not in argv, - "Compile action of {} had LTO but it wasn't expected".format( - target, - ), - ) + if target in argv_map: + argv = argv_map[target] + asserts.true( + env, + lto_flag not in argv, + "Compile action of {} had LTO but it wasn't expected".format( + target, + ), + ) return analysistest.end(env) +_compile_action_argv_aspect = compile_action_argv_aspect_generator({ + "_cc_library_combiner": ["deps", "roots", "includes"], + "_cc_includes": ["deps"], + "_cc_library_shared_proxy": ["deps"], + "stripped_binary": ["androidmk_deps"], +}) + lto_deps_test = analysistest.make( _lto_deps_test_impl, attrs = { diff --git a/rules/cc/testing/transitions.bzl b/rules/cc/testing/transitions.bzl new file mode 100644 index 00000000..0dc62bb4 --- /dev/null +++ b/rules/cc/testing/transitions.bzl @@ -0,0 +1,58 @@ +load("@bazel_skylib//lib:dicts.bzl", "dicts") +load("@bazel_skylib//lib:sets.bzl", "sets") + +ActionArgsInfo = provider( + fields = { + "argv_map": "A dict with compile action arguments keyed by the target label", + }, +) + +def _compile_action_argv_aspect_impl(target, ctx): + argv_map = {} + if ctx.rule.kind == "cc_library": + cpp_compile_commands_args = [] + for action in target.actions: + if action.mnemonic == "CppCompile": + cpp_compile_commands_args.extend(action.argv) + + if len(cpp_compile_commands_args): + argv_map = dicts.add( + argv_map, + { + target.label.name: cpp_compile_commands_args, + }, + ) + elif ctx.rule.kind in ctx.attr._attr_aspect_dict.keys(): + attrs = ctx.attr._attr_aspect_dict.get(ctx.rule.kind, []) + for attr_name in attrs: + for value in getattr(ctx.rule.attr, attr_name): + argv_map = dicts.add( + argv_map, + value[ActionArgsInfo].argv_map, + ) + return ActionArgsInfo( + argv_map = argv_map, + ) + +def _get_attr_aspects_list(attr_aspects_dict): + return sets.to_list( + sets.make( + [attr for rule in attr_aspects_dict.values() for attr in rule], + ), + ) + +# The aspects generated by this function are used to examine compile actions +# from cc_library targets generated by our macros for the purpose of assessing +# the results of transitions. Checking the targets directly using their names +# gives info from before the transition is applied. +# attr_aspects should be a dict where the keys are the names of rules and the +# values are lists of attrs that should be traversed by the aspect looking for +# cc_library targets. +def compile_action_argv_aspect_generator(attr_aspects): + return aspect( + implementation = _compile_action_argv_aspect_impl, + attr_aspects = _get_attr_aspects_list(attr_aspects), + attrs = { + "_attr_aspect_dict": attr.string_list_dict(default = attr_aspects), + }, + ) diff --git a/rules/common/api.bzl b/rules/common/api.bzl index 2547133e..4d8e6db2 100644 --- a/rules/common/api.bzl +++ b/rules/common/api.bzl @@ -18,17 +18,17 @@ load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@soong_injection//api_levels:api_levels.bzl", "api_levels_released_versions") -load("@soong_injection//product_config:product_variables.bzl", "product_vars") +load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") _NONE_API_LEVEL_INT = -1 _PREVIEW_API_LEVEL_BASE = 9000 # Base constant for preview API levels. _FUTURE_API_LEVEL_INT = 10000 # API Level associated with an arbitrary future release # TODO(b/271280342): access these variables in a transition friendly way. -_PLATFORM_SDK_FINAL = product_vars.get("Platform_sdk_final") -_PLATFORM_SDK_VERSION = product_vars.get("Platform_sdk_version") -_PLATFORM_SDK_CODENAME = product_vars.get("Platform_sdk_codename") -_PLATFORM_VERSION_ACTIVE_CODENAMES = product_vars.get("Platform_version_active_codenames", []) +_PLATFORM_SDK_FINAL = platform_versions.platform_sdk_final +_PLATFORM_SDK_VERSION = platform_versions.platform_sdk_version +_PLATFORM_SDK_CODENAME = platform_versions.platform_sdk_codename +_PLATFORM_VERSION_ACTIVE_CODENAMES = platform_versions.platform_version_active_codenames # Dict of unfinalized codenames to a placeholder preview API int. _preview_codenames_to_ints = { @@ -61,7 +61,7 @@ _final_codename = { } if _PLATFORM_SDK_FINAL and _PLATFORM_SDK_VERSION else {} _api_levels_with_previews = dicts.add(api_levels_released_versions, _preview_codenames_to_ints) -_api_levels_with_final_codenames = dicts.add(api_levels_released_versions, _final_codename) +_api_levels_with_final_codenames = dicts.add(api_levels_released_versions, _final_codename) # @unused # parse_api_level_from_version is a Starlark implementation of ApiLevelFromUser # at https://cs.android.com/android/platform/superproject/+/master:build/soong/android/api_levels.go;l=221-250;drc=5095a6c4b484f34d5c4f55a855d6174e00fb7f5e diff --git a/rules/java/host_for_device.bzl b/rules/java/host_for_device.bzl index a3e99fb5..9d7990a1 100644 --- a/rules/java/host_for_device.bzl +++ b/rules/java/host_for_device.bzl @@ -36,4 +36,5 @@ This is rarely necessary and restricted to a few allowed projects. doc = "List of targets whose contents will be visible to targets that depend on this target.", ), }, + provides = [JavaInfo], ) diff --git a/rules/test_common/flags.bzl b/rules/test_common/flags.bzl index aea18719..542a8213 100644 --- a/rules/test_common/flags.bzl +++ b/rules/test_common/flags.bzl @@ -72,8 +72,10 @@ def _action_flags_present_only_for_mnemonic_test_impl(ctx): env = analysistest.begin(ctx) actions = analysistest.target_actions(env) + found_at_least_one_action = False for action in actions: if action.mnemonic in ctx.attr.mnemonics: + found_at_least_one_action = True _assert_flags_present_in_action( env, action, @@ -90,21 +92,31 @@ def _action_flags_present_only_for_mnemonic_test_impl(ctx): action.argv, ), ) - + asserts.true( + env, + found_at_least_one_action, + "did not find any actions with mnemonic %s" % ( + ctx.attr.mnemonics, + ), + ) return analysistest.end(env) -action_flags_present_only_for_mnemonic_test = analysistest.make( - _action_flags_present_only_for_mnemonic_test_impl, - attrs = { - "mnemonics": attr.string_list( - doc = """ - Actions with these mnemonics will be expected to have the flags - specified in expected_flags - """, - ), - "expected_flags": attr.string_list(doc = "The flags to be checked for"), - }, -) +def action_flags_present_only_for_mnemonic_test_with_config_settings(config_settings = {}): + return analysistest.make( + _action_flags_present_only_for_mnemonic_test_impl, + attrs = { + "mnemonics": attr.string_list( + doc = """ + Actions with these mnemonics will be expected to have the flags + specified in expected_flags + """, + ), + "expected_flags": attr.string_list(doc = "The flags to be checked for"), + }, + config_settings = config_settings, + ) + +action_flags_present_only_for_mnemonic_test = action_flags_present_only_for_mnemonic_test_with_config_settings() # Checks that a given set of flags are NOT present in a given set of actions. # Unlike the above test, this test does NOT confirm the absence of flags |