aboutsummaryrefslogtreecommitdiff
path: root/product_config/product_variables_providing_rule.bzl
blob: b1af0e0fd28ebf54dbb511d8f7d7b36041e59007 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# 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.
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@soong_injection//metrics:converted_modules_path_map.bzl", "modules")

ProductVariablesInfo = provider(
    "ProductVariablesInfo provides the android product config variables.",
    fields = {
        "Always_use_prebuilt_sdks": "Boolean to always use a prebuilt sdk instead of source-built.",
        "CompressedApex": "Boolean indicating if apexes are compressed or not.",
        "DefaultAppCertificate": "The default certificate to sign APKs and APEXes with. The $(dirname) of this certificate will also be used to find additional certificates when modules only give their names.",
        "TidyChecks": "List of clang tidy checks to enable.",
        "Unbundled_apps": "List of apps to build as unbundled.",
        "Unbundled_build": "True if this is an unbundled build",
        "ManifestPackageNameOverrides": "A list of string:string mapping from APEX/APK name to package name to override the AndroidManifest.xml package of the module.",
        "CertificateOverrides": "A list of string:string mapping from APEX/APK name to the certificate name to override the certificate used to sign the APEX/APK container.",
    },
)

ProductVariablesDepsInfo = provider(
    "ProductVariablesDepsInfo provides fields that are not regular product config variables, but rather the concrete files that other product config vars reference.",
    fields = {
        "DefaultAppCertificateFiles": "All the .pk8, .pem, and .avbpubkey files in the DefaultAppCertificate directory.",
        "OverridingCertificateFiles": "All the android_certificate_directory filegroups referenced by certificates in the CertificateOverrides mapping. Superset of DefaultAppCertificateFiles.",
    },
)

def _product_variables_providing_rule_impl(ctx):
    vars = json.decode(ctx.attr.product_vars)

    tidy_checks = vars.get("TidyChecks", "")
    tidy_checks = tidy_checks.split(",") if tidy_checks else []

    return [
        platform_common.TemplateVariableInfo(ctx.attr.attribute_vars),
        ProductVariablesInfo(
            Always_use_prebuilt_sdks = vars.get("Always_use_prebuilt_sdks", False),
            CompressedApex = vars.get("CompressedApex", False),
            DefaultAppCertificate = vars.get("DefaultAppCertificate", None),
            TidyChecks = tidy_checks,
            Unbundled_apps = vars.get("Unbundled_apps", []),
            Unbundled_build = vars.get("Unbundled_build", False),
            ManifestPackageNameOverrides = vars.get("ManifestPackageNameOverrides", []),
            CertificateOverrides = vars.get("CertificateOverrides", []),
        ),
        ProductVariablesDepsInfo(
            DefaultAppCertificateFiles = ctx.files.default_app_certificate_filegroup,
            OverridingCertificateFiles = ctx.files.overriding_cert_filegroups,
        ),
    ]

# Provides product variables for templated string replacement.
_product_variables_providing_rule = rule(
    implementation = _product_variables_providing_rule_impl,
    attrs = {
        "attribute_vars": attr.string_dict(doc = "Variables that can be expanded using make-style syntax in attributes"),
        "product_vars": attr.string(doc = "Regular android product variables, a copy of the soong.variables file. Unfortunately this needs to be a json-encoded string because bazel attributes can only be simple types."),
        "default_app_certificate_filegroup": attr.label(doc = "The filegroup that contains all the .pem, .pk8, and .avbpubkey files in $(dirname product_vars.DefaultAppCertificate)"),
        "overriding_cert_filegroups": attr.label_list(doc = "All certificates that are used to override an android_app_certificate using the CertificatesOverride product variable."),
    },
)

def product_variables_providing_rule(
        name,
        attribute_vars,
        product_vars):
    default_app_certificate_filegroup = None
    default_app_certificate = product_vars.get("DefaultAppCertificate", None)
    if default_app_certificate:
        default_app_certificate_filegroup = "@//" + paths.dirname(default_app_certificate) + ":android_certificate_directory"

    # Overriding certificates can be from anywhere, and may not always be in the
    # same directory as DefaultAppCertificate / PRODUCT_DEFAULT_DEV_CERTIFICATE.
    # Collect their additional 'android_certificate_directory' filegroups here.
    #
    # e.g. if CertificateOverrides is [m1:c1, m2:c2, ..., mn:cn], then collect
    # //pkg(c1):android_certificate_directory,
    # //pkg(c2):android_certificate_directory, and so on.
    #
    # We cannot add directory dependencies on c1, c2, etc because that would
    # form a cyclic dependency graph from product_vars to
    # android_app_certificate (where the override happens) and back to
    # product_vars again. So reference the filegroups instead.
    #
    # Note that this relies on a global bzl mapping of android_app_certificate
    # module names to the packages they belong to.  This is currently generated
    # by bp2build, but may need to be maintained in a different approach in the
    # future when the android_app_certificate modules are no longer auto converted.
    cert_overrides = product_vars.get("CertificateOverrides", [])
    cert_filegroups = {}
    if default_app_certificate_filegroup:
        cert_filegroups[default_app_certificate_filegroup] = True
    if cert_overrides:
        for c in cert_overrides:
            module_name = c.split(":")[1]
            pkg = modules.get(module_name)  # use the global mapping of module names to their enclosing package.
            if pkg:
                # not everything is converted.
                cert_filegroups["@" + pkg + ":android_certificate_directory"] = True

    _product_variables_providing_rule(
        name = name,
        attribute_vars = attribute_vars,
        product_vars = json.encode(product_vars),
        default_app_certificate_filegroup = default_app_certificate_filegroup,
        overriding_cert_filegroups = cert_filegroups.keys(),
    )