Fix bazel support for npm and npx on Mac

We can now run all the presubmits on Mac when uploading.

Implementation inspired from https://github.com/google/skia-buildbot/blob/main/bazel/tools/protoc/BUILD.bazel

Change-Id: I36cebc291c4cb9cc2ae9bfc3c202886c30229db2
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/846689
Commit-Queue: Eric Boren <borenet@google.com>
Auto-Submit: Kaylee Lubick <kjlubick@google.com>
Reviewed-by: Eric Boren <borenet@google.com>
diff --git a/bazel/tools/npm/BUILD.bazel b/bazel/tools/npm/BUILD.bazel
index 61d1b0a..5fdd3cb 100644
--- a/bazel/tools/npm/BUILD.bazel
+++ b/bazel/tools/npm/BUILD.bazel
@@ -2,15 +2,14 @@
 # https://bazel.build/reference/be/make-variables#predefined_label_variables.
 #
 # We cannot use single quotes here because of the "echo '%s' > $@" command in the below genrule.
-_SCRIPT = """
-
+_SCRIPT_TEMPLATE = """
 # The "realpath" comand gives us an absolute path where any symlinks are resolved.
-NPM_BIN=$$(realpath $(rootpath @nodejs_linux_amd64//:bin/nodejs/bin/npm))
+NPM_BIN=$$(realpath $(rootpath {nodejs_root}//:bin/nodejs/bin/npm))
 
 # We need to make sure the Bazel-downloaded "node" binary comes first in the PATH environment
 # variable, or "npm" might fail if it picks up the system "node" binary and its version is too
 # old.
-NODE_BIN_DIR=$$(realpath $$(dirname $(rootpath @nodejs_linux_amd64//:bin/nodejs/bin/node)))
+NODE_BIN_DIR=$$(realpath $$(dirname $(rootpath {nodejs_root}//:bin/nodejs/bin/node)))
 export PATH=$$NODE_BIN_DIR:$$PATH
 
 
@@ -23,27 +22,67 @@
 """
 
 genrule(
-    name = "gen_script",
-    outs = ["npm.sh"],
-    cmd = "echo '%s' > $@" % _SCRIPT,
+    name = "gen_script_linux_x64",
+    outs = ["npm_linux_x64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_linux_amd64",
+    ),
     exec_tools = [
         "@nodejs_linux_amd64//:bin/nodejs/bin/npm",
         "@nodejs_linux_amd64//:bin/nodejs/bin/node",
     ],
 )
 
+genrule(
+    name = "gen_script_mac_x64",
+    outs = ["npm_mac_x64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_darwin_amd64",
+    ),
+    exec_tools = [
+        "@nodejs_darwin_amd64//:bin/nodejs/bin/npm",
+        "@nodejs_darwin_amd64//:bin/nodejs/bin/node",
+    ],
+)
+
+genrule(
+    name = "gen_script_mac_arm64",
+    outs = ["npm_mac_arm64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_darwin_arm64",
+    ),
+    exec_tools = [
+        "@nodejs_darwin_arm64//:bin/nodejs/bin/npm",
+        "@nodejs_darwin_arm64//:bin/nodejs/bin/node",
+    ],
+)
+
 # Wrapper script around the Bazel-downloaded "npm" binary.
 #
 # This script ensures "npm" always uses the Bazel-downloaded "node" binary rather than the system's
-# "node" binary.
+# "node" binary. It uses select statements to find the appropriate binary for the host platform.
 #
 # Reference: https://bazel.build/reference/be/shell#sh_binary.
 sh_binary(
     name = "npm",
-    srcs = ["npm.sh"],
-    data = [
-        "@nodejs_linux_amd64//:bin/nodejs/bin/node",
-        "@nodejs_linux_amd64//:bin/nodejs/bin/npm",
-    ],
+    srcs = select({
+        "//bazel/constraints:linux_x64": ["npm_linux_x64.sh"],
+        "//bazel/constraints:mac_x64": ["npm_mac_x64.sh"],
+        "//bazel/constraints:mac_arm64": ["npm_mac_arm64.sh"],
+    }),
+    data = select({
+        "//bazel/constraints:linux_x64": [
+            "@nodejs_linux_amd64//:bin/nodejs/bin/node",
+            "@nodejs_linux_amd64//:bin/nodejs/bin/npm",
+        ],
+        "//bazel/constraints:mac_x64": [
+            "@nodejs_darwin_amd64//:bin/nodejs/bin/node",
+            "@nodejs_darwin_amd64//:bin/nodejs/bin/npm",
+        ],
+        "//bazel/constraints:mac_arm64": [
+            "@nodejs_darwin_arm64//:bin/nodejs/bin/node",
+            "@nodejs_darwin_arm64//:bin/nodejs/bin/npm",
+        ],
+    }),
     visibility = ["//visibility:public"],
 )
diff --git a/bazel/tools/npx/BUILD.bazel b/bazel/tools/npx/BUILD.bazel
index 3838226..f91f2c9 100644
--- a/bazel/tools/npx/BUILD.bazel
+++ b/bazel/tools/npx/BUILD.bazel
@@ -2,15 +2,15 @@
 # https://bazel.build/reference/be/make-variables#predefined_label_variables.
 #
 # We cannot use single quotes here because of the "echo '%s' > $@" command in the below genrule.
-_SCRIPT = """
+_SCRIPT_TEMPLATE = """
 
 # The "realpath" comand gives us an absolute path where any symlinks are resolved.
-NPX_BIN=$$(realpath $(rootpath @nodejs_linux_amd64//:bin/nodejs/bin/npx))
+NPX_BIN=$$(realpath $(rootpath {nodejs_root}//:bin/nodejs/bin/npx))
 
 # We need to make sure the Bazel-downloaded "node" binary comes first in the PATH environment
 # variable, or "npx" might fail if it picks up the system "node" binary and its version is too
 # old.
-NODE_BIN_DIR=$$(realpath $$(dirname $(rootpath @nodejs_linux_amd64//:bin/nodejs/bin/node)))
+NODE_BIN_DIR=$$(realpath $$(dirname $(rootpath {nodejs_root}//:bin/nodejs/bin/node)))
 export PATH=$$NODE_BIN_DIR:$$PATH
 
 # Change into the directory where Bazel was invoked.
@@ -20,27 +20,67 @@
 """
 
 genrule(
-    name = "gen_script",
-    outs = ["npx.sh"],
-    cmd = "echo '%s' > $@" % _SCRIPT,
+    name = "gen_script_linux_x64",
+    outs = ["npx_linux_x64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_linux_amd64",
+    ),
     exec_tools = [
         "@nodejs_linux_amd64//:bin/nodejs/bin/npx",
         "@nodejs_linux_amd64//:bin/nodejs/bin/node",
     ],
 )
 
+genrule(
+    name = "gen_script_mac_x64",
+    outs = ["npx_mac_x64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_darwin_amd64",
+    ),
+    exec_tools = [
+        "@nodejs_darwin_amd64//:bin/nodejs/bin/npx",
+        "@nodejs_darwin_amd64//:bin/nodejs/bin/node",
+    ],
+)
+
+genrule(
+    name = "gen_script_mac_arm64",
+    outs = ["npx_mac_arm64.sh"],
+    cmd = "echo '%s' > $@" % _SCRIPT_TEMPLATE.format(
+        nodejs_root = "@nodejs_darwin_arm64",
+    ),
+    exec_tools = [
+        "@nodejs_darwin_arm64//:bin/nodejs/bin/npx",
+        "@nodejs_darwin_arm64//:bin/nodejs/bin/node",
+    ],
+)
+
 # Wrapper script around the Bazel-downloaded "npx" binary.
 #
 # This script ensures "npx" always uses the Bazel-downloaded "node" binary rather than the system's
-# "node" binary.
+# "node" binary. It uses select statements to find the appropriate binary for the host platform.
 #
 # Reference: https://bazel.build/reference/be/shell#sh_binary.
 sh_binary(
     name = "npx",
-    srcs = ["npx.sh"],
-    data = [
-        "@nodejs_linux_amd64//:bin/nodejs/bin/node",
-        "@nodejs_linux_amd64//:bin/nodejs/bin/npx",
-    ],
+    srcs = select({
+        "//bazel/constraints:linux_x64": ["npx_linux_x64.sh"],
+        "//bazel/constraints:mac_x64": ["npx_mac_x64.sh"],
+        "//bazel/constraints:mac_arm64": ["npx_mac_arm64.sh"],
+    }),
+    data = select({
+        "//bazel/constraints:linux_x64": [
+            "@nodejs_linux_amd64//:bin/nodejs/bin/node",
+            "@nodejs_linux_amd64//:bin/nodejs/bin/npx",
+        ],
+        "//bazel/constraints:mac_x64": [
+            "@nodejs_darwin_amd64//:bin/nodejs/bin/node",
+            "@nodejs_darwin_amd64//:bin/nodejs/bin/npx",
+        ],
+        "//bazel/constraints:mac_arm64": [
+            "@nodejs_darwin_arm64//:bin/nodejs/bin/node",
+            "@nodejs_darwin_arm64//:bin/nodejs/bin/npx",
+        ],
+    }),
     visibility = ["//visibility:public"],
 )