Add rules_cros test rules and emulation toolchain
Add emulation toolchain and test rules to run basic "Hello World"
binaries for rules_cros toolchain verfication. rules_cros_(cc|rust)_test
rules run the CC and Rust binaries against an individual platform;
rules_cros_toolchain_test fans out to run rules_cros_(cc|rust)_test tests
against all platforms.
BUG=b:217770417
TEST=`bazel-5 test //test:rules_cros_platforms_test`
Change-Id: I415f260fbbd13fb1b9c850cee8f3daa61afc63a6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/rules_cros/+/3442709
Reviewed-by: Chris McDonald <cjmcdonald@chromium.org>
Tested-by: Sloan Johnson <sloanjohnson@google.com>
diff --git a/cros/repositories.bzl b/cros/repositories.bzl
index ec556b9..2b3613c 100644
--- a/cros/repositories.bzl
+++ b/cros/repositories.bzl
@@ -35,4 +35,6 @@
"@rules_cros//cros/toolchain/cc:cros-sdk-x86_64-cros-linux-gnu-cc-toolchain",
"@rules_cros//cros/toolchain/rust:cros-sdk-x86_64-pc-linux-gnu-rust",
"@rules_cros//cros/toolchain/rust:cros-sdk-x86_64-cros-linux-gnu-rust",
+ "@rules_cros//cros/toolchain/emulation:cros-sdk-x86_64-pc-linux-gnu-emulation",
+ "@rules_cros//cros/toolchain/emulation:cros-sdk-x86_64-cros-linux-gnu-emulation",
)
diff --git a/cros/toolchain/emulation/BUILD b/cros/toolchain/emulation/BUILD
new file mode 100644
index 0000000..fc7f6f7
--- /dev/null
+++ b/cros/toolchain/emulation/BUILD
@@ -0,0 +1,51 @@
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+load(":toolchain.bzl", "emulation_toolchain")
+
+package(default_visibility = ["//visibility:public"])
+
+emulation_toolchain(
+ name = "cros-sdk-x86_64-pc-linux-gnu-emulation_impl",
+ emulator_path = "/lib64/ld-linux-x86-64.so.2",
+)
+
+emulation_toolchain(
+ name = "cros-sdk-x86_64-cros-linux-gnu-emulation_impl",
+ emulator_path = "qemu-x86_64",
+)
+
+toolchain(
+ name = "cros-sdk-x86_64-pc-linux-gnu-emulation",
+ exec_compatible_with = [
+ "@platforms//cpu:x86_64",
+ "@platforms//os:linux",
+ ],
+ target_compatible_with = [
+ "@platforms//cpu:x86_64",
+ "@platforms//os:linux",
+ "//cros/platforms/vendor:pc",
+ ],
+ toolchain = ":cros-sdk-x86_64-pc-linux-gnu-emulation_impl",
+ toolchain_type = ":toolchain_type",
+)
+
+toolchain(
+ name = "cros-sdk-x86_64-cros-linux-gnu-emulation",
+ exec_compatible_with = [
+ "@platforms//cpu:x86_64",
+ "@platforms//os:linux",
+ ],
+ target_compatible_with = [
+ "@platforms//cpu:x86_64",
+ "@platforms//os:linux",
+ "//cros/platforms/vendor:cros",
+ ],
+ toolchain = ":cros-sdk-x86_64-cros-linux-gnu-emulation_impl",
+ toolchain_type = ":toolchain_type",
+)
+
+toolchain_type(
+ name = "toolchain_type",
+)
diff --git a/cros/toolchain/emulation/toolchain.bzl b/cros/toolchain/emulation/toolchain.bzl
new file mode 100644
index 0000000..3bfdb43
--- /dev/null
+++ b/cros/toolchain/emulation/toolchain.bzl
@@ -0,0 +1,19 @@
+EmuInfo = provider(
+ fields = ["emulator_path"],
+)
+
+def _impl(ctx):
+ toolchain_info = platform_common.ToolchainInfo(
+ emuinfo = EmuInfo(
+ emulator_path = ctx.attr.emulator_path,
+ ),
+ )
+ return [toolchain_info]
+
+emulation_toolchain = rule(
+ implementation = _impl,
+ attrs = {
+ "emulator_path": attr.string(),
+ },
+ provides = [platform_common.ToolchainInfo],
+)
diff --git a/run_tests.sh b/run_tests.sh
new file mode 100755
index 0000000..01bc0e0
--- /dev/null
+++ b/run_tests.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Runs the rules_cros tests. Must be run in the chroot.
+
+if ! test -f "/etc/cros_chroot_version"; then
+ echo "Must be run in the chroot."
+ exit 1
+fi
+
+cd $(dirname ${BASH_SOURCE[0]})
+bazel-5 test --test_output=all //test:rules_cros_toolchain_test
diff --git a/test/BUILD.bazel b/test/BUILD.bazel
new file mode 100644
index 0000000..454fac4
--- /dev/null
+++ b/test/BUILD.bazel
@@ -0,0 +1,36 @@
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+load("@rules_rust//rust:defs.bzl", "rust_binary")
+load(":toolchain.bzl", "qemu_test", "toolchain_test")
+
+package(default_visibility = ["//visibility:private"])
+
+rust_binary(
+ name = "rust_toolchain_test",
+ srcs = glob(["src/**/*.rs"]),
+)
+
+cc_binary(
+ name = "cc_toolchain_test",
+ srcs = glob(["src/**/*.c"])
+)
+
+qemu_test(
+ name = "rules_cros_cc_test",
+ dep = ":cc_toolchain_test",
+)
+
+qemu_test(
+ name = "rules_cros_rust_test",
+ dep = ":rust_toolchain_test",
+)
+
+toolchain_test(
+ name = "rules_cros_toolchain_test",
+ deps = [
+ ":rules_cros_cc_test",
+ ":rules_cros_rust_test",
+ ]
+)
diff --git a/test/qemu_test_template.sh b/test/qemu_test_template.sh
new file mode 100644
index 0000000..98d5888
--- /dev/null
+++ b/test/qemu_test_template.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+BINARY=${1:-%PATH%}
+echo "Testing that $BINARY outputs "Hello, world!""
+if [ "$(%EMULATOR% "$BINARY")" != "Hello, world!" ]
+then
+ echo "$BINARY failed test"
+ echo
+ exit 1
+fi
+echo
diff --git a/test/src/hello.c b/test/src/hello.c
new file mode 100644
index 0000000..288568c
--- /dev/null
+++ b/test/src/hello.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+ printf("Hello, world!\n");
+}
diff --git a/test/src/main.rs b/test/src/main.rs
new file mode 100644
index 0000000..8c52602
--- /dev/null
+++ b/test/src/main.rs
@@ -0,0 +1,7 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/test/toolchain.bzl b/test/toolchain.bzl
new file mode 100644
index 0000000..20f6b09
--- /dev/null
+++ b/test/toolchain.bzl
@@ -0,0 +1,103 @@
+def _transition_impl(settings, attr):
+ _ignore = [settings, attr]
+
+ return {
+ "linux_x86_64": {
+ "//command_line_option:platforms": "//cros/platforms:linux_x86_64"
+ },
+ "cros_x86_64": {
+ "//command_line_option:platforms": "//cros/platforms:cros_x86_64"
+ },
+ }
+
+full_toolchain_fanout = transition(
+ implementation = _transition_impl,
+ inputs = [],
+ outputs = ["//command_line_option:platforms"],
+)
+
+_QEMU_TEST_TEMPLATE = "//test:qemu_test_template.sh"
+
+def _qemu_test_impl(ctx):
+ emu_toolchain = ctx.toolchains["//cros/toolchain/emulation:toolchain_type"]
+ emulator_path = emu_toolchain.emuinfo.emulator_path
+
+ ctx.actions.expand_template(
+ template = ctx.file._template,
+ output = ctx.outputs.executable,
+ substitutions = {
+ "%EMULATOR%": emulator_path,
+ "%PATH%": ctx.files.dep[0].short_path,
+ },
+ )
+
+ runfiles = ctx.runfiles(ctx.files.dep)
+ return [DefaultInfo(runfiles = runfiles)]
+
+qemu_test = rule(
+ implementation = _qemu_test_impl,
+ attrs = {
+ "dep": attr.label(mandatory = True, executable = True, cfg = "target"),
+ "_template": attr.label(
+ default = Label(_QEMU_TEST_TEMPLATE),
+ allow_single_file = True,
+ )
+ },
+ toolchains = ["//cros/toolchain/emulation:toolchain_type"],
+ test = True,
+)
+
+def _run_tests(test, args):
+ return """
+{test} {args}
+((err+=$?))
+""".format(test = test, args = " ".join(args))
+
+def _toolchain_test_impl(ctx):
+ script = ""
+ symlinks = {}
+
+ for platform in ctx.split_attr.deps:
+ for d in ctx.split_attr.deps[platform]:
+ executable = d.files_to_run.executable
+ # Need to specify symlinks with platform appended for the runfiles,
+ # otherwise they will overwrite eachother for each platform.
+ test_path = "{}.{}".format(executable.short_path, platform)
+ symlinks[test_path] = executable
+ args = []
+ for f in d.default_runfiles.files.to_list():
+ if f != executable:
+ rf_path = "{}.{}".format(f.short_path, platform)
+ args.append(rf_path)
+ symlinks[rf_path] = f
+
+ script = "\n".join(
+ [script] +
+ [_run_tests(test_path, args)]
+ )
+
+ script = "\n".join(
+ ["#!/bin/bash"] +
+ ["err=0"] +
+ [script] +
+ ["exit $err"],
+ )
+
+ ctx.actions.write(
+ output = ctx.outputs.executable,
+ content = script,
+ )
+
+ runfiles = ctx.runfiles(symlinks = symlinks)
+ return [DefaultInfo(runfiles = runfiles)]
+
+toolchain_test = rule(
+ implementation = _toolchain_test_impl,
+ attrs = {
+ "deps": attr.label_list(cfg = full_toolchain_fanout),
+ "_allowlist_function_transition": attr.label(
+ default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+ ),
+ },
+ test = True,
+)