xref: /aosp_15_r20/build/bazel_common_rules/dist/dist.bzl (revision 7887bec861e78e44e4e86ae7a52515235a00b778)
1*7887bec8SAndroid Build Coastguard Worker"""Rule to support Bazel in copying its output files to the dist dir outside of
2*7887bec8SAndroid Build Coastguard Workerthe standard Bazel output user root.
3*7887bec8SAndroid Build Coastguard Worker"""
4*7887bec8SAndroid Build Coastguard Worker
5*7887bec8SAndroid Build Coastguard Workerload("@bazel_skylib//rules:copy_file.bzl", "copy_file")
6*7887bec8SAndroid Build Coastguard Workerload("//build/bazel_common_rules/exec/impl:embedded_exec.bzl", "embedded_exec")
7*7887bec8SAndroid Build Coastguard Worker
8*7887bec8SAndroid Build Coastguard Workerdef _label_list_to_manifest(lst):
9*7887bec8SAndroid Build Coastguard Worker    """Convert the outputs of a label list to manifest content."""
10*7887bec8SAndroid Build Coastguard Worker    all_dist_files = []
11*7887bec8SAndroid Build Coastguard Worker    for f in lst:
12*7887bec8SAndroid Build Coastguard Worker        all_dist_files += f[DefaultInfo].files.to_list()
13*7887bec8SAndroid Build Coastguard Worker    return all_dist_files, "\n".join([dist_file.short_path for dist_file in all_dist_files])
14*7887bec8SAndroid Build Coastguard Worker
15*7887bec8SAndroid Build Coastguard Workerdef _generate_dist_manifest_impl(ctx):
16*7887bec8SAndroid Build Coastguard Worker    if ctx.attr.archives:
17*7887bec8SAndroid Build Coastguard Worker        # buildifier: disable=print
18*7887bec8SAndroid Build Coastguard Worker        print("archives is deprecated. Please file a bug if you are using it.")
19*7887bec8SAndroid Build Coastguard Worker
20*7887bec8SAndroid Build Coastguard Worker    # Create a manifest of dist files to differentiate them from other runfiles.
21*7887bec8SAndroid Build Coastguard Worker    dist_manifest = ctx.actions.declare_file(ctx.attr.name + "_dist_manifest.txt")
22*7887bec8SAndroid Build Coastguard Worker    all_dist_files, dist_manifest_content = _label_list_to_manifest(ctx.attr.data)
23*7887bec8SAndroid Build Coastguard Worker    ctx.actions.write(
24*7887bec8SAndroid Build Coastguard Worker        output = dist_manifest,
25*7887bec8SAndroid Build Coastguard Worker        content = dist_manifest_content,
26*7887bec8SAndroid Build Coastguard Worker    )
27*7887bec8SAndroid Build Coastguard Worker
28*7887bec8SAndroid Build Coastguard Worker    dist_archives_manifest = ctx.actions.declare_file(ctx.attr.name + "_dist_archives_manifest.txt")
29*7887bec8SAndroid Build Coastguard Worker    all_dist_archives, dist_archives_manifest_content = _label_list_to_manifest(ctx.attr.archives)
30*7887bec8SAndroid Build Coastguard Worker    ctx.actions.write(
31*7887bec8SAndroid Build Coastguard Worker        output = dist_archives_manifest,
32*7887bec8SAndroid Build Coastguard Worker        content = dist_archives_manifest_content,
33*7887bec8SAndroid Build Coastguard Worker    )
34*7887bec8SAndroid Build Coastguard Worker
35*7887bec8SAndroid Build Coastguard Worker    # Create the runfiles object.
36*7887bec8SAndroid Build Coastguard Worker    runfiles = ctx.runfiles(files = all_dist_files + all_dist_archives + [
37*7887bec8SAndroid Build Coastguard Worker        dist_manifest,
38*7887bec8SAndroid Build Coastguard Worker        dist_archives_manifest,
39*7887bec8SAndroid Build Coastguard Worker    ])
40*7887bec8SAndroid Build Coastguard Worker
41*7887bec8SAndroid Build Coastguard Worker    return [DefaultInfo(runfiles = runfiles)]
42*7887bec8SAndroid Build Coastguard Worker
43*7887bec8SAndroid Build Coastguard Worker_generate_dist_manifest = rule(
44*7887bec8SAndroid Build Coastguard Worker    implementation = _generate_dist_manifest_impl,
45*7887bec8SAndroid Build Coastguard Worker    doc = """Generate a manifest of files to be dist to a directory.""",
46*7887bec8SAndroid Build Coastguard Worker    attrs = {
47*7887bec8SAndroid Build Coastguard Worker        "data": attr.label_list(
48*7887bec8SAndroid Build Coastguard Worker            allow_files = True,
49*7887bec8SAndroid Build Coastguard Worker            doc = """Files or targets to copy to the dist dir.
50*7887bec8SAndroid Build Coastguard Worker
51*7887bec8SAndroid Build Coastguard WorkerIn the case of targets, the rule copies the list of `files` from the target's DefaultInfo provider.
52*7887bec8SAndroid Build Coastguard Worker""",
53*7887bec8SAndroid Build Coastguard Worker        ),
54*7887bec8SAndroid Build Coastguard Worker        "archives": attr.label_list(
55*7887bec8SAndroid Build Coastguard Worker            allow_files = [".tar.gz", ".tar"],
56*7887bec8SAndroid Build Coastguard Worker            doc = """Files or targets to be extracted to the dist dir.
57*7887bec8SAndroid Build Coastguard Worker
58*7887bec8SAndroid Build Coastguard WorkerIn the case of targets, the rule copies the list of `files` from the target's DefaultInfo provider.
59*7887bec8SAndroid Build Coastguard Worker""",
60*7887bec8SAndroid Build Coastguard Worker        ),
61*7887bec8SAndroid Build Coastguard Worker    },
62*7887bec8SAndroid Build Coastguard Worker)
63*7887bec8SAndroid Build Coastguard Worker
64*7887bec8SAndroid Build Coastguard Workerdef copy_to_dist_dir(
65*7887bec8SAndroid Build Coastguard Worker        name,
66*7887bec8SAndroid Build Coastguard Worker        data = None,
67*7887bec8SAndroid Build Coastguard Worker        archives = None,
68*7887bec8SAndroid Build Coastguard Worker        flat = None,
69*7887bec8SAndroid Build Coastguard Worker        prefix = None,
70*7887bec8SAndroid Build Coastguard Worker        strip_components = 0,
71*7887bec8SAndroid Build Coastguard Worker        archive_prefix = None,
72*7887bec8SAndroid Build Coastguard Worker        dist_dir = None,
73*7887bec8SAndroid Build Coastguard Worker        wipe_dist_dir = None,
74*7887bec8SAndroid Build Coastguard Worker        allow_duplicate_filenames = None,
75*7887bec8SAndroid Build Coastguard Worker        mode_overrides = None,
76*7887bec8SAndroid Build Coastguard Worker        log = None,
77*7887bec8SAndroid Build Coastguard Worker        testonly = False,
78*7887bec8SAndroid Build Coastguard Worker        **kwargs):
79*7887bec8SAndroid Build Coastguard Worker    """A dist rule to copy files out of Bazel's output directory into a custom location.
80*7887bec8SAndroid Build Coastguard Worker
81*7887bec8SAndroid Build Coastguard Worker    Example:
82*7887bec8SAndroid Build Coastguard Worker    ```
83*7887bec8SAndroid Build Coastguard Worker    bazel run //path/to/my:dist_target -- --dist_dir=/tmp/dist
84*7887bec8SAndroid Build Coastguard Worker    ```
85*7887bec8SAndroid Build Coastguard Worker
86*7887bec8SAndroid Build Coastguard Worker    Run `bazel run //path/to/my:dist_target -- --help` for explanations of
87*7887bec8SAndroid Build Coastguard Worker    options.
88*7887bec8SAndroid Build Coastguard Worker
89*7887bec8SAndroid Build Coastguard Worker    Args:
90*7887bec8SAndroid Build Coastguard Worker        name: name of this rule
91*7887bec8SAndroid Build Coastguard Worker        data: A list of labels, whose outputs are copied to `--dist_dir`.
92*7887bec8SAndroid Build Coastguard Worker        archives: **DEPRECATED**. A list of labels, whose outputs are treated as tarballs and
93*7887bec8SAndroid Build Coastguard Worker          extracted to `--dist_dir`.
94*7887bec8SAndroid Build Coastguard Worker
95*7887bec8SAndroid Build Coastguard Worker          Deprecated:
96*7887bec8SAndroid Build Coastguard Worker
97*7887bec8SAndroid Build Coastguard Worker            This is deprecated due to inactive usage. If you are using it, please file
98*7887bec8SAndroid Build Coastguard Worker            a bug.
99*7887bec8SAndroid Build Coastguard Worker        flat: If true, `--flat` is provided to the script by default. Flatten the distribution
100*7887bec8SAndroid Build Coastguard Worker          directory.
101*7887bec8SAndroid Build Coastguard Worker        strip_components: If specified, `--strip_components <prefix>` is provided to the script. Strip
102*7887bec8SAndroid Build Coastguard Worker          leading components from the existing copied file paths before applying --prefix
103*7887bec8SAndroid Build Coastguard Worker          (if specified).
104*7887bec8SAndroid Build Coastguard Worker        prefix: If specified, `--prefix <prefix>` is provided to the script by default. Path prefix
105*7887bec8SAndroid Build Coastguard Worker          to apply within dist_dir for copied files.
106*7887bec8SAndroid Build Coastguard Worker        archive_prefix: **DEPRECATED**. If specified, `--archive_prefix <prefix>` is provided to the script by
107*7887bec8SAndroid Build Coastguard Worker          default. Path prefix to apply within dist_dir for extracted archives.
108*7887bec8SAndroid Build Coastguard Worker
109*7887bec8SAndroid Build Coastguard Worker          Deprecated:
110*7887bec8SAndroid Build Coastguard Worker
111*7887bec8SAndroid Build Coastguard Worker            This is deprecated due to inactive usage. If you are using it, please file
112*7887bec8SAndroid Build Coastguard Worker            a bug.
113*7887bec8SAndroid Build Coastguard Worker        dist_dir: If specified, `--dist_dir <dist_dir>` is provided to the script by default.
114*7887bec8SAndroid Build Coastguard Worker
115*7887bec8SAndroid Build Coastguard Worker          In particular, if this is a relative path, it is interpreted as a relative path
116*7887bec8SAndroid Build Coastguard Worker          under workspace root when the target is executed with `bazel run`.
117*7887bec8SAndroid Build Coastguard Worker
118*7887bec8SAndroid Build Coastguard Worker          By default, the script will overwrite any files of the same name in `dist_dir`, but preserve
119*7887bec8SAndroid Build Coastguard Worker          any other contents there. This can be overridden with `wipe_dist_dir`.
120*7887bec8SAndroid Build Coastguard Worker
121*7887bec8SAndroid Build Coastguard Worker          See details by running the target with `--help`.
122*7887bec8SAndroid Build Coastguard Worker        wipe_dist_dir: If true, and `dist_dir` already exists, `dist_dir` will be removed prior to
123*7887bec8SAndroid Build Coastguard Worker          copying.
124*7887bec8SAndroid Build Coastguard Worker        allow_duplicate_filenames: If true, duplicate filenames from different sources will be allowed to
125*7887bec8SAndroid Build Coastguard Worker          be copied to the same `dist_dir` (with subsequent sources overwriting previous sources).
126*7887bec8SAndroid Build Coastguard Worker
127*7887bec8SAndroid Build Coastguard Worker          With this option enabled, order matters. The final source of the file listed in `data` will be the
128*7887bec8SAndroid Build Coastguard Worker          final version copied.
129*7887bec8SAndroid Build Coastguard Worker
130*7887bec8SAndroid Build Coastguard Worker          Use of this option is discouraged. Preferably, the input `data` targets would not include labels
131*7887bec8SAndroid Build Coastguard Worker          which produce a duplicate filename. This option is available as a last resort.
132*7887bec8SAndroid Build Coastguard Worker        mode_overrides: Map of glob patterns to octal permissions. If the file path being copied matches the
133*7887bec8SAndroid Build Coastguard Worker          glob pattern, the corresponding permissions will be set in `dist_dir`. Full file paths are used for
134*7887bec8SAndroid Build Coastguard Worker          matching even if `flat = True`. Paths are relative to the workspace root.
135*7887bec8SAndroid Build Coastguard Worker
136*7887bec8SAndroid Build Coastguard Worker          Order matters; the overrides will be stepped through in the order given for each file. To prevent
137*7887bec8SAndroid Build Coastguard Worker          buildifier from sorting the list, use the `# do not sort` magic line. For example:
138*7887bec8SAndroid Build Coastguard Worker          ```
139*7887bec8SAndroid Build Coastguard Worker          mode_overrides = {
140*7887bec8SAndroid Build Coastguard Worker              # do not sort
141*7887bec8SAndroid Build Coastguard Worker              "**/*.sh": 755,
142*7887bec8SAndroid Build Coastguard Worker              "**/hello_world": 755,
143*7887bec8SAndroid Build Coastguard Worker              "restricted_dir/**": 600,
144*7887bec8SAndroid Build Coastguard Worker              "common/kernel_aarch64/vmlinux": 755,
145*7887bec8SAndroid Build Coastguard Worker              "**/*": 644,
146*7887bec8SAndroid Build Coastguard Worker          },
147*7887bec8SAndroid Build Coastguard Worker          ```
148*7887bec8SAndroid Build Coastguard Worker
149*7887bec8SAndroid Build Coastguard Worker          If no `mode_overrides` are provided, the default Bazel output permissions are preserved.
150*7887bec8SAndroid Build Coastguard Worker        log: If specified, `--log <log>` is provided to the script by default. This sets the
151*7887bec8SAndroid Build Coastguard Worker          default log level of the script.
152*7887bec8SAndroid Build Coastguard Worker
153*7887bec8SAndroid Build Coastguard Worker        testonly: If enabled, testonly will also be set on the internal targets
154*7887bec8SAndroid Build Coastguard Worker          for Bazel analysis to succeed due to the nature of testonly enforcement
155*7887bec8SAndroid Build Coastguard Worker          on reverse dependencies.
156*7887bec8SAndroid Build Coastguard Worker
157*7887bec8SAndroid Build Coastguard Worker          See `dist.py` for allowed values and the default value.
158*7887bec8SAndroid Build Coastguard Worker        **kwargs: Additional attributes to the internal rule, e.g.
159*7887bec8SAndroid Build Coastguard Worker          [`visibility`](https://docs.bazel.build/versions/main/visibility.html).
160*7887bec8SAndroid Build Coastguard Worker
161*7887bec8SAndroid Build Coastguard Worker          These additional attributes are only passed to the underlying embedded_exec rule.
162*7887bec8SAndroid Build Coastguard Worker    """
163*7887bec8SAndroid Build Coastguard Worker
164*7887bec8SAndroid Build Coastguard Worker    unhandled_attrs = []
165*7887bec8SAndroid Build Coastguard Worker    unsupported_attrs = []
166*7887bec8SAndroid Build Coastguard Worker
167*7887bec8SAndroid Build Coastguard Worker    default_args = []
168*7887bec8SAndroid Build Coastguard Worker    if flat:
169*7887bec8SAndroid Build Coastguard Worker        default_args.append("--flat")
170*7887bec8SAndroid Build Coastguard Worker    if strip_components != None:
171*7887bec8SAndroid Build Coastguard Worker        if strip_components < 0:
172*7887bec8SAndroid Build Coastguard Worker            fail("strip_components must greater than 0, but is %s" % strip_components)
173*7887bec8SAndroid Build Coastguard Worker        default_args += ["--strip_components", str(strip_components)]
174*7887bec8SAndroid Build Coastguard Worker    if strip_components:
175*7887bec8SAndroid Build Coastguard Worker        unhandled_attrs.append("strip_components")
176*7887bec8SAndroid Build Coastguard Worker    if prefix != None:
177*7887bec8SAndroid Build Coastguard Worker        default_args += ["--prefix", prefix]
178*7887bec8SAndroid Build Coastguard Worker        unhandled_attrs.append("archive_prefix")
179*7887bec8SAndroid Build Coastguard Worker    if archive_prefix != None:
180*7887bec8SAndroid Build Coastguard Worker        default_args += ["--archive_prefix", archive_prefix]
181*7887bec8SAndroid Build Coastguard Worker        unsupported_attrs.append("archive_prefix")
182*7887bec8SAndroid Build Coastguard Worker    if dist_dir != None:
183*7887bec8SAndroid Build Coastguard Worker        default_args += ["--dist_dir", dist_dir]
184*7887bec8SAndroid Build Coastguard Worker    if wipe_dist_dir:
185*7887bec8SAndroid Build Coastguard Worker        default_args.append("--wipe_dist_dir")
186*7887bec8SAndroid Build Coastguard Worker        unsupported_attrs.append("wipe_dist_dir")
187*7887bec8SAndroid Build Coastguard Worker    if allow_duplicate_filenames:
188*7887bec8SAndroid Build Coastguard Worker        default_args.append("--allow_duplicate_filenames")
189*7887bec8SAndroid Build Coastguard Worker        unsupported_attrs.append("allow_duplicate_filenames")
190*7887bec8SAndroid Build Coastguard Worker    if mode_overrides != None:
191*7887bec8SAndroid Build Coastguard Worker        for (pattern, mode) in mode_overrides.items():
192*7887bec8SAndroid Build Coastguard Worker            default_args += ["--mode_override", pattern, str(mode)]
193*7887bec8SAndroid Build Coastguard Worker        unhandled_attrs.append("mode_overrides")
194*7887bec8SAndroid Build Coastguard Worker    if log != None:
195*7887bec8SAndroid Build Coastguard Worker        default_args += ["--log", log]
196*7887bec8SAndroid Build Coastguard Worker
197*7887bec8SAndroid Build Coastguard Worker    # Separate flags from BUILD with flags from command line
198*7887bec8SAndroid Build Coastguard Worker    default_args.append("CMDLINE_FLAGS_SENTINEL")
199*7887bec8SAndroid Build Coastguard Worker
200*7887bec8SAndroid Build Coastguard Worker    _generate_dist_manifest(
201*7887bec8SAndroid Build Coastguard Worker        name = name + "_dist_manifest",
202*7887bec8SAndroid Build Coastguard Worker        data = data,
203*7887bec8SAndroid Build Coastguard Worker        archives = archives,
204*7887bec8SAndroid Build Coastguard Worker        testonly = testonly,
205*7887bec8SAndroid Build Coastguard Worker    )
206*7887bec8SAndroid Build Coastguard Worker
207*7887bec8SAndroid Build Coastguard Worker    copy_file(
208*7887bec8SAndroid Build Coastguard Worker        name = name + "_dist_tool",
209*7887bec8SAndroid Build Coastguard Worker        src = "//build/bazel_common_rules/dist:dist.py",
210*7887bec8SAndroid Build Coastguard Worker        out = name + "_dist.py",
211*7887bec8SAndroid Build Coastguard Worker    )
212*7887bec8SAndroid Build Coastguard Worker
213*7887bec8SAndroid Build Coastguard Worker    # The dist py_binary tool must be colocated in the same package as the
214*7887bec8SAndroid Build Coastguard Worker    # dist_manifest so that the runfiles directory is the same, and that the
215*7887bec8SAndroid Build Coastguard Worker    # dist_manifest is in the data runfiles of the dist tool.
216*7887bec8SAndroid Build Coastguard Worker    native.py_binary(
217*7887bec8SAndroid Build Coastguard Worker        name = name + "_internal",
218*7887bec8SAndroid Build Coastguard Worker        main = name + "_dist.py",
219*7887bec8SAndroid Build Coastguard Worker        srcs = [name + "_dist.py"],
220*7887bec8SAndroid Build Coastguard Worker        python_version = "PY3",
221*7887bec8SAndroid Build Coastguard Worker        visibility = ["//visibility:public"],
222*7887bec8SAndroid Build Coastguard Worker        data = [name + "_dist_manifest"],
223*7887bec8SAndroid Build Coastguard Worker        testonly = testonly,
224*7887bec8SAndroid Build Coastguard Worker        args = default_args,
225*7887bec8SAndroid Build Coastguard Worker    )
226*7887bec8SAndroid Build Coastguard Worker
227*7887bec8SAndroid Build Coastguard Worker    kwargs.setdefault("deprecation", """copy_to_dist_dir() is deprecated. Use pkg_install() instead.
228*7887bec8SAndroid Build Coastguard Worker
229*7887bec8SAndroid Build Coastguard WorkerSuggested edit:
230*7887bec8SAndroid Build Coastguard Worker
231*7887bec8SAndroid Build Coastguard Workerload("@rules_pkg//pkg:install.bzl", "pkg_install")
232*7887bec8SAndroid Build Coastguard Workerload("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
233*7887bec8SAndroid Build Coastguard Workerpkg_files(
234*7887bec8SAndroid Build Coastguard Worker    name = {name_files},
235*7887bec8SAndroid Build Coastguard Worker    srcs = {data},
236*7887bec8SAndroid Build Coastguard Worker    strip_prefix = {strip_prefix},
237*7887bec8SAndroid Build Coastguard Worker    visibility = ["//visibility:private"],
238*7887bec8SAndroid Build Coastguard Worker)
239*7887bec8SAndroid Build Coastguard Workerpkg_install(
240*7887bec8SAndroid Build Coastguard Worker    name = {name},
241*7887bec8SAndroid Build Coastguard Worker    srcs = [{colon_name_files}],
242*7887bec8SAndroid Build Coastguard Worker    destdir = {dist_dir},
243*7887bec8SAndroid Build Coastguard Worker){unhandled_attrs}{unsupported_attrs}""".format(
244*7887bec8SAndroid Build Coastguard Worker        name = repr(name),
245*7887bec8SAndroid Build Coastguard Worker        name_files = repr(name + "_files"),
246*7887bec8SAndroid Build Coastguard Worker        colon_name_files = repr(":" + name + "_files"),
247*7887bec8SAndroid Build Coastguard Worker        dist_dir = repr(dist_dir),
248*7887bec8SAndroid Build Coastguard Worker        strip_prefix = "strip_prefix.files_only()" if flat else "None",
249*7887bec8SAndroid Build Coastguard Worker        data = repr(data),
250*7887bec8SAndroid Build Coastguard Worker        unhandled_attrs = "" if not unhandled_attrs else "\nThe following attributes are not converted; read the API reference of rules_pkg " +
251*7887bec8SAndroid Build Coastguard Worker                                                         "for an alternative: {}".format(repr(unhandled_attrs)),
252*7887bec8SAndroid Build Coastguard Worker        unsupported_attrs = "" if not unsupported_attrs else "\nThe following attributes may not be supported by rules_pkg: {}".format(repr(unsupported_attrs)),
253*7887bec8SAndroid Build Coastguard Worker    ))
254*7887bec8SAndroid Build Coastguard Worker
255*7887bec8SAndroid Build Coastguard Worker    embedded_exec(
256*7887bec8SAndroid Build Coastguard Worker        name = name,
257*7887bec8SAndroid Build Coastguard Worker        actual = name + "_internal",
258*7887bec8SAndroid Build Coastguard Worker        testonly = testonly,
259*7887bec8SAndroid Build Coastguard Worker        **kwargs
260*7887bec8SAndroid Build Coastguard Worker    )
261