2018-02-02 18:25:33 -05:00
|
|
|
# Copyright Google Inc. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Use of this source code is governed by an MIT-style license that can be
|
|
|
|
# found in the LICENSE file at https://angular.io/license
|
|
|
|
|
|
|
|
"""Provides ES5 syntax with ESModule import/exports.
|
|
|
|
|
|
|
|
This exposes another flavor of output JavaScript, which is ES5 syntax
|
|
|
|
with ES2015 module syntax (import/export).
|
|
|
|
All Bazel rules should consume the standard dev or prod mode.
|
|
|
|
However we need to publish this flavor on NPM, so it's necessary to be able
|
|
|
|
to produce it.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# The provider downstream rules use to access the outputs
|
|
|
|
ESM5Info = provider(
|
|
|
|
doc = "Typescript compilation outputs in ES5 syntax with ES Modules",
|
|
|
|
fields = {
|
|
|
|
"transitive_output": """Dict of [rootDir, .js depset] entries.
|
|
|
|
|
|
|
|
The value is a depset of the .js output files.
|
|
|
|
The key is the prefix that should be stripped off the files
|
|
|
|
when resolving modules, eg. for file
|
|
|
|
bazel-bin/[external/wkspc/]path/to/package/label.esm5/path/to/package/file.js
|
|
|
|
the rootdir would be
|
|
|
|
bazel-bin/[external/wkspc/]path/to/package/label.esm5""",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
def _map_closure_path(file):
|
|
|
|
result = file.short_path[:-len(".closure.js")]
|
|
|
|
# short_path is meant to be used when accessing runfiles in a binary, where
|
|
|
|
# the CWD is inside the current repo. Therefore files in external repo have a
|
|
|
|
# short_path of ../external/wkspc/path/to/package
|
|
|
|
# We want to strip the first two segments from such paths.
|
|
|
|
if (result.startswith("../")):
|
|
|
|
result = "/".join(result.split("/")[2:])
|
|
|
|
return result + ".js"
|
|
|
|
|
|
|
|
def _join(array):
|
|
|
|
return "/".join([p for p in array if p])
|
|
|
|
|
|
|
|
def _esm5_outputs_aspect(target, ctx):
|
|
|
|
if not hasattr(target, "typescript"):
|
|
|
|
return []
|
|
|
|
|
|
|
|
# We create a new tsconfig.json file that will have our compilation settings
|
|
|
|
tsconfig = ctx.actions.declare_file("%s_esm5.tsconfig.json" % target.label.name)
|
|
|
|
|
|
|
|
workspace = target.label.workspace_root if target.label.workspace_root else ""
|
|
|
|
|
|
|
|
# re-root the outputs under a ".esm5" directory so the path don't collide
|
|
|
|
out_dir = ctx.label.name + ".esm5"
|
|
|
|
if workspace:
|
|
|
|
out_dir = out_dir + "/" + workspace
|
|
|
|
|
|
|
|
outputs = [ctx.actions.declare_file(_join([out_dir, _map_closure_path(f)]))
|
|
|
|
for f in target.typescript.replay_params.outputs
|
|
|
|
if not f.short_path.endswith(".externs.js")]
|
|
|
|
|
|
|
|
ctx.actions.run(
|
|
|
|
executable = ctx.executable._modify_tsconfig,
|
|
|
|
inputs = [target.typescript.replay_params.tsconfig],
|
|
|
|
outputs = [tsconfig],
|
|
|
|
arguments = [
|
|
|
|
target.typescript.replay_params.tsconfig.path,
|
|
|
|
tsconfig.path,
|
|
|
|
_join([workspace, target.label.package, ctx.label.name + ".esm5"]),
|
|
|
|
ctx.bin_dir.path
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
ctx.action(
|
|
|
|
progress_message = "Compiling TypeScript (ES5 with ES Modules) %s" % target.label,
|
|
|
|
inputs = target.typescript.replay_params.inputs + [tsconfig],
|
|
|
|
outputs = outputs,
|
|
|
|
arguments = [tsconfig.path],
|
|
|
|
executable = target.typescript.replay_params.compiler,
|
|
|
|
execution_requirements = {
|
2018-03-13 14:00:53 -04:00
|
|
|
# TODO(alexeagle): enable worker mode for these compilations
|
2018-02-02 18:25:33 -05:00
|
|
|
"supports-workers": "0",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
root_dir = _join([
|
|
|
|
ctx.bin_dir.path,
|
|
|
|
workspace,
|
|
|
|
target.label.package,
|
|
|
|
ctx.label.name + ".esm5",
|
|
|
|
])
|
|
|
|
|
|
|
|
transitive_output={root_dir: depset(outputs)}
|
|
|
|
for dep in ctx.rule.attr.deps:
|
|
|
|
if ESM5Info in dep:
|
|
|
|
transitive_output.update(dep[ESM5Info].transitive_output)
|
|
|
|
|
|
|
|
return [ESM5Info(
|
|
|
|
transitive_output = transitive_output,
|
|
|
|
)]
|
|
|
|
|
|
|
|
# Downstream rules can use this aspect to access the ESM5 output flavor.
|
|
|
|
# Only terminal rules (those which expect never to be used in deps[]) should do
|
|
|
|
# this.
|
|
|
|
esm5_outputs_aspect = aspect(
|
|
|
|
implementation = _esm5_outputs_aspect,
|
|
|
|
# Recurse to the deps of any target we visit
|
|
|
|
attr_aspects = ['deps'],
|
|
|
|
attrs = {
|
|
|
|
"_modify_tsconfig": attr.label(
|
|
|
|
default = Label("//packages/bazel/src:modify_tsconfig"),
|
|
|
|
executable = True,
|
|
|
|
cfg = "host"),
|
|
|
|
# We must list tsc_wrapped here to ensure it's built before the action runs
|
|
|
|
# For some reason, having the compiler output as an input to the action above
|
|
|
|
# is not sufficient.
|
|
|
|
"_tsc_wrapped": attr.label(
|
2018-03-02 13:10:59 -05:00
|
|
|
default = Label("@build_bazel_rules_typescript//internal:tsc_wrapped_bin"),
|
2018-02-02 18:25:33 -05:00
|
|
|
executable = True,
|
|
|
|
cfg = "host",
|
|
|
|
),
|
|
|
|
# Same comment as for tsc_wrapped above.
|
|
|
|
"_ngc_wrapped": attr.label(
|
|
|
|
default = Label("//packages/bazel/src/ngc-wrapped"),
|
|
|
|
executable = True,
|
|
|
|
cfg = "host",
|
|
|
|
),
|
|
|
|
},
|
|
|
|
)
|