bazel: mkosi toolchain

Co-authored-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>
This commit is contained in:
Malte Poll 2023-09-06 15:31:41 +02:00 committed by Malte Poll
parent 347659e2b0
commit 5323c2d870
5 changed files with 203 additions and 0 deletions

View File

@ -18,6 +18,10 @@ nixpkgs_flake_package(
package = "mkosi",
)
load("//bazel/mkosi:mkosi_configure.bzl", "find_system_mkosi")
find_system_mkosi(name="constellation_mkosi")
# Python toolchain
load("//bazel/toolchains:python_deps.bzl", "python_deps")

70
bazel/mkosi/BUILD.bazel Normal file
View File

@ -0,0 +1,70 @@
"""toolchain to wrap an mkosi binary.
Type: @constellation//bazel/mkosi:toolchain_type
Toolchains:
- mkosi_missing_toolchain: provides a fallback toolchain for exec platforms
where mkosi might not be available.
- mkosi_auto_toolchain: a toolchain that uses the installed mkosi. See
mkosi_configure.bzl%find_system_mkosi for usage.
"""
load(":toolchain.bzl", "is_mkosi_available", "mkosi_make_variables", "mkosi_toolchain")
# Expose the availability of an actual mkosi as a config_setting, so we can
# select() on it.
config_setting(
name = "have_mkosi",
flag_values = {
":is_mkosi_available": "1",
},
visibility = ["//visibility:public"],
)
# Expose the availability of an actual mkosi as a feature flag, so we can
# create a config_setting from it.
is_mkosi_available(
name = "is_mkosi_available",
visibility = ["//:__subpackages__"],
)
toolchain_type(
name = "toolchain_type",
visibility = ["//visibility:public"],
)
mkosi_make_variables(
name = "make_variables",
visibility = ["//visibility:public"],
)
# mkosi_missing_toolchain provides a fallback toolchain so that toolchain
# resolution can succeed even on platforms that do not have a working mkosi.
# If this toolchain is selected, the constraint ":have_mkosi" will not be
# satistifed.
mkosi_toolchain(
name = "no_mkosi",
)
toolchain(
name = "mkosi_missing_toolchain",
toolchain = ":no_mkosi",
toolchain_type = ":toolchain_type",
)
mkosi_toolchain(
name = "nix_mkosi",
label = "@mkosi//:bin/mkosi",
)
toolchain(
name = "mkosi_nix_toolchain",
exec_compatible_with = [
"@rules_nixpkgs_core//constraints:support_nix",
],
toolchain = ":nix_mkosi",
toolchain_type = "@constellation//bazel/mkosi:toolchain_type",
)
exports_files(["mkosi_wrapper.sh.in"])

13
bazel/mkosi/BUILD.tpl Normal file
View File

@ -0,0 +1,13 @@
# This content is generated by {GENERATOR}
load("@constellation//bazel/mkosi:toolchain.bzl", "mkosi_toolchain")
mkosi_toolchain(
name = "mkosi_auto",
path = "{MKOSI_PATH}",
)
toolchain(
name = "mkosi_auto_toolchain",
toolchain = ":mkosi_auto",
toolchain_type = "@constellation//bazel/mkosi:toolchain_type",
)

View File

@ -0,0 +1,43 @@
"""Repository rule to autoconfigure a toolchain using the system mkosi."""
def _write_build(rctx, path):
if not path:
path = ""
rctx.template(
"BUILD",
Label("//bazel/mkosi:BUILD.tpl"),
substitutions = {
"{GENERATOR}": "@constellation//bazel/mkosi/mkosi_configure.bzl%find_system_mkosi",
"{MKOSI_PATH}": str(path),
},
executable = False,
)
def _find_system_mkosi_impl(rctx):
mkosi_path = rctx.which("mkosi")
if rctx.attr.verbose:
if mkosi_path:
print("Found mkosi at '%s'" % mkosi_path) # buildifier: disable=print
else:
print("No system mkosi found.") # buildifier: disable=print
_write_build(rctx = rctx, path = mkosi_path)
_find_system_mkosi = repository_rule(
implementation = _find_system_mkosi_impl,
doc = """Create a repository that defines an mkosi toolchain based on the system mkosi.""",
local = True,
environ = ["PATH"],
attrs = {
"verbose": attr.bool(
doc = "If true, print status messages.",
),
},
)
def find_system_mkosi(name, verbose = False):
_find_system_mkosi(name = name, verbose = verbose)
native.register_toolchains(
"@constellation//bazel/mkosi:mkosi_nix_toolchain",
"@%s//:mkosi_auto_toolchain" % name,
"@constellation//bazel/mkosi:mkosi_missing_toolchain",
)

73
bazel/mkosi/toolchain.bzl Normal file
View File

@ -0,0 +1,73 @@
"""toolchain to provide an mkosi binary."""
TOOLCHAIN_TYPE = "@constellation//bazel/mkosi:toolchain_type"
MAKE_VARIABLES = "@constellation//bazel/mkosi:make_variables"
MkosiInfo = provider(
doc = """Information needed to invoke mkosi.""",
fields = {
"label": "Label of a target providing a mkosi binary",
"name": "The name of the toolchain",
"path": "Path to the mkosi binary",
"valid": "Is this toolchain valid and usable?",
},
)
def _mkosi_toolchain_impl(ctx):
if ctx.attr.label and ctx.attr.path:
fail("mkosi_toolchain: label and path are mutually exclusive")
valid = bool(ctx.attr.label) or bool(ctx.attr.path)
mkosi_info = MkosiInfo(
name = str(ctx.label),
valid = valid,
label = ctx.attr.label,
path = ctx.attr.path,
)
toolchain_info = platform_common.ToolchainInfo(
mkosi = mkosi_info,
)
return [toolchain_info]
mkosi_toolchain = rule(
implementation = _mkosi_toolchain_impl,
attrs = {
"label": attr.label(
doc = "Label of a target providing a mkosi binary. Mutually exclusive with path.",
executable = True,
cfg = "exec",
allow_single_file = True,
default = None,
),
"path": attr.string(
doc = "Path to the mkosi binary. Mutually exclusive with label.",
),
},
)
def _mkosi_make_variables_impl(ctx):
info = ctx.toolchains[TOOLCHAIN_TYPE].mkosi
variables = {}
if info.valid:
binary_path = info.label[DefaultInfo].files_to_run.executable.path if info.label else info.path
variables["MKOSI"] = binary_path
return [platform_common.TemplateVariableInfo(variables)]
mkosi_make_variables = rule(
doc = "Make variables for mkosi.",
implementation = _mkosi_make_variables_impl,
toolchains = [TOOLCHAIN_TYPE],
)
def _is_mkosi_available_impl(ctx):
toolchain = ctx.toolchains[TOOLCHAIN_TYPE]
available = toolchain and toolchain.mkosi.valid
return [config_common.FeatureFlagInfo(
value = ("1" if available else "0"),
)]
is_mkosi_available = rule(
implementation = _is_mkosi_available_impl,
attrs = {},
toolchains = [TOOLCHAIN_TYPE],
)