rules_vsg

Bazel rules for VSG (VHDL Style Guide).

Overview

rules_vsg runs the VSG linter and formatter against vhdl_library targets:

  • vsg_test — a Bazel test rule that lints a vhdl_library and fails on violations.
  • @rules_vsg//vsg:fix — a bazel run-able binary that discovers vhdl_* targets under a query scope and applies vsg --fix in place to their sources.
  • vsg_aspect — an aspect that runs VSG as a side effect of bazel build, opt-in via .bazelrc.
  • vsg_toolchain — wraps the vsg pip package as a Bazel toolchain.

Setup

rules_vsg ships with no registered toolchain. VSG is a pip-distributed Python tool and you supply it as a py_library via whichever pip integration you prefer.

The example below uses rules_req_compile, but anything that produces a py_library exposing the vsg package will work.

MODULE.bazel

bazel_dep(name = "rules_vsg",  version = "{version}")
bazel_dep(name = "rules_vhdl", version = "0.1.2")
bazel_dep(name = "rules_venv", version = "0.17.0")
bazel_dep(name = "rules_req_compile", version = "1.1.2")

requirements = use_extension("@rules_req_compile//extensions:python.bzl", "requirements")
requirements.parse(
    name = "pip_deps",
    requirements_locks = {
        "//tools/requirements:requirements_linux_x86_64.txt": "//tools/requirements:linux_x86_64",
    },
)
use_repo(requirements, "pip_deps")

register_toolchains("//tools/toolchains:vsg_toolchain")

//tools/toolchains/BUILD.bazel

load("@rules_vsg//vsg:defs.bzl", "vsg_toolchain")

vsg_toolchain(
    name = "vsg_toolchain_impl",
    vsg = "@pip_deps//vsg",
)

toolchain(
    name = "vsg_toolchain",
    toolchain = ":vsg_toolchain_impl",
    toolchain_type = "@rules_vsg//vsg:toolchain_type",
)

//tools/requirements/requirements.in

vsg

Populate the lockfile with:

bazel run //tools/requirements:requirements.linux_x86_64.update

Usage

load("@rules_vhdl//vhdl:defs.bzl", "vhdl_library")
load("@rules_vsg//vsg:defs.bzl", "vsg_test")

vhdl_library(
    name = "math_pkg",
    srcs = ["math_pkg.vhd", "adder.vhd"],
)

vsg_test(
    name = "math_pkg_vsg_test",
    target = ":math_pkg",
    config = ":vsg_config.yaml",
)

Run:

  • bazel test //:math_pkg_vsg_test — fails on violations
  • bazel run @rules_vsg//vsg:fix -- //:math_pkg — applies vsg --fix in place to that library's sources
  • bazel run @rules_vsg//vsg:fix — same, across every vhdl_* target in the workspace

vsg_test always emits JUnit XML at $XML_OUTPUT_FILE when running under bazel test, so test results integrate with the standard Bazel test report. The workspace fixer discovers targets via bazel query and only mutates files inside the calling workspace — external-repo sources (@repo//...) are never touched.

Aspect mode

To run VSG on every vhdl_library in the workspace as part of bazel build, add to .bazelrc:

build:vsg --aspects=@rules_vsg//vsg:vsg_aspect.bzl%vsg_aspect
build:vsg --output_groups=+vsg_checks
build:vsg --@rules_vsg//vsg:config=//:vsg_config.yaml

Then run with bazel build --config=vsg //.... Tag a target with no_vsg (or nolint, noformat) to opt out.

Extra vsg arguments

The //vsg:extra_args build flag forwards additional arguments to vsg_test and vsg_aspect invocations. Set it repeatedly in .bazelrc, one flag per argument:

build --@rules_vsg//vsg:extra_args=-of=summary

The workspace fixer (@rules_vsg//vsg:fix) does not read this flag — it accepts extra vsg arguments via CLI passthrough only (-- <args> after the scope). See the vsg:fix page for details.

Rule reference

Generated reference for each rule is in the Rules section.

Rules

vsg_test

Rules

vsg_test

load("@rules_vsg//vsg:vsg_test.bzl", "vsg_test")

vsg_test(name, config, extra_configs, target)

A rule for running vsg as a Bazel test (check mode; fails on violations).

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
configVSG configuration file. Defaults to the //vsg:config label_flag.Labeloptional"@rules_vsg//vsg:config"
extra_configsAdditional VSG configuration files to merge on top of config (left-to-right).List of labelsoptional[]
targetThe vhdl_library (or anything providing VhdlInfo) whose sources to lint.Labelrequired

vsg:fix

@rules_vsg//vsg:fix is a bazel run-able binary that discovers every vhdl_* target under a query scope, collects its .vhd / .vhdl sources, and applies vsg --fix in place to the workspace tree. It replaces the legacy per-target vsg_fixer rule — one binary handles the whole workspace, so no companion target is needed for each vhdl_library.

Usage

# Fix everything in the current workspace
bazel run @rules_vsg//vsg:fix

# Fix a single package or target
bazel run @rules_vsg//vsg:fix -- //some/pkg:all
bazel run @rules_vsg//vsg:fix -- //some/pkg:my_lib

# Forward extra arguments to vsg (anything after `--` after the scope)
bazel run @rules_vsg//vsg:fix -- //some/pkg:all -- --junit /tmp/vsg.xml

scope accepts any bazel query-compatible label pattern. If omitted it defaults to //...:all — the entire workspace.

Configuration

The fixer uses the //vsg:config label_flag as its VSG configuration file (identical to vsg_test and vsg_aspect). Override it per-invocation with:

bazel run --@rules_vsg//vsg:config=//path/to:vsg.yaml @rules_vsg//vsg:fix

Extra vsg arguments

The fixer accepts extra vsg arguments only via the CLI passthrough — anything after a second -- is forwarded verbatim to vsg:

bazel run @rules_vsg//vsg:fix -- //some/pkg:all -- -of=summary -b

The fixer defaults to --output_format=syntastic; passing -of=<other> overrides it.

The //vsg:extra_args build flag exists for vsg_test and vsg_aspect — it does not affect the fixer. Fixer runs are already interactive (bazel run under a user's shell), so per-invocation CLI args are the natural surface. Common vsg flags worth knowing:

  • -of=summary — one line per file.
  • -of=vsg — vsg's verbose default.
  • -b — write <file>.vsg.bak alongside each fixed source.
  • -fp=<N> — apply fixes only up to phase N.

Ignore tags

Targets tagged with any of the following are skipped by the fixer (matching vsg_aspect's behavior):

  • no_vsg / novsg
  • no_lint / nolint
  • no_format / noformat

Tag comparison is case-insensitive and treats - and _ as equivalent.

External sources

Sources from external repositories (@repo//...) are never fixed — the fixer only mutates files inside the calling workspace.

vsg_aspect

Aspects

vsg_aspect

load("@rules_vsg//vsg:vsg_aspect.bzl", "vsg_aspect")

vsg_aspect()

An aspect for running vsg on targets providing VhdlInfo.

Enable by adding the following to a workspace's .bazelrc:

build --aspects=@rules_vsg//vsg:vsg_aspect.bzl%vsg_aspect
build --output_groups=+vsg_checks

ASPECT ATTRIBUTES

ATTRIBUTES

vsg_toolchain

Rules

vsg_toolchain

load("@rules_vsg//vsg:vsg_toolchain.bzl", "vsg_toolchain")

vsg_toolchain(name, vsg)

A toolchain for the vsg VHDL style guide rules.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
vsgThe vsg py_library to use with the rules.Labelrequired