diff --git a/packages/bazel/src/ng_module.bzl b/packages/bazel/src/ng_module.bzl index 65596e2849..1f7d2a4eb2 100644 --- a/packages/bazel/src/ng_module.bzl +++ b/packages/bazel/src/ng_module.bzl @@ -22,6 +22,11 @@ def _basename_of(ctx, file): ext_len = len(".html") return file.short_path[len(ctx.label.package) + 1:-ext_len] +# Return true if run with bazel (the open-sourced version of blaze), false if +# run with blaze. +def _is_bazel(): + return not hasattr(native, "genmpm") + def _flat_module_out_file(ctx): """Provide a default for the flat_module_out_file attribute. @@ -50,8 +55,7 @@ def _should_produce_flat_module_outs(ctx): Returns: true iff we should run the bundle_index_host to produce flat module metadata and bundle index """ - is_bazel = not hasattr(native, "genmpm") - return is_bazel and ctx.attr.module_name + return _is_bazel() and ctx.attr.module_name # Calculate the expected output of the template compiler for every source in # in the library. Most of these will be produced as empty files but it is @@ -81,9 +85,11 @@ def _expected_outs(ctx): ".js", ] summaries = [".ngsummary.json"] + metadata = [".metadata.json"] else: devmode_js = [".js"] summaries = [] + metadata = [] elif short_path.endswith(".css"): basename = short_path[len(package_prefix):-len(".css")] devmode_js = [ @@ -91,7 +97,7 @@ def _expected_outs(ctx): ".css.ngstyle.js", ] summaries = [] - + metadata = [] else: continue @@ -99,10 +105,12 @@ def _expected_outs(ctx): closure_js = [f.replace(".js", ".closure.js") for f in devmode_js if not filter_summaries or not f.endswith(".ngsummary.js")] declarations = [f.replace(".js", ".d.ts") for f in devmode_js] - devmode_js_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in devmode_js] - closure_js_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in closure_js] - declaration_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in declarations] - summary_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in summaries] + devmode_js_files += [ctx.actions.declare_file(basename + ext) for ext in devmode_js] + closure_js_files += [ctx.actions.declare_file(basename + ext) for ext in closure_js] + declaration_files += [ctx.actions.declare_file(basename + ext) for ext in declarations] + summary_files += [ctx.actions.declare_file(basename + ext) for ext in summaries] + if not _is_bazel(): + metadata_files += [ctx.actions.declare_file(basename + ext) for ext in metadata] # We do this just when producing a flat module index for a publishable ng_module if _should_produce_flat_module_outs(ctx): @@ -330,7 +338,8 @@ def ng_module_impl(ctx, ts_compile_actions, ivy = False): outs = _expected_outs(ctx) providers["angular"] = { - "summaries": outs.summaries + "summaries": outs.summaries, + "metadata": outs.metadata } providers["ngc_messages"] = outs.i18n_messages diff --git a/packages/bazel/src/ngc-wrapped/index.ts b/packages/bazel/src/ngc-wrapped/index.ts index 928cfe8e59..193ce58bc2 100644 --- a/packages/bazel/src/ngc-wrapped/index.ts +++ b/packages/bazel/src/ngc-wrapped/index.ts @@ -268,6 +268,12 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true, } } + if (!bazelOpts.nodeModulesPrefix) { + // If there is no node modules, then metadata.json should be emitted since + // there is no other way to obtain the information + generateMetadataJson(program.getTsProgram(), files, compilerOpts.rootDirs, bazelBin, tsHost); + } + if (bazelOpts.tsickleExternsPath) { // Note: when tsickleExternsPath is provided, we always write a file as a // marker that compilation succeeded, even if it's empty (just containing an @@ -282,6 +288,31 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true, return {program, diagnostics}; } +/** + * Generate metadata.json for the specified `files`. By default, metadata.json + * is only generated by the compiler if --flatModuleOutFile is specified. But + * if compiled under blaze, we want the metadata to be generated for each + * Angular component. + */ +function generateMetadataJson( + program: ts.Program, files: string[], rootDirs: string[], bazelBin: string, + tsHost: ts.CompilerHost) { + const collector = new ng.MetadataCollector(); + for (const file of files) { + const sourceFile = program.getSourceFile(file); + if (sourceFile) { + const metadata = collector.getMetadata(sourceFile); + if (metadata) { + const relative = relativeToRootDirs(file, rootDirs); + const shortPath = relative.replace(EXT, '.metadata.json'); + const outFile = resolveNormalizedPath(bazelBin, shortPath); + const data = JSON.stringify(metadata); + tsHost.writeFile(outFile, data, false, undefined, []); + } + } + } +} + function isCompilationTarget(bazelOpts: BazelOptions, sf: ts.SourceFile): boolean { return !NGC_GEN_FILES.test(sf.fileName) && (bazelOpts.compilationTargetSrc.indexOf(sf.fileName) !== -1);