Skip to content

Commit

Permalink
feat: new toolchain bzlmod extension (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
zaucy committed Apr 3, 2024
1 parent 5409246 commit f4ec81e
Show file tree
Hide file tree
Showing 8 changed files with 3,313 additions and 554 deletions.
5 changes: 3 additions & 2 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module(
)

bazel_dep(name = "rules_cc", version = "0.0.9")
bazel_dep(name = "bazel_skylib", version = "1.4.2")
bazel_dep(name = "platforms", version = "0.0.7")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "platforms", version = "0.0.9")
bazel_dep(name = "ecsact_cli", version = "0.3.1")

bazel_dep(name = "aspect_bazel_lib", version = "1.32.1", dev_dependency = True)
3,673 changes: 3,217 additions & 456 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions e2e/bzlmod-ecsact-sdk/.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ common --registry=https://raw.githubusercontent.com/ecsact-dev/bazel_registry/ma
common --registry=https://raw.githubusercontent.com/bazelboost/registry/main
common --registry=https://bcr.bazel.build

build --@boost.dll//:use_std_fs
query --@boost.dll//:use_std_fs
build --@boost.process//:use_std_fs
query --@boost.process//:use_std_fs

try-import %workspace%/../../.bazelrc.user
20 changes: 1 addition & 19 deletions e2e/bzlmod-ecsact-sdk/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@rules_ecsact//ecsact:defs.bzl", "ecsact_codegen")

ecsact_codegen(
name = "all_default_codegen_plugins",
output_directory = "codegen_outputs",
srcs = [
"example.ecsact",
"extras.ecsact",
],
plugins = [
"@ecsact_sdk//codegen_plugins:cpp_header",
# TODO(zaucy): Make other builtin plugins available
# "@ecsact_sdk//codegen_plugins:cpp_meta_header",
# "@ecsact_sdk//codegen_plugins:cpp_systems_header",
# "@ecsact_sdk//codegen_plugins:csharp",
# "@ecsact_sdk//codegen_plugins:systems_header",
],
)

build_test(
name = "build_test",
targets = [
":all_default_codegen_plugins",
"@ecsact_cli",
],
)
22 changes: 17 additions & 5 deletions e2e/bzlmod-ecsact-sdk/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
module(name = "rules_ecsact_e2e_bzlmod_ecsact_sdk")

bazel_dep(name = "bazel_skylib", version = "1.4.2")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "rules_ecsact")
bazel_dep(name = "boost.process", version = "1.83.0.bzl.2")
bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2")
bazel_dep(name = "ecsact_cli", version = "0.3.1")
bazel_dep(name = "toolchains_llvm", version = "1.0.0", dev_dependency = True)

local_path_override(
module_name = "rules_ecsact",
path = "../..",
)

ecsact = use_extension("@rules_ecsact//ecsact:extensions.bzl", "ecsact")
ecsact.sdk_toolchain(version = "0.6.2")
use_repo(ecsact, "ecsact_toolchains", "ecsact_sdk")
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True)
llvm.toolchain(llvm_version = "17.0.6")
use_repo(llvm, "llvm_toolchain")

register_toolchains("@ecsact_toolchains//:all")
ecsact = use_extension("@rules_ecsact//ecsact:extensions.bzl", "ecsact", dev_dependency = True)
ecsact.toolchain(use_ecsact_cli = True)
use_repo(ecsact, "ecsact_toolchain")

register_toolchains(
"@llvm_toolchain//:all",
"@ecsact_toolchain//:all",
dev_dependency = True,
)
134 changes: 65 additions & 69 deletions ecsact/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,98 +5,72 @@ package(default_visibility = ["//visibility:public"])
exports_files(glob["**/*"])
"""

_ECSACT_TOOLCHAINS_BUILD_FILE_CONTENTS = """
load("@rules_ecsact//ecsact:toolchain.bzl", "ecsact_toolchain")
package(default_visibility = ["//visibility:public"])
ecsact_toolchain(
name = "ecsact_sdk_system",
target_tool_path = "{ecsact_exe_path}",
)
toolchain(
name = "ecsact_sdk_system_toolchain",
toolchain = ":ecsact_sdk_system",
toolchain_type = "@rules_ecsact//ecsact:toolchain_type",
)
_ECSACT_TOOLCHAIN_SDK = """
# Ecsact toolchain from your locally installed SDK
# https://github.com/ecsact-dev/ecsact_sdk
ecsact_toolchain(name = "ecsact_sdk_system", target_tool_path = "{ecsact_exe_path}")
toolchain(name = "ecsact_sdk_system_toolchain", toolchain = ":ecsact_sdk_system", toolchain_type = "@rules_ecsact//ecsact:toolchain_type")
"""

_ECSACT_SDK_BUILD_FILE_CONTENTS = """
load("@rules_ecsact//ecsact:defs.bzl", "ecsact_codegen_plugin")
package(default_visibility = ["//visibility:public"])
ecsact_codegen_plugin(
name = "cpp_header",
output_extension = "hh",
plugin_path = "cpp_header",
)
_ECSACT_TOOLCHAIN_CLI = """
# Ecsact toolchain from the ecsact_cli bazel module
# https://github.com/ecsact-dev/ecsact_cli
ecsact_toolchain(name = "ecsact_cli", target_tool = "@ecsact_cli")
toolchain(name = "ecsact_cli_toolchain", toolchain = ":ecsact_cli", toolchain_type = "@rules_ecsact//ecsact:toolchain_type")
"""

def _ecsact_sdk_repository_impl(rctx):
rctx.file(
"BUILD.bazel",
executable = False,
content = "",
)
def _ecsact_toolchain_repository_impl(rctx):
# type: (repository_ctx) -> None

rctx.file(
"codegen_plugins/BUILD.bazel",
executable = False,
content = _ECSACT_SDK_BUILD_FILE_CONTENTS,
)
build_file_contents = 'load("@rules_ecsact//ecsact:toolchain.bzl", "ecsact_toolchain")\n'
build_file_contents += 'package(default_visibility = ["//visibility:public"])\n\n'

_ecsact_sdk_repository = repository_rule(
implementation = _ecsact_sdk_repository_impl,
attrs = {
},
)
if rctx.attr.ecsact_system_sdk_exe:
build_file_contents += _ECSACT_TOOLCHAIN_SDK.format(
ecsact_exe_path = rctx.attr.ecsact_system_sdk_exe.replace("\\", "/"),
)

if rctx.attr.use_ecsact_cli:
build_file_contents += _ECSACT_TOOLCHAIN_CLI

def _ecsact_toolchains_repository_impl(rctx):
rctx.file(
"BUILD.bazel",
executable = False,
content = _ECSACT_TOOLCHAINS_BUILD_FILE_CONTENTS.format(
ecsact_exe_path = rctx.attr.ecsact_exe.replace("\\", "/"),
),
content = build_file_contents,
)

_ecsact_toolchains_repository = repository_rule(
implementation = _ecsact_toolchains_repository_impl,
_ecsact_toolchain_repository = repository_rule(
implementation = _ecsact_toolchain_repository_impl,
attrs = {
"ecsact_exe": attr.string(mandatory = True),
"ecsact_system_sdk_exe": attr.string(mandatory = False),
"use_ecsact_cli": attr.bool(mandatory = True),
},
)

def _windows_find_ecsact_from_app_installer(ctx):
def _windows_find_ecsact_from_app_installer(mctx):
# type: (module_ctx) -> path

# ctx.which doesn't work for everything available on Windows. Using cmd's
# built-in 'where' command can find programs installed from the Microsoft
# store or MSIX packages.
cmd = ctx.which("cmd.exe")
cmd = mctx.which("cmd.exe")
if cmd:
where_result = ctx.execute([cmd, "/C", "where ecsact.exe"])
where_result = mctx.execute([cmd, "/C", "where ecsact.exe"])
if where_result.stdout:
return ctx.path(where_result.stdout.strip())
return mctx.path(where_result.stdout.strip())

return None

def _ecsact_impl(mctx):
wanted_ecsact_version = None

for mod in mctx.modules:
for sdk_toolchain in mod.tags.sdk_toolchain:
if wanted_ecsact_version != None:
fail("ecsact extension sdk_toolchain called multiple times. Please only call it once.")
wanted_ecsact_version = sdk_toolchain.version
def _get_escact_system_sdk(mctx, wanted_ecsact_version = None):
# type: (module_ctx, string) -> string

ecsact_exe = mctx.which("ecsact")

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

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

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

_ecsact_sdk_repository(
name = "ecsact_sdk",
)
_ecsact_toolchains_repository(
name = "ecsact_toolchains",
ecsact_exe = str(ecsact_exe),
return ecsact_exe

def _ecsact_impl(mctx):
# type: (module_ctx) -> None

wanted_ecsact_version = None
use_ecsact_cli = False

for mod in mctx.modules:
for toolchain in mod.tags.toolchain:
if toolchain.use_ecsact_cli:
use_ecsact_cli = True

if toolchain.version:
if wanted_ecsact_version != None:
fail("ecsact extension toolchain called multiple times. Please only call it once.")
wanted_ecsact_version = toolchain.version

ecsact_exe = _get_escact_system_sdk(mctx, wanted_ecsact_version)

if ecsact_exe != None:
ecsact_exe = str(ecsact_exe)

_ecsact_toolchain_repository(
name = "ecsact_toolchain",
ecsact_system_sdk_exe = ecsact_exe,
use_ecsact_cli = use_ecsact_cli,
)

ecsact = module_extension(
implementation = _ecsact_impl,
tag_classes = {
"sdk_toolchain": tag_class(attrs = {
"version": attr.string(mandatory = True),
"toolchain": tag_class(attrs = {
"use_ecsact_cli": attr.bool(mandatory = False, default = False),
"version": attr.string(mandatory = False),
}),
},
)
2 changes: 1 addition & 1 deletion ecsact/private/ecsact_binary.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain")
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain")
load("//ecsact/private:ecsact_build_recipe.bzl", "EcsactBuildRecipeInfo")

def _ecsact_binary_impl(ctx):
Expand Down
6 changes: 4 additions & 2 deletions ecsact/private/ecsact_build_recipe.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ EcsactBuildRecipeInfo = provider(
)

def _ecsact_build_recipe(ctx):
# type: (ctx) -> None

recipe_yaml = ctx.actions.declare_file("{}.yml".format(ctx.attr.name))

sources = []
Expand All @@ -17,15 +19,15 @@ def _ecsact_build_recipe(ctx):
for src in ctx.files.srcs:
sources.append({
"path": src.path,
"outdir": "src",
"outdir": src.dirname,
"relative_to_cwd": True,
})
recipe_data.append(src)

for codegen_plugin in ctx.attr.codegen_plugins:
info = codegen_plugin[EcsactCodegenPluginInfo]
sources.append({
"codegen": [info.plugin],
"codegen": info.plugin.path,
"outdir": ctx.attr.codegen_plugins[codegen_plugin],
})
recipe_data.append(info.plugin)
Expand Down

0 comments on commit f4ec81e

Please # to comment.