Skip to content

Commit

Permalink
Add bazel genrule test
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Carroll <[email protected]>
  • Loading branch information
mjcarroll committed Dec 20, 2024
1 parent d48c5c6 commit 1b815f6
Show file tree
Hide file tree
Showing 21 changed files with 408 additions and 12 deletions.
2 changes: 1 addition & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ license(
license_text = "LICENSE",
)


write_file(
name = "write_xacro_main",
# This is the same as scripts/xacro from upstream, except that we lose the
Expand All @@ -35,6 +34,7 @@ py_library(
visibility = ["//visibility:public"],
deps = [
"@pypi//pyyaml:pkg",
"@rules_python//python/runfiles",
]
)

Expand Down
4 changes: 2 additions & 2 deletions bazel/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ compile_pip_requirements(
)

bzl_library(
name = "build_defs_bzl",
srcs = ["build_defs.bzl"],
name = "defs",
srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
)

Expand Down
52 changes: 52 additions & 0 deletions bazel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Bazel

This directory contains support files and tests for the bazel build system.

In addition to supporting building xacro with bazel, this also introduces two rules for build-time generation of xacro files.

## xacro_file

Allows you to transform a single xacro file into a generated output

A simple example:

```
load("@xacro//bazel:defs.bzl", "xacro_file")
# By default, will transform input filename with .xacro removed
xacro_file(
name = "sample1",
src = "sample1.xml.xacro",
)
```


A more complex example:

```
load("@xacro//bazel:defs.bzl", "xacro_file")
# By default, will transform input filename with .xacro removed
xacro_file(
name = "complex_example",
src = "complex.xml.xacro",
# Override the default output file name
out = "my_complex_model.xml",
# Depend on the XML file that we generated in the previous step
deps = [":sample1"],
# Set extra substitution args via the command line
extra_args = ["special_argument:=foo"]
)
```

Note in the case of the more complex example, you can use bazel-specified filenames if they are specified in the `deps` field:

```
<?xml version="1.0"?>
<root xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- include a file from a bazel path -->
<xacro:include filename="//sample1.xml"/>
</root>
```

## xacro_filegroup
52 changes: 52 additions & 0 deletions bazel/bazel_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Support methods for xacro.
Since xacro needs to access the file system for its include functionality, we
need to provide an implementation for dealing with files in bazel.
"""

import os
import errno

def open_bazel(path, *args, **kwargs):
"""Open a file.
If path starts with '//', assume it's a bazel path and look for it in
the list of input files (in os.environ['XACRO_INPUTS']).
Args:
path: Path of the file to open. If this starts with '//', assume it's a
bazel path
*args: passed through to open()
**kwargs: passed through to open()
Raises:
IOError: If the requested path is not available either on the filesystem or
in bazel.
"""

print("here, ", path)

if path.startswith('//'):
print("bazel open")
print(os.environ['XACRO_INPUTS'].split('\n'))
# Get path of file, without leading //
bazel_path = path[2:]
# Extract list of input files from environment variable
input_paths = os.environ['XACRO_INPUTS'].split('\n')
best_match = None
# Find the match that is shortest overall – this avoids selecting
# not/my/package/file.xacro when we really want my/package/file.xacro.
for input_path in input_paths:
if input_path.endswith(bazel_path):
if best_match is None or len(best_match) > len(input_path):
best_match = input_path

if best_match is None:
raise IOError(
errno.ENOENT,
'Unable to find bazel file. Is it or the rule that produces it an input?',
path)

path = best_match

return open(path, *args, **kwargs)
6 changes: 0 additions & 6 deletions bazel/build_defs.bzl

This file was deleted.

97 changes: 97 additions & 0 deletions bazel/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""Provider and rules for generating xacro output at build time."""

XacroInfo = provider(
"Provider holding the result of a xacro generation step.",
fields = ["result", "data"],
)

def _xacro_impl(ctx):
if ctx.outputs.out:
out = ctx.outputs.out
else:
src = ctx.file.src.basename
if not src.endswith(".xacro"):
fail("xacro_file src should be named *.xacro not {}".format(src))
out = ctx.actions.declare_file(src[:-6])


# The list of arguments we pass to the script.
args = [ctx.file.src.path, "-o", out.path] + ctx.attr.extra_args

# Action to call the script.
all_inputs = [ctx.file.src] + ctx.files.data + [dep[XacroInfo].result for dep in ctx.attr.deps]
ctx.actions.run(
inputs = all_inputs,
outputs = [out],
arguments = args,
env = {"XACRO_INPUTS": "\n".join([file.path for file in all_inputs])},
progress_message = "Running xacro: %s -> %s" % (ctx.file.src.short_path, out.short_path),
executable = ctx.executable._xacro,
)

xacro_data = depset(
direct = [out] + ctx.files.data + [d[XacroInfo].result for d in ctx.attr.deps],
transitive = [d[XacroInfo].data for d in ctx.attr.deps],
)

runfiles = ctx.runfiles(files = xacro_data.to_list())

return [
XacroInfo(result = out, data = xacro_data),
DefaultInfo(
files = depset([out]),
data_runfiles = ctx.runfiles(files = [out]),
)
]

_xacro_rule = rule(
attrs = {
"src": attr.label(
mandatory = True,
allow_single_file = True,
),
"out": attr.output(),
"data": attr.label_list(
allow_files = True,
),
"extra_args": attr.string_list(),
"deps": attr.label_list(providers = [XacroInfo]),
"_xacro": attr.label(
default = "@xacro//:xacro",
cfg = "host",
executable = True,
),
},
implementation = _xacro_impl,
)

def xacro_file(
name,
src = None,
out = None,
data = [],
tags = [],
deps = [],
extra_args = [],
visibility = None):
"""Runs xacro on a single input file, creating a single output file.
Xacro is the ROS XML macro tool; http://wiki.ros.org/xacro.
Args:
name: The xml output file of this rule.
src: The single xacro input file of this rule.
out: Optional output file name
data: Optional supplemental files required by the src file.
extra_args: Optional arguments to be interpreted by xacro
"""
_xacro_rule(
name = name,
src = src,
out = out,
data = data,
tags = tags,
deps = deps,
extra_args = extra_args,
visibility = visibility,
)
1 change: 1 addition & 0 deletions bazel/integration_test/.bazelversion
64 changes: 64 additions & 0 deletions bazel/integration_test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
load("@xacro//bazel:defs.bzl", "xacro_file")
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")

xacro_file(
name = "sample1",
src = "sample1.xml.xacro",
)

xacro_file(
name = "sample2",
src = "sample2.xml.xacro",
data = ["box.xml"]
)

xacro_file(
name = "complex_example",
src = "complex.xml.xacro",
out = "my_complex_model.xml",
deps = [":sample1"],
extra_args = ["special_argument:=foo"]
)

xacro_file(
name = "conditional_default",
src = "conditional.xml.xacro",
out = "conditional_default.xml"
)

xacro_file(
name = "conditional_false",
src = "conditional.xml.xacro",
out = "conditional_false.xml",
extra_args = ["myarg:=false"]
)

diff_test(
name = "sample1_test",
file1 = ":sample1",
file2 = "expected/sample1.xml"
)

diff_test(
name = "sample2_test",
file1 = ":sample2",
file2 = "expected/sample2.xml"
)

diff_test(
name = "complex_example_test",
file1 = ":complex_example",
file2 = "expected/my_complex_model.xml"
)

diff_test(
name = "conditional_default_test",
file1 = ":conditional_default",
file2 = "expected/conditional_default.xml"
)

diff_test(
name = "conditional_false_test",
file1 = ":conditional_false",
file2 = "expected/conditional_false.xml"
)
7 changes: 7 additions & 0 deletions bazel/integration_test/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bazel_dep(name = "bazel_skylib", version = "1.7.1")

bazel_dep(name = "xacro")
local_path_override(
module_name = "xacro",
path = "../.."
)
4 changes: 4 additions & 0 deletions bazel/integration_test/box.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<root>
<box size="1.0 1.0 1.0"/>
</root>
8 changes: 8 additions & 0 deletions bazel/integration_test/complex.xml.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<root xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- include a file from a bazel path -->
<xacro:include filename="//sample1.xml"/>

<!-- populate an argument from command line -->
<sphere name="$(arg special_argument)" radius="1"/>
</root>
7 changes: 7 additions & 0 deletions bazel/integration_test/conditional.xml.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<root xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:arg name="myarg" default="true"/>
<xacro:if value="$(arg myarg)">
<sphere radius="1"/>
</xacro:if>
</root>
8 changes: 8 additions & 0 deletions bazel/integration_test/expected/conditional_default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from conditional.xml.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<root>
<sphere radius="1"/>
</root>
7 changes: 7 additions & 0 deletions bazel/integration_test/expected/conditional_false.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from conditional.xml.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<root>
</root>
10 changes: 10 additions & 0 deletions bazel/integration_test/expected/my_complex_model.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from complex.xml.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<root>
<sphere radius="1.0"/>
<!-- populate an argument from command line -->
<sphere name="foo" radius="1"/>
</root>
8 changes: 8 additions & 0 deletions bazel/integration_test/expected/sample1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from sample1.xml.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<root>
<sphere radius="1.0"/>
</root>
9 changes: 9 additions & 0 deletions bazel/integration_test/expected/sample2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from sample2.xml.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<root>
<sphere radius="1.0"/>
<box size="1.0 1.0 1.0"/>
</root>
5 changes: 5 additions & 0 deletions bazel/integration_test/sample1.xml.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<root xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="diameter" value="2.0"/>
<sphere radius="${diameter/2}"/>
</root>
6 changes: 6 additions & 0 deletions bazel/integration_test/sample2.xml.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<root xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="diameter" value="2.0"/>
<sphere radius="${diameter/2}"/>
<xacro:include filename="box.xml"/>
</root>
Loading

0 comments on commit 1b815f6

Please sign in to comment.