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