Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add module extension for nodejs toolchain #505

Merged
merged 14 commits into from
Apr 30, 2024
Merged
14 changes: 4 additions & 10 deletions testing/nodejs/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,16 @@ bazel_dep(name = "bazel_skylib", version = "1.0.3")
bazel_dep(name = "rules_cc", version = "0.0.4")
bazel_dep(name = "rules_nodejs", version = "5.5.3")

nix_repo = use_extension("@rules_nixpkgs_core//extensions:repository.bzl", "nix_repo")
nix_repo.default(name = "nixpkgs")
use_repo(nix_repo, "nixpkgs")

# TODO[AH] Remove these transitive dependencies once nixpkgs_java_configure has
# become a module extension in rules_nixpkgs_java.
bazel_dep(name = "platforms", version = "0.0.4")
bazel_dep(name = "rules_java", version = "6.5.2")

non_module_deps = use_extension("//:non_module_deps.bzl", "non_module_deps")
use_repo(non_module_deps, "nixpkgs")
[
(
use_repo(non_module_deps, "nixpkgs_nodejs_{}_{}_toolchain".format(os, arch)),
register_toolchains("@nixpkgs_nodejs_{}_{}_toolchain//:all".format(os, arch)),
)
for os in ["linux", "darwin"]
for arch in ["amd64", "arm64"]
]

use_repo(non_module_deps, "nixpkgs_config_cc")
use_repo(non_module_deps, "nixpkgs_config_cc_info")
use_repo(non_module_deps, "nixpkgs_config_cc_toolchains")
Expand Down
23 changes: 12 additions & 11 deletions testing/nodejs/tests/nixpkgs_repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ load("@rules_nixpkgs_java//:java.bzl", "nixpkgs_java_configure")
load("@rules_nixpkgs_nodejs//:nodejs.bzl", "nixpkgs_nodejs_configure_platforms")

def nixpkgs_repositories(*, bzlmod):
nixpkgs_local_repository(
name = "nixpkgs",
nix_file = "//:nixpkgs.nix",
nix_file_deps = ["//:flake.lock"],
)
if not bzlmod:
nixpkgs_local_repository(
name = "nixpkgs",
nix_file = "//:nixpkgs.nix",
nix_file_deps = ["//:flake.lock"],
)

nixpkgs_nodejs_configure_platforms(
name = "nixpkgs_nodejs",
repository = "@nixpkgs",
register = not bzlmod,
)

nixpkgs_cc_configure(
name = "nixpkgs_config_cc",
Expand All @@ -25,9 +32,3 @@ def nixpkgs_repositories(*, bzlmod):
toolchain_name = "nixpkgs_java",
toolchain_version = "11",
)

nixpkgs_nodejs_configure_platforms(
name = "nixpkgs_nodejs",
repository = "@nixpkgs",
register = not bzlmod,
)
6 changes: 5 additions & 1 deletion toolchains/nodejs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ package(default_visibility = ["//visibility:public"])

filegroup(
name = "srcs",
srcs = glob(["**"]),
srcs = glob(["**"]) + [
"//extensions:srcs",
"//private:srcs",
],
visibility = ["//visibility:public"],
)

Expand All @@ -14,5 +17,6 @@ bzl_library(
deps = [
"@rules_nixpkgs_core//:nixpkgs",
"@rules_nodejs//nodejs:bzl",
"//private:common",
],
)
9 changes: 9 additions & 0 deletions toolchains/nodejs/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,14 @@ module(
)

bazel_dep(name = "rules_nixpkgs_core", version = "0.11.1")
bazel_dep(name = "platforms", version = "0.0.4")
bazel_dep(name = "rules_nodejs", version = "5.5.3")
bazel_dep(name = "bazel_skylib", version = "1.0.3")

nix_repo = use_extension("@rules_nixpkgs_core//extensions:repository.bzl", "nix_repo")
nix_repo.default(name = "nixpkgs")
use_repo(nix_repo, "nixpkgs")

nix_nodejs = use_extension("//extensions:toolchain.bzl", "nix_nodejs")
use_repo(nix_nodejs, "nixpkgs_nodejs_toolchains")
register_toolchains("@nixpkgs_nodejs_toolchains//:all")
13 changes: 13 additions & 0 deletions toolchains/nodejs/extensions/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")

filegroup(
name = "srcs",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)

bzl_library(
name = "toolchain",
srcs = ["toolchain.bzl"],
visibility = ["//:__pkg__"],
)
120 changes: 120 additions & 0 deletions toolchains/nodejs/extensions/toolchain.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
"""Defines the nix_nodejs module extension.
"""

load(
"//private:common.bzl",
"DEFAULT_PLATFORMS_MAPPING",
"nixpkgs_nodejs",
"nodejs_toolchain",
)

_DEFAULT_NIXPKGS = "@nixpkgs"
_DEFAULT_ATTR = "nodejs"

_TOOLCHAINS_REPO = "nixpkgs_nodejs_toolchains"
_NODEJS_REPO = "nixpkgs_nodejs_{platform}"
_NODEJS_LABEL = "@{repo}//:nodejs_nix_impl"

def _nodejs_label(repo_name):
return _NODEJS_LABEL.format(repo = repo_name)

def _toolchain_name(*, name, count, prefix_digits):
prefix = str(count)
prefix = "0" * (prefix_digits - len(prefix)) + prefix
return prefix + "-" + name

def _toolchains_repo_impl(repository_ctx):
num_toolchains = len(repository_ctx.attr.labels)
prefix_digits = len(str(num_toolchains))

sequence = zip(
repository_ctx.attr.names,
repository_ctx.attr.labels,
repository_ctx.attr.exec_lengths,
repository_ctx.attr.target_lengths,
)

exec_offset = 0
target_offset = 0
builder = []

for count, (name, label, exec_length, target_length) in enumerate(sequence, start = 1):
name = _toolchain_name(
name = name,
count = count,
prefix_digits = prefix_digits,
)
exec_end = exec_offset + exec_length
exec_constraints = repository_ctx.attr.exec_constraints[exec_offset:exec_end]
exec_offset = exec_end
target_end = target_offset + target_length
target_constraints = repository_ctx.attr.target_constraints[target_offset:target_end]
target_offset = target_end
builder.append(nodejs_toolchain(
name = name,
label = label,
exec_constraints = exec_constraints,
target_constraints = target_constraints,
))

repository_ctx.file(
"BUILD.bazel",
content = "\n".join(builder),
executable = False,
)

_toolchains_repo = repository_rule(
_toolchains_repo_impl,
attrs = {
"names": attr.string_list(),
"labels": attr.string_list(),
"exec_constraints": attr.string_list(),
"exec_lengths": attr.int_list(),
"target_constraints": attr.string_list(),
"target_lengths": attr.int_list(),
},
)

def _nix_nodejs_impl(module_ctx):
toolchain_names = []
toolchain_labels = []
toolchain_exec_constraints = []
toolchain_exec_lengths = []
toolchain_target_constraints = []
toolchain_target_lengths = []

for nix_platform, bazel_platform in DEFAULT_PLATFORMS_MAPPING.items():
name = bazel_platform.rules_nodejs_platform
repo_name = _NODEJS_REPO.format(platform = bazel_platform.rules_nodejs_platform)
exec_constraints = [str(Label(c)) for c in bazel_platform.exec_constraints]
target_constraints = [str(Label(c)) for c in bazel_platform.target_constraints]

nixpkgs_nodejs(
name = repo_name,
nix_platform = nix_platform,
attribute_path = _DEFAULT_ATTR,
repository = _DEFAULT_NIXPKGS,
)

toolchain_names.append(name)
toolchain_labels.append(_nodejs_label(repo_name))
toolchain_exec_constraints.extend(exec_constraints)
toolchain_exec_lengths.append(len(exec_constraints))
toolchain_target_constraints.extend(target_constraints)
toolchain_target_lengths.append(len(target_constraints))

_toolchains_repo(
name = _TOOLCHAINS_REPO,
names = toolchain_names,
labels = toolchain_labels,
exec_constraints = toolchain_exec_constraints,
exec_lengths = toolchain_exec_lengths,
target_constraints = toolchain_target_constraints,
target_lengths = toolchain_target_lengths,
)

nix_nodejs = module_extension(
_nix_nodejs_impl,
tag_classes = {
},
)
82 changes: 11 additions & 71 deletions toolchains/nodejs/nodejs.bzl
Original file line number Diff line number Diff line change
@@ -1,74 +1,20 @@
load("@rules_nixpkgs_core//:nixpkgs.bzl", "nixpkgs_package")
load("@rules_nixpkgs_core//:util.bzl", "ensure_constraints")
load("@rules_nodejs//nodejs/private:toolchains_repo.bzl", "PLATFORMS")


def _mk_mapping(rules_nodejs_platform_name):
constraints = PLATFORMS[rules_nodejs_platform_name].compatible_with
return struct(
rules_nodejs_platform = rules_nodejs_platform_name,
exec_constraints = constraints,
target_constraints = constraints,
)

# obtained (and matched) from:
# nixpkgs search: https://search.nixos.org/packages?channel=22.11&show=nodejs&from=0&size=50&sort=relevance&type=packages&query=nodejs
# rules_nodejs: https://github.com/bazelbuild/rules_nodejs/blob/a5755eb458c2dd8e0e2cf9b92d8304d9e77ea117/nodejs/private/toolchains_repo.bzl#L20
DEFAULT_PLATFORMS_MAPPING = {
"aarch64-darwin": _mk_mapping("darwin_arm64"),
"x86_64-linux": _mk_mapping("linux_amd64"),
"x86_64-darwin": _mk_mapping("darwin_amd64"),
"aarch64-linux": _mk_mapping("linux_arm64"),
}

_nodejs_nix_content = """\
let
pkgs = import <nixpkgs> {{ config = {{}}; overlays = []; system = {nix_platform}; }};
nodejs = pkgs.{attribute_path};
in
pkgs.buildEnv {{
extraOutputsToInstall = ["out" "bin" "lib"];
name = "bazel-nodejs-toolchain";
paths = [ nodejs ];
postBuild = ''
touch $out/ROOT
cat <<EOF > $out/BUILD

filegroup(
name = "nodejs",
srcs = ["bin/node"],
visibility = ["//visibility:public"],
)

load("@rules_nodejs//nodejs:toolchain.bzl", "node_toolchain")
node_toolchain(
name = "nodejs_nix_impl",
target_tool = ":nodejs",
visibility = ["//visibility:public"],
)

EOF
'';
}}
"""

_nodejs_nix_toolchain = """
toolchain(
name = "nodejs_nix",
toolchain = "@{toolchain_repo}//:nodejs_nix_impl",
toolchain_type = "@rules_nodejs//nodejs:toolchain_type",
exec_compatible_with = {exec_constraints},
target_compatible_with = {target_constraints},
load(
"//private:common.bzl",
"DEFAULT_PLATFORMS_MAPPING",
"nixpkgs_nodejs",
"nodejs_toolchain",
)
"""

def _nixpkgs_nodejs_toolchain_impl(repository_ctx):
exec_constraints, target_constraints = ensure_constraints(repository_ctx)
repository_ctx.file(
"BUILD.bazel",
executable = False,
content = _nodejs_nix_toolchain.format(
toolchain_repo = repository_ctx.attr.toolchain_repo,
content = nodejs_toolchain(
name = "nodejs_nix",
label = "@{}//:nodejs_nix_impl".format(repository_ctx.attr.toolchain_repo),
exec_constraints = exec_constraints,
target_constraints = target_constraints,
),
Expand Down Expand Up @@ -99,16 +45,10 @@ def nixpkgs_nodejs_configure(
target_constraints = None,
register = True,
):
if attribute_path == None:
fail("'attribute_path' is required.", "attribute_path")
if not nix_file and not nix_file_content:
nix_file_content = _nodejs_nix_content.format(
attribute_path = attribute_path,
nix_platform = "builtins.currentSystem" if nix_platform == None else repr(nix_platform),
)

nixpkgs_package(
nixpkgs_nodejs(
name = name,
nix_platform = nix_platform,
attribute_path = attribute_path,
repository = repository,
repositories = repositories,
nix_file = nix_file,
Expand Down
13 changes: 13 additions & 0 deletions toolchains/nodejs/private/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")

filegroup(
name = "srcs",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)

bzl_library(
name = "common",
srcs = ["common.bzl"],
visibility = ["//:__pkg__"],
)
Loading