xref: /aosp_15_r20/external/bazelbuild-rules_rust/cargo/private/cargo_build_script_wrapper.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1"""Rules for Cargo build scripts (`build.rs` files)"""
2
3load(
4    "//cargo/private:cargo_build_script.bzl",
5    "name_to_crate_name",
6    "name_to_pkg_name",
7    _build_script_run = "cargo_build_script",
8)
9load("//rust:defs.bzl", "rust_binary")
10
11def cargo_build_script(
12        name,
13        edition = None,
14        crate_name = None,
15        crate_root = None,
16        srcs = [],
17        crate_features = [],
18        version = None,
19        deps = [],
20        link_deps = [],
21        proc_macro_deps = [],
22        build_script_env = {},
23        data = [],
24        compile_data = [],
25        tools = [],
26        links = None,
27        rundir = None,
28        rustc_env = {},
29        rustc_env_files = [],
30        rustc_flags = [],
31        visibility = None,
32        tags = None,
33        aliases = None,
34        pkg_name = None,
35        **kwargs):
36    """Compile and execute a rust build script to generate build attributes
37
38    This rules take the same arguments as rust_binary.
39
40    Example:
41
42    Suppose you have a crate with a cargo build script `build.rs`:
43
44    ```output
45    [workspace]/
46        hello_lib/
47            BUILD
48            build.rs
49            src/
50                lib.rs
51    ```
52
53    Then you want to use the build script in the following:
54
55    `hello_lib/BUILD`:
56    ```python
57    package(default_visibility = ["//visibility:public"])
58
59    load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
60    load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
61
62    # This will run the build script from the root of the workspace, and
63    # collect the outputs.
64    cargo_build_script(
65        name = "build_script",
66        srcs = ["build.rs"],
67        # Optional environment variables passed during build.rs compilation
68        rustc_env = {
69           "CARGO_PKG_VERSION": "0.1.2",
70        },
71        # Optional environment variables passed during build.rs execution.
72        # Note that as the build script's working directory is not execroot,
73        # execpath/location will return an absolute path, instead of a relative
74        # one.
75        build_script_env = {
76            "SOME_TOOL_OR_FILE": "$(execpath @tool//:binary)"
77        },
78        # Optional data/tool dependencies
79        data = ["@tool//:binary"],
80    )
81
82    rust_library(
83        name = "hello_lib",
84        srcs = [
85            "src/lib.rs",
86        ],
87        deps = [":build_script"],
88    )
89    ```
90
91    The `hello_lib` target will be build with the flags and the environment variables declared by the \
92    build script in addition to the file generated by it.
93
94    Args:
95        name (str): The name for the underlying rule. This should be the name of the package
96            being compiled, optionally with a suffix of `_bs`. Otherwise, you can set the package name via `pkg_name`.
97        edition (str): The rust edition to use for the internal binary crate.
98        crate_name (str): Crate name to use for build script.
99        crate_root (label): The file that will be passed to rustc to be used for building this crate.
100        srcs (list of label): Souce files of the crate to build. Passing source files here can be used to trigger rebuilds when changes are made.
101        crate_features (list, optional): A list of features to enable for the build script.
102        version (str, optional): The semantic version (semver) of the crate.
103        deps (list, optional): The build-dependencies of the crate.
104        pkg_name (string, optional): Override the package name used for the build script. This is useful if the build target name gets too long otherwise.
105        link_deps (list, optional): The subset of the (normal) dependencies of the crate that have the
106            links attribute and therefore provide environment variables to this build script.
107        proc_macro_deps (list of label, optional): List of rust_proc_macro targets used to build the script.
108        build_script_env (dict, optional): Environment variables for build scripts.
109        data (list, optional): Files needed by the build script.
110        compile_data (list, optional): Files needed for the compilation of the build script.
111        tools (list, optional): Tools (executables) needed by the build script.
112        links (str, optional): Name of the native library this crate links against.
113        rundir (str, optional): A directory to `cd` to before the cargo_build_script is run. This should be a path relative to the exec root.
114
115            The default behaviour (and the behaviour if rundir is set to the empty string) is to change to the relative path corresponding to the cargo manifest directory, which replicates the normal behaviour of cargo so it is easy to write compatible build scripts.
116
117            If set to `.`, the cargo build script will run in the exec root.
118        rustc_env (dict, optional): Environment variables to set in rustc when compiling the build script.
119        rustc_env_files (list of label, optional): Files containing additional environment variables to set for rustc
120            when building the build script.
121        rustc_flags (list, optional): List of compiler flags passed to `rustc`.
122        visibility (list of label, optional): Visibility to apply to the generated build script output.
123        tags: (list of str, optional): Tags to apply to the generated build script output.
124        aliases (dict, optional): Remap crates to a new name or moniker for linkage to this target. \
125            These are other `rust_library` targets and will be presented as the new name given.
126        **kwargs: Forwards to the underlying `rust_binary` rule. An exception is the `compatible_with`
127            attribute, which shouldn't be forwarded to the `rust_binary`, as the `rust_binary` is only
128            built and used in `exec` mode. We propagate the `compatible_with` attribute to the `_build_scirpt_run`
129            target.
130    """
131
132    # This duplicates the code in _cargo_build_script_impl because we need to make these
133    # available both when we invoke rustc (this code) and when we run the compiled build
134    # script (_cargo_build_script_impl). https://github.com/bazelbuild/rules_rust/issues/661
135    # will hopefully remove this duplication.
136    if pkg_name == None:
137        pkg_name = name_to_pkg_name(name)
138
139    rustc_env = dict(rustc_env)
140    if "CARGO_PKG_NAME" not in rustc_env:
141        rustc_env["CARGO_PKG_NAME"] = pkg_name
142    if "CARGO_CRATE_NAME" not in rustc_env:
143        rustc_env["CARGO_CRATE_NAME"] = name_to_crate_name(name_to_pkg_name(name))
144
145    binary_tags = [tag for tag in tags or []]
146    if "manual" not in binary_tags:
147        binary_tags.append("manual")
148
149    rust_binary(
150        name = name + "_",
151        crate_name = crate_name,
152        srcs = srcs,
153        crate_root = crate_root,
154        crate_features = crate_features,
155        deps = deps,
156        proc_macro_deps = proc_macro_deps,
157        data = data,
158        compile_data = compile_data,
159        rustc_env = rustc_env,
160        rustc_env_files = rustc_env_files,
161        rustc_flags = rustc_flags,
162        edition = edition,
163        tags = binary_tags,
164        aliases = aliases,
165    )
166    _build_script_run(
167        name = name,
168        script = ":{}_".format(name),
169        crate_features = crate_features,
170        version = version,
171        build_script_env = build_script_env,
172        links = links,
173        deps = deps,
174        link_deps = link_deps,
175        data = data,
176        tools = tools,
177        rundir = rundir,
178        rustc_flags = rustc_flags,
179        visibility = visibility,
180        tags = tags,
181        pkg_name = pkg_name,
182        **kwargs
183    )
184