diff --git a/WORKSPACE b/WORKSPACE index dfa542aa053e..a9986ac255d0 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -40,6 +40,7 @@ yarn_install( data = [ "//:angular-tsconfig.json", "//:tools/bazel/flat_module_factory_resolution.patch", + "//:tools/bazel/manifest_externs_hermeticity.patch", "//:tools/bazel/postinstall-patches.js", "//:tools/bazel/rollup_windows_arguments.patch", "//:tools/npm/check-npm.js", diff --git a/tools/bazel/manifest_externs_hermeticity.patch b/tools/bazel/manifest_externs_hermeticity.patch new file mode 100644 index 000000000000..e3eb64e20929 --- /dev/null +++ b/tools/bazel/manifest_externs_hermeticity.patch @@ -0,0 +1,87 @@ +diff --git node_modules/@bazel/typescript/internal/build_defs.bzl node_modules/@bazel/typescript/internal/build_defs.bzl +index 7fef44c..4e25ed7 100644 +--- node_modules/@bazel/typescript/internal/build_defs.bzl ++++ node_modules/@bazel/typescript/internal/build_defs.bzl +@@ -93,25 +93,23 @@ def _filter_ts_inputs(all_inputs): + if f.path.endswith(".js") or f.path.endswith(".ts") or f.path.endswith(".json") + ] + ++def _filter_compile_outputs(all_outputs): ++ return [ ++ f ++ for f in all_outputs ++ if not f.basename.endswith(".externs.js") and not f.basename.endswith(".es5.MF") ++ ] ++ + def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description = "prodmode"): + externs_files = [] + action_inputs = inputs +- action_outputs = [] +- for output in outputs: +- if output.basename.endswith(".externs.js"): +- externs_files.append(output) +- elif output.basename.endswith(".es5.MF"): +- ctx.actions.write(output, content = "") +- else: +- action_outputs.append(output) +- +- # TODO(plf): For now we mock creation of files other than {name}.js. +- for externs_file in externs_files: +- ctx.actions.write(output = externs_file, content = "") ++ compile_outputs = _filter_compile_outputs(outputs) + + # A ts_library that has only .d.ts inputs will have no outputs, + # therefore there are no actions to execute +- if not action_outputs: ++ if not compile_outputs: ++ for file in [f for f in outputs if not f in compile_outputs]: ++ ctx.actions.write(output = file, content = "") + return None + + action_inputs.extend(_filter_ts_inputs(ctx.files.node_modules)) +@@ -146,7 +142,7 @@ def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description + progress_message = "Compiling TypeScript (%s) %s" % (description, ctx.label), + mnemonic = mnemonic, + inputs = action_inputs, +- outputs = action_outputs, ++ outputs = outputs, + # Use the built-in shell environment + # Allow for users who set a custom shell that can locate standard binaries like tr and uname + # See https://github.com/NixOS/nixpkgs/issues/43955#issuecomment-407546331 +@@ -163,7 +159,7 @@ def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description + label = ctx.label, + tsconfig = tsconfig_file, + inputs = action_inputs, +- outputs = action_outputs, ++ outputs = compile_outputs, + compiler = ctx.executable.compiler, + ) + +diff --git node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js +index 0346123..3d9bc64 100644 +--- node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js ++++ node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js +@@ -307,6 +307,23 @@ + } + else { + diagnostics = emitWithTypescript(program, compilationTargets, transforms); ++ if (bazelOpts.manifest) { ++ fs.writeFileSync(bazelOpts.manifest, ""); ++ } ++ if (bazelOpts.tsickleExternsPath) { ++ fs.writeFileSync(bazelOpts.tsickleExternsPath, ""); ++ if (bazelOpts.tsickleGenerateExterns && compilerHost.provideExternalModuleDtsNamespace) { ++ for (const extern of compilationTargets) { ++ if (!extern.isDeclarationFile) ++ continue; ++ const outputBaseDir = options.outDir; ++ const relativeOutputPath = compilerHost.relativeOutputPath(extern.fileName); ++ mkdirp(outputBaseDir, path.dirname(relativeOutputPath)); ++ const outputPath = path.join(outputBaseDir, relativeOutputPath); ++ fs.writeFileSync(outputPath, ""); ++ } ++ } ++ } + } + if (diagnostics.length > 0) { + console.error(bazelDiagnostics.format(bazelOpts.target, diagnostics)); diff --git a/tools/bazel/postinstall-patches.js b/tools/bazel/postinstall-patches.js index 77be6dbf9ac2..b34f96fda497 100644 --- a/tools/bazel/postinstall-patches.js +++ b/tools/bazel/postinstall-patches.js @@ -29,9 +29,6 @@ shelljs.exec('ngc -p angular-tsconfig.json'); searchAndReplace( /(this\.transformTypesToClosure) = bazelOpts\.tsickle;/, '$1 = false;', 'node_modules/@bazel/typescript/internal/tsc_wrapped/compiler_host.js'); -searchAndReplace( - 'bazelOpts\.tsickleExternsPath', 'null', - 'node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js'); // Workaround for https://github.com/angular/angular/issues/32389. We need to ensure // that tsickle is available for esm5 output re-compilations. @@ -99,6 +96,9 @@ searchAndReplace( `$1 + [m for dep in ctx.attr.deps if hasattr(dep, "angular") for m in dep.angular.metadata],`, 'node_modules/@angular/bazel/src/ng_module.bzl'); +// Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1208. +shelljs.cat(path.join(__dirname, './manifest_externs_hermeticity.patch')).exec('patch -p0'); + /** * Reads the specified file and replaces matches of the search expression * with the given replacement. Throws if no changes were made.