Skip to content

Commit 41e6e54

Browse files
committed
Add miri_test
1 parent e8f3393 commit 41e6e54

31 files changed

Lines changed: 2023 additions & 137 deletions

rs/experimental/miri/BUILD.bazel

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
load("@bazel_lib//:bzl_library.bzl", "bzl_library")
2+
3+
package(default_visibility = ["//visibility:private"])
4+
5+
toolchain_type(
6+
name = "toolchain_type",
7+
visibility = ["//visibility:public"],
8+
)
9+
10+
toolchain_type(
11+
name = "sysroot_toolchain_type",
12+
visibility = ["//visibility:public"],
13+
)
14+
15+
bzl_library(
16+
name = "miri_test",
17+
srcs = ["miri_test.bzl"],
18+
visibility = ["//visibility:public"],
19+
deps = [
20+
"//rs/experimental/miri/private:compile",
21+
"//rs/experimental/miri/private:providers",
22+
"//rs/experimental/miri/private:toolchain",
23+
"@bazel_features//:features",
24+
],
25+
)
26+
27+
bzl_library(
28+
name = "module_extension",
29+
srcs = ["module_extension.bzl"],
30+
visibility = ["//visibility:public"],
31+
deps = [
32+
"//rs/platforms:triples",
33+
"//rs/private:cargo_repository",
34+
"//rs/private:miri_repository",
35+
"//rs/private:module_extension_utils",
36+
"//rs/private:rustc_repository",
37+
"//rs/private:rustc_src_repository",
38+
"//rs/private:stdlib_repository",
39+
"//rs/toolchains:toolchain_utils",
40+
"@rules_rust//rust/platform:bzl_lib",
41+
"@rules_rust//rust/private:bzl_lib",
42+
],
43+
)

rs/experimental/miri/miri_test.bzl

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
"""Miri test rule."""
2+
3+
load("//rs/experimental/miri/private:compile.bzl", "alias_for_dep", "miri_compile_aspect")
4+
load("//rs/experimental/miri/private:providers.bzl", "MiriCrateInfo")
5+
load("//rs/experimental/miri/private:toolchain.bzl", "MIRI_TOOLCHAIN_TYPE")
6+
7+
def _default_crate_name(label):
8+
return label.name.replace("-", "_")
9+
10+
def _crate_root(ctx):
11+
if ctx.file.crate_root:
12+
return ctx.file.crate_root
13+
14+
for src in ctx.files.srcs:
15+
if src.basename in ("main.rs", "lib.rs"):
16+
return src
17+
18+
if len(ctx.files.srcs) == 1:
19+
return ctx.files.srcs[0]
20+
21+
fail("miri_test requires crate_root when srcs does not contain main.rs or lib.rs")
22+
23+
def _miri_extern_arg(extern):
24+
return ["--extern", "{}={}".format(extern.name, extern.output.path)]
25+
26+
def _dependency_search_dir_arg(file):
27+
return "-Ldependency={}".format(file.dirname)
28+
29+
def _miri_deps(deps, aliases):
30+
externs = []
31+
dependency_inputs = []
32+
dependency_outputs = []
33+
for dep in deps:
34+
if MiriCrateInfo not in dep:
35+
continue
36+
miri_dep = dep[MiriCrateInfo]
37+
name = alias_for_dep(aliases, dep, miri_dep.crate_info)
38+
externs.append(struct(
39+
name = name,
40+
output = miri_dep.output,
41+
))
42+
dependency_inputs.append(miri_dep.transitive_inputs)
43+
dependency_outputs.append(miri_dep.transitive_outputs)
44+
45+
return struct(
46+
externs = externs,
47+
inputs = depset(transitive = dependency_inputs),
48+
outputs = depset(transitive = dependency_outputs),
49+
)
50+
51+
def _miri_test_impl(ctx):
52+
toolchain = ctx.toolchains[MIRI_TOOLCHAIN_TYPE]
53+
crate_root = _crate_root(ctx)
54+
crate_name = ctx.attr.crate_name or _default_crate_name(ctx.label)
55+
deps = _miri_deps(ctx.attr.deps, ctx.attr.aliases)
56+
57+
test_runner_name = ctx.label.name
58+
if ctx.executable._test_runner.extension:
59+
test_runner_name += "." + ctx.executable._test_runner.extension
60+
61+
test_runner = ctx.actions.declare_file(test_runner_name)
62+
stdout_file = ctx.actions.declare_file(test_runner.basename + ".miri_test.stdout", sibling = test_runner)
63+
stderr_file = ctx.actions.declare_file(test_runner.basename + ".miri_test.stderr", sibling = test_runner)
64+
exit_code_file = ctx.actions.declare_file(test_runner.basename + ".miri_test.exit_code", sibling = test_runner)
65+
66+
miri_args = ctx.actions.args()
67+
miri_args.set_param_file_format("multiline")
68+
miri_args.use_param_file("@%s", use_always = True)
69+
miri_args.add_all([
70+
"--sysroot",
71+
toolchain.miri_sysroot.path,
72+
crate_root.path,
73+
"--crate-name",
74+
crate_name,
75+
"--crate-type",
76+
"bin",
77+
"--edition",
78+
ctx.attr.edition,
79+
"--test",
80+
"--target",
81+
toolchain.target_triple,
82+
"--cfg=miri",
83+
])
84+
85+
miri_args.add_all(deps.externs, map_each = _miri_extern_arg)
86+
miri_args.add_all(deps.outputs, map_each = _dependency_search_dir_arg)
87+
miri_args.add_all(ctx.attr.rustc_flags)
88+
miri_args.add_all(ctx.attr.miri_flags)
89+
miri_args.add("--")
90+
miri_args.add_all(ctx.attr.args)
91+
92+
process_wrapper_args = ctx.actions.args()
93+
process_wrapper_args.add("--stdout-file", stdout_file)
94+
process_wrapper_args.add("--stderr-file", stderr_file)
95+
process_wrapper_args.add("--captured-exit-code-file", exit_code_file)
96+
process_wrapper_args.add("--subst", "pwd=${pwd}")
97+
process_wrapper_args.add("--subst", "exec_root=${exec_root}")
98+
process_wrapper_args.add("--subst", "output_base=${output_base}")
99+
100+
miri_path = ctx.actions.args()
101+
miri_path.add("--")
102+
miri_path.add(toolchain.miri)
103+
104+
ctx.actions.run(
105+
executable = toolchain.process_wrapper,
106+
arguments = [process_wrapper_args, miri_path, miri_args],
107+
env = ctx.attr.env | {"MIRI_SYSROOT": toolchain.miri_sysroot.path},
108+
inputs = depset(
109+
direct = ctx.files.srcs + ctx.files.data + [crate_root],
110+
transitive = [
111+
deps.inputs,
112+
deps.outputs,
113+
toolchain.all_files,
114+
],
115+
),
116+
outputs = [
117+
stdout_file,
118+
stderr_file,
119+
exit_code_file,
120+
],
121+
mnemonic = "MiriTest",
122+
progress_message = "Running Miri test %{label}",
123+
toolchain = MIRI_TOOLCHAIN_TYPE,
124+
)
125+
126+
ctx.actions.symlink(
127+
output = test_runner,
128+
target_file = ctx.executable._test_runner,
129+
is_executable = True,
130+
)
131+
132+
runfiles = ctx.runfiles(files = [stdout_file, stderr_file, exit_code_file])
133+
runfiles = runfiles.merge(ctx.attr._test_runner[DefaultInfo].default_runfiles)
134+
135+
return [DefaultInfo(
136+
executable = test_runner,
137+
files = depset([test_runner]),
138+
runfiles = runfiles,
139+
)]
140+
141+
miri_test = rule(
142+
implementation = _miri_test_impl,
143+
attrs = {
144+
"crate_name": attr.string(doc = "Rust crate name. Defaults to the target name with '-' replaced by '_'."),
145+
"crate_root": attr.label(allow_single_file = [".rs"]),
146+
"aliases": attr.label_keyed_string_dict(doc = "Remap direct dependencies to another extern crate name."),
147+
"data": attr.label_list(allow_files = True),
148+
"deps": attr.label_list(aspects = [miri_compile_aspect]),
149+
"edition": attr.string(default = "2021"),
150+
"env": attr.string_dict(doc = "Environment variables set while running Miri."),
151+
"miri_flags": attr.string_list(doc = "Extra flags passed to the Miri driver."),
152+
"rustc_flags": attr.string_list(doc = "Extra rustc-compatible flags passed to Miri."),
153+
"srcs": attr.label_list(allow_files = [".rs"], mandatory = True),
154+
"_test_runner": attr.label(
155+
default = Label("//rs/experimental/miri/private:miri_test_runner"),
156+
executable = True,
157+
cfg = "exec",
158+
),
159+
},
160+
test = True,
161+
toolchains = [MIRI_TOOLCHAIN_TYPE],
162+
)

0 commit comments

Comments
 (0)