Search code examples
qemubazel

Bazel: Run a command without an output


I am using bazel for building bare metal programs. I would like to run the unit tests generated by bazel on qemu.

qemu-system-* -some_args -kernel bazel-bin/whatever/generated.elf

I've tried to run those by creating my own rule in a '.bzl'-file, but it seems that outputs are mandatory on all the rule actions. Note, that I need to invoke different qemu commands with different arguments depending on the target architecture. I would like to pass those to the rule.

Is there a way to invoke a shell command without any outputs?

If needed, this is what I have so far (yet I'm not sure which parts are correct as bazel stops in the analysis phase):

# run_tests.bzl
===============
def _impl(ctx):
  qemu = ctx.attr.qemu
  machine = ctx.attr.machine
  cpu = ctx.attr.cpu
  target = ctx.attr.target
  # The command may only access files declared in inputs.
  ctx.actions.run_shell(
      arguments = [qemu, machine, cpu, target],
      command="$1 -M $2 -cpu $3 -nographic -monitor null -serial null -semihosting -kernel $4")

run_tests = rule(
    implementation=_impl,
    attrs = {"qemu" : attr.string(),
             "machine" : attr.string(),
             "cpu" : attr.string(),
             "target" : attr.string(),},
    executable = True
)

And my BUILD-File:

# BUILD
=======
load("//make:run_tests.bzl", "run_tests")

run_tests(
    name = "portos",
    qemu = "qemu-system-arm",
    machine = "realview-pbx-a9",
    cpu = "cortex-a9",
    target = ":test_portos.elf"
)

cc_binary(
    name = "test_portos.elf",
    srcs = glob(["*.cc"]),
    deps = ["//src:portos", 
            "@unity//:unity"],
    copts = ["-Isrc", 
             "-Iexternal/unity/src",
             "-Iexternal/unity/extras/fixture/src"] 
)

Solution

  • Skylark has support for writing test rules. Basically instead of setting executable = True, you would set test = True, and then your rule would create an executable that is the test, then you set ctx.outputs.executable to that executable. Then you can use the bazel test command with your rule.

    See:

    docs: https://docs.bazel.build/versions/master/skylark/rules.html#test-rules

    example: https://github.com/bazelbuild/examples/tree/master/rules/test_rule

    rule.test: https://docs.bazel.build/versions/master/skylark/lib/globals.html#rule.test