xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/baseline_profiles.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2023 The Bazel Authors. All rights reserved.
2*9e965d6fSRomain Jobredeaux#
3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License");
4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License.
5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at
6*9e965d6fSRomain Jobredeaux#
7*9e965d6fSRomain Jobredeaux#    http://www.apache.org/licenses/LICENSE-2.0
8*9e965d6fSRomain Jobredeaux#
9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software
10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS,
11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and
13*9e965d6fSRomain Jobredeaux# limitations under the License.
14*9e965d6fSRomain Jobredeaux
15*9e965d6fSRomain Jobredeaux"""
16*9e965d6fSRomain JobredeauxDefines baseline profiles processing methods in Android Rules.
17*9e965d6fSRomain Jobredeaux"""
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain Jobredeaux_BASELINE_PROFILE_DIR_SUFFIX = "-baseline-profile/"
20*9e965d6fSRomain Jobredeaux
21*9e965d6fSRomain Jobredeauxdef _process(
22*9e965d6fSRomain Jobredeaux        ctx,
23*9e965d6fSRomain Jobredeaux        transitive_profiles = depset(),
24*9e965d6fSRomain Jobredeaux        startup_profiles = [],
25*9e965d6fSRomain Jobredeaux        deploy_jar = None,
26*9e965d6fSRomain Jobredeaux        has_proguard_specs = False,
27*9e965d6fSRomain Jobredeaux        enable_optimizer_integration = False,
28*9e965d6fSRomain Jobredeaux        merge_tool = None,
29*9e965d6fSRomain Jobredeaux        profgen = None,
30*9e965d6fSRomain Jobredeaux        toolchain_type = None):
31*9e965d6fSRomain Jobredeaux    """Processes all the transitive baseline profiles.
32*9e965d6fSRomain Jobredeaux
33*9e965d6fSRomain Jobredeaux    Baseline profiles propagated from libraries will be merged, and if optimizer integration is
34*9e965d6fSRomain Jobredeaux    enabled, startup profiles will be merged as well, and wildcards in baseline profiles will be
35*9e965d6fSRomain Jobredeaux    expanded.
36*9e965d6fSRomain Jobredeaux
37*9e965d6fSRomain Jobredeaux    Args:
38*9e965d6fSRomain Jobredeaux      ctx: The context.
39*9e965d6fSRomain Jobredeaux      transitive_profiles: Depset. The transitive baseline profiles propagated from android_library
40*9e965d6fSRomain Jobredeaux          and aar_import.
41*9e965d6fSRomain Jobredeaux      startup_profiles: List. The startup profiles.
42*9e965d6fSRomain Jobredeaux      deploy_jar: File. The deploy jar.
43*9e965d6fSRomain Jobredeaux      has_proguard_specs: Boolean. Whether to have proguard specs.
44*9e965d6fSRomain Jobredeaux      enable_optimizer_integration: Boolean. Whether to use startup profile and baseline profiles in optimization.
45*9e965d6fSRomain Jobredeaux      merge_tool: FilesToRunProvider. An executable for merging baseline profiles.
46*9e965d6fSRomain Jobredeaux      profgen: FilesToRunProvider: An executable for compiling baseline profiles.
47*9e965d6fSRomain Jobredeaux      toolchain_type: Label or String. Toolchain type of the executable used in actions.
48*9e965d6fSRomain Jobredeaux    Returns:
49*9e965d6fSRomain Jobredeaux      A struct containing all the outputs from processing baseline profiles.
50*9e965d6fSRomain Jobredeaux    """
51*9e965d6fSRomain Jobredeaux
52*9e965d6fSRomain Jobredeaux    baseline_profile = None
53*9e965d6fSRomain Jobredeaux    startup_profile = None
54*9e965d6fSRomain Jobredeaux    if transitive_profiles:
55*9e965d6fSRomain Jobredeaux        baseline_profile = _get_profile_artifact(ctx, "static-prof.txt")
56*9e965d6fSRomain Jobredeaux        _merge(
57*9e965d6fSRomain Jobredeaux            ctx,
58*9e965d6fSRomain Jobredeaux            baseline_profile,
59*9e965d6fSRomain Jobredeaux            transitive_profiles,
60*9e965d6fSRomain Jobredeaux            "MergeBaselineProfiles",
61*9e965d6fSRomain Jobredeaux            merge_tool = merge_tool,
62*9e965d6fSRomain Jobredeaux            toolchain_type = toolchain_type,
63*9e965d6fSRomain Jobredeaux        )
64*9e965d6fSRomain Jobredeaux
65*9e965d6fSRomain Jobredeaux    if has_proguard_specs and enable_optimizer_integration:
66*9e965d6fSRomain Jobredeaux        # This is only needed for optimized builds since otherwise the dexer doesn't process this.
67*9e965d6fSRomain Jobredeaux        if startup_profiles:
68*9e965d6fSRomain Jobredeaux            startup_profile = _get_profile_artifact(ctx, "static-startup-prof.txt")
69*9e965d6fSRomain Jobredeaux            _merge(
70*9e965d6fSRomain Jobredeaux                ctx,
71*9e965d6fSRomain Jobredeaux                output = startup_profile,
72*9e965d6fSRomain Jobredeaux                inputs = ctx.files.startup_profiles,
73*9e965d6fSRomain Jobredeaux                mnemonic = "MergeStartupProfiles",
74*9e965d6fSRomain Jobredeaux                merge_tool = merge_tool,
75*9e965d6fSRomain Jobredeaux                toolchain_type = toolchain_type,
76*9e965d6fSRomain Jobredeaux            )
77*9e965d6fSRomain Jobredeaux
78*9e965d6fSRomain Jobredeaux        # Wildcards only need to be expanded for optimized builds since if these aren't consumed by
79*9e965d6fSRomain Jobredeaux        # the optimizer, they can just be expanded during profile compilation instead.
80*9e965d6fSRomain Jobredeaux        # Start-up profiles are not expanded because it shouldn't be necessary as these should
81*9e965d6fSRomain Jobredeaux        # contain profiles generated by devices on start-up.
82*9e965d6fSRomain Jobredeaux        if baseline_profile:
83*9e965d6fSRomain Jobredeaux            expanded_baseline_profile = _get_profile_artifact(ctx, "expanded-static-prof.txt")
84*9e965d6fSRomain Jobredeaux            _expand_wildcards(
85*9e965d6fSRomain Jobredeaux                ctx,
86*9e965d6fSRomain Jobredeaux                output = expanded_baseline_profile,
87*9e965d6fSRomain Jobredeaux                deploy_jar = deploy_jar,
88*9e965d6fSRomain Jobredeaux                profile = baseline_profile,
89*9e965d6fSRomain Jobredeaux                profgen = profgen,
90*9e965d6fSRomain Jobredeaux                toolchain_type = toolchain_type,
91*9e965d6fSRomain Jobredeaux            )
92*9e965d6fSRomain Jobredeaux            baseline_profile = expanded_baseline_profile
93*9e965d6fSRomain Jobredeaux    return struct(
94*9e965d6fSRomain Jobredeaux        baseline_profile = baseline_profile,
95*9e965d6fSRomain Jobredeaux        startup_profile = startup_profile,
96*9e965d6fSRomain Jobredeaux    )
97*9e965d6fSRomain Jobredeaux
98*9e965d6fSRomain Jobredeauxdef _process_art_profile(
99*9e965d6fSRomain Jobredeaux        ctx,
100*9e965d6fSRomain Jobredeaux        final_classes_dex,
101*9e965d6fSRomain Jobredeaux        merged_profile,
102*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
103*9e965d6fSRomain Jobredeaux        profgen = None,
104*9e965d6fSRomain Jobredeaux        zipper = None,
105*9e965d6fSRomain Jobredeaux        toolchain_type = None):
106*9e965d6fSRomain Jobredeaux    """ Compiles the merged baseline profile.
107*9e965d6fSRomain Jobredeaux
108*9e965d6fSRomain Jobredeaux    Profiles are compiled with profgen into binary ART profiles. The binary
109*9e965d6fSRomain Jobredeaux    profiles will be bundled into the final APK and used at installation time to speed up app
110*9e965d6fSRomain Jobredeaux    startup and reduce jank.
111*9e965d6fSRomain Jobredeaux
112*9e965d6fSRomain Jobredeaux    Args:
113*9e965d6fSRomain Jobredeaux      ctx: The context.
114*9e965d6fSRomain Jobredeaux      final_classes_dex: File. Final classes zip artifact.
115*9e965d6fSRomain Jobredeaux      merged_profile: File. The merged profile from transitive baseline profile files.
116*9e965d6fSRomain Jobredeaux      proguard_output_map: File. Optional. The proguard output mapping file.
117*9e965d6fSRomain Jobredeaux      profgen: FilesToRunProvider. The profgen executable for profile compilation.
118*9e965d6fSRomain Jobredeaux      zipper: FilesToRunProvider. An executable for compressing files to an archive.
119*9e965d6fSRomain Jobredeaux      toolchain_type: Label or String. Toolchain type of the executable used in actions.
120*9e965d6fSRomain Jobredeaux    Returns:
121*9e965d6fSRomain Jobredeaux      Provider info containing BaselineProfileProvider for all merged profiles.
122*9e965d6fSRomain Jobredeaux    """
123*9e965d6fSRomain Jobredeaux
124*9e965d6fSRomain Jobredeaux    # Profgen
125*9e965d6fSRomain Jobredeaux    output_profile = _get_profile_artifact(ctx, "baseline.prof")
126*9e965d6fSRomain Jobredeaux    output_profile_meta = _get_profile_artifact(ctx, "baseline.profm")
127*9e965d6fSRomain Jobredeaux    profgen_inputs = [final_classes_dex, merged_profile]
128*9e965d6fSRomain Jobredeaux    profgen_args = ctx.actions.args()
129*9e965d6fSRomain Jobredeaux    profgen_args.add("bin", merged_profile)
130*9e965d6fSRomain Jobredeaux    profgen_args.add("--apk", final_classes_dex)
131*9e965d6fSRomain Jobredeaux    profgen_args.add("--output", output_profile)
132*9e965d6fSRomain Jobredeaux    profgen_args.add("--output-meta", output_profile_meta)
133*9e965d6fSRomain Jobredeaux    if proguard_output_map:
134*9e965d6fSRomain Jobredeaux        profgen_args.add("--map", proguard_output_map)
135*9e965d6fSRomain Jobredeaux        profgen_inputs.append(proguard_output_map)
136*9e965d6fSRomain Jobredeaux    ctx.actions.run(
137*9e965d6fSRomain Jobredeaux        mnemonic = "GenerateARTProfile",
138*9e965d6fSRomain Jobredeaux        executable = profgen,
139*9e965d6fSRomain Jobredeaux        progress_message = "Generating Android P-R ART profile for %{label} APK",
140*9e965d6fSRomain Jobredeaux        arguments = [profgen_args],
141*9e965d6fSRomain Jobredeaux        inputs = profgen_inputs,
142*9e965d6fSRomain Jobredeaux        outputs = [output_profile, output_profile_meta],
143*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
144*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
145*9e965d6fSRomain Jobredeaux    )
146*9e965d6fSRomain Jobredeaux
147*9e965d6fSRomain Jobredeaux    # Zip ART profiles
148*9e965d6fSRomain Jobredeaux    output_profile_zip = _get_profile_artifact(ctx, "art_profile.zip")
149*9e965d6fSRomain Jobredeaux    zip_args = ctx.actions.args()
150*9e965d6fSRomain Jobredeaux    zip_args.add("c", output_profile_zip)
151*9e965d6fSRomain Jobredeaux    zip_args.add(output_profile.path, format = "assets/dexopt/baseline.prof=%s")
152*9e965d6fSRomain Jobredeaux    zip_args.add(output_profile_meta.path, format = "assets/dexopt/baseline.profm=%s")
153*9e965d6fSRomain Jobredeaux    ctx.actions.run(
154*9e965d6fSRomain Jobredeaux        mnemonic = "ZipARTProfiles",
155*9e965d6fSRomain Jobredeaux        executable = zipper,
156*9e965d6fSRomain Jobredeaux        progress_message = "Zip ART Profiles for %{label}",
157*9e965d6fSRomain Jobredeaux        arguments = [zip_args],
158*9e965d6fSRomain Jobredeaux        inputs = [output_profile, output_profile_meta],
159*9e965d6fSRomain Jobredeaux        outputs = [output_profile_zip],
160*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
161*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
162*9e965d6fSRomain Jobredeaux    )
163*9e965d6fSRomain Jobredeaux    return BaselineProfileProvider(
164*9e965d6fSRomain Jobredeaux        # Unnecessary to pass the transitive profiles to native rule
165*9e965d6fSRomain Jobredeaux        depset(),
166*9e965d6fSRomain Jobredeaux        output_profile_zip,
167*9e965d6fSRomain Jobredeaux    )
168*9e965d6fSRomain Jobredeaux
169*9e965d6fSRomain Jobredeauxdef _get_profile_dir(ctx):
170*9e965d6fSRomain Jobredeaux    return ctx.label.name + _BASELINE_PROFILE_DIR_SUFFIX
171*9e965d6fSRomain Jobredeaux
172*9e965d6fSRomain Jobredeauxdef _get_profile_artifact(ctx, name):
173*9e965d6fSRomain Jobredeaux    return ctx.actions.declare_file(_get_profile_dir(ctx) + name)
174*9e965d6fSRomain Jobredeaux
175*9e965d6fSRomain Jobredeauxdef _merge(
176*9e965d6fSRomain Jobredeaux        ctx,
177*9e965d6fSRomain Jobredeaux        output,
178*9e965d6fSRomain Jobredeaux        inputs = [],
179*9e965d6fSRomain Jobredeaux        mnemonic = "MergeBaselineProfiles",
180*9e965d6fSRomain Jobredeaux        merge_tool = None,
181*9e965d6fSRomain Jobredeaux        toolchain_type = None):
182*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
183*9e965d6fSRomain Jobredeaux    args.add_all(inputs, before_each = "--input")
184*9e965d6fSRomain Jobredeaux    args.add("--output", output)
185*9e965d6fSRomain Jobredeaux
186*9e965d6fSRomain Jobredeaux    ctx.actions.run(
187*9e965d6fSRomain Jobredeaux        executable = merge_tool,
188*9e965d6fSRomain Jobredeaux        mnemonic = mnemonic,
189*9e965d6fSRomain Jobredeaux        arguments = [args],
190*9e965d6fSRomain Jobredeaux        inputs = inputs,
191*9e965d6fSRomain Jobredeaux        outputs = [output],
192*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
193*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
194*9e965d6fSRomain Jobredeaux    )
195*9e965d6fSRomain Jobredeaux
196*9e965d6fSRomain Jobredeauxdef _expand_wildcards(
197*9e965d6fSRomain Jobredeaux        ctx,
198*9e965d6fSRomain Jobredeaux        output,
199*9e965d6fSRomain Jobredeaux        deploy_jar = None,
200*9e965d6fSRomain Jobredeaux        profile = None,
201*9e965d6fSRomain Jobredeaux        profgen = None,
202*9e965d6fSRomain Jobredeaux        toolchain_type = None):
203*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
204*9e965d6fSRomain Jobredeaux    args.add("expandWildcards", deploy_jar)
205*9e965d6fSRomain Jobredeaux    args.add("--profile", profile)
206*9e965d6fSRomain Jobredeaux    args.add("--output", output)
207*9e965d6fSRomain Jobredeaux
208*9e965d6fSRomain Jobredeaux    ctx.actions.run(
209*9e965d6fSRomain Jobredeaux        executable = profgen,
210*9e965d6fSRomain Jobredeaux        outputs = [output],
211*9e965d6fSRomain Jobredeaux        inputs = [deploy_jar, profile],
212*9e965d6fSRomain Jobredeaux        arguments = [args],
213*9e965d6fSRomain Jobredeaux        mnemonic = "ExpandBaselineProfileWildcards",
214*9e965d6fSRomain Jobredeaux        progress_message = "Expanding baseline profile wildcards for %{label} APK",
215*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
216*9e965d6fSRomain Jobredeaux    )
217*9e965d6fSRomain Jobredeaux
218*9e965d6fSRomain Jobredeauxbaseline_profiles = struct(
219*9e965d6fSRomain Jobredeaux    expand_wildcards = _expand_wildcards,
220*9e965d6fSRomain Jobredeaux    get_profile_artifact = _get_profile_artifact,
221*9e965d6fSRomain Jobredeaux    process = _process,
222*9e965d6fSRomain Jobredeaux    process_art_profile = _process_art_profile,
223*9e965d6fSRomain Jobredeaux)
224