Skip to content

Commit f4ec81e

Browse files
authored
feat: new toolchain bzlmod extension (#43)
1 parent 5409246 commit f4ec81e

File tree

8 files changed

+3313
-554
lines changed

8 files changed

+3313
-554
lines changed

MODULE.bazel

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module(
55
)
66

77
bazel_dep(name = "rules_cc", version = "0.0.9")
8-
bazel_dep(name = "bazel_skylib", version = "1.4.2")
9-
bazel_dep(name = "platforms", version = "0.0.7")
8+
bazel_dep(name = "bazel_skylib", version = "1.5.0")
9+
bazel_dep(name = "platforms", version = "0.0.9")
10+
bazel_dep(name = "ecsact_cli", version = "0.3.1")
1011

1112
bazel_dep(name = "aspect_bazel_lib", version = "1.32.1", dev_dependency = True)

MODULE.bazel.lock

Lines changed: 3217 additions & 456 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/bzlmod-ecsact-sdk/.bazelrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ common --registry=https://raw.githubusercontent.com/ecsact-dev/bazel_registry/ma
33
common --registry=https://raw.githubusercontent.com/bazelboost/registry/main
44
common --registry=https://bcr.bazel.build
55

6+
build --@boost.dll//:use_std_fs
7+
query --@boost.dll//:use_std_fs
8+
build --@boost.process//:use_std_fs
9+
query --@boost.process//:use_std_fs
10+
611
try-import %workspace%/../../.bazelrc.user

e2e/bzlmod-ecsact-sdk/BUILD.bazel

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,8 @@
11
load("@bazel_skylib//rules:build_test.bzl", "build_test")
2-
load("@rules_ecsact//ecsact:defs.bzl", "ecsact_codegen")
3-
4-
ecsact_codegen(
5-
name = "all_default_codegen_plugins",
6-
output_directory = "codegen_outputs",
7-
srcs = [
8-
"example.ecsact",
9-
"extras.ecsact",
10-
],
11-
plugins = [
12-
"@ecsact_sdk//codegen_plugins:cpp_header",
13-
# TODO(zaucy): Make other builtin plugins available
14-
# "@ecsact_sdk//codegen_plugins:cpp_meta_header",
15-
# "@ecsact_sdk//codegen_plugins:cpp_systems_header",
16-
# "@ecsact_sdk//codegen_plugins:csharp",
17-
# "@ecsact_sdk//codegen_plugins:systems_header",
18-
],
19-
)
202

213
build_test(
224
name = "build_test",
235
targets = [
24-
":all_default_codegen_plugins",
6+
"@ecsact_cli",
257
],
268
)

e2e/bzlmod-ecsact-sdk/MODULE.bazel

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
module(name = "rules_ecsact_e2e_bzlmod_ecsact_sdk")
22

3-
bazel_dep(name = "bazel_skylib", version = "1.4.2")
3+
bazel_dep(name = "bazel_skylib", version = "1.5.0")
44
bazel_dep(name = "rules_ecsact")
5+
bazel_dep(name = "boost.process", version = "1.83.0.bzl.2")
6+
bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2")
7+
bazel_dep(name = "ecsact_cli", version = "0.3.1")
8+
bazel_dep(name = "toolchains_llvm", version = "1.0.0", dev_dependency = True)
59

610
local_path_override(
711
module_name = "rules_ecsact",
812
path = "../..",
913
)
1014

11-
ecsact = use_extension("@rules_ecsact//ecsact:extensions.bzl", "ecsact")
12-
ecsact.sdk_toolchain(version = "0.6.2")
13-
use_repo(ecsact, "ecsact_toolchains", "ecsact_sdk")
15+
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True)
16+
llvm.toolchain(llvm_version = "17.0.6")
17+
use_repo(llvm, "llvm_toolchain")
1418

15-
register_toolchains("@ecsact_toolchains//:all")
19+
ecsact = use_extension("@rules_ecsact//ecsact:extensions.bzl", "ecsact", dev_dependency = True)
20+
ecsact.toolchain(use_ecsact_cli = True)
21+
use_repo(ecsact, "ecsact_toolchain")
22+
23+
register_toolchains(
24+
"@llvm_toolchain//:all",
25+
"@ecsact_toolchain//:all",
26+
dev_dependency = True,
27+
)

ecsact/extensions.bzl

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,98 +5,72 @@ package(default_visibility = ["//visibility:public"])
55
exports_files(glob["**/*"])
66
"""
77

8-
_ECSACT_TOOLCHAINS_BUILD_FILE_CONTENTS = """
9-
load("@rules_ecsact//ecsact:toolchain.bzl", "ecsact_toolchain")
10-
11-
package(default_visibility = ["//visibility:public"])
12-
13-
ecsact_toolchain(
14-
name = "ecsact_sdk_system",
15-
target_tool_path = "{ecsact_exe_path}",
16-
)
17-
18-
toolchain(
19-
name = "ecsact_sdk_system_toolchain",
20-
toolchain = ":ecsact_sdk_system",
21-
toolchain_type = "@rules_ecsact//ecsact:toolchain_type",
22-
)
8+
_ECSACT_TOOLCHAIN_SDK = """
9+
# Ecsact toolchain from your locally installed SDK
10+
# https://github.com/ecsact-dev/ecsact_sdk
11+
ecsact_toolchain(name = "ecsact_sdk_system", target_tool_path = "{ecsact_exe_path}")
12+
toolchain(name = "ecsact_sdk_system_toolchain", toolchain = ":ecsact_sdk_system", toolchain_type = "@rules_ecsact//ecsact:toolchain_type")
2313
"""
2414

25-
_ECSACT_SDK_BUILD_FILE_CONTENTS = """
26-
load("@rules_ecsact//ecsact:defs.bzl", "ecsact_codegen_plugin")
27-
28-
package(default_visibility = ["//visibility:public"])
29-
30-
ecsact_codegen_plugin(
31-
name = "cpp_header",
32-
output_extension = "hh",
33-
plugin_path = "cpp_header",
34-
)
15+
_ECSACT_TOOLCHAIN_CLI = """
16+
# Ecsact toolchain from the ecsact_cli bazel module
17+
# https://github.com/ecsact-dev/ecsact_cli
18+
ecsact_toolchain(name = "ecsact_cli", target_tool = "@ecsact_cli")
19+
toolchain(name = "ecsact_cli_toolchain", toolchain = ":ecsact_cli", toolchain_type = "@rules_ecsact//ecsact:toolchain_type")
3520
"""
3621

37-
def _ecsact_sdk_repository_impl(rctx):
38-
rctx.file(
39-
"BUILD.bazel",
40-
executable = False,
41-
content = "",
42-
)
22+
def _ecsact_toolchain_repository_impl(rctx):
23+
# type: (repository_ctx) -> None
4324

44-
rctx.file(
45-
"codegen_plugins/BUILD.bazel",
46-
executable = False,
47-
content = _ECSACT_SDK_BUILD_FILE_CONTENTS,
48-
)
25+
build_file_contents = 'load("@rules_ecsact//ecsact:toolchain.bzl", "ecsact_toolchain")\n'
26+
build_file_contents += 'package(default_visibility = ["//visibility:public"])\n\n'
4927

50-
_ecsact_sdk_repository = repository_rule(
51-
implementation = _ecsact_sdk_repository_impl,
52-
attrs = {
53-
},
54-
)
28+
if rctx.attr.ecsact_system_sdk_exe:
29+
build_file_contents += _ECSACT_TOOLCHAIN_SDK.format(
30+
ecsact_exe_path = rctx.attr.ecsact_system_sdk_exe.replace("\\", "/"),
31+
)
32+
33+
if rctx.attr.use_ecsact_cli:
34+
build_file_contents += _ECSACT_TOOLCHAIN_CLI
5535

56-
def _ecsact_toolchains_repository_impl(rctx):
5736
rctx.file(
5837
"BUILD.bazel",
5938
executable = False,
60-
content = _ECSACT_TOOLCHAINS_BUILD_FILE_CONTENTS.format(
61-
ecsact_exe_path = rctx.attr.ecsact_exe.replace("\\", "/"),
62-
),
39+
content = build_file_contents,
6340
)
6441

65-
_ecsact_toolchains_repository = repository_rule(
66-
implementation = _ecsact_toolchains_repository_impl,
42+
_ecsact_toolchain_repository = repository_rule(
43+
implementation = _ecsact_toolchain_repository_impl,
6744
attrs = {
68-
"ecsact_exe": attr.string(mandatory = True),
45+
"ecsact_system_sdk_exe": attr.string(mandatory = False),
46+
"use_ecsact_cli": attr.bool(mandatory = True),
6947
},
7048
)
7149

72-
def _windows_find_ecsact_from_app_installer(ctx):
50+
def _windows_find_ecsact_from_app_installer(mctx):
51+
# type: (module_ctx) -> path
52+
7353
# ctx.which doesn't work for everything available on Windows. Using cmd's
7454
# built-in 'where' command can find programs installed from the Microsoft
7555
# store or MSIX packages.
76-
cmd = ctx.which("cmd.exe")
56+
cmd = mctx.which("cmd.exe")
7757
if cmd:
78-
where_result = ctx.execute([cmd, "/C", "where ecsact.exe"])
58+
where_result = mctx.execute([cmd, "/C", "where ecsact.exe"])
7959
if where_result.stdout:
80-
return ctx.path(where_result.stdout.strip())
60+
return mctx.path(where_result.stdout.strip())
8161

8262
return None
8363

84-
def _ecsact_impl(mctx):
85-
wanted_ecsact_version = None
86-
87-
for mod in mctx.modules:
88-
for sdk_toolchain in mod.tags.sdk_toolchain:
89-
if wanted_ecsact_version != None:
90-
fail("ecsact extension sdk_toolchain called multiple times. Please only call it once.")
91-
wanted_ecsact_version = sdk_toolchain.version
64+
def _get_escact_system_sdk(mctx, wanted_ecsact_version = None):
65+
# type: (module_ctx, string) -> string
9266

9367
ecsact_exe = mctx.which("ecsact")
9468

9569
if ecsact_exe == None and mctx.os.name.startswith("windows"):
9670
ecsact_exe = _windows_find_ecsact_from_app_installer(mctx)
9771

9872
if ecsact_exe == None:
99-
fail("Cannot find the Ecsact SDK installed on your system. See https://ecsact.dev/start for instructions.")
73+
return None
10074

10175
ecsact_version_output = mctx.execute([ecsact_exe, "--version"])
10276
if ecsact_version_output.return_code != 0:
@@ -113,19 +87,41 @@ def _ecsact_impl(mctx):
11387
if found_ecsact_version != wanted_ecsact_version and found_ecsact_version != "refs/tags/{}".format(wanted_ecsact_version):
11488
fail("Wanted Ecsact SDK {}, but {} is installed on your system".format(wanted_ecsact_version, found_ecsact_version))
11589

116-
_ecsact_sdk_repository(
117-
name = "ecsact_sdk",
118-
)
119-
_ecsact_toolchains_repository(
120-
name = "ecsact_toolchains",
121-
ecsact_exe = str(ecsact_exe),
90+
return ecsact_exe
91+
92+
def _ecsact_impl(mctx):
93+
# type: (module_ctx) -> None
94+
95+
wanted_ecsact_version = None
96+
use_ecsact_cli = False
97+
98+
for mod in mctx.modules:
99+
for toolchain in mod.tags.toolchain:
100+
if toolchain.use_ecsact_cli:
101+
use_ecsact_cli = True
102+
103+
if toolchain.version:
104+
if wanted_ecsact_version != None:
105+
fail("ecsact extension toolchain called multiple times. Please only call it once.")
106+
wanted_ecsact_version = toolchain.version
107+
108+
ecsact_exe = _get_escact_system_sdk(mctx, wanted_ecsact_version)
109+
110+
if ecsact_exe != None:
111+
ecsact_exe = str(ecsact_exe)
112+
113+
_ecsact_toolchain_repository(
114+
name = "ecsact_toolchain",
115+
ecsact_system_sdk_exe = ecsact_exe,
116+
use_ecsact_cli = use_ecsact_cli,
122117
)
123118

124119
ecsact = module_extension(
125120
implementation = _ecsact_impl,
126121
tag_classes = {
127-
"sdk_toolchain": tag_class(attrs = {
128-
"version": attr.string(mandatory = True),
122+
"toolchain": tag_class(attrs = {
123+
"use_ecsact_cli": attr.bool(mandatory = False, default = False),
124+
"version": attr.string(mandatory = False),
129125
}),
130126
},
131127
)

ecsact/private/ecsact_binary.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain")
21
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
2+
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain")
33
load("//ecsact/private:ecsact_build_recipe.bzl", "EcsactBuildRecipeInfo")
44

55
def _ecsact_binary_impl(ctx):

ecsact/private/ecsact_build_recipe.bzl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ EcsactBuildRecipeInfo = provider(
99
)
1010

1111
def _ecsact_build_recipe(ctx):
12+
# type: (ctx) -> None
13+
1214
recipe_yaml = ctx.actions.declare_file("{}.yml".format(ctx.attr.name))
1315

1416
sources = []
@@ -17,15 +19,15 @@ def _ecsact_build_recipe(ctx):
1719
for src in ctx.files.srcs:
1820
sources.append({
1921
"path": src.path,
20-
"outdir": "src",
22+
"outdir": src.dirname,
2123
"relative_to_cwd": True,
2224
})
2325
recipe_data.append(src)
2426

2527
for codegen_plugin in ctx.attr.codegen_plugins:
2628
info = codegen_plugin[EcsactCodegenPluginInfo]
2729
sources.append({
28-
"codegen": [info.plugin],
30+
"codegen": info.plugin.path,
2931
"outdir": ctx.attr.codegen_plugins[codegen_plugin],
3032
})
3133
recipe_data.append(info.plugin)

0 commit comments

Comments
 (0)