From 801da6bcdfe9fd63cb4ef068ce01453f6701ecb6 Mon Sep 17 00:00:00 2001 From: Greg Magolan Date: Sat, 6 Apr 2019 23:18:52 -0700 Subject: [PATCH] Consolidate node module rules & providers & support transitive npm deps via collect_node_modules_aspect --- BUILD.bazel | 1 - internal/common/node_module_info.bzl | 28 +++- internal/common/providers.bzl | 2 +- internal/common/sources_aspect.bzl | 8 +- internal/ng_apf_library/BUILD.bazel | 40 ------ internal/ng_apf_library/ng_apf_library.bzl | 50 -------- internal/ng_apf_library/ng_apf_library.js | 63 --------- internal/node/node.bzl | 54 +++++--- internal/npm_install/BUILD.bazel | 1 - internal/npm_install/generate_build_file.js | 120 ++++++++++-------- internal/npm_install/node_module_library.bzl | 70 ++++++++++ internal/npm_install/npm_install.bzl | 6 - internal/npm_install/test/BUILD.bazel | 4 - .../npm_install/test/copy_ng_apf_library.js | 33 ----- .../test/golden/BUILD.bazel.golden | 3 +- .../@angular/core/BUILD.bazel.golden | 19 ++- .../@gregmagolan/BUILD.bazel.golden | 11 +- .../@gregmagolan/test-a/BUILD.bazel.golden | 14 +- .../@gregmagolan/test-b/BUILD.bazel.golden | 14 +- .../node_modules/ajv/BUILD.bazel.golden | 14 +- .../node_modules/jasmine/BUILD.bazel.golden | 14 +- .../node_modules/rxjs/BUILD.bazel.golden | 14 +- .../node_modules/unidiff/BUILD.bazel.golden | 14 +- .../node_modules/zone.js/BUILD.bazel.golden | 14 +- internal/rollup/rollup_bundle.bzl | 75 ++++++----- packages/typescript/internal/build_defs.bzl | 15 ++- 26 files changed, 325 insertions(+), 376 deletions(-) delete mode 100644 internal/ng_apf_library/BUILD.bazel delete mode 100644 internal/ng_apf_library/ng_apf_library.bzl delete mode 100644 internal/ng_apf_library/ng_apf_library.js create mode 100644 internal/npm_install/node_module_library.bzl delete mode 100644 internal/npm_install/test/copy_ng_apf_library.js diff --git a/BUILD.bazel b/BUILD.bazel index 31a19fafb3..157aa04ceb 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -54,7 +54,6 @@ npm_package( "//internal/js_library:package_contents", # TODO(alexeagle): distribute separately as @bazel/rollup "//internal/rollup:package_contents", - "//internal/ng_apf_library:package_contents", "//internal/node:package_contents", "//internal/npm_install:package_contents", "//internal/npm_package:package_contents", diff --git a/internal/common/node_module_info.bzl b/internal/common/node_module_info.bzl index 34b2b2f3f1..0617e87458 100644 --- a/internal/common/node_module_info.bzl +++ b/internal/common/node_module_info.bzl @@ -12,22 +12,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""NodeModuleInfo provider and apsect to collect node_modules from deps. +"""NodeModuleInfo & NodeModuleSources providers and apsect to collect node_modules from deps. """ NodeModuleInfo = provider( - doc = "This provider contains information about npm dependencies installed with yarn_install and npm_install rules", + doc = "Provides information about npm dependencies installed with yarn_install and npm_install rules", fields = { "workspace": "The workspace name that the npm dependencies are provided from", }, ) +NodeModuleSources = provider( + doc = "Provides sources for npm dependencies installed with yarn_install and npm_install rules", + fields = { + "sources": "Source files that are npm dependencies", + "workspace": "The workspace name that the npm dependencies are provided from", + }, +) + def _collect_node_modules_aspect_impl(target, ctx): nm_wksp = None - if hasattr(ctx.rule.attr, "tags") and "NODE_MODULE_MARKER" in ctx.rule.attr.tags: - nm_wksp = target.label.workspace_root.split("/")[1] if target.label.workspace_root else ctx.workspace_name - return [NodeModuleInfo(workspace = nm_wksp)] + if NodeModuleSources in target: + return [] + + if hasattr(ctx.rule.attr, "deps"): + sources = depset() + for dep in ctx.rule.attr.deps: + if NodeModuleSources in dep: + if nm_wksp and dep[NodeModuleSources].workspace != nm_wksp: + fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (nm_wksp, dep[NodeModuleSources].workspace)) + nm_wksp = dep[NodeModuleSources].workspace + sources = depset(transitive = [dep[NodeModuleSources].sources, sources]) + if sources: + return [NodeModuleSources(sources = sources, workspace = nm_wksp)] return [] diff --git a/internal/common/providers.bzl b/internal/common/providers.bzl index c9559613a4..7645e92ea1 100644 --- a/internal/common/providers.bzl +++ b/internal/common/providers.bzl @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Provider for "node-module-like" rules such as `ng_apf_library`. +# Provider for "node-module-like" rules such as `node_module_library`. # It tells downstream rules how to consume Javascript files in the NPM package. ScriptsProvider = provider(fields = ["scripts"]) diff --git a/internal/common/sources_aspect.bzl b/internal/common/sources_aspect.bzl index 9bf319ba0f..4268dcff4b 100644 --- a/internal/common/sources_aspect.bzl +++ b/internal/common/sources_aspect.bzl @@ -15,6 +15,7 @@ """Aspect to collect es5 js sources and scripts from deps. """ +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo") load("@build_bazel_rules_nodejs//internal/common:providers.bzl", "ScriptsProvider") def _sources_aspect_impl(target, ctx): @@ -26,7 +27,7 @@ def _sources_aspect_impl(target, ctx): node_sources = depset() # dev_scripts is a collection of "scripts" from "node-module-like" targets - # such as `ng_apf_library`. Note that nothing is collected from the default + # such as `node_module_library`. Note that nothing is collected from the default # filegroup target for generic node modules because it does not have the # `scripts` provider nor does it have the `deps` attribute. dev_scripts = depset() @@ -37,9 +38,8 @@ def _sources_aspect_impl(target, ctx): node_sources = depset(transitive = [node_sources, target.typescript.es5_sources]) elif ScriptsProvider in target: dev_scripts = depset(transitive = [dev_scripts, target[ScriptsProvider].scripts]) - elif hasattr(target, "files") and "NODE_MODULE_MARKER" not in ctx.rule.attr.tags: - # Sources from npm fine grained deps which are tagged with NODE_MODULE_MARKER - # should not be included + elif hasattr(target, "files") and not NodeModuleInfo in target: + # Sources from npm fine grained deps should not be included node_sources = depset( [f for f in target.files if f.path.endswith(".js")], transitive = [node_sources], diff --git a/internal/ng_apf_library/BUILD.bazel b/internal/ng_apf_library/BUILD.bazel deleted file mode 100644 index e8b8b5f6e4..0000000000 --- a/internal/ng_apf_library/BUILD.bazel +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2019 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -licenses(["notice"]) # Apache 2.0 - -package(default_visibility = ["//internal:__subpackages__"]) - -bzl_library( - name = "bzl", - srcs = glob(["*.bzl"]), - visibility = ["//visibility:public"], -) - -filegroup( - name = "package_contents", - srcs = [ - "BUILD.bazel", - "ng_apf_library.bzl", - "ng_apf_library.js", - ], - visibility = ["//:__pkg__"], -) - -exports_files([ - "ng_apf_library.bzl", - "ng_apf_library.js", -]) diff --git a/internal/ng_apf_library/ng_apf_library.bzl b/internal/ng_apf_library/ng_apf_library.bzl deleted file mode 100644 index 8a2469de5a..0000000000 --- a/internal/ng_apf_library/ng_apf_library.bzl +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2019 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -load("@build_bazel_rules_nodejs//internal/common:providers.bzl", "ScriptsProvider") - -def _ng_apf_library_impl(ctx): - umds = [] - factories = [] - summaries = [] - - for file in ctx.files.srcs: - if file.basename.endswith(".umd.js"): - umds.append(file) - elif file.basename.endswith(".ngfactory.js"): - factories.append(file) - elif file.basename.endswith(".ngsummary.js"): - summaries.append(file) - - return [ - DefaultInfo(files = depset( - transitive = [src.files for src in ctx.attr.srcs] + [dep.files for dep in ctx.attr.deps], - )), - ScriptsProvider( - scripts = depset(umds + factories + summaries), - ), - ] - -ng_apf_library = rule( - implementation = _ng_apf_library_impl, - attrs = { - "srcs": attr.label_list( - doc = "The list of files that comprise the package", - ), - "deps": attr.label_list( - doc = "Flattened dependencies of the package", - ), - }, - doc = "Provides a replacement for the default filegroup target, with the addition of `scripts` provider.", -) diff --git a/internal/ng_apf_library/ng_apf_library.js b/internal/ng_apf_library/ng_apf_library.js deleted file mode 100644 index 4c763df78b..0000000000 --- a/internal/ng_apf_library/ng_apf_library.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright 2019 The Bazel Authors. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Returns true if the specified `pkg` conforms to Angular Package Format (APF), - * false otherwise. If the package contains `*.metadata.json` and a - * corresponding sibling `.d.ts` file, then the package is considered to be APF. - */ -function isNgApfPackage(pkg) { - const set = new Set(pkg._files); - const metadataExt = /\.metadata\.json$/; - return pkg._files.some((file) => { - if (metadataExt.test(file)) { - const sibling = file.replace(metadataExt, '.d.ts'); - if (set.has(sibling)) { - return true; - } - } - return false; - }); -} - -/** - * Prints a `ng_apf_library` rule that replaces the generated filegroup target - * that the user will depend on, e.g. `@npm//@angular/core` will be an - * `ng_apf_library`. - */ -function printNgApfLibrary(pkg, pkgDeps) { - return ` -load("@build_bazel_rules_nodejs//internal/ng_apf_library:ng_apf_library.bzl", "ng_apf_library") -ng_apf_library( - name = "${pkg._name}__pkg", - srcs = [ - # ${pkg._dir} package contents (and contents of nested node_modules) - ":${pkg._name}__files", - ], - deps = [ - # direct or transitive dependencies hoisted to root by the package manager - ${pkgDeps.map(dep => `"//node_modules/${dep._dir}:${dep._name}__pkg",`).join('\n ')} - ], - tags = ["NODE_MODULE_MARKER"], -) -`; -} - -module.exports = { - isNgApfPackage, - printNgApfLibrary, -} diff --git a/internal/node/node.bzl b/internal/node/node.bzl index 32d25d7cd8..ababd6a880 100644 --- a/internal/node/node.bzl +++ b/internal/node/node.bzl @@ -20,9 +20,9 @@ They support module mapping: any targets in the transitive dependencies with a `module_name` attribute can be `require`d by that name. """ +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") load("//internal/common:expand_into_runfiles.bzl", "expand_location_into_runfiles") load("//internal/common:module_mappings.bzl", "module_mappings_runtime_aspect") -load("//internal/common:node_module_info.bzl", "NodeModuleInfo", "collect_node_modules_aspect") load("//internal/common:sources_aspect.bzl", "sources_aspect") def _trim_package_node_modules(package_name): @@ -36,18 +36,15 @@ def _trim_package_node_modules(package_name): segments += [n] return "/".join(segments) -def _write_loader_script(ctx): - # Generates the JavaScript snippet of module roots mappings, with each entry - # in the form: - # {module_name: /^mod_name\b/, module_root: 'path/to/mod_name'} - module_mappings = [] - for d in ctx.attr.data: - if hasattr(d, "runfiles_module_mappings"): - for [mn, mr] in d.runfiles_module_mappings.items(): - escaped = mn.replace("/", "\/").replace(".", "\.") - mapping = "{module_name: /^%s\\b/, module_root: '%s'}" % (escaped, mr) - module_mappings.append(mapping) +def _compute_node_modules_root(ctx): + """Computes the node_modules root from the node_modules and deps attributes. + Args: + ctx: the skylark execution context + + Returns: + The node_modules root as a string + """ node_modules_root = None if ctx.files.node_modules: # ctx.files.node_modules is not an empty list @@ -58,8 +55,8 @@ def _write_loader_script(ctx): "node_modules", ] if f]) for d in ctx.attr.data: - if NodeModuleInfo in d: - possible_root = "/".join([d[NodeModuleInfo].workspace, "node_modules"]) + if NodeModuleSources in d: + possible_root = "/".join([d[NodeModuleSources].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -73,6 +70,21 @@ def _write_loader_script(ctx): ctx.attr.node_modules.label.package, "node_modules", ] if f]) + return node_modules_root + +def _write_loader_script(ctx): + # Generates the JavaScript snippet of module roots mappings, with each entry + # in the form: + # {module_name: /^mod_name\b/, module_root: 'path/to/mod_name'} + module_mappings = [] + for d in ctx.attr.data: + if hasattr(d, "runfiles_module_mappings"): + for [mn, mr] in d.runfiles_module_mappings.items(): + escaped = mn.replace("/", "\/").replace(".", "\.") + mapping = "{module_name: /^%s\\b/, module_root: '%s'}" % (escaped, mr) + module_mappings.append(mapping) + + node_modules_root = _compute_node_modules_root(ctx) ctx.actions.expand_template( template = ctx.file._loader_template, @@ -101,7 +113,13 @@ def _short_path_to_manifest_path(ctx, short_path): def _nodejs_binary_impl(ctx): node = ctx.file.node - node_modules = ctx.files.node_modules + node_modules = depset(ctx.files.node_modules) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NodeModuleSources provider. + for d in ctx.attr.data: + if NodeModuleSources in d: + node_modules = depset(transitive = [node_modules, d[NodeModuleSources].sources]) # Using a depset will allow us to avoid flattening files and sources # inside this loop. This should reduce the performances hits, @@ -151,7 +169,7 @@ def _nodejs_binary_impl(ctx): is_executable = True, ) - runfiles = depset([node, ctx.outputs.loader, ctx.file._repository_args] + node_modules + ctx.files._node_runfiles, transitive = [sources]) + runfiles = depset([node, ctx.outputs.loader, ctx.file._repository_args] + ctx.files._node_runfiles, transitive = [sources, node_modules]) return [DefaultInfo( executable = ctx.outputs.script, @@ -160,13 +178,13 @@ def _nodejs_binary_impl(ctx): files = [ node, ctx.outputs.loader, - ] + ctx.files._source_map_support_files + node_modules + + ] + ctx.files._source_map_support_files + # We need this call to the list of Files. # Calling the .to_list() method may have some perfs hits, # so we should be running this method only once per rule. # see: https://docs.bazel.build/versions/master/skylark/depsets.html#performance - sources.to_list(), + node_modules.to_list() + sources.to_list(), collect_data = True, ), )] diff --git a/internal/npm_install/BUILD.bazel b/internal/npm_install/BUILD.bazel index 740870555d..60b9e25c62 100644 --- a/internal/npm_install/BUILD.bazel +++ b/internal/npm_install/BUILD.bazel @@ -13,7 +13,6 @@ filegroup( name = "generate_build_file", srcs = [ "generate_build_file.js", - "//internal/ng_apf_library:ng_apf_library.js", ], visibility = ["//internal:__subpackages__"], ) diff --git a/internal/npm_install/generate_build_file.js b/internal/npm_install/generate_build_file.js index 98439210e4..5add0f00ae 100644 --- a/internal/npm_install/generate_build_file.js +++ b/internal/npm_install/generate_build_file.js @@ -17,9 +17,9 @@ /** * @fileoverview This script generates BUILD.bazel files by analyzing * the node_modules folder layed out by yarn or npm. It generates - * fine grained Bazel filegroup targets for each root npm package + * fine grained Bazel `node_module_library` targets for each root npm package * and all files for that package and its transitive deps are included - * in the filegroup. For example, `@//jasmine` would + * in the target. For example, `@//jasmine` would * include all files in the jasmine npm package and all of its * transitive dependencies. * @@ -28,7 +28,7 @@ * target will be generated for the `jasmine` binary in the `jasmine` * npm package. * - * Additionally, a `@//:node_modules` filegroup + * Additionally, a `@//:node_modules` `node_module_library` * is generated that includes all packages under node_modules * as well as the .bin folder. * @@ -41,10 +41,6 @@ const fs = require('fs'); const path = require('path'); -// When ng_apf_library.js is executed at installation time the script is copied -// from internal/ng_apf_library to external/npm so import path here is relative -// to current directory. -const apf = require('./ng_apf_library.js'); const BUILD_FILE_HEADER = `# Generated file from yarn_install/npm_install rule. # See $(bazel info output_base)/external/build_bazel_rules_nodejs/internal/npm_install/generate_build_file.js @@ -121,20 +117,14 @@ module.exports = {main}; function generateRootBuildFile(pkgs) { const srcs = pkgs.filter(pkg => !pkg._isNested); - let buildFile = BUILD_FILE_HEADER + `# The node_modules directory in one catch-all filegroup. + let buildFile = BUILD_FILE_HEADER + + `load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") + +# The node_modules directory in one catch-all node_module_library. # NB: Using this target may have bad performance implications if -# there are many files in filegroup. +# there are many files in target. # See https://github.com/bazelbuild/bazel/issues/5153. -# -# This filegroup includes only js, d.ts, json and proto files as well as the -# pkg/bin folders and .bin folder. This can be used in some cases to improve -# performance by reducing the number of runfiles. The recommended approach -# to reducing performance is to use fine grained deps such as -# ["@npm//a", "@npm//b", ...]. There are cases where the node_modules -# filegroup will not include files with no extension that are needed. The -# feature request https://github.com/bazelbuild/bazel/issues/5769 would allow -# this filegroup to include those files. -filegroup( +node_module_library( name = "node_modules", srcs = [ ${srcs.map(pkg => `"//node_modules/${pkg._dir}:${pkg._name}__files",`).join('\n ')} @@ -156,10 +146,7 @@ filegroup( * Generates all BUILD files for a package. */ function generatePackageBuildFiles(pkg) { - const buildFile = - BUILD_FILE_HEADER + `load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") - -` + printPackage(pkg); + const buildFile = BUILD_FILE_HEADER + printPackage(pkg); writeFileSync(path.posix.join('node_modules', pkg._dir, 'BUILD.bazel'), buildFile); const aliasBuildFile = BUILD_FILE_HEADER + printPackageAliases(pkg); @@ -644,13 +631,13 @@ function printJson(pkg) { } /** - * A filter function for a bazel filegroup. + * A filter function for files in an npm package. * @param files array of files to filter * @param exts list of white listed extensions; if empty, no filter is done on extensions; * '' empty string denotes to allow files with no extensions, other extensions * are listed with '.ext' notation such as '.d.ts'. */ -function filterFilesForFilegroup(files, exts = []) { +function filterFiles(files, exts = []) { // Files with spaces (\x20) or unicode characters (<\x20 && >\x7E) are not allowed in // Bazel runfiles. See https://github.com/bazelbuild/bazel/issues/4327 files = files.filter(f => !f.match(/[^\x21-\x7E]/)); @@ -672,53 +659,65 @@ function filterFilesForFilegroup(files, exts = []) { } /** - * Given a `pkg`, return the skylark `filegroup` target which is the default - * target for the alias `@npm//${pkg.name}`. + * Returns true if the specified `pkg` conforms to Angular Package Format (APF), + * false otherwise. If the package contains `*.metadata.json` and a + * corresponding sibling `.d.ts` file, then the package is considered to be APF. */ -function printPkgTarget(pkg, pkgDeps) { - return ` -filegroup( - name = "${pkg._name}__pkg", - srcs = [ - # ${pkg._dir} package contents (and contents of nested node_modules) - ":${pkg._name}__files", - # direct or transitive dependencies hoisted to root by the package manager - ${ - pkgDeps.map(dep => `"//node_modules/${dep._dir}:${dep._name}__files",`).join('\n ')} - ], - tags = ["NODE_MODULE_MARKER"], -) -`; +function isNgApfPackage(pkg) { + const set = new Set(pkg._files); + const metadataExt = /\.metadata\.json$/; + return pkg._files.some((file) => { + if (metadataExt.test(file)) { + const sibling = file.replace(metadataExt, '.d.ts'); + if (set.has(sibling)) { + return true; + } + } + return false; + }); } /** - * Given a pkg, return the skylark `filegroup` and/or `ng_apf_library` targets for the package. + * Given a pkg, return the skylark `node_module_library` targets for the package. */ function printPackage(pkg) { - const sources = filterFilesForFilegroup(pkg._files, INCLUDED_FILES); - const dtsSources = filterFilesForFilegroup(pkg._files, ['.d.ts']); + const sources = filterFiles(pkg._files, INCLUDED_FILES); + const dtsSources = filterFiles(pkg._files, ['.d.ts']); const pkgDeps = pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested); - let result = ` + let result = `load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") + # Generated targets for npm package "${pkg._dir}" ${printJson(pkg)} -${apf.isNgApfPackage(pkg) ? apf.printNgApfLibrary(pkg, pkgDeps) : printPkgTarget(pkg, pkgDeps)} +node_module_library( + name = "${pkg._name}__pkg", + # ${pkg._dir} package contents (and contents of nested node_modules) + srcs = [ + ":${pkg._name}__files", + ], + # flattened list of direct and transitive dependencies hoisted to root by the package manager + deps = [ + ${ + pkgDeps.map(dep => `"//node_modules/${dep._dir}:${dep._name}__files",`).join('\n ')} + ], + is_apf = ${isNgApfPackage(pkg) ? 'True' : 'False'}, +) -filegroup( +node_module_library( name = "${pkg._name}__files", srcs = [ ${sources.map(f => `":${f}",`).join('\n ')} ], - tags = ["NODE_MODULE_MARKER"], + is_apf = ${isNgApfPackage(pkg) ? 'True' : 'False'}, ) -filegroup( +node_module_library( name = "${pkg._name}__typings", srcs = [ ${dtsSources.map(f => `":${f}",`).join('\n ')} ], - tags = ["NODE_MODULE_MARKER"], ) `; @@ -803,18 +802,27 @@ alias( } /** - * Given a scope, return the skylark `filegroup` target for the scope. + * Given a scope, return the skylark `node_module_library` target for the scope. */ function printScope(scope, pkgs) { - const srcs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`)); - return ` + pkgs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`)); + let pkgDeps = []; + pkgs.forEach(pkg => { + pkgDeps = pkgDeps.concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested)); + }); + + return `load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") + # Generated target for npm scope ${scope} -filegroup( +node_module_library( name = "${scope}", srcs = [ - ${srcs.map(pkg => `"//node_modules/${pkg._dir}:${pkg._name}__pkg",`).join('\n ')} + ${pkgs.map(pkg => `"//node_modules/${pkg._dir}:${pkg._name}__files",`).join('\n ')} + ], + deps = [ + ${ + pkgDeps.map(dep => `"//node_modules/${dep._dir}:${dep._name}__files",`).join('\n ')} ], - tags = ["NODE_MODULE_MARKER"], ) `; diff --git a/internal/npm_install/node_module_library.bzl b/internal/npm_install/node_module_library.bzl new file mode 100644 index 0000000000..479db50457 --- /dev/null +++ b/internal/npm_install/node_module_library.bzl @@ -0,0 +1,70 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources") +load("@build_bazel_rules_nodejs//internal/common:providers.bzl", "ScriptsProvider") + +def _node_module_library_impl(ctx): + apf_umds = [] + apf_factories = [] + apf_summaries = [] + + # If this npm package is in the Angular package format then collect + # umd bundles, ngfactory files & ngsummary files and provide them + # via the ScriptsProvider + if ctx.attr.is_apf: + for file in ctx.files.srcs: + if file.basename.endswith(".umd.js"): + apf_umds.append(file) + elif file.basename.endswith(".ngfactory.js"): + apf_factories.append(file) + elif file.basename.endswith(".ngsummary.js"): + apf_summaries.append(file) + + sources = depset(transitive = [src.files for src in ctx.attr.srcs] + [dep.files for dep in ctx.attr.deps]) + workspace = ctx.label.workspace_root.split("/")[1] if ctx.label.workspace_root else ctx.workspace_name + + return [ + DefaultInfo( + files = sources, + ), + NodeModuleInfo( + workspace = workspace, + ), + NodeModuleSources( + sources = sources, + workspace = workspace, + ), + ScriptsProvider( + scripts = depset(apf_umds + apf_factories + apf_summaries), + ), + ] + +node_module_library = rule( + implementation = _node_module_library_impl, + attrs = { + "srcs": attr.label_list( + doc = "The list of files that comprise the package", + allow_files = True, + ), + "is_apf": attr.bool( + default = False, + doc = "True if this npm package is in the Angular package format", + ), + "deps": attr.label_list( + doc = "Transitive dependencies of the package", + ), + }, + doc = "Defines an npm package under node_modules", +) diff --git a/internal/npm_install/npm_install.bzl b/internal/npm_install/npm_install.bzl index affe40b311..9287b5cfa0 100644 --- a/internal/npm_install/npm_install.bzl +++ b/internal/npm_install/npm_install.bzl @@ -107,12 +107,6 @@ def _add_scripts(repository_ctx): {}, ) - repository_ctx.template( - "ng_apf_library.js", - repository_ctx.path(Label("//internal/ng_apf_library:ng_apf_library.js")), - {}, - ) - def _add_data_dependencies(repository_ctx): """Add data dependencies to the repository.""" for f in repository_ctx.attr.data: diff --git a/internal/npm_install/test/BUILD.bazel b/internal/npm_install/test/BUILD.bazel index 337f425f87..ec4524bd56 100644 --- a/internal/npm_install/test/BUILD.bazel +++ b/internal/npm_install/test/BUILD.bazel @@ -13,10 +13,8 @@ filegroup( jasmine_node_test( name = "test", srcs = glob(["*.spec.js"]), - bootstrap = ["build_bazel_rules_nodejs/internal/npm_install/test/copy_ng_apf_library.js"], data = [ ":check.js", - ":copy_ng_apf_library.js", ":goldens", ":package", "//internal/npm_install:generate_build_file", @@ -27,10 +25,8 @@ jasmine_node_test( nodejs_binary( name = "test.accept", - bootstrap = ["build_bazel_rules_nodejs/internal/npm_install/test/copy_ng_apf_library.js"], data = [ ":check.js", - ":copy_ng_apf_library.js", ":goldens", ":package", ":update_golden.js", diff --git a/internal/npm_install/test/copy_ng_apf_library.js b/internal/npm_install/test/copy_ng_apf_library.js deleted file mode 100644 index baf8f97a58..0000000000 --- a/internal/npm_install/test/copy_ng_apf_library.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @fileoverview - * This script is run as part of the nodejs binary bootstrapping process. - * It is required because generate_build_file.js imports ng_apf_library.js - * from the same directory it is in. This script moves the dependency to the - * right location to simulate Bazel copy the template to npm/external. - */ - -const path = require('path'); -const fs = require('fs'); - -let source, dist; -const {RUNFILES_MANIFEST_FILE, TEST_TARGET} = process.env; - -// Read the manifest only when running under `bazel test`. -if (TEST_TARGET && RUNFILES_MANIFEST_FILE) { - // This code path is executed on Windows where runfiles are not used. - const manifest = fs.readFileSync(RUNFILES_MANIFEST_FILE, 'utf-8'); - const entry = manifest.split('\n').find(line => { - return line.startsWith("build_bazel_rules_nodejs/internal/ng_apf_library/ng_apf_library.js"); - }); - if (!entry) { - throw new Error(`Could not find entry for 'ng_apf_library.js' in MANIFEST`); - } - source = entry.split(' ')[1]; - dest = path.resolve(source, '../../npm_install/ng_apf_library.js'); -} else { - // For generating the golden files under `bazel run`. - source = 'internal/ng_apf_library/ng_apf_library.js'; - dest = 'internal/npm_install/ng_apf_library.js'; -} - -fs.copyFileSync(source, dest); diff --git a/internal/npm_install/test/golden/BUILD.bazel.golden b/internal/npm_install/test/golden/BUILD.bazel.golden index a202f9d5b0..9adc7d434e 100644 --- a/internal/npm_install/test/golden/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/BUILD.bazel.golden @@ -1,6 +1,7 @@ package(default_visibility = ["//visibility:public"]) -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "node_modules", srcs = [ "//node_modules/.bin:.bin__files", diff --git a/internal/npm_install/test/golden/node_modules/@angular/core/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/@angular/core/BUILD.bazel.golden index 82fd6fa63b..7345bbca24 100644 --- a/internal/npm_install/test/golden/node_modules/@angular/core/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/@angular/core/BUILD.bazel.golden @@ -1,20 +1,20 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -load("@build_bazel_rules_nodejs//internal/ng_apf_library:ng_apf_library.bzl", "ng_apf_library") -ng_apf_library( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "core__pkg", srcs = [ ":core__files", ], deps = [ - "//node_modules/tslib:tslib__pkg", - "//node_modules/rxjs:rxjs__pkg", - "//node_modules/zone.js:zone.js__pkg", + "//node_modules/tslib:tslib__files", + "//node_modules/rxjs:rxjs__files", + "//node_modules/zone.js:zone.js__files", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = True, ) -filegroup( +node_module_library( name = "core__files", srcs = [ ":README.md", @@ -629,9 +629,9 @@ filegroup( ":testing/testing.d.ts", ":testing/testing.metadata.json", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = True, ) -filegroup( +node_module_library( name = "core__typings", srcs = [ ":core.d.ts", @@ -830,5 +830,4 @@ filegroup( ":testing/src/testing_internal.d.ts", ":testing/testing.d.ts", ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/@gregmagolan/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/@gregmagolan/BUILD.bazel.golden index def527cf3c..6a226a0972 100644 --- a/internal/npm_install/test/golden/node_modules/@gregmagolan/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/@gregmagolan/BUILD.bazel.golden @@ -1,10 +1,13 @@ package(default_visibility = ["//visibility:public"]) -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "@gregmagolan", srcs = [ - "//node_modules/@gregmagolan/test-a:test-a__pkg", - "//node_modules/@gregmagolan/test-b:test-b__pkg", + "//node_modules/@gregmagolan/test-a:test-a__files", + "//node_modules/@gregmagolan/test-b:test-b__files", + ], + deps = [ + ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/@gregmagolan/test-a/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/@gregmagolan/test-a/BUILD.bazel.golden index 881edc16f0..3a50293b78 100644 --- a/internal/npm_install/test/golden/node_modules/@gregmagolan/test-a/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/@gregmagolan/test-a/BUILD.bazel.golden @@ -1,29 +1,31 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "test-a__pkg", srcs = [ ":test-a__files", + ], + deps = [ ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "test-a__files", srcs = [ ":@bin/test.js", ":main.js", ":package.json", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "test-a__typings", srcs = [ ], - tags = ["NODE_MODULE_MARKER"], ) nodejs_binary( name = "test__bin", diff --git a/internal/npm_install/test/golden/node_modules/@gregmagolan/test-b/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/@gregmagolan/test-b/BUILD.bazel.golden index 8d298f3d10..fc274df3b5 100644 --- a/internal/npm_install/test/golden/node_modules/@gregmagolan/test-b/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/@gregmagolan/test-b/BUILD.bazel.golden @@ -1,15 +1,18 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "test-b__pkg", srcs = [ ":test-b__files", + ], + deps = [ ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "test-b__files", srcs = [ ":main.js", @@ -17,12 +20,11 @@ filegroup( ":node_modules/@gregmagolan/test-a/package.json", ":package.json", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "test-b__typings", srcs = [ ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/ajv/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/ajv/BUILD.bazel.golden index eea9f62917..3a650c2b57 100644 --- a/internal/npm_install/test/golden/node_modules/ajv/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/ajv/BUILD.bazel.golden @@ -1,18 +1,21 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "ajv__pkg", srcs = [ ":ajv__files", + ], + deps = [ "//node_modules/co:co__files", "//node_modules/fast-deep-equal:fast-deep-equal__files", "//node_modules/fast-json-stable-stringify:fast-json-stable-stringify__files", "//node_modules/json-schema-traverse:json-schema-traverse__files", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "ajv__files", srcs = [ ":.tonic_example.js", @@ -104,12 +107,11 @@ filegroup( ":scripts/prepare-tests", ":scripts/travis-gh-pages", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "ajv__typings", srcs = [ ":lib/ajv.d.ts", ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/jasmine/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/jasmine/BUILD.bazel.golden index 094243a005..2d22bf989f 100644 --- a/internal/npm_install/test/golden/node_modules/jasmine/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/jasmine/BUILD.bazel.golden @@ -1,10 +1,13 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "jasmine__pkg", srcs = [ ":jasmine__files", + ], + deps = [ "//node_modules/glob:glob__files", "//node_modules/fs.realpath:fs.realpath__files", "//node_modules/inflight:inflight__files", @@ -18,9 +21,9 @@ filegroup( "//node_modules/path-is-absolute:path-is-absolute__files", "//node_modules/jasmine-core:jasmine-core__files", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "jasmine__files", srcs = [ ":.editorconfig", @@ -38,14 +41,13 @@ filegroup( ":package.json", ":tasks/jasmine.js", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "jasmine__typings", srcs = [ ], - tags = ["NODE_MODULE_MARKER"], ) nodejs_binary( name = "jasmine__bin", diff --git a/internal/npm_install/test/golden/node_modules/rxjs/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/rxjs/BUILD.bazel.golden index e3cd33d0b0..8404795b48 100644 --- a/internal/npm_install/test/golden/node_modules/rxjs/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/rxjs/BUILD.bazel.golden @@ -1,15 +1,18 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "rxjs__pkg", srcs = [ ":rxjs__files", + ], + deps = [ "//node_modules/tslib:tslib__files", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "rxjs__files", srcs = [ ":AsyncSubject.d.ts", @@ -3570,9 +3573,9 @@ filegroup( ":webSocket/index.js.map", ":webSocket/package.json", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "rxjs__typings", srcs = [ ":AsyncSubject.d.ts", @@ -4238,5 +4241,4 @@ filegroup( ":util/tryCatch.d.ts", ":webSocket/index.d.ts", ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/unidiff/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/unidiff/BUILD.bazel.golden index 854b3a1bd9..cfd7ea5e96 100644 --- a/internal/npm_install/test/golden/node_modules/unidiff/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/unidiff/BUILD.bazel.golden @@ -1,15 +1,18 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "unidiff__pkg", srcs = [ ":unidiff__files", + ], + deps = [ "//node_modules/diff:diff__files", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "unidiff__files", srcs = [ ":.npmignore", @@ -23,12 +26,11 @@ filegroup( ":test/test_unidiff.js", ":unidiff.js", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "unidiff__typings", srcs = [ ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/npm_install/test/golden/node_modules/zone.js/BUILD.bazel.golden b/internal/npm_install/test/golden/node_modules/zone.js/BUILD.bazel.golden index b88a4050f8..fdfd80f724 100644 --- a/internal/npm_install/test/golden/node_modules/zone.js/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/node_modules/zone.js/BUILD.bazel.golden @@ -1,15 +1,18 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") -filegroup( +load("@build_bazel_rules_nodejs//internal/npm_install:node_module_library.bzl", "node_module_library") +node_module_library( name = "zone.js__pkg", srcs = [ ":zone.js__files", + ], + deps = [ ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "zone.js__files", srcs = [ ":CHANGELOG.md", @@ -141,12 +144,11 @@ filegroup( ":lib/zone.ts", ":package.json", ], - tags = ["NODE_MODULE_MARKER"], + is_apf = False, ) -filegroup( +node_module_library( name = "zone.js__typings", srcs = [ ":dist/zone.js.d.ts", ], - tags = ["NODE_MODULE_MARKER"], ) diff --git a/internal/rollup/rollup_bundle.bzl b/internal/rollup/rollup_bundle.bzl index 0c35d165a5..67b6309190 100644 --- a/internal/rollup/rollup_bundle.bzl +++ b/internal/rollup/rollup_bundle.bzl @@ -18,9 +18,9 @@ The versions of Rollup and terser are controlled by the Bazel toolchain. You do not need to install them into your project. """ +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") load("//internal/common:collect_es6_sources.bzl", _collect_es2015_sources = "collect_es6_sources") load("//internal/common:module_mappings.bzl", "get_module_mappings") -load("//internal/common:node_module_info.bzl", "NodeModuleInfo", "collect_node_modules_aspect") _ROLLUP_MODULE_MAPPINGS_ATTR = "rollup_module_mappings" @@ -44,6 +44,42 @@ def _trim_package_node_modules(package_name): segments += [n] return "/".join(segments) +# This function is similar but slightly different than _compute_node_modules_root +# in /internal/node/node.bzl. TODO(gregmagolan): consolidate these functions +def _compute_node_modules_root(ctx): + """Computes the node_modules root from the node_modules and deps attributes. + + Args: + ctx: the skylark execution context + + Returns: + The node_modules root as a string + """ + node_modules_root = None + if ctx.files.node_modules: + # ctx.files.node_modules is not an empty list + node_modules_root = "/".join([f for f in [ + ctx.attr.node_modules.label.workspace_root, + _trim_package_node_modules(ctx.attr.node_modules.label.package), + "node_modules", + ] if f]) + for d in ctx.attr.deps: + if NodeModuleSources in d: + possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) + if not node_modules_root: + node_modules_root = possible_root + elif node_modules_root != possible_root: + fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (node_modules_root, possible_root)) + if not node_modules_root: + # there are no fine grained deps and the node_modules attribute is an empty filegroup + # but we still need a node_modules_root even if its empty + node_modules_root = "/".join([f for f in [ + ctx.attr.node_modules.label.workspace_root, + ctx.attr.node_modules.label.package, + "node_modules", + ] if f]) + return node_modules_root + def write_rollup_config(ctx, plugins = [], root_dir = None, filename = "_%s.rollup.conf.js", output_format = "iife", additional_entry_points = []): """Generate a rollup config file. @@ -82,33 +118,10 @@ def write_rollup_config(ctx, plugins = [], root_dir = None, filename = "_%s.roll # This must be .es6 to match collect_es6_sources.bzl root_dir = "/".join([ctx.bin_dir.path, build_file_dirname, ctx.label.name + ".es6"]) - node_modules_root = None + node_modules_root = _compute_node_modules_root(ctx) is_default_node_modules = False - if ctx.files.node_modules: - # ctx.files.node_modules is not an empty list - node_modules_root = "/".join([f for f in [ - ctx.attr.node_modules.label.workspace_root, - _trim_package_node_modules(ctx.attr.node_modules.label.package), - "node_modules", - ] if f]) - for d in ctx.attr.deps: - if NodeModuleInfo in d: - possible_root = "/".join(["external", d[NodeModuleInfo].workspace, "node_modules"]) - if not node_modules_root: - node_modules_root = possible_root - elif node_modules_root != possible_root: - fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (node_modules_root, possible_root)) - if not node_modules_root: - # there are no fine grained deps and the node_modules attribute is an empty filegroup - # but we still need a node_modules_root even if its empty - workspace = ctx.attr.node_modules.label.workspace_root.split("/")[1] if ctx.attr.node_modules.label.workspace_root else ctx.workspace_name - if workspace == "build_bazel_rules_nodejs" and ctx.attr.node_modules.label.package == "" and ctx.attr.node_modules.label.name == "node_modules_none": - is_default_node_modules = True - node_modules_root = "/".join([f for f in [ - ctx.attr.node_modules.label.workspace_root, - ctx.attr.node_modules.label.package, - "node_modules", - ] if f]) + if node_modules_root == "node_modules" and ctx.attr.node_modules.label.package == "" and ctx.attr.node_modules.label.name == "node_modules_none": + is_default_node_modules = True ctx.actions.expand_template( output = config, @@ -184,11 +197,11 @@ def _run_rollup(ctx, sources, config, output, map_output = None): direct_inputs += _filter_js_inputs(ctx.files.node_modules) # Also include files from npm fine grained deps as inputs. - # These deps are identified by the NodeModuleInfo provider. + # These deps are identified by the NodeModuleSources provider. for d in ctx.attr.deps: - if NodeModuleInfo in d: - # Note: we can't avoid calling .to_list() on files - direct_inputs += _filter_js_inputs(d.files.to_list()) + if NodeModuleSources in d: + # Note: we can't avoid calling .to_list() on sources + direct_inputs += _filter_js_inputs(d[NodeModuleSources].sources.to_list()) if ctx.file.license_banner: direct_inputs += [ctx.file.license_banner] diff --git a/packages/typescript/internal/build_defs.bzl b/packages/typescript/internal/build_defs.bzl index 4061186f20..29b98914ac 100644 --- a/packages/typescript/internal/build_defs.bzl +++ b/packages/typescript/internal/build_defs.bzl @@ -14,7 +14,7 @@ "TypeScript compilation" -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources", "collect_node_modules_aspect") # pylint: disable=unused-argument # pylint: disable=missing-docstring @@ -35,6 +35,8 @@ def _trim_package_node_modules(package_name): segments += [n] return "/".join(segments) +# This function is similar but slightly different than _compute_node_modules_root +# in /internal/node/node.bzl. TODO(gregmagolan): consolidate these functions def _compute_node_modules_root(ctx): """Computes the node_modules root from the node_modules and deps attributes. @@ -53,8 +55,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.deps: - if NodeModuleInfo in d: - possible_root = "/".join(["external", d[NodeModuleInfo].workspace, "node_modules"]) + if NodeModuleSources in d: + possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -100,10 +102,11 @@ def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description action_inputs.extend(_filter_ts_inputs(ctx.files.node_modules)) # Also include files from npm fine grained deps as action_inputs. - # These deps are identified by the NodeModuleInfo provider. + # These deps are identified by the NodeModuleSources provider. for d in ctx.attr.deps: - if NodeModuleInfo in d: - action_inputs.extend(_filter_ts_inputs(d.files.to_list())) + if NodeModuleSources in d: + # Note: we can't avoid calling .to_list() on sources + action_inputs.extend(_filter_ts_inputs(d[NodeModuleSources].sources.to_list())) if ctx.file.tsconfig: action_inputs.append(ctx.file.tsconfig)