Skip to content

Commit 6ec80c8

Browse files
authored
Add shellcheck_toolchain rule (#48)
This allows for users to provide custom shellcheck binaries to power the shellcheck rules. Additionally, this adds support for `.shellcheckrc` files via `--@rules_shellcheck//shellcheck:rc=<label_of_file>` closes #24
1 parent aed416c commit 6ec80c8

File tree

10 files changed

+324
-114
lines changed

10 files changed

+324
-114
lines changed

BUILD.bazel

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -22,72 +22,8 @@ alias(
2222
visibility = ["//:__subpackages__"],
2323
)
2424

25-
constraint_value(
26-
name = "armv6hf",
27-
constraint_setting = "@platforms//cpu",
28-
)
29-
30-
# Raspberry Pi
31-
config_setting(
32-
name = "linux_armv6hf",
33-
constraint_values = [
34-
"@platforms//os:linux",
35-
"//:armv6hf",
36-
],
37-
)
38-
39-
config_setting(
40-
name = "darwin_x86_64",
41-
constraint_values = [
42-
"@platforms//os:macos",
43-
"@platforms//cpu:x86_64",
44-
],
45-
)
46-
47-
config_setting(
48-
name = "darwin_aarch64",
49-
constraint_values = [
50-
"@platforms//os:macos",
51-
"@platforms//cpu:aarch64",
52-
],
53-
)
54-
55-
config_setting(
56-
name = "linux_x86_64",
57-
constraint_values = [
58-
"@platforms//os:linux",
59-
"@platforms//cpu:x86_64",
60-
],
61-
)
62-
63-
config_setting(
64-
name = "linux_aarch64",
65-
constraint_values = [
66-
"@platforms//os:linux",
67-
"@platforms//cpu:aarch64",
68-
],
69-
)
70-
71-
config_setting(
72-
name = "windows_x86_64",
73-
constraint_values = [
74-
"@platforms//os:windows",
75-
"@platforms//cpu:x86_64",
76-
],
77-
)
78-
7925
alias(
8026
name = "shellcheck",
81-
actual = select(
82-
{
83-
":darwin_aarch64": "@shellcheck_darwin_aarch64//:shellcheck",
84-
":darwin_x86_64": "@shellcheck_darwin_x86_64//:shellcheck",
85-
":linux_aarch64": "@shellcheck_linux_aarch64//:shellcheck",
86-
":linux_armv6hf": "@shellcheck_linux_armv6hf//:shellcheck",
87-
":linux_x86_64": "@shellcheck_linux_x86_64//:shellcheck",
88-
":windows_x86_64": "@shellcheck_windows_x86_64//:shellcheck",
89-
},
90-
no_match_error = "binaries for your platform could not be found",
91-
),
27+
actual = "//shellcheck:current_shellcheck_toolchain",
9228
visibility = ["//visibility:public"],
9329
)

MODULE.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ use_repo(
1616
"shellcheck_linux_aarch64",
1717
"shellcheck_linux_armv6hf",
1818
"shellcheck_linux_x86_64",
19+
"shellcheck_toolchains",
1920
"shellcheck_windows_x86_64",
2021
)
2122

23+
register_toolchains(
24+
"@shellcheck_toolchains//:all",
25+
)
26+
2227
# Dev dependencies
2328

2429
bazel_dep(name = "rules_pkg", version = "0.9.1", dev_dependency = True)

deps.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- OSX 64-bit
44
"""
55

6+
# buildifier: disable=bzl-visibility
67
load("//shellcheck/internal:extensions.bzl", _shellcheck_dependencies = "shellcheck_dependencies")
78

89
shellcheck_dependencies = _shellcheck_dependencies

shellcheck/.shellcheckrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# https://github.com/koalaman/shellcheck/blob/v0.11.0/shellcheck.1.md#rc-files

shellcheck/BUILD.bazel

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
1+
load("//shellcheck/internal:toolchain.bzl", "current_shellcheck_toolchain")
2+
13
filegroup(
24
name = "distribution",
35
srcs = [
6+
".shellcheckrc",
47
"BUILD.bazel",
58
"defs.bzl",
69
"shellcheck_aspect.bzl",
710
"shellcheck_test.bzl",
11+
"shellcheck_toolchain.bzl",
812
"//shellcheck/internal:distribution",
913
"//shellcheck/settings:distribution",
1014
],
1115
visibility = ["//:__pkg__"],
1216
)
17+
18+
toolchain_type(
19+
name = "toolchain_type",
20+
visibility = ["//visibility:public"],
21+
)
22+
23+
current_shellcheck_toolchain(
24+
name = "current_shellcheck_toolchain",
25+
visibility = ["//visibility:public"],
26+
)
27+
28+
alias(
29+
name = "shellcheck",
30+
actual = ":current_shellcheck_toolchain",
31+
visibility = ["//visibility:public"],
32+
)
33+
34+
label_flag(
35+
name = "rc",
36+
build_setting_default = ".shellcheckrc",
37+
visibility = ["//visibility:public"],
38+
)

shellcheck/internal/extensions.bzl

Lines changed: 136 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,76 @@
55

66
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
77
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
8+
load("@rules_shellcheck//shellcheck:shellcheck_toolchain.bzl", "shellcheck_toolchain")
9+
10+
_HUB_BUILD_CONTENT = """\
11+
{toolchains}
12+
"""
13+
14+
_CONSTRAINTS = {
15+
"darwin_aarch64": [
16+
"@platforms//os:macos",
17+
"@platforms//cpu:aarch64",
18+
],
19+
"darwin_x86_64": [
20+
"@platforms//os:macos",
21+
"@platforms//cpu:x86_64",
22+
],
23+
"linux_aarch64": [
24+
"@platforms//os:linux",
25+
"@platforms//cpu:aarch64",
26+
],
27+
"linux_armv6hf": [
28+
"@platforms//cpu:armv6-m",
29+
"@platforms//os:linux",
30+
],
31+
"linux_x86_64": [
32+
"@platforms//os:linux",
33+
"@platforms//cpu:x86_64",
34+
],
35+
"windows_x86_64": [
36+
"@platforms//os:windows",
37+
"@platforms//cpu:x86_64",
38+
],
39+
}
40+
41+
_TOOLCHAIN_ENTRY = """\
42+
toolchain(
43+
name = "shellcheck_toolchain_{arch}",
44+
toolchain_type = "@rules_shellcheck//shellcheck:toolchain_type",
45+
toolchain = "{toolchain}",
46+
exec_compatible_with = {constraints},
47+
visibility = ["//visibility:public"],
48+
)
49+
"""
50+
51+
def _shellcheck_toolchains_hub_impl(repository_ctx):
52+
toolchains = []
53+
for toolchain, arch in repository_ctx.attr.toolchains.items():
54+
toolchains.append(_TOOLCHAIN_ENTRY.format(
55+
arch = arch,
56+
constraints = repr(_CONSTRAINTS[arch]),
57+
toolchain = str(toolchain),
58+
))
59+
60+
repository_ctx.file("BUILD.bazel", _HUB_BUILD_CONTENT.format(
61+
toolchains = "\n".join(toolchains),
62+
))
63+
64+
repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
65+
repository_ctx.name,
66+
))
67+
68+
shellcheck_toolchains_hub = repository_rule(
69+
doc = "A repository rule for defining shellcheck toolchains",
70+
implementation = _shellcheck_toolchains_hub_impl,
71+
attrs = {
72+
"toolchains": attr.label_keyed_string_dict(
73+
doc = "A mapping of toolchain labels to platforms.",
74+
mandatory = True,
75+
),
76+
},
77+
)
878

979
def _urls(arch, version):
1080
archive_template_name = {
@@ -27,6 +97,48 @@ def _urls(arch, version):
2797
url,
2898
]
2999

100+
def create_shellcheck_repository_targets(name, shellcheck):
101+
"""A utility function for defining shellcheck repositories
102+
103+
Args:
104+
name (str): The name of the repository.
105+
shellcheck (str): THe path to the shellcheck binary.
106+
"""
107+
visibility = ["//visibility:public"]
108+
109+
native.exports_files(
110+
[shellcheck],
111+
visibility = visibility,
112+
)
113+
114+
native.alias(
115+
name = name,
116+
actual = shellcheck,
117+
visibility = visibility,
118+
)
119+
120+
if shellcheck.endswith(".exe"):
121+
native.alias(
122+
name = shellcheck[:-4],
123+
actual = shellcheck,
124+
visibility = visibility,
125+
)
126+
127+
shellcheck_toolchain(
128+
name = "toolchain",
129+
shellcheck = shellcheck,
130+
visibility = visibility,
131+
)
132+
133+
_SHELLCHECK_CONTENT = """\
134+
load("@rules_shellcheck//shellcheck/internal:extensions.bzl", "create_shellcheck_repository_targets")
135+
136+
create_shellcheck_repository_targets(
137+
name = "{name}",
138+
shellcheck = "{shellcheck}",
139+
)
140+
"""
141+
30142
def shellcheck_dependencies():
31143
"""Define shellcheck repositories"""
32144
version = "v0.11.0"
@@ -36,27 +148,40 @@ def shellcheck_dependencies():
36148
"linux_aarch64": "12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588",
37149
"linux_armv6hf": "8afc50b302d5feeac9381ea114d563f0150d061520042b254d6eb715797c8223",
38150
"linux_x86_64": "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198",
151+
"windows_x86_64": "8a4e35ab0b331c85d73567b12f2a444df187f483e5079ceffa6bda1faa2e740e",
39152
}
40153

154+
toolchains = {}
155+
41156
for arch, sha256 in sha256.items():
157+
name = "shellcheck_{arch}".format(arch = arch)
158+
159+
strip_prefix = "shellcheck-{version}".format(version = version)
160+
shellcheck_bin = "shellcheck"
161+
162+
# Special case, as it is a zip archive with no prefix to strip.
163+
if "windows" in arch:
164+
strip_prefix = None
165+
shellcheck_bin = "shellcheck.exe"
166+
42167
maybe(
43168
http_archive,
44-
name = "shellcheck_{arch}".format(arch = arch),
45-
strip_prefix = "shellcheck-{version}".format(version = version),
46-
build_file_content = """exports_files(["shellcheck"])
47-
""",
169+
name = name,
170+
strip_prefix = strip_prefix,
171+
build_file_content = _SHELLCHECK_CONTENT.format(
172+
name = name,
173+
shellcheck = shellcheck_bin,
174+
),
48175
sha256 = sha256,
49176
urls = _urls(arch = arch, version = version),
50177
)
51178

52-
# Special case, as it is a zip archive with no prefix to strip.
179+
toolchains["@{}//:toolchain".format(name)] = arch
180+
53181
maybe(
54-
http_archive,
55-
name = "shellcheck_windows_x86_64",
56-
build_file_content = """exports_files(["shellcheck"])
57-
""",
58-
sha256 = "8a4e35ab0b331c85d73567b12f2a444df187f483e5079ceffa6bda1faa2e740e",
59-
urls = _urls(arch = "windows_x86_64", version = version),
182+
shellcheck_toolchains_hub,
183+
name = "shellcheck_toolchains",
184+
toolchains = toolchains,
60185
)
61186

62187
def _impl(_):

0 commit comments

Comments
 (0)