aboutsummaryrefslogtreecommitdiff
path: root/platforms/product_variables/product_platform.bzl
blob: f2c6f91f34036a5273526e37a2ad251d3d35e3f8 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Parallels variable.go to provide variables and create a platform based on converted config."""

load("//build/bazel/product_variables:constants.bzl", "constants")
load("//prebuilts/clang/host/linux-x86:cc_toolchain_constants.bzl", "variant_name")

def _product_variables_providing_rule_impl(ctx):
    return [
        platform_common.TemplateVariableInfo(ctx.attr.product_vars),
    ]

# Provides product variables for templated string replacement.
product_variables_providing_rule = rule(
    implementation = _product_variables_providing_rule_impl,
    attrs = {
        "product_vars": attr.string_dict(),
    },
)

_arch_os_only_suffix = "_arch_os"
_product_only_suffix = "_product"

def add_providing_var(providing_vars, typ, var, value):
    if typ == "bool":
        providing_vars[var] = "1" if value else "0"
    elif typ == "list":
        providing_vars[var] = ",".join(value)
    elif typ == "int":
        providing_vars[var] = str(value)
    elif typ == "string":
        providing_vars[var] = value

def product_variable_config(name, product_config_vars):
    constraints = []

    local_vars = dict(product_config_vars)

    # Native_coverage is not set within soong.variables, but is hardcoded
    # within config.go NewConfig
    local_vars["Native_coverage"] = (
        local_vars.get("ClangCoverage", False) or
        local_vars.get("GcovCoverage", False)
    )

    providing_vars = {}

    # Generate constraints for Soong config variables (bool, value, string typed).
    vendor_vars = local_vars.pop("VendorVars", default = {})
    for (namespace, variables) in vendor_vars.items():
        for (var, value) in variables.items():
            # All vendor vars are Starlark string-typed, even though they may be
            # boxed bools/strings/arbitrary printf'd values, like numbers, so
            # we'll need to do some translation work here by referring to
            # soong_injection's generated data.

            if value == "":
                # Variable is not set so skip adding this as a constraint.
                continue

            # Create the identifier for the constraint var (or select key)
            config_var = namespace + "__" + var

            # List of all soong_config_module_type variables.
            if not config_var in constants.SoongConfigVariables:
                continue

            # Normalize all constraint vars (i.e. select keys) to be lowercased.
            constraint_var = config_var.lower()

            if config_var in constants.SoongConfigBoolVariables:
                constraints.append("//build/bazel/product_variables:" + constraint_var)
            elif config_var in constants.SoongConfigStringVariables:
                # The string value is part of the the select key.
                constraints.append("//build/bazel/product_variables:" + constraint_var + "__" + value.lower())
            elif config_var in constants.SoongConfigValueVariables:
                # For value variables, providing_vars add support for substituting
                # the value using TemplateVariableInfo.
                constraints.append("//build/bazel/product_variables:" + constraint_var)
                add_providing_var(providing_vars, "string", constraint_var, value)

    for (var, value) in local_vars.items():
        # TODO(b/187323817): determine how to handle remaining product
        # variables not used in product_variables
        constraint_var = var.lower()
        if not constants.ProductVariables.get(constraint_var):
            continue

        # variable.go excludes nil values
        add_constraint = (value != None)
        add_providing_var(providing_vars, type(value), var, value)
        if type(value) == "bool":
            # variable.go special cases bools
            add_constraint = value

        if add_constraint:
            constraints.append("//build/bazel/product_variables:" + constraint_var)

    native.platform(
        name = name + _product_only_suffix,
        constraint_values = constraints,
    )

    arch = local_vars.get("DeviceArch")
    arch_variant = local_vars.get("DeviceArchVariant")
    cpu_variant = local_vars.get("DeviceCpuVariant")

    os = "android"

    native.alias(
        name = name,
        actual = "{os}_{arch}{variant}".format(os = os, arch = arch, variant = _variant_name(arch, arch_variant, cpu_variant)),
    )

    arch = local_vars.get("DeviceSecondaryArch")
    arch_variant = local_vars.get("DeviceSecondaryArchVariant")
    cpu_variant = local_vars.get("DeviceSecondaryCpuVariant")

    if arch:
        native.alias(
            name = name + "_secondary",
            actual = "{os}_{arch}{variant}".format(os = os, arch = arch, variant = _variant_name(arch, arch_variant, cpu_variant)),
        )

    product_variables_providing_rule(
        name = name + "_product_vars",
        product_vars = providing_vars,
    )

def _is_variant_default(arch, variant):
    return variant == None or variant in (arch, "generic")

def _variant_name(arch, arch_variant, cpu_variant):
    if _is_variant_default(arch, arch_variant):
        arch_variant = ""
    if _is_variant_default(arch, cpu_variant):
        cpu_variant = ""
    variant = struct(
        arch_variant = arch_variant,
        cpu_variant = cpu_variant,
    )
    return variant_name(variant)

def android_platform(name = None, constraint_values = [], product = None):
    """ android_platform creates a platform with the specified constraint_values and product constraints."""
    native.platform(
        name = name,
        constraint_values = constraint_values,
        parents = [product + _product_only_suffix],
    )