rules_js icon indicating copy to clipboard operation
rules_js copied to clipboard

[Bug]: `genrule` using `$(NODE_PATH)` doesn't install/resolve correctly when using `container_image` on mac

Open snapbug opened this issue 2 years ago • 2 comments

What happened?

I'm using a genrule rule, similar to the example to run tailwind cli for my project.

I then want to include the output into a container image, using rules_docker's container_image, which includes transitions to linux host on macOS (totally expected because of the way docker works on Mac).

This transition causes the nodejs toolchain, and therefore $(NODE_PATH) to resolve to the linux toolchain, which won't execute on Mac:

...
external/nodejs_linux_amd64/bin/nodejs/bin/node: cannot execute binary file
...

It's specifically the container_image transition, as container_layer using the genrule output succeeds as well.

Version

Development (host) and target OS/architectures: host: Mac amd64 target: linux amd64 (via docker_rules transition)

Output of bazel --version: Bazel 6.0.0

Version of the Aspect rules, or other relevant rules from your WORKSPACE or MODULE.bazel file: rules_docker: 0.25.0 rules_js: 1.11.1

Language(s) and/or frameworks involved: n/a

How to reproduce

Steps are above, but I've created a [repro repo here](https://github.com/snapbug/js_docker_repro), which has the various rules and which fails and why in the README.md

Any other information?

No response

Fund our work

  • [ ] Sponsor our open source work by donating a bug bounty

snapbug avatar Jan 17 '23 04:01 snapbug

The resolved_toolchain code is in the rules_nodejs core: https://github.com/bazelbuild/rules_nodejs/blob/e5c7a3d0013d257fec4db5c3a01a2050a9a7c6d1/nodejs/private/toolchains_repo.bzl#L65.

Interestingly the comment the says the toolchain is the "result of Bazel resolving the toolchain for the execution or target platform.". Seems it is resolving to the target platform and not the execution platform.

@alexeagle any idea how to get the toolchain for the execution platform in this context?

genrule(
    name = "tailwind",
    srcs = [
        "//:tailwind.config.js",
        "//:package.json",
        "//:index.html",
        "//:node_modules",
        "//:node_modules/tailwindcss",
        "//:node_modules/tailwindcss/dir",
    ],
    outs = ["tailwind.css"],
    cmd = " ".join([
        "$(NODE_PATH)",
        "./$(execpath //:node_modules/tailwindcss/dir)/lib/cli.js",
        "-o $(OUTS)",
        "-c $(location :tailwind.config.js)",
    ]),
    toolchains = ["@nodejs_toolchains//:resolved_toolchain"],
    tools = ["@nodejs_toolchains//:resolved_toolchain"],
)

container_layer(
    name = "tailwind_layer",
    files = [
        ":tailwind",
    ],
)

container_image(
    name = "tailwind_image",
    layers = [
        ":tailwind_layer",
    ],
)

gregmagolan avatar Jan 24 '23 08:01 gregmagolan

Leaving some notes on how I hooked up Tailwind v4 alpha 10 to Bazel. You will need to add a pnpm dependency for both @tailwindcss/cli and tailwindcss. Bazel needs to be executed with the --spawn_strategy=local due to Tailwind not detecting template files when sandboxed (still looking into this).

Hope this helps someone :)

load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("@npm//zavix/website:@tailwindcss/cli/package_json.bzl", tailwind_bin = "bin")

copy_to_directory(
    name = "template",
    replace_prefixes = {
        "zavix/template": ""
    },
    srcs = [
        "//zavix/website/template/partial",
        "//zavix/website/template/view",
    ],
)

tailwind_bin.tailwindcss(
    name = "css",
    chdir = package_name(),
    outs = ["output.css"],
    visibility = ["//zavix/website/public:__pkg__"],
    args = [
        "-i",
        "input.css",
        "-o",
        "output.css",
    ],
    srcs = [
        "input.css",
        ":template",
        "//zavix/website:node_modules/tailwindcss",
    ],
)

nekinie avatar Mar 28 '24 01:03 nekinie