Skip to content

Commit 798389a

Browse files
committed
Add miri_test
1 parent e8f3393 commit 798389a

32 files changed

Lines changed: 1976 additions & 137 deletions

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use_repo(
5252
bazel_dep(name = "bazel_lib", version = "3.0.0")
5353
bazel_dep(name = "bazel_features", version = "1.45.0")
5454
bazel_dep(name = "bazel_skylib", version = "1.4.1")
55+
bazel_dep(name = "hermetic_launcher", version = "0.0.5")
5556
bazel_dep(name = "package_metadata", version = "0.0.7")
5657
bazel_dep(name = "platforms", version = "1.1.0")
5758
bazel_dep(name = "protobuf", version = "34.0.bcr.1", repo_name = "com_google_protobuf")

MODULE.bazel.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rs/experimental/miri/BUILD.bazel

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
"@hermetic_launcher//launcher:lib_bzl",
25+
],
26+
)
27+
28+
bzl_library(
29+
name = "module_extension",
30+
srcs = ["module_extension.bzl"],
31+
visibility = ["//visibility:public"],
32+
deps = [
33+
"//rs/platforms:triples",
34+
"//rs/private:cargo_repository",
35+
"//rs/private:miri_repository",
36+
"//rs/private:module_extension_utils",
37+
"//rs/private:rustc_repository",
38+
"//rs/private:rustc_src_repository",
39+
"//rs/private:stdlib_repository",
40+
"//rs/toolchains:toolchain_utils",
41+
"@rules_rust//rust/platform:bzl_lib",
42+
"@rules_rust//rust/private:bzl_lib",
43+
],
44+
)

rs/experimental/miri/miri_test.bzl

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
"""Miri test rule."""
2+
3+
load("@hermetic_launcher//launcher:lib.bzl", "launcher")
4+
load("//rs/experimental/miri/private:compile.bzl", "alias_for_dep", "dependency_search_dir_arg", "miri_compile_aspect")
5+
load("//rs/experimental/miri/private:providers.bzl", "MiriCrateInfo")
6+
load("//rs/experimental/miri/private:toolchain.bzl", "MIRI_TOOLCHAIN_TYPE")
7+
8+
def _dirname(path):
9+
if "/" not in path:
10+
return "."
11+
return path.rsplit("/", 1)[0]
12+
13+
def _default_crate_name(label):
14+
return label.name.replace("-", "_")
15+
16+
def _crate_root(ctx):
17+
if ctx.file.crate_root:
18+
return ctx.file.crate_root
19+
20+
for src in ctx.files.srcs:
21+
if src.basename in ("main.rs", "lib.rs"):
22+
return src
23+
24+
if len(ctx.files.srcs) == 1:
25+
return ctx.files.srcs[0]
26+
27+
fail("miri_test requires crate_root when srcs does not contain main.rs or lib.rs")
28+
29+
def _miri_extern_arg(extern):
30+
name, output = extern
31+
return ["--extern", "{}={}".format(name, output.short_path)]
32+
33+
def _miri_extern_args(deps, aliases):
34+
externs = []
35+
dependency_search_dirs = set()
36+
dependency_inputs = []
37+
for dep in deps:
38+
if MiriCrateInfo not in dep:
39+
continue
40+
miri_dep = dep[MiriCrateInfo]
41+
name = alias_for_dep(aliases, dep, miri_dep.crate_info)
42+
externs.append((name, miri_dep.output))
43+
dependency_search_dirs.add(_dirname(miri_dep.output.short_path))
44+
dependency_inputs.append(miri_dep.transitive_inputs)
45+
for transitive_output in miri_dep.transitive_outputs.to_list():
46+
dependency_search_dirs.add(_dirname(transitive_output.short_path))
47+
48+
return struct(
49+
dependency_inputs = dependency_inputs,
50+
dependency_search_dirs = sorted(dependency_search_dirs),
51+
externs = externs,
52+
)
53+
54+
def _miri_test_impl(ctx):
55+
toolchain = ctx.toolchains[MIRI_TOOLCHAIN_TYPE]
56+
crate_root = _crate_root(ctx)
57+
crate_name = ctx.attr.crate_name or _default_crate_name(ctx.label)
58+
deps = _miri_extern_args(ctx.attr.deps, ctx.attr.aliases)
59+
60+
miri_args = ctx.actions.args()
61+
miri_args.set_param_file_format("multiline")
62+
miri_args.add_all([
63+
"--sysroot",
64+
toolchain.miri_sysroot.short_path,
65+
crate_root.short_path,
66+
"--crate-name",
67+
crate_name,
68+
"--crate-type",
69+
"bin",
70+
"--edition",
71+
ctx.attr.edition,
72+
"--test",
73+
"--target",
74+
toolchain.target_triple,
75+
"--cfg=miri",
76+
])
77+
78+
miri_args.add_all(deps.externs, map_each = _miri_extern_arg)
79+
miri_args.add_all(deps.dependency_search_dirs, map_each = dependency_search_dir_arg)
80+
miri_args.add_all(ctx.attr.rustc_flags)
81+
miri_args.add_all(ctx.attr.miri_flags)
82+
miri_args.add("--")
83+
miri_args.add_all(ctx.attr.args)
84+
85+
args_file = ctx.actions.declare_file(ctx.label.name + ".miri_args")
86+
ctx.actions.write(
87+
output = args_file,
88+
content = miri_args,
89+
)
90+
91+
executable = ctx.actions.declare_file(ctx.label.name)
92+
embedded_args, transformed_args = launcher.args_from_entrypoint(toolchain.miri)
93+
embedded_args = embedded_args + ["@" + args_file.short_path]
94+
launcher.compile_stub(
95+
ctx = ctx,
96+
embedded_args = embedded_args,
97+
transformed_args = transformed_args,
98+
output_file = executable,
99+
)
100+
101+
runfiles = ctx.runfiles(
102+
files = ctx.files.srcs + ctx.files.data + [args_file, crate_root],
103+
transitive_files = depset(transitive = [
104+
toolchain.all_files,
105+
depset([output for _, output in deps.externs]),
106+
depset(transitive = deps.dependency_inputs),
107+
]),
108+
)
109+
110+
return [
111+
DefaultInfo(
112+
executable = executable,
113+
runfiles = runfiles,
114+
),
115+
RunEnvironmentInfo(environment = ctx.attr.env | {"MIRI_SYSROOT": toolchain.miri_sysroot.short_path}),
116+
]
117+
118+
miri_test = rule(
119+
implementation = _miri_test_impl,
120+
attrs = {
121+
"crate_name": attr.string(doc = "Rust crate name. Defaults to the target name with '-' replaced by '_'."),
122+
"crate_root": attr.label(allow_single_file = [".rs"]),
123+
"aliases": attr.label_keyed_string_dict(doc = "Remap direct dependencies to another extern crate name."),
124+
"data": attr.label_list(allow_files = True),
125+
"deps": attr.label_list(aspects = [miri_compile_aspect]),
126+
"edition": attr.string(default = "2021"),
127+
"env": attr.string_dict(doc = "Environment variables set while running Miri."),
128+
"miri_flags": attr.string_list(doc = "Extra flags passed to the Miri driver."),
129+
"rustc_flags": attr.string_list(doc = "Extra rustc-compatible flags passed to Miri."),
130+
"srcs": attr.label_list(allow_files = [".rs"], mandatory = True),
131+
},
132+
test = True,
133+
toolchains = [
134+
MIRI_TOOLCHAIN_TYPE,
135+
launcher.finalizer_toolchain_type,
136+
launcher.template_toolchain_type,
137+
],
138+
)

0 commit comments

Comments
 (0)