Skip to content

Commit

Permalink
refactor: update node toolchain to provider File objects instead of p…
Browse files Browse the repository at this point in the history
…aths
  • Loading branch information
gregmagolan committed Apr 1, 2024
1 parent 6199ad0 commit 944c2f4
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 159 deletions.
9 changes: 4 additions & 5 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@ load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
# The order matters because Bazel will provide the first registered toolchain when a rule asks Bazel to select it
# This applies to the resolved_toolchain
nodejs_register_toolchains(
name = "node16",
node_version = "16.5.0",
name = "node18",
node_version = "18.20.0",
)

nodejs_register_toolchains(
name = "node15",
node_version = "15.14.0",
name = "node16",
node_version = "16.20.2",
)

http_archive(
Expand Down
33 changes: 10 additions & 23 deletions docs/Core.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ Defaults to `None`
**USAGE**

<pre>
node_toolchain(<a href="#node_toolchain-name">name</a>, <a href="#node_toolchain-headers">headers</a>, <a href="#node_toolchain-npm">npm</a>, <a href="#node_toolchain-npm_files">npm_files</a>, <a href="#node_toolchain-npm_path">npm_path</a>, <a href="#node_toolchain-target_tool">target_tool</a>, <a href="#node_toolchain-target_tool_path">target_tool_path</a>)
node_toolchain(<a href="#node_toolchain-name">name</a>, <a href="#node_toolchain-headers">headers</a>, <a href="#node_toolchain-node">node</a>, <a href="#node_toolchain-npm">npm</a>, <a href="#node_toolchain-npm_files">npm_files</a>)
</pre>

Defines a node toolchain for a platform.
Expand All @@ -157,7 +157,7 @@ load("@rules_nodejs//nodejs:toolchain.bzl", "node_toolchain")

node_toolchain(
name = "node_toolchain",
target_tool = "//some/path/bin/node",
node = "//some/path/bin/node",
)
```

Expand Down Expand Up @@ -195,39 +195,26 @@ You can use the `--toolchain_resolution_debug` flag to `bazel` to help diagnose

<h4 id="node_toolchain-headers">headers</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A cc_library that contains the Node/v8 header files for this target platform.
(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): cc_library that contains the Node/v8 header files

Defaults to `None`

<h4 id="node_toolchain-npm">npm</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A hermetically downloaded npm executable target for this target's platform.

Defaults to `None`
<h4 id="node_toolchain-node">node</h4>

<h4 id="node_toolchain-npm_files">npm_files</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">List of labels</a>*): Files required in runfiles to run npm.

Defaults to `[]`
(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>, mandatory*): Node.js executable file

<h4 id="node_toolchain-npm_path">npm_path</h4>

(*String*): Path to an existing npm executable for this target's platform.

Defaults to `""`

<h4 id="node_toolchain-target_tool">target_tool</h4>
<h4 id="node_toolchain-npm">npm</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A hermetically downloaded nodejs executable target for this target's platform.
(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): Npm entry point JavaScript file

Defaults to `None`

<h4 id="node_toolchain-target_tool_path">target_tool_path</h4>
<h4 id="node_toolchain-npm_files">npm_files</h4>

(*String*): Path to an existing nodejs executable for this target's platform.
(*<a href="https://bazel.build/docs/build-ref.html#labels">List of labels</a>*): Additional files required to run npm

Defaults to `""`
Defaults to `[]`


## UserBuildSettingInfo
Expand Down
28 changes: 1 addition & 27 deletions docs/Toolchains.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,17 @@ When you call `nodejs_register_toolchains()` in your `WORKSPACE` file it will se

If you have an advanced use-case and want to use a version of node not supported by this repository, you can also register your own toolchains.

## Node.js binary for the target platform

Sometimes your target platform (where your software runs) is different from the host platform (where you run Bazel) or execution platform (where Bazel actions run).
The most common case is developing a docker image on MacOS, which will execute in a Linux container.

Our toolchain support is conditional on the execution platform, as it's meant for running nodejs tools during the build.
It is not needed for this use case. Instead, simply select the nodejs you want to include in the runtime.

For example, rules_docker has a `nodejs_image` rule, which takes a `node_repository_name` attribute indicating
which nodejs binary you want to include in the image. `nodejs_linux_amd64` is the value you'd use.

## Cross-compilation

Bazel Toolchains are intended to support cross-compilation, e.g. building a linux binary from mac or windows.
Most JavaScript use cases produce platform-independent code,
but the exception is native modules which use [node-gyp](https://github.com/nodejs/node-gyp).
Any native modules will still be fetched and built, by npm/yarn, for your host platform,
so they will not work on the target platform.
The workaround is to perform the npm_install inside a docker container so that it produces modules for the target platform.

Follow https://github.com/bazelbuild/rules_nodejs/issues/506 for updates on support for node-gyp cross-compilation.

## Registering a custom toolchain

To run a custom toolchain (i.e., to run a node binary not supported by the built-in toolchains), you'll need four things:

1) A rule which can build or load a node binary from your repository
(a checked-in binary or a build using a relevant [`rules_foreign_cc` build rule](https://bazelbuild.github.io/rules_foreign_cc/) will do nicely).
2) A [`node_toolchain` rule](Core.html#node_toolchain) which depends on your binary defined in step 1 as its `target_tool`.
2) A [`node_toolchain` rule](Core.html#node_toolchain) which depends on your binary defined in step 1 as its `node`.
3) A [`toolchain` rule](https://bazel.build/reference/be/platform#toolchain) that depends on your `node_toolchain` rule defined in step 2 as its `toolchain`
and on `@rules_nodejs//nodejs:toolchain_type` as its `toolchain_type`. Make sure to define appropriate platform restrictions as described in the
documentation for the `toolchain` rule.
4) A call to [the `register_toolchains` function](https://bazel.build/rules/lib/globals#register_toolchains) in your `WORKSPACE`
that refers to the `toolchain` rule defined in step 3.

Examples of steps 2-4 can be found in the [documentation for `node_toolchain`](Core.html#node_toolchain).

If necessary, you can substitute building the node binary as part of the build with using a locally installed version by skipping step 1 and replacing step 2 with:

2) A `node_toolchain` rule which has the path of the system binary as its `target_tool_path`
2 changes: 1 addition & 1 deletion e2e/nodejs_host/.nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16.13.2
16.20.2
6 changes: 5 additions & 1 deletion e2e/nodejs_host/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
# Note, this gets the default version of Node.js from
# https://github.com/bazelbuild/rules_nodejs/blob/5.8.0/nodejs/repositories.bzl#L11
node.toolchain()
node.toolchain(
name = "node18",
node_version = "18.20.0",
)
node.toolchain(
name = "node16",
node_version = "16.5.0",
use_nvmrc = "//:.nvmrc",
)

# TODO: nvmrc test like WORKSPACE?
Expand Down
5 changes: 2 additions & 3 deletions e2e/nodejs_host/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ nodejs_register_toolchains()

# Create additional parallel toolchains using explicit nodejs_register_toolchains targets
nodejs_register_toolchains(
name = "node14",
node_version = "14.19.0",
name = "node18",
node_version = "18.20.0",
)

nodejs_register_toolchains(
name = "node16_nvmrc",
use_nvmrc = "//:.nvmrc",
Expand Down
44 changes: 22 additions & 22 deletions e2e/smoke/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,15 @@ write_file(
# Files used in test cases later that contain the correct nodejs version
# that is imported into the workspace.
write_file(
name = "write_node_version_15",
out = "expected_node_15",
content = ["v15.14.0"],
name = "write_node_version_16",
out = "expected_node_16",
content = ["v16.20.2"],
)

write_file(
name = "write_node_version_16",
out = "expected_node_16",
content = ["v16.5.0"],
name = "write_node_version_18",
out = "expected_node_18",
content = ["v18.20.0"],
)

# To see what nodejs version is used by default
Expand All @@ -239,42 +239,42 @@ my_nodejs(
# Output contains the version number of node that is used.
# This is used in tests later to verify the toolchain specified is resolved correctly
my_nodejs(
name = "run_15",
out = "thing_toolchain_15",
name = "run_16",
out = "thing_toolchain_16",
entry_point = "version.js",
# using the select statement will download toolchains for all three platforms
# you can also just provide an individual toolchain if you don't want to download them all
toolchain = select({
"@bazel_tools//src/conditions:linux_x86_64": "@node15_linux_amd64//:node_toolchain",
"@bazel_tools//src/conditions:darwin": "@node15_darwin_amd64//:node_toolchain",
"@bazel_tools//src/conditions:windows": "@node15_windows_amd64//:node_toolchain",
"@bazel_tools//src/conditions:linux_x86_64": "@node16_linux_amd64//:node_toolchain",
"@bazel_tools//src/conditions:darwin": "@node16_darwin_amd64//:node_toolchain",
"@bazel_tools//src/conditions:windows": "@node16_windows_amd64//:node_toolchain",
}),
)

# Section of test the verify the toolchain work as expected matching node version used with expected
diff_test(
name = "test_node_version_15",
file1 = "write_node_version_15",
file2 = "thing_toolchain_15",
name = "test_node_version_16",
file1 = "write_node_version_16",
file2 = "thing_toolchain_16",
)

my_nodejs(
name = "run_16",
out = "thing_toolchain_16",
name = "run_18",
out = "thing_toolchain_18",
entry_point = "version.js",
# using the select statement will download toolchains for all three platforms
# you can also just provide an individual toolchain if you don't want to download them all
toolchain = select({
"@bazel_tools//src/conditions:linux_x86_64": "@node16_linux_amd64//:node_toolchain",
"@bazel_tools//src/conditions:darwin": "@node16_darwin_amd64//:node_toolchain",
"@bazel_tools//src/conditions:windows": "@node16_windows_amd64//:node_toolchain",
"@bazel_tools//src/conditions:linux_x86_64": "@node18_linux_amd64//:node_toolchain",
"@bazel_tools//src/conditions:darwin": "@node18_darwin_amd64//:node_toolchain",
"@bazel_tools//src/conditions:windows": "@node18_windows_amd64//:node_toolchain",
}),
)

diff_test(
name = "test_node_version_16",
file1 = "write_node_version_16",
file2 = "thing_toolchain_16",
name = "test_node_version_18",
file1 = "write_node_version_18",
file2 = "thing_toolchain_18",
)

cc_binary(
Expand Down
21 changes: 11 additions & 10 deletions e2e/smoke/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ module(
)

bazel_dep(name = "rules_nodejs", version = "0.0.0", dev_dependency = True)
bazel_dep(name = "bazel_skylib", version = "1.4.1", dev_dependency = True)
bazel_dep(name = "aspect_bazel_lib", version = "1.30.2", dev_dependency = True)
bazel_dep(name = "platforms", version = "0.0.5", dev_dependency = True)
bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True)
bazel_dep(name = "aspect_bazel_lib", version = "2.6.1", dev_dependency = True)
bazel_dep(name = "platforms", version = "0.0.9", dev_dependency = True)

local_path_override(
module_name = "rules_nodejs",
Expand All @@ -21,22 +21,23 @@ node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
# Note, this gets the default version of Node.js from
# https://github.com/bazelbuild/rules_nodejs/blob/5.8.0/nodejs/repositories.bzl#L11
node.toolchain(
name = "node16",
node_version = "16.5.0",
name = "node18",
node_version = "18.20.0",
)
node.toolchain(
name = "node15",
node_version = "15.14.0",
name = "node16",
node_version = "16.20.2",
)

# FIXME(6.0): a repo rule with name=foo should create a repo named @foo, not @foo_toolchains
use_repo(
node,
"node15_darwin_amd64",
"node15_linux_amd64",
"node15_windows_amd64",
"node16_darwin_amd64",
"node16_linux_amd64",
"node16_toolchains",
"node16_windows_amd64",
"node18_darwin_amd64",
"node18_linux_amd64",
"node18_toolchains",
"node18_windows_amd64",
)
9 changes: 4 additions & 5 deletions e2e/smoke/WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ rules_nodejs_dependencies()
# The order matters because Bazel will provide the first registered toolchain when a rule asks Bazel to select it
# This applies to the resolved_toolchain
nodejs_register_toolchains(
name = "node16",
node_version = "16.5.0",
name = "node18",
node_version = "18.20.0",
)

nodejs_register_toolchains(
name = "node15",
node_version = "15.14.0",
name = "node16",
node_version = "16.20.2",
)

http_archive(
Expand Down
4 changes: 2 additions & 2 deletions e2e/smoke/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ def _my_nodejs_impl(ctx):
else:
toolchain = ctx.toolchains["@rules_nodejs//nodejs:toolchain_type"].nodeinfo
ctx.actions.run(
inputs = toolchain.tool_files + [ctx.file.entry_point],
executable = toolchain.target_tool_path,
inputs = [ctx.file.entry_point],
executable = toolchain.node,
arguments = [ctx.file.entry_point.path, ctx.outputs.out.path],
outputs = [ctx.outputs.out],
)
Expand Down
2 changes: 1 addition & 1 deletion nodejs/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ cc_library(
load("@rules_nodejs//nodejs:toolchain.bzl", "node_toolchain")
node_toolchain(
name = "node_toolchain",
target_tool = ":node_bin",
node = ":node_bin",
npm = ":npm",
npm_files = [":npm_files"],
headers = ":headers",
Expand Down
Loading

0 comments on commit 944c2f4

Please sign in to comment.