|
| 1 | +# Copyright 2017 The Bazel Authors. All rights reserved. |
| 2 | +# |
| 3 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +# you may not use this file except in compliance with the License. |
| 5 | +# You may obtain a copy of the License at |
| 6 | +# |
| 7 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +# |
| 9 | +# Unless required by applicable law or agreed to in writing, software |
| 10 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +# See the License for the specific language governing permissions and |
| 13 | +# limitations under the License. |
| 14 | + |
| 15 | +"""Install NodeJS when the user runs node_repositories() from their WORKSPACE. |
| 16 | +
|
| 17 | +We fetch a specific version of Node, to ensure builds are hermetic. |
| 18 | +We then create a repository @nodejs which provides the |
| 19 | +node binary to other rules. |
| 20 | +""" |
| 21 | + |
| 22 | +load(":node_labels.bzl", "get_node_label") |
| 23 | + |
| 24 | +def _node_impl(repository_ctx): |
| 25 | + os_name = repository_ctx.os.name.lower() |
| 26 | + if os_name.startswith("mac os"): |
| 27 | + repository_ctx.download_and_extract( |
| 28 | + [ |
| 29 | + "https://mirror.bazel.build/nodejs.org/dist/v8.9.1/node-v8.9.1-darwin-x64.tar.gz", |
| 30 | + "https://nodejs.org/dist/v8.9.1/node-v8.9.1-darwin-x64.tar.gz", |
| 31 | + ], |
| 32 | + stripPrefix = "node-v8.9.1-darwin-x64", |
| 33 | + sha256 = "05c992a6621d28d564b92bf3051a5dc0adf83839237c0d4653a8cdb8a1c73b94" |
| 34 | + ) |
| 35 | + elif os_name.find("windows") != -1: |
| 36 | + repository_ctx.download_and_extract( |
| 37 | + [ |
| 38 | + "https://mirror.bazel.build/nodejs.org/dist/v8.9.1/node-v8.9.1-win-x64.zip", |
| 39 | + "http://nodejs.org/dist/v8.9.1/node-v8.9.1-win-x64.zip", |
| 40 | + ], |
| 41 | + stripPrefix = "node-v8.9.1-win-x64", |
| 42 | + sha256 = "db89c6e041da359561fbe7da075bb4f9881a0f7d3e98c203e83732cfb283fa4a" |
| 43 | + ) |
| 44 | + else: |
| 45 | + repository_ctx.download_and_extract( |
| 46 | + [ |
| 47 | + "https://mirror.bazel.build/nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz", |
| 48 | + "http://nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz", |
| 49 | + ], |
| 50 | + stripPrefix = "node-v8.9.1-linux-x64", |
| 51 | + sha256 = "8be82805f7c1ab3e64d4569fb9a90ded2de78dd27cadbb91bad1bf975dae1e2d" |
| 52 | + ) |
| 53 | + if os_name.lower().find("windows") != -1: |
| 54 | + # The windows distribution of nodejs has the binaries in different paths |
| 55 | + node = "node.exe" |
| 56 | + npm = "node_modules/npm/bin/npm-cli.js" |
| 57 | + else: |
| 58 | + node = "bin/node" |
| 59 | + npm = "bin/npm" |
| 60 | + repository_ctx.file("BUILD.bazel", content="""#Generated by node_repositories.bzl |
| 61 | +package(default_visibility = ["//visibility:public"]) |
| 62 | +exports_files(["{0}", "run_npm.sh.template"]) |
| 63 | +alias(name = "node", actual = "{0}") |
| 64 | +sh_binary( |
| 65 | + name = "npm", |
| 66 | + srcs = ["npm.sh"], |
| 67 | +) |
| 68 | +""".format(node)) |
| 69 | + |
| 70 | + # `yarn publish` is not ready for use under Bazel, see https://github.com/yarnpkg/yarn/issues/610 |
| 71 | + repository_ctx.file("run_npm.sh.template", content=""" |
| 72 | +NODE="{}" |
| 73 | +NPM="{}" |
| 74 | +"$NODE" "$NPM" TMPL_args "$@" |
| 75 | +""".format(repository_ctx.path(node), repository_ctx.path(npm))) |
| 76 | + |
| 77 | + repository_ctx.file("npm.sh", content="""#!/bin/bash |
| 78 | +#Generated by node_repositories.bzl |
| 79 | +""" + "".join([""" |
| 80 | +ROOT="{}" |
| 81 | +NODE="{}" |
| 82 | +SCRIPT="{}" |
| 83 | +(cd "$ROOT"; "$NODE" "$SCRIPT" "$@") |
| 84 | +""".format( |
| 85 | + repository_ctx.path(package_json).dirname, |
| 86 | + repository_ctx.path(node), |
| 87 | + repository_ctx.path(npm)) |
| 88 | + for package_json in repository_ctx.attr.package_json]), executable = True) |
| 89 | + |
| 90 | +_node_repo = repository_rule( |
| 91 | + _node_impl, |
| 92 | + attrs = { "package_json": attr.label_list() }, |
| 93 | +) |
| 94 | + |
| 95 | +# def _write_node_modules_impl(repository_ctx): |
| 96 | + # WORKAROUND for https://github.com/bazelbuild/bazel/issues/374#issuecomment-296217940 |
| 97 | + # Bazel does not allow labels to start with `@`, so when installing eg. the `@types/node` |
| 98 | + # module from the @types scoped package, you'll get an error. |
| 99 | + # The workaround is to move the rule up one level, from /node_modules to the project root. |
| 100 | + # For now, users must instead write their own /BUILD file on setup. |
| 101 | + |
| 102 | + # repository_ctx.symlink(project_dir.get_child("node_modules"), "node_modules") |
| 103 | + # add a BUILD file inside the user's node_modules project folder |
| 104 | + # repository_ctx.file("installed/BUILD", """ |
| 105 | + # filegroup(name = "node_modules", srcs = glob(["node_modules/**/*"]), visibility = ["//visibility:public"]) |
| 106 | + # """) |
| 107 | + |
| 108 | +# _write_node_modules = repository_rule( |
| 109 | +# _write_node_modules_impl, |
| 110 | +# attrs = { "package_json": attr.label() }, |
| 111 | +# ) |
| 112 | + |
| 113 | +def _yarn_impl(repository_ctx): |
| 114 | + # Yarn is a package manager that downloads dependencies. Yarn is an improvement over the `npm` tool in |
| 115 | + # speed and correctness. We download a specific version of Yarn to ensure a hermetic build. |
| 116 | + repository_ctx.file("BUILD.bazel", content="""#Generated by node_repositories.bzl |
| 117 | +package(default_visibility = ["//visibility:public"]) |
| 118 | +exports_files(["bin/yarn.js"]) |
| 119 | +sh_binary( |
| 120 | + name = "yarn", |
| 121 | + srcs = ["yarn.sh"], |
| 122 | +) |
| 123 | +""") |
| 124 | + node = get_node_label(repository_ctx) |
| 125 | + |
| 126 | + repository_ctx.file("yarn.sh", content="""#!/bin/bash |
| 127 | +#Generated by node_repositories.bzl |
| 128 | +""" + "".join([""" |
| 129 | +NODE="{}" |
| 130 | +SCRIPT="{}" |
| 131 | +ROOT="{}" |
| 132 | +"$NODE" "$SCRIPT" --cwd "$ROOT" "$@" |
| 133 | +""".format( |
| 134 | + repository_ctx.path(node), |
| 135 | + repository_ctx.path("bin/yarn.js"), |
| 136 | + repository_ctx.path(package_json).dirname) |
| 137 | + for package_json in repository_ctx.attr.package_json]), executable = True) |
| 138 | + repository_ctx.download_and_extract( |
| 139 | + [ |
| 140 | + "https://mirror.bazel.build/github.com/yarnpkg/yarn/releases/download/v1.3.2/yarn-v1.3.2.tar.gz", |
| 141 | + "https://github.com/yarnpkg/yarn/releases/download/v1.3.2/yarn-v1.3.2.tar.gz", |
| 142 | + ], |
| 143 | + stripPrefix = "yarn-v1.3.2", |
| 144 | + sha256 = "6cfe82e530ef0837212f13e45c1565ba53f5199eec2527b85ecbcd88bf26821d" |
| 145 | + ) |
| 146 | + |
| 147 | +_yarn_repo = repository_rule( |
| 148 | + _yarn_impl, |
| 149 | + attrs = { "package_json": attr.label_list() }, |
| 150 | +) |
| 151 | + |
| 152 | +def node_repositories(package_json): |
| 153 | + """To be run in user's WORKSPACE to install NodeJS and rules_nodejs npm dependencies. |
| 154 | + """ |
| 155 | + |
| 156 | + _node_repo(name = "nodejs", package_json = package_json) |
| 157 | + |
| 158 | + _yarn_repo(name = "yarn", package_json = package_json) |
0 commit comments