diff --git a/docs/Providers.md b/docs/Providers.md
index 6e70e0dbbb..5d86d351dc 100755
--- a/docs/Providers.md
+++ b/docs/Providers.md
@@ -66,7 +66,7 @@ Joins a label pointing to a TreeArtifact with a path nested within that director
**USAGE**
-ExternalNpmPackageInfo(direct_sources, has_directories, path, sources, workspace)
+ExternalNpmPackageInfo(direct_sources, path, sources, workspace)
Provides information about one or more external npm packages
@@ -76,9 +76,6 @@ Provides information about one or more external npm packages
direct_sources
Depset of direct source files in these external npm package(s)
-has_directories
-
- True if any sources are directories
path
The local workspace path that these external npm deps should be linked at. If empty, they will be linked at the root.
@@ -260,7 +257,7 @@ do the same.
**USAGE**
-NpmPackageInfo(direct_sources, has_directories, path, sources, workspace)
+NpmPackageInfo(direct_sources, path, sources, workspace)
Provides information about one or more external npm packages
@@ -270,9 +267,6 @@ Provides information about one or more external npm packages
direct_sources
Depset of direct source files in these external npm package(s)
-has_directories
-
- True if any sources are directories
path
The local workspace path that these external npm deps should be linked at. If empty, they will be linked at the root.
diff --git a/internal/js_library/js_library.bzl b/internal/js_library/js_library.bzl
index 7f52858801..14e11c74c6 100644
--- a/internal/js_library/js_library.bzl
+++ b/internal/js_library/js_library.bzl
@@ -110,14 +110,14 @@ def _link_path(ctx, all_files):
link_path += "/" + ctx.attr.strip_prefix
# Check that strip_prefix contains at least one src path
- check_prefix = "/".join([p for p in [ctx.label.package, ctx.attr.strip_prefix] if p])
- prefix_contains_src = False
- for file in all_files:
- if file.short_path.startswith(check_prefix):
- prefix_contains_src = True
- break
- if not prefix_contains_src:
- fail("js_library %s strip_prefix path does not contain any of the provided sources" % ctx.label)
+ # check_prefix = "/".join([p for p in [ctx.label.package, ctx.attr.strip_prefix] if p])
+ # prefix_contains_src = False
+ # for file in all_files:
+ # if file.short_path.startswith(check_prefix):
+ # prefix_contains_src = True
+ # break
+ # if not prefix_contains_src:
+ # fail("js_library %s strip_prefix path does not contain any of the provided sources" % ctx.label)
return link_path
@@ -127,10 +127,14 @@ def _impl(ctx):
typings = []
js_files = []
named_module_files = []
+ has_directories = False
for idx, f in enumerate(input_files):
file = f
+ if file.is_directory:
+ has_directories = True
+
# copy files into bin if needed
if file.is_source and not file.path.startswith("external/"):
dst = ctx.actions.declare_file(file.basename, sibling = file)
@@ -226,7 +230,7 @@ def _impl(ctx):
),
]
- if ctx.attr.package_name == "$node_modules$" or ctx.attr.package_name == "$node_modules_dir$":
+ if ctx.attr.package_name == "$node_modules$":
# special case for external npm deps
workspace_name = ctx.label.workspace_name if ctx.label.workspace_name else ctx.workspace_name
providers.append(ExternalNpmPackageInfo(
@@ -234,7 +238,6 @@ def _impl(ctx):
sources = depset(transitive = npm_sources_depsets),
workspace = workspace_name,
path = ctx.attr.package_path,
- has_directories = (ctx.attr.package_name == "$node_modules_dir$"),
))
else:
providers.append(LinkablePackageInfo(
@@ -253,7 +256,7 @@ def _impl(ctx):
deps = ctx.attr.deps,
))
providers.append(OutputGroupInfo(types = decls))
- elif ctx.attr.package_name == "$node_modules_dir$":
+ elif has_directories:
# If this is directory artifacts npm package then always provide declaration_info
# since we can't scan through files
decls = depset(transitive = files_depsets)
diff --git a/internal/linker/test/default_path/custom_external_npm_package_info.bzl b/internal/linker/test/default_path/custom_external_npm_package_info.bzl
index 865934c4aa..98a5c3090e 100644
--- a/internal/linker/test/default_path/custom_external_npm_package_info.bzl
+++ b/internal/linker/test/default_path/custom_external_npm_package_info.bzl
@@ -9,7 +9,6 @@ def _custom_external_npm_package_info_impl(ctx):
return ExternalNpmPackageInfo(
direct_sources = depset([], transitive = ctx.files.deps),
sources = depset(ctx.files.srcs, transitive = ctx.files.deps),
- has_directories = False,
workspace = "npm",
# `path` is intentionally **not** provided.
# Historical note: `ExternalNpmPackageInfo` was publicly exported prior
diff --git a/internal/node/test/BUILD.bazel b/internal/node/test/BUILD.bazel
index 0b0cb8e8cf..96472ce4c0 100644
--- a/internal/node/test/BUILD.bazel
+++ b/internal/node/test/BUILD.bazel
@@ -511,29 +511,3 @@ nodejs_test(
data = [":main_lib"],
entry_point = ":main.js",
)
-
-# Test that we can run a nodejs_binary with --bazel_patch_module_resolver with exports_directories_only = True
-nodejs_binary(
- name = "protractor_directory_artifacts_version",
- data = ["@npm_directory_artifacts//protractor"],
- entry_point = {"@npm_directory_artifacts//:node_modules/protractor": "bin/protractor"},
- tags = ["requires-runfiles"],
- templated_args = [
- "--bazel_patch_module_resolver",
- "--version",
- ],
-)
-
-npm_package_bin(
- name = "protractor_directory_artifacts_version_output",
- stdout = "protractor_directory_artifacts_version.out",
- tags = ["requires-runfiles"],
- tool = ":protractor_directory_artifacts_version",
-)
-
-generated_file_test(
- name = "protractor_directory_artifacts_version_test",
- src = "protractor_directory_artifacts_version.golden",
- generated = ":protractor_directory_artifacts_version.out",
- tags = ["requires-runfiles"],
-)
diff --git a/internal/npm_install/generate_build_file.ts b/internal/npm_install/generate_build_file.ts
index 576ea5267e..b018d4f408 100644
--- a/internal/npm_install/generate_build_file.ts
+++ b/internal/npm_install/generate_build_file.ts
@@ -49,7 +49,7 @@ function log_verbose(...m: any[]) {
const PUBLIC_VISIBILITY = '//visibility:public';
-let NODE_MODULES_PACKAGE_NAME = '$node_modules$';
+let LEGACY_NODE_MODULES_PACKAGE_NAME = '$node_modules$';
// Default values for unit testing; overridden in main()
let config: any = {
@@ -138,10 +138,6 @@ export async function main() {
config = require('./generate_config.json');
config.limited_visibility = `@${config.workspace}//:__subpackages__`;
- if (config.exports_directories_only) {
- NODE_MODULES_PACKAGE_NAME = '$node_modules_dir$';
- }
-
// get a set of all the direct dependencies for visibility
const deps = await getDirectDependencySet(config.package_json);
@@ -208,14 +204,60 @@ function flattenDependencies(pkgs: Dep[]) {
* Generates the root BUILD file.
*/
async function generateRootBuildFile(pkgs: Dep[]) {
+ let buildFile = config.exports_directories_only ?
+ printRootExportsDirectories(pkgs) :
+ printRoot(pkgs);
+
+ // Add the manual build file contents if they exists
+ try {
+ const manualContents = await fs.readFile(`manual_build_file_contents`, {encoding: 'utf8'});
+ buildFile += '\n\n';
+ buildFile += manualContents;
+ } catch (e) {
+ }
+
+ await writeFile('BUILD.bazel', buildFile);
+}
+
+function printRootExportsDirectories(pkgs: Dep[]) {
+ let filegroupsStarlark = '';
+ pkgs.forEach(pkg => filegroupsStarlark += `filegroup(
+ name = "${pkg._dir.replace("/", "_")}__source_directory",
+ srcs = ["node_modules/${pkg._dir}"],
+ visibility = ["@${config.workspace}//:__subpackages__"],
+)
+
+`);
+
+let depsStarlark = '';
+if (pkgs.length) {
+ const list = pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}",`).join('\n ');
+ depsStarlark = `
+ deps = [
+ ${list}
+ ],`;
+}
+
+ const result =
+ generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+
+${filegroupsStarlark}
+
+# The node_modules directory in one catch-all js_library
+js_library(
+ name = "node_modules",${depsStarlark}
+)`;
+
+ return result
+}
+
+function printRoot(pkgs: Dep[]) {
let pkgFilesStarlark = '';
if (pkgs.length) {
let list = '';
list = pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__files",`).join('\n ');
- if (!config.exports_directories_only) {
- list += '\n ';
- list += pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__nested_node_modules",`).join('\n ');
- }
+ list += '\n ';
+ list += pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__nested_node_modules",`).join('\n ');
pkgFilesStarlark = `
# direct sources listed for strict deps support
srcs = [
@@ -234,15 +276,11 @@ async function generateRootBuildFile(pkgs: Dep[]) {
}
let exportsStarlark = '';
- if (config.exports_directories_only) {
- pkgs.forEach(pkg => exportsStarlark += ` "node_modules/${pkg._dir}",\n`);
- } else {
- pkgs.forEach(pkg => {pkg._files.forEach(f => {
- exportsStarlark += ` "node_modules/${pkg._dir}/${f}",\n`;
- });});
- }
+ pkgs.forEach(pkg => {pkg._files.forEach(f => {
+ exportsStarlark += ` "node_modules/${pkg._dir}/${f}",\n`;
+ });});
- let buildFile =
+ const result =
generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
exports_files([
@@ -254,19 +292,13 @@ ${exportsStarlark}])
# See https://github.com/bazelbuild/bazel/issues/5153.
js_library(
name = "node_modules",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${pkgFilesStarlark}${depsStarlark}
)
`;
- // Add the manual build file contents if they exists
- try {
- buildFile += await fs.readFile(`manual_build_file_contents`, {encoding: 'utf8'});
- } catch (e) {
- }
-
- await writeFile('BUILD.bazel', buildFile);
+ return result
}
/**
@@ -301,7 +333,7 @@ async function generatePackageBuildFiles(pkg: Dep) {
// The following won't be used in a symlink build file case
let buildFile = config.exports_directories_only ?
- printPackageExperimentalDirectoryArtifacts(pkg) :
+ printPackageExportsDirectories(pkg) :
printPackage(pkg);
if (buildFilePath) {
buildFile = buildFile + '\n' +
@@ -477,7 +509,17 @@ def _maybe(repo_rule, name, **kwargs):
* Generate build files for a scope.
*/
async function generateScopeBuildFiles(scope: string, pkgs: Dep[]) {
- const buildFile = generateBuildFileHeader() + printScope(scope, pkgs);
+ pkgs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`));
+ let deps: Dep[] = [];
+ pkgs.forEach(pkg => {
+ deps = deps.concat(pkg._dependencies.filter(dep => !dep._isNested && !pkgs.includes(pkg)));
+ });
+ // filter out duplicate deps
+ deps = [...pkgs, ...new Set(deps)];
+
+ let buildFile = config.exports_directories_only ?
+ printScopeExportsDirectories(scope, deps) :
+ printScope(scope, deps);
await writeFile(path.posix.join(scope, 'BUILD.bazel'), buildFile);
}
@@ -998,32 +1040,28 @@ function findFile(pkg: Dep, m: string) {
/**
* Given a pkg, return the skylark `js_library` targets for the package.
*/
-function printPackageExperimentalDirectoryArtifacts(pkg: Dep) {
+function printPackageExportsDirectories(pkg: Dep) {
// Flattened list of direct and transitive dependencies hoisted to root by the package manager
const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested));
const depsStarlark =
deps.map(dep => `"//${dep._dir}:${dep._name}__contents",`).join('\n ');
let result = `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
# Generated targets for npm package "${pkg._dir}"
${printJson(pkg)}
-# Files that are part of the npm package
-filegroup(
- name = "${pkg._name}__files",
- srcs = ["//:node_modules/${pkg._dir}"],
+# To support remote-execution, we must create a tree artifact from the source directory
+copy_directory(
+ name = "directory",
+ src = "@${config.workspace}//:${pkg._dir.replace("/", "_")}__source_directory",
+ out = "tree",
)
# The primary target for this package for use in rule deps
js_library(
name = "${pkg._name}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
- package_path = "${config.package_path}",
- # direct sources listed for strict deps support
- srcs = [":${pkg._name}__files"],
- # nested node_modules for this package plus flattened list of direct and transitive dependencies
- # hoisted to root by the package manager
deps = [
${depsStarlark}
],
@@ -1031,17 +1069,30 @@ js_library(
# Target is used as dep for main targets to prevent circular dependencies errors
js_library(
- name = "${pkg._name}__contents",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ name = "contents",
+ package_name = "${pkg._dir}",
package_path = "${config.package_path}",
- srcs = [":${pkg._name}__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+# For ts_library backward compat which uses @npm//typescript:__files
+alias(
+ name = "${pkg._name}__files",
+ actual = "directory",
+)
+
+# For ts_library backward compat which uses @npm//typescript:__files
+alias(
+ name = "${pkg._name}__contents",
+ actual = "contents",
+)
+
# For ts_library backward compat which uses @npm//typescript:typescript__typings
alias(
name = "${pkg._name}__typings",
- actual = "${pkg._name}__contents",
+ actual = "contents",
)
`;
@@ -1056,7 +1107,7 @@ alias(
npm_umd_bundle(
name = "${pkg._name}__umd",
package_name = "${pkg._moduleName}",
- entry_point = { "@${config.workspace}//:node_modules/${pkg._dir}": "${mainEntryPoint}" },
+ entry_point = { "@${config.workspace}//:${pkg._dir.replace("/", "_")}__source_directory": "${mainEntryPoint}" },
package = ":${pkg._name}",
)
@@ -1162,7 +1213,7 @@ filegroup(
# The primary target for this package for use in rule deps
js_library(
name = "${pkg._name}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",
# direct sources listed for strict deps support
srcs = [":${pkg._name}__files"],
@@ -1176,7 +1227,7 @@ js_library(
# Target is used as dep for main targets to prevent circular dependencies errors
js_library(
name = "${pkg._name}__contents",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",
srcs = [":${pkg._name}__files", ":${pkg._name}__nested_node_modules"],${namedSourcesStarlark}
visibility = ["//:__subpackages__"],
@@ -1185,7 +1236,7 @@ js_library(
# Typings files that are part of the npm package not including nested node_modules
js_library(
name = "${pkg._name}__typings",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${dtsStarlark}
)
@@ -1279,7 +1330,7 @@ export function printPackageBin(pkg: Dep) {
for (const [name, path] of executables.entries()) {
const entryPoint = config.exports_directories_only ?
- `{ "@${config.workspace}//:node_modules/${pkg._dir}": "${path}" }` :
+ `{ "@${config.workspace}//${pkg._dir}:${pkg._name}__files": "${path}" }` :
`"@${config.workspace}//:node_modules/${pkg._dir}/${path}"`;
result += `# Wire up the \`bin\` entry \`${name}\`
nodejs_binary(
@@ -1309,7 +1360,7 @@ export function printIndexBzl(pkg: Dep) {
for (const [name, path] of executables.entries()) {
const entryPoint = config.exports_directories_only ?
- `{ "@${config.workspace}//:node_modules/${pkg._dir}": "${path}" }` :
+ `{ "@${config.workspace}//${pkg._dir}:${pkg._name}__files": "${path}" }` :
`"@${config.workspace}//:node_modules/${pkg._dir}/${path}"`;
result = `${result}
@@ -1354,15 +1405,7 @@ type Dep = {
/**
* Given a scope, return the skylark `js_library` target for the scope.
*/
-function printScope(scope: string, pkgs: Dep[]) {
- pkgs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`));
- let deps: Dep[] = [];
- pkgs.forEach(pkg => {
- deps = deps.concat(pkg._dependencies.filter(dep => !dep._isNested && !pkgs.includes(pkg)));
- });
- // filter out duplicate deps
- deps = [...pkgs, ...new Set(deps)];
-
+function printScope(scope: string, deps: Dep[]) {
let pkgFilesStarlark = '';
if (deps.length) {
const list = deps.map(dep => `"//${dep._dir}:${dep._name}__files",`).join('\n ');
@@ -1383,14 +1426,36 @@ function printScope(scope: string, pkgs: Dep[]) {
],`;
}
- return `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+ return generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
# Generated target for npm scope ${scope}
js_library(
name = "${scope}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${pkgFilesStarlark}${depsStarlark}
)
`;
}
+
+function printScopeExportsDirectories(scope: string, deps: Dep[]) {
+ let depsStarlark = '';
+ if (deps.length) {
+ const list = deps.map(dep => `"//${dep._dir}",`).join('\n ');
+ depsStarlark = `
+ # flattened list of direct and transitive dependencies hoisted to root by the package manager
+ deps = [
+ ${list}
+ ],`;
+ }
+
+ return generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+
+# Generated target for npm scope ${scope}
+js_library(
+ name = "${scope}",
+ ${depsStarlark}
+)
+
+`;
+}
\ No newline at end of file
diff --git a/internal/npm_install/index.js b/internal/npm_install/index.js
index 07383dce9b..9530858a04 100644
--- a/internal/npm_install/index.js
+++ b/internal/npm_install/index.js
@@ -9,7 +9,7 @@ function log_verbose(...m) {
console.error('[generate_build_file.ts]', ...m);
}
const PUBLIC_VISIBILITY = '//visibility:public';
-let NODE_MODULES_PACKAGE_NAME = '$node_modules$';
+let LEGACY_NODE_MODULES_PACKAGE_NAME = '$node_modules$';
let config = {
exports_directories_only: false,
generate_local_modules_build_files: false,
@@ -71,9 +71,6 @@ async function createFileSymlink(target, p) {
async function main() {
config = require('./generate_config.json');
config.limited_visibility = `@${config.workspace}//:__subpackages__`;
- if (config.exports_directories_only) {
- NODE_MODULES_PACKAGE_NAME = '$node_modules_dir$';
- }
const deps = await getDirectDependencySet(config.package_json);
const pkgs = [];
await findPackagesAndPush(pkgs, 'node_modules', deps);
@@ -112,14 +109,52 @@ function flattenDependencies(pkgs) {
pkgs.forEach(pkg => flattenPkgDependencies(pkg, pkg, pkgsMap));
}
async function generateRootBuildFile(pkgs) {
+ let buildFile = config.exports_directories_only ?
+ printRootExportsDirectories(pkgs) :
+ printRoot(pkgs);
+ try {
+ const manualContents = await fs_1.promises.readFile(`manual_build_file_contents`, { encoding: 'utf8' });
+ buildFile += '\n\n';
+ buildFile += manualContents;
+ }
+ catch (e) {
+ }
+ await writeFile('BUILD.bazel', buildFile);
+}
+function printRootExportsDirectories(pkgs) {
+ let filegroupsStarlark = '';
+ pkgs.forEach(pkg => filegroupsStarlark += `filegroup(
+ name = "${pkg._dir.replace("/", "_")}__source_directory",
+ srcs = ["node_modules/${pkg._dir}"],
+ visibility = ["@${config.workspace}//:__subpackages__"],
+)
+
+`);
+ let depsStarlark = '';
+ if (pkgs.length) {
+ const list = pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}",`).join('\n ');
+ depsStarlark = `
+ deps = [
+ ${list}
+ ],`;
+ }
+ const result = generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+
+${filegroupsStarlark}
+
+# The node_modules directory in one catch-all js_library
+js_library(
+ name = "node_modules",${depsStarlark}
+)`;
+ return result;
+}
+function printRoot(pkgs) {
let pkgFilesStarlark = '';
if (pkgs.length) {
let list = '';
list = pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__files",`).join('\n ');
- if (!config.exports_directories_only) {
- list += '\n ';
- list += pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__nested_node_modules",`).join('\n ');
- }
+ list += '\n ';
+ list += pkgs.map(pkg => `"//${pkg._dir}:${pkg._name}__nested_node_modules",`).join('\n ');
pkgFilesStarlark = `
# direct sources listed for strict deps support
srcs = [
@@ -136,17 +171,12 @@ async function generateRootBuildFile(pkgs) {
],`;
}
let exportsStarlark = '';
- if (config.exports_directories_only) {
- pkgs.forEach(pkg => exportsStarlark += ` "node_modules/${pkg._dir}",\n`);
- }
- else {
- pkgs.forEach(pkg => {
- pkg._files.forEach(f => {
- exportsStarlark += ` "node_modules/${pkg._dir}/${f}",\n`;
- });
+ pkgs.forEach(pkg => {
+ pkg._files.forEach(f => {
+ exportsStarlark += ` "node_modules/${pkg._dir}/${f}",\n`;
});
- }
- let buildFile = generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+ });
+ const result = generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
exports_files([
${exportsStarlark}])
@@ -157,17 +187,12 @@ ${exportsStarlark}])
# See https://github.com/bazelbuild/bazel/issues/5153.
js_library(
name = "node_modules",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${pkgFilesStarlark}${depsStarlark}
)
`;
- try {
- buildFile += await fs_1.promises.readFile(`manual_build_file_contents`, { encoding: 'utf8' });
- }
- catch (e) {
- }
- await writeFile('BUILD.bazel', buildFile);
+ return result;
}
async function generatePackageBuildFiles(pkg) {
let buildFilePath;
@@ -184,7 +209,7 @@ async function generatePackageBuildFiles(pkg) {
console.log(`[yarn_install/npm_install]: package ${nodeModulesPkgDir} is local symlink and as such a BUILD file for it is expected but none was found. Please add one at ${await fs_1.promises.realpath(nodeModulesPkgDir)}`);
}
let buildFile = config.exports_directories_only ?
- printPackageExperimentalDirectoryArtifacts(pkg) :
+ printPackageExportsDirectories(pkg) :
printPackage(pkg);
if (buildFilePath) {
buildFile = buildFile + '\n' +
@@ -304,7 +329,15 @@ def _maybe(repo_rule, name, **kwargs):
await writeFile(`install_${workspace}.bzl`, bzlFile);
}
async function generateScopeBuildFiles(scope, pkgs) {
- const buildFile = generateBuildFileHeader() + printScope(scope, pkgs);
+ pkgs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`));
+ let deps = [];
+ pkgs.forEach(pkg => {
+ deps = deps.concat(pkg._dependencies.filter(dep => !dep._isNested && !pkgs.includes(pkg)));
+ });
+ deps = [...pkgs, ...new Set(deps)];
+ let buildFile = config.exports_directories_only ?
+ printScopeExportsDirectories(scope, deps) :
+ printScope(scope, deps);
await writeFile(path.posix.join(scope, 'BUILD.bazel'), buildFile);
}
async function isFile(p) {
@@ -590,29 +623,25 @@ function findFile(pkg, m) {
}
return undefined;
}
-function printPackageExperimentalDirectoryArtifacts(pkg) {
+function printPackageExportsDirectories(pkg) {
const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested));
const depsStarlark = deps.map(dep => `"//${dep._dir}:${dep._name}__contents",`).join('\n ');
let result = `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
# Generated targets for npm package "${pkg._dir}"
${printJson(pkg)}
-# Files that are part of the npm package
-filegroup(
- name = "${pkg._name}__files",
- srcs = ["//:node_modules/${pkg._dir}"],
+# To support remote-execution, we must create a tree artifact from the source directory
+copy_directory(
+ name = "directory",
+ src = "@${config.workspace}//:${pkg._dir.replace("/", "_")}__source_directory",
+ out = "tree",
)
# The primary target for this package for use in rule deps
js_library(
name = "${pkg._name}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
- package_path = "${config.package_path}",
- # direct sources listed for strict deps support
- srcs = [":${pkg._name}__files"],
- # nested node_modules for this package plus flattened list of direct and transitive dependencies
- # hoisted to root by the package manager
deps = [
${depsStarlark}
],
@@ -620,17 +649,30 @@ js_library(
# Target is used as dep for main targets to prevent circular dependencies errors
js_library(
- name = "${pkg._name}__contents",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ name = "contents",
+ package_name = "${pkg._dir}",
package_path = "${config.package_path}",
- srcs = [":${pkg._name}__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+# For ts_library backward compat which uses @npm//typescript:__files
+alias(
+ name = "${pkg._name}__files",
+ actual = "directory",
+)
+
+# For ts_library backward compat which uses @npm//typescript:__files
+alias(
+ name = "${pkg._name}__contents",
+ actual = "contents",
+)
+
# For ts_library backward compat which uses @npm//typescript:typescript__typings
alias(
name = "${pkg._name}__typings",
- actual = "${pkg._name}__contents",
+ actual = "contents",
)
`;
let mainEntryPoint = resolvePkgMainFile(pkg);
@@ -641,7 +683,7 @@ alias(
npm_umd_bundle(
name = "${pkg._name}__umd",
package_name = "${pkg._moduleName}",
- entry_point = { "@${config.workspace}//:node_modules/${pkg._dir}": "${mainEntryPoint}" },
+ entry_point = { "@${config.workspace}//:${pkg._dir.replace("/", "_")}__source_directory": "${mainEntryPoint}" },
package = ":${pkg._name}",
)
@@ -712,7 +754,7 @@ filegroup(
# The primary target for this package for use in rule deps
js_library(
name = "${pkg._name}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",
# direct sources listed for strict deps support
srcs = [":${pkg._name}__files"],
@@ -726,7 +768,7 @@ js_library(
# Target is used as dep for main targets to prevent circular dependencies errors
js_library(
name = "${pkg._name}__contents",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",
srcs = [":${pkg._name}__files", ":${pkg._name}__nested_node_modules"],${namedSourcesStarlark}
visibility = ["//:__subpackages__"],
@@ -735,7 +777,7 @@ js_library(
# Typings files that are part of the npm package not including nested node_modules
js_library(
name = "${pkg._name}__typings",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${dtsStarlark}
)
@@ -805,7 +847,7 @@ function printPackageBin(pkg) {
}
for (const [name, path] of executables.entries()) {
const entryPoint = config.exports_directories_only ?
- `{ "@${config.workspace}//:node_modules/${pkg._dir}": "${path}" }` :
+ `{ "@${config.workspace}//${pkg._dir}:${pkg._name}__files": "${path}" }` :
`"@${config.workspace}//:node_modules/${pkg._dir}/${path}"`;
result += `# Wire up the \`bin\` entry \`${name}\`
nodejs_binary(
@@ -833,7 +875,7 @@ function printIndexBzl(pkg) {
}
for (const [name, path] of executables.entries()) {
const entryPoint = config.exports_directories_only ?
- `{ "@${config.workspace}//:node_modules/${pkg._dir}": "${path}" }` :
+ `{ "@${config.workspace}//${pkg._dir}:${pkg._name}__files": "${path}" }` :
`"@${config.workspace}//:node_modules/${pkg._dir}/${path}"`;
result = `${result}
@@ -862,13 +904,7 @@ def ${name.replace(/-/g, '_')}_test(**kwargs):
return result;
}
exports.printIndexBzl = printIndexBzl;
-function printScope(scope, pkgs) {
- pkgs = pkgs.filter(pkg => !pkg._isNested && pkg._dir.startsWith(`${scope}/`));
- let deps = [];
- pkgs.forEach(pkg => {
- deps = deps.concat(pkg._dependencies.filter(dep => !dep._isNested && !pkgs.includes(pkg)));
- });
- deps = [...pkgs, ...new Set(deps)];
+function printScope(scope, deps) {
let pkgFilesStarlark = '';
if (deps.length) {
const list = deps.map(dep => `"//${dep._dir}:${dep._name}__files",`).join('\n ');
@@ -887,14 +923,34 @@ function printScope(scope, pkgs) {
${list}
],`;
}
- return `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+ return generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
# Generated target for npm scope ${scope}
js_library(
name = "${scope}",
- package_name = "${NODE_MODULES_PACKAGE_NAME}",
+ package_name = "${LEGACY_NODE_MODULES_PACKAGE_NAME}",
package_path = "${config.package_path}",${pkgFilesStarlark}${depsStarlark}
)
`;
}
+function printScopeExportsDirectories(scope, deps) {
+ let depsStarlark = '';
+ if (deps.length) {
+ const list = deps.map(dep => `"//${dep._dir}",`).join('\n ');
+ depsStarlark = `
+ # flattened list of direct and transitive dependencies hoisted to root by the package manager
+ deps = [
+ ${list}
+ ],`;
+ }
+ return generateBuildFileHeader() + `load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+
+# Generated target for npm scope ${scope}
+js_library(
+ name = "${scope}",
+ ${depsStarlark}
+)
+
+`;
+}
diff --git a/internal/npm_install/npm_umd_bundle.bzl b/internal/npm_install/npm_umd_bundle.bzl
index 31462bcc68..be99a547b0 100644
--- a/internal/npm_install/npm_umd_bundle.bzl
+++ b/internal/npm_install/npm_umd_bundle.bzl
@@ -45,17 +45,13 @@ def _impl(ctx):
sources = ctx.attr.package[ExternalNpmPackageInfo].sources.to_list()
- if ctx.attr.package[ExternalNpmPackageInfo].has_directories:
- # If sources contain directories then we cannot filter by extension
- inputs = sources
- else:
- # Only pass .js and package.json files as inputs to browserify.
- # The latter is required for module resolution in some cases.
- inputs = [
- f
- for f in sources
- if f.path.endswith(".js") or f.path.endswith(".json")
- ]
+ # Only pass .js and package.json files as inputs to browserify.
+ # The latter is required for module resolution in some cases.
+ inputs = [
+ f
+ for f in sources
+ if f.path.endswith(".js") or f.path.endswith(".json")
+ ]
ctx.actions.run(
progress_message = "Generated UMD bundle for %s npm package [browserify]" % ctx.attr.package_name,
diff --git a/internal/npm_install/test/BUILD.bazel b/internal/npm_install/test/BUILD.bazel
index 513e212f8d..586807970a 100644
--- a/internal/npm_install/test/BUILD.bazel
+++ b/internal/npm_install/test/BUILD.bazel
@@ -123,8 +123,6 @@ sh_test(
"@fine_grained_deps_%s//:node_modules" % pkgmgr,
],
tags = tags + ["no-local-jasmine-deps"],
- # TODO: get this test running with just linker: failing under --config=no-runfiles
- templated_args = ["--bazel_patch_module_resolver"],
deps = [
"@fine_grained_deps_%s//jasmine" % pkgmgr,
"@fine_grained_deps_%s//jasmine-core" % pkgmgr,
@@ -167,8 +165,6 @@ sh_test(
"fine.spec.js",
],
tags = tags + ["no-local-jasmine-deps"],
- # TODO: get this test running with just linker: failing under --config=no-runfiles
- templated_args = ["--bazel_patch_module_resolver"],
deps = [
"@fine_grained_deps_%s//jasmine" % pkgmgr,
"@fine_grained_deps_%s//jasmine-core" % pkgmgr,
diff --git a/internal/npm_install/test/golden_directory_artifacts/@angular/core/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/@angular/core/BUILD.bazel.golden
index 1b5fb657fa..aef0cafc8d 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@angular/core/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@angular/core/BUILD.bazel.golden
@@ -1,15 +1,14 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "core__files",
- srcs = ["//:node_modules/@angular/core"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:@angular_core__source_directory",
+ out = "tree",
)
js_library(
name = "core",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":core__files"],
deps = [
"//@angular/core:core__contents",
"//tslib:tslib__contents",
@@ -18,20 +17,29 @@ js_library(
],
)
js_library(
- name = "core__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "@angular/core",
package_path = "",
- srcs = [":core__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "core__files",
+ actual = "directory",
+)
+alias(
+ name = "core__contents",
+ actual = "contents",
+)
alias(
name = "core__typings",
- actual = "core__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "core__umd",
package_name = "@angular/core",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@angular/core": "fesm5/core.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:@angular_core__source_directory": "fesm5/core.js" },
package = ":core",
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/BUILD.bazel.golden
index 5dfc9ee4ec..78f215c32b 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/BUILD.bazel.golden
@@ -3,14 +3,9 @@ package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
js_library(
name = "@gregmagolan",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [
- "//@gregmagolan/test-a:test-a__files",
- "//@gregmagolan/test-b:test-b__files",
- ],
+
deps = [
- "//@gregmagolan/test-a:test-a__contents",
- "//@gregmagolan/test-b:test-b__contents",
+ "//@gregmagolan/test-a",
+ "//@gregmagolan/test-b",
],
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/BUILD.bazel.golden
index 2e801b627a..7214d46d0f 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/BUILD.bazel.golden
@@ -1,35 +1,43 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "test-a__files",
- srcs = ["//:node_modules/@gregmagolan/test-a"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:@gregmagolan_test-a__source_directory",
+ out = "tree",
)
js_library(
name = "test-a",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":test-a__files"],
deps = [
"//@gregmagolan/test-a:test-a__contents",
],
)
js_library(
- name = "test-a__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "@gregmagolan/test-a",
package_path = "",
- srcs = [":test-a__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "test-a__files",
+ actual = "directory",
+)
+alias(
+ name = "test-a__contents",
+ actual = "contents",
+)
alias(
name = "test-a__typings",
- actual = "test-a__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "test-a__umd",
package_name = "@gregmagolan/test-a",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@gregmagolan/test-a": "main.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:@gregmagolan_test-a__source_directory": "main.js" },
package = ":test-a",
)
exports_files(["index.bzl"])
diff --git a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/bin/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/bin/BUILD.bazel.golden
index 1de86e18ce..fa954062c4 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/bin/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/bin/BUILD.bazel.golden
@@ -3,6 +3,6 @@ package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
nodejs_binary(
name = "test",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@gregmagolan/test-a": "@bin/test.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a:test-a__files": "@bin/test.js" },
data = ["//@gregmagolan/test-a:test-a"],
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/index.bzl.golden b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/index.bzl.golden
index 43a37b2c2a..802446ec67 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/index.bzl.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-a/index.bzl.golden
@@ -5,13 +5,13 @@ def test(**kwargs):
npm_package_bin(tool = "@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a/bin:test", output_dir = output_dir, **kwargs)
else:
nodejs_binary(
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@gregmagolan/test-a": "@bin/test.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a:test-a__files": "@bin/test.js" },
data = ["@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a:test-a"] + kwargs.pop("data", []),
**kwargs
)
def test_test(**kwargs):
nodejs_test(
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@gregmagolan/test-a": "@bin/test.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a:test-a__files": "@bin/test.js" },
data = ["@fine_grained_directory_artifacts_goldens//@gregmagolan/test-a:test-a"] + kwargs.pop("data", []),
**kwargs
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-b/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-b/BUILD.bazel.golden
index b0c43fe7c3..4686d72c12 100644
--- a/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-b/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/@gregmagolan/test-b/BUILD.bazel.golden
@@ -1,34 +1,42 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "test-b__files",
- srcs = ["//:node_modules/@gregmagolan/test-b"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:@gregmagolan_test-b__source_directory",
+ out = "tree",
)
js_library(
name = "test-b",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":test-b__files"],
deps = [
"//@gregmagolan/test-b:test-b__contents",
],
)
js_library(
- name = "test-b__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "@gregmagolan/test-b",
package_path = "",
- srcs = [":test-b__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "test-b__files",
+ actual = "directory",
+)
+alias(
+ name = "test-b__contents",
+ actual = "contents",
+)
alias(
name = "test-b__typings",
- actual = "test-b__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "test-b__umd",
package_name = "@gregmagolan/test-b",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/@gregmagolan/test-b": "main.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:@gregmagolan_test-b__source_directory": "main.js" },
package = ":test-b",
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/BUILD.bazel.golden
index 82761d979c..a55598e5f2 100644
--- a/internal/npm_install/test/golden_directory_artifacts/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/BUILD.bazel.golden
@@ -1,94 +1,166 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-exports_files([
- "node_modules/@angular/core",
- "node_modules/@gregmagolan/test-a",
- "node_modules/@gregmagolan/test-b",
- "node_modules/ajv",
- "node_modules/balanced-match",
- "node_modules/brace-expansion",
- "node_modules/co",
- "node_modules/concat-map",
- "node_modules/diff",
- "node_modules/fast-deep-equal",
- "node_modules/fast-json-stable-stringify",
- "node_modules/fs.realpath",
- "node_modules/glob",
- "node_modules/inflight",
- "node_modules/inherits",
- "node_modules/jasmine",
- "node_modules/jasmine-core",
- "node_modules/json-schema-traverse",
- "node_modules/minimatch",
- "node_modules/once",
- "node_modules/path-is-absolute",
- "node_modules/rxjs",
- "node_modules/tslib",
- "node_modules/unidiff",
- "node_modules/wrappy",
- "node_modules/zone.js",
-])
+filegroup(
+ name = "@angular_core__source_directory",
+ srcs = ["node_modules/@angular/core"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "@gregmagolan_test-a__source_directory",
+ srcs = ["node_modules/@gregmagolan/test-a"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "@gregmagolan_test-b__source_directory",
+ srcs = ["node_modules/@gregmagolan/test-b"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "ajv__source_directory",
+ srcs = ["node_modules/ajv"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "balanced-match__source_directory",
+ srcs = ["node_modules/balanced-match"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "brace-expansion__source_directory",
+ srcs = ["node_modules/brace-expansion"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "co__source_directory",
+ srcs = ["node_modules/co"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "concat-map__source_directory",
+ srcs = ["node_modules/concat-map"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "diff__source_directory",
+ srcs = ["node_modules/diff"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "fast-deep-equal__source_directory",
+ srcs = ["node_modules/fast-deep-equal"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "fast-json-stable-stringify__source_directory",
+ srcs = ["node_modules/fast-json-stable-stringify"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "fs.realpath__source_directory",
+ srcs = ["node_modules/fs.realpath"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "glob__source_directory",
+ srcs = ["node_modules/glob"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "inflight__source_directory",
+ srcs = ["node_modules/inflight"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "inherits__source_directory",
+ srcs = ["node_modules/inherits"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "jasmine__source_directory",
+ srcs = ["node_modules/jasmine"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "jasmine-core__source_directory",
+ srcs = ["node_modules/jasmine-core"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "json-schema-traverse__source_directory",
+ srcs = ["node_modules/json-schema-traverse"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "minimatch__source_directory",
+ srcs = ["node_modules/minimatch"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "once__source_directory",
+ srcs = ["node_modules/once"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "path-is-absolute__source_directory",
+ srcs = ["node_modules/path-is-absolute"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "rxjs__source_directory",
+ srcs = ["node_modules/rxjs"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "tslib__source_directory",
+ srcs = ["node_modules/tslib"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "unidiff__source_directory",
+ srcs = ["node_modules/unidiff"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "wrappy__source_directory",
+ srcs = ["node_modules/wrappy"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
+filegroup(
+ name = "zone.js__source_directory",
+ srcs = ["node_modules/zone.js"],
+ visibility = ["@fine_grained_directory_artifacts_goldens//:__subpackages__"],
+)
js_library(
- name = "node_modules",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [
- "//@angular/core:core__files",
- "//@gregmagolan/test-a:test-a__files",
- "//@gregmagolan/test-b:test-b__files",
- "//ajv:ajv__files",
- "//balanced-match:balanced-match__files",
- "//brace-expansion:brace-expansion__files",
- "//co:co__files",
- "//concat-map:concat-map__files",
- "//diff:diff__files",
- "//fast-deep-equal:fast-deep-equal__files",
- "//fast-json-stable-stringify:fast-json-stable-stringify__files",
- "//fs.realpath:fs.realpath__files",
- "//glob:glob__files",
- "//inflight:inflight__files",
- "//inherits:inherits__files",
- "//jasmine:jasmine__files",
- "//jasmine-core:jasmine-core__files",
- "//json-schema-traverse:json-schema-traverse__files",
- "//minimatch:minimatch__files",
- "//once:once__files",
- "//path-is-absolute:path-is-absolute__files",
- "//rxjs:rxjs__files",
- "//tslib:tslib__files",
- "//unidiff:unidiff__files",
- "//wrappy:wrappy__files",
- "//zone.js:zone.js__files",
- ],
- deps = [
- "//@angular/core:core__contents",
- "//@gregmagolan/test-a:test-a__contents",
- "//@gregmagolan/test-b:test-b__contents",
- "//ajv:ajv__contents",
- "//balanced-match:balanced-match__contents",
- "//brace-expansion:brace-expansion__contents",
- "//co:co__contents",
- "//concat-map:concat-map__contents",
- "//diff:diff__contents",
- "//fast-deep-equal:fast-deep-equal__contents",
- "//fast-json-stable-stringify:fast-json-stable-stringify__contents",
- "//fs.realpath:fs.realpath__contents",
- "//glob:glob__contents",
- "//inflight:inflight__contents",
- "//inherits:inherits__contents",
- "//jasmine:jasmine__contents",
- "//jasmine-core:jasmine-core__contents",
- "//json-schema-traverse:json-schema-traverse__contents",
- "//minimatch:minimatch__contents",
- "//once:once__contents",
- "//path-is-absolute:path-is-absolute__contents",
- "//rxjs:rxjs__contents",
- "//tslib:tslib__contents",
- "//unidiff:unidiff__contents",
- "//wrappy:wrappy__contents",
- "//zone.js:zone.js__contents",
- ],
+ name = "node_modules",
+ deps = [
+ "//@angular/core:core",
+ "//@gregmagolan/test-a:test-a",
+ "//@gregmagolan/test-b:test-b",
+ "//ajv:ajv",
+ "//balanced-match:balanced-match",
+ "//brace-expansion:brace-expansion",
+ "//co:co",
+ "//concat-map:concat-map",
+ "//diff:diff",
+ "//fast-deep-equal:fast-deep-equal",
+ "//fast-json-stable-stringify:fast-json-stable-stringify",
+ "//fs.realpath:fs.realpath",
+ "//glob:glob",
+ "//inflight:inflight",
+ "//inherits:inherits",
+ "//jasmine:jasmine",
+ "//jasmine-core:jasmine-core",
+ "//json-schema-traverse:json-schema-traverse",
+ "//minimatch:minimatch",
+ "//once:once",
+ "//path-is-absolute:path-is-absolute",
+ "//rxjs:rxjs",
+ "//tslib:tslib",
+ "//unidiff:unidiff",
+ "//wrappy:wrappy",
+ "//zone.js:zone.js",
+ ],
)
filegroup(
name = "golden_files",
diff --git a/internal/npm_install/test/golden_directory_artifacts/ajv/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/ajv/BUILD.bazel.golden
index cbca06fe14..f629872f3d 100644
--- a/internal/npm_install/test/golden_directory_artifacts/ajv/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/ajv/BUILD.bazel.golden
@@ -1,15 +1,14 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "ajv__files",
- srcs = ["//:node_modules/ajv"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:ajv__source_directory",
+ out = "tree",
)
js_library(
name = "ajv",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":ajv__files"],
deps = [
"//ajv:ajv__contents",
"//co:co__contents",
@@ -19,20 +18,29 @@ js_library(
],
)
js_library(
- name = "ajv__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "ajv",
package_path = "",
- srcs = [":ajv__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "ajv__files",
+ actual = "directory",
+)
+alias(
+ name = "ajv__contents",
+ actual = "contents",
+)
alias(
name = "ajv__typings",
- actual = "ajv__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "ajv__umd",
package_name = "ajv",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/ajv": "lib/ajv.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:ajv__source_directory": "lib/ajv.js" },
package = ":ajv",
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/jasmine/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/jasmine/BUILD.bazel.golden
index d5778ff38a..c9657140b7 100644
--- a/internal/npm_install/test/golden_directory_artifacts/jasmine/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/jasmine/BUILD.bazel.golden
@@ -1,15 +1,14 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "jasmine__files",
- srcs = ["//:node_modules/jasmine"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:jasmine__source_directory",
+ out = "tree",
)
js_library(
name = "jasmine",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":jasmine__files"],
deps = [
"//jasmine:jasmine__contents",
"//glob:glob__contents",
@@ -26,21 +25,30 @@ js_library(
],
)
js_library(
- name = "jasmine__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "jasmine",
package_path = "",
- srcs = [":jasmine__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "jasmine__files",
+ actual = "directory",
+)
+alias(
+ name = "jasmine__contents",
+ actual = "contents",
+)
alias(
name = "jasmine__typings",
- actual = "jasmine__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "jasmine__umd",
package_name = "jasmine",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/jasmine": "lib/jasmine.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:jasmine__source_directory": "lib/jasmine.js" },
package = ":jasmine",
)
exports_files(["index.bzl"])
diff --git a/internal/npm_install/test/golden_directory_artifacts/jasmine/bin/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/jasmine/bin/BUILD.bazel.golden
index 5838043f2e..296958cc7e 100644
--- a/internal/npm_install/test/golden_directory_artifacts/jasmine/bin/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/jasmine/bin/BUILD.bazel.golden
@@ -3,6 +3,6 @@ package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
nodejs_binary(
name = "jasmine",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/jasmine": "bin/jasmine.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//jasmine:jasmine__files": "bin/jasmine.js" },
data = ["//jasmine:jasmine"],
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/jasmine/index.bzl.golden b/internal/npm_install/test/golden_directory_artifacts/jasmine/index.bzl.golden
index 06565b507d..248eeab6e8 100644
--- a/internal/npm_install/test/golden_directory_artifacts/jasmine/index.bzl.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/jasmine/index.bzl.golden
@@ -5,13 +5,13 @@ def jasmine(**kwargs):
npm_package_bin(tool = "@fine_grained_directory_artifacts_goldens//jasmine/bin:jasmine", output_dir = output_dir, **kwargs)
else:
nodejs_binary(
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/jasmine": "bin/jasmine.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//jasmine:jasmine__files": "bin/jasmine.js" },
data = ["@fine_grained_directory_artifacts_goldens//jasmine:jasmine"] + kwargs.pop("data", []),
**kwargs
)
def jasmine_test(**kwargs):
nodejs_test(
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/jasmine": "bin/jasmine.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//jasmine:jasmine__files": "bin/jasmine.js" },
data = ["@fine_grained_directory_artifacts_goldens//jasmine:jasmine"] + kwargs.pop("data", []),
**kwargs
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/rxjs/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/rxjs/BUILD.bazel.golden
index 5e631c7411..6f98066cab 100644
--- a/internal/npm_install/test/golden_directory_artifacts/rxjs/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/rxjs/BUILD.bazel.golden
@@ -1,35 +1,43 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "rxjs__files",
- srcs = ["//:node_modules/rxjs"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:rxjs__source_directory",
+ out = "tree",
)
js_library(
name = "rxjs",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":rxjs__files"],
deps = [
"//rxjs:rxjs__contents",
"//tslib:tslib__contents",
],
)
js_library(
- name = "rxjs__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "rxjs",
package_path = "",
- srcs = [":rxjs__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "rxjs__files",
+ actual = "directory",
+)
+alias(
+ name = "rxjs__contents",
+ actual = "contents",
+)
alias(
name = "rxjs__typings",
- actual = "rxjs__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "rxjs__umd",
package_name = "rxjs",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/rxjs": "_esm5/index.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:rxjs__source_directory": "_esm5/index.js" },
package = ":rxjs",
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/unidiff/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/unidiff/BUILD.bazel.golden
index 1dbd1b7f3a..fbfbfe5a4e 100644
--- a/internal/npm_install/test/golden_directory_artifacts/unidiff/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/unidiff/BUILD.bazel.golden
@@ -1,35 +1,43 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "unidiff__files",
- srcs = ["//:node_modules/unidiff"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:unidiff__source_directory",
+ out = "tree",
)
js_library(
name = "unidiff",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":unidiff__files"],
deps = [
"//unidiff:unidiff__contents",
"//diff:diff__contents",
],
)
js_library(
- name = "unidiff__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "unidiff",
package_path = "",
- srcs = [":unidiff__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "unidiff__files",
+ actual = "directory",
+)
+alias(
+ name = "unidiff__contents",
+ actual = "contents",
+)
alias(
name = "unidiff__typings",
- actual = "unidiff__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "unidiff__umd",
package_name = "unidiff",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/unidiff": "unidiff.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:unidiff__source_directory": "unidiff.js" },
package = ":unidiff",
)
diff --git a/internal/npm_install/test/golden_directory_artifacts/zone.js/BUILD.bazel.golden b/internal/npm_install/test/golden_directory_artifacts/zone.js/BUILD.bazel.golden
index 3af886727a..91474c7c4b 100644
--- a/internal/npm_install/test/golden_directory_artifacts/zone.js/BUILD.bazel.golden
+++ b/internal/npm_install/test/golden_directory_artifacts/zone.js/BUILD.bazel.golden
@@ -1,34 +1,42 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
-filegroup(
- name = "zone.js__files",
- srcs = ["//:node_modules/zone.js"],
+load("@build_bazel_rules_nodejs//nodejs/private:copy_directory.bzl", "copy_directory")
+copy_directory(
+ name = "directory",
+ src = "@fine_grained_directory_artifacts_goldens//:zone.js__source_directory",
+ out = "tree",
)
js_library(
name = "zone.js",
- package_name = "$node_modules_dir$",
- package_path = "",
- srcs = [":zone.js__files"],
deps = [
"//zone.js:zone.js__contents",
],
)
js_library(
- name = "zone.js__contents",
- package_name = "$node_modules_dir$",
+ name = "contents",
+ package_name = "zone.js",
package_path = "",
- srcs = [":zone.js__files"],
+ strip_prefix = "tree",
+ srcs = [":directory"],
visibility = ["//:__subpackages__"],
)
+alias(
+ name = "zone.js__files",
+ actual = "directory",
+)
+alias(
+ name = "zone.js__contents",
+ actual = "contents",
+)
alias(
name = "zone.js__typings",
- actual = "zone.js__contents",
+ actual = "contents",
)
load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")
npm_umd_bundle(
name = "zone.js__umd",
package_name = "zone.js",
- entry_point = { "@fine_grained_directory_artifacts_goldens//:node_modules/zone.js": "dist/zone.js" },
+ entry_point = { "@fine_grained_directory_artifacts_goldens//:zone.js__source_directory": "dist/zone.js" },
package = ":zone.js",
)
diff --git a/internal/providers/external_npm_package_info.bzl b/internal/providers/external_npm_package_info.bzl
index 72aecdaa3f..9ccf1df00f 100644
--- a/internal/providers/external_npm_package_info.bzl
+++ b/internal/providers/external_npm_package_info.bzl
@@ -22,7 +22,6 @@ ExternalNpmPackageInfo = provider(
doc = "Provides information about one or more external npm packages",
fields = {
"direct_sources": "Depset of direct source files in these external npm package(s)",
- "has_directories": "True if any sources are directories",
"path": "The local workspace path that these external npm deps should be linked at. If empty, they will be linked at the root.",
"sources": "Depset of direct & transitive source files in these external npm package(s) and transitive dependencies",
"workspace": "The workspace name that these external npm package(s) are provided from",
@@ -40,11 +39,8 @@ def _node_modules_aspect_impl(target, ctx):
paths = {}
if hasattr(ctx.rule.attr, "deps"):
- # if any deps have has_directories set then has_directories will be true in the exported ExternalNpmPackageInfo
- has_directories = False
for dep in ctx.rule.attr.deps:
if ExternalNpmPackageInfo in dep:
- has_directories = has_directories or dep[ExternalNpmPackageInfo].has_directories
path = getattr(dep[ExternalNpmPackageInfo], "path", "")
workspace = dep[ExternalNpmPackageInfo].workspace
sources_depsets = []
@@ -61,7 +57,6 @@ def _node_modules_aspect_impl(target, ctx):
sources = depset(transitive = path_entry[1]),
workspace = path_entry[0],
path = path,
- has_directories = has_directories,
)])
return providers
diff --git a/nodejs/private/copy_directory.bzl b/nodejs/private/copy_directory.bzl
new file mode 100644
index 0000000000..b65d4cb360
--- /dev/null
+++ b/nodejs/private/copy_directory.bzl
@@ -0,0 +1,104 @@
+"""Implementation of copy_directory macro and underlying rules.
+These rules copy a directory to another location using Bash (on Linux/macOS) or
+cmd.exe (on Windows).
+"""
+
+def copy_cmd(ctx, src, dst):
+ # Most Windows binaries built with MSVC use a certain argument quoting
+ # scheme. Bazel uses that scheme too to quote arguments. However,
+ # cmd.exe uses different semantics, so Bazel's quoting is wrong here.
+ # To fix that we write the command to a .bat file so no command line
+ # quoting or escaping is required.
+ bat = ctx.actions.declare_file(ctx.label.name + "-cmd.bat")
+ ctx.actions.write(
+ output = bat,
+ # Do not use lib/shell.bzl's shell.quote() method, because that uses
+ # Bash quoting syntax, which is different from cmd.exe's syntax.
+ # xcopy manpage https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/xcopy
+ content = "@xcopy \"%s\" \"%s\\\" /V /E /H /Y /Q >NUL" % (
+ src.path.replace("/", "\\"),
+ dst.path.replace("/", "\\"),
+ ),
+ is_executable = True,
+ )
+ ctx.actions.run(
+ inputs = [src],
+ tools = [bat],
+ outputs = [dst],
+ executable = "cmd.exe",
+ arguments = ["/C", bat.path.replace("/", "\\")],
+ mnemonic = "CopyDirectory",
+ progress_message = "Copying directory",
+ use_default_shell_env = True,
+ # remote-execution does not allow source directory inputs
+ # https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2
+ execution_requirements = {"no-remote-exec": "1"},
+ )
+
+def copy_bash(ctx, src, dst):
+ ctx.actions.run_shell(
+ tools = [src],
+ outputs = [dst],
+ command = "cp -rf \"$1/\" \"$2\"",
+ arguments = [src.path, dst.path],
+ mnemonic = "CopyDirectory",
+ progress_message = "Copying directory",
+ use_default_shell_env = True,
+ # remote-execution does not allow source directory inputs
+ # https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2
+ execution_requirements = {"no-remote-exec": "1"},
+ )
+
+def _copy_directory_impl(ctx):
+ out = ctx.attr.out.strip()
+ if not out:
+ fail("out attr must not be empty")
+ output = ctx.actions.declare_directory(out)
+ if ctx.attr.is_windows:
+ copy_cmd(ctx, ctx.file.src, output)
+ else:
+ copy_bash(ctx, ctx.file.src, output)
+
+ files = depset(direct = [output])
+ runfiles = ctx.runfiles(files = [output])
+ return [DefaultInfo(files = files, runfiles = runfiles)]
+
+_ATTRS = {
+ "src": attr.label(mandatory = True, allow_single_file = True),
+ "out": attr.string(mandatory = True),
+ "is_windows": attr.bool(mandatory = True),
+}
+
+_copy_directory = rule(
+ implementation = _copy_directory_impl,
+ provides = [DefaultInfo],
+ attrs = _ATTRS,
+)
+
+def copy_directory(name, src, out, **kwargs):
+ """Copies a directory to another location.
+
+ If using this rule with source directories, it is recommended that you use the
+ --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1 startup option so that changes
+ to files within source directories are detected. See
+ https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2
+ for more context.
+
+ Args:
+ name: Name of the rule.
+ src: A Label. The directory to make a copy of. (Can also be the label of a rule
+ that generates a directory.)
+ out: Path of the output directory, relative to this package.
+ **kwargs: further keyword arguments, e.g. `visibility`
+ """
+
+ _copy_directory(
+ name = name,
+ src = src,
+ out = out,
+ is_windows = select({
+ "@bazel_tools//src/conditions:host_windows": True,
+ "//conditions:default": False,
+ }),
+ **kwargs
+ )