From 17403a2b1d2cd1cfc28c462469848ab15eb85aae Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Thu, 10 Jan 2019 23:38:06 +0100 Subject: [PATCH] fix(bazel): replay compilation uses wrong compiler for building esm5 (#28053) With the update to TypeScript 3.2.x, a big issue seems to have appeared for downstream Bazel users. If the downstream user still uses a lower TypeScript version, normal Bazel targets using the `ng_module` rule are still compiled with the correct/old TypeScript version (assuming they set the `node_modules` attribute properly). But, if they build the previous Bazel targets by specifying them within a `ng_package` rule, the TypeScript version from the Angular `workspace` is being used for the replayed ESM5 compilation. This is because we resolve the replay compiler to `ngc_wrapped` or `tsc_wrapped` Bazel executables which are defined as part of the `angular` workspace. This means that the compilers are different if the downstream user uses `ngc-wrapped` from the `@npm` repository because the replayed compilation would use the compiler with `@ngdeps//typescript`. In order to fix this, we should just use the compiler that is defined in the `@angular//BUILD.bazel` file. This target by defaults to the "@npm" workspace which is working for downstream users. This is similar to how it is handled for `tsc-wrapped`. `tsc-wrapped` works as expected for downstream users. **Note**: This is not the ideal solution because ideally we would completely respect the `compiler` option from the base `ng_module`, but this is not possible in a hermetic way, unless we somehow accept the `compiler` as an attribute that builds all transitive deps. This is something we should explore in the future. For now, we just fix this in a reasonable way that is also used for `tsc_wrapped` from the TypeScript rules. PR Close #28053 --- packages/bazel/src/esm5.bzl | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/bazel/src/esm5.bzl b/packages/bazel/src/esm5.bzl index 450200e4c0..adbec24c5d 100644 --- a/packages/bazel/src/esm5.bzl +++ b/packages/bazel/src/esm5.bzl @@ -12,6 +12,8 @@ However we need to publish this flavor on NPM, so it's necessary to be able to produce it. """ +load(":external.bzl", "DEFAULT_NG_COMPILER") + # The provider downstream rules use to access the outputs ESM5Info = provider( doc = "Typescript compilation outputs in ES5 syntax with ES Modules", @@ -84,13 +86,23 @@ def _esm5_outputs_aspect(target, ctx): ], ) - replay_compiler = target.typescript.replay_params.compiler.path.split("/")[-1] + replay_compiler_path = target.typescript.replay_params.compiler.short_path + replay_compiler_name = replay_compiler_path.split("/")[-1] # in windows replay_compiler path end with '.exe' - if replay_compiler.startswith("tsc_wrapped"): + if replay_compiler_name.startswith("tsc_wrapped"): compiler = ctx.executable._tsc_wrapped - elif replay_compiler.startswith("ngc-wrapped"): + elif replay_compiler_name.startswith("ngc-wrapped"): compiler = ctx.executable._ngc_wrapped + + # BEGIN-INTERNAL + # If the "replay_compiler" path refers to "ngc_wrapped" from within the Angular workspace, + # we need to use "ngc_wrapped" from source. This is necessary because we don't have + # a "npm" workspace with the "@angular/bazel" NPM package installed. + if not replay_compiler_path.startswith("../"): + compiler = ctx.executable._internal_ngc_wrapped + + # END-INTERNAL else: fail("Unknown replay compiler", target.typescript.replay_params.compiler.path) @@ -131,6 +143,14 @@ esm5_outputs_aspect = aspect( # Recurse to the deps of any target we visit attr_aspects = ["deps"], attrs = { + # This is only used if the replay_compiler refers to the "angular" workspace. In that + # case we need to use "ngc_wrapped" from its source location because we can't have + # the "npm" workspace that has the "@angular/bazel" NPM package installed. + "_internal_ngc_wrapped": attr.label( + default = Label("//packages/bazel/src/ngc-wrapped"), + executable = True, + cfg = "host", + ), "_modify_tsconfig": attr.label( default = Label("//packages/bazel/src:modify_tsconfig"), executable = True, @@ -141,8 +161,12 @@ esm5_outputs_aspect = aspect( executable = True, cfg = "host", ), + # This is the default "ngc_wrapped" executable that will be used to replay the compilation + # for ESM5 mode. The default compiler consumes "ngc_wrapped" from the "@npm" workspace. + # This is needed for downstream Bazel users that can have a different TypeScript + # version installed. "_ngc_wrapped": attr.label( - default = Label("//packages/bazel/src/ngc-wrapped"), + default = Label(DEFAULT_NG_COMPILER), executable = True, cfg = "host", ),