angular-cn/packages/bazel/src/ng_module.bzl

532 lines
18 KiB
Python
Raw Normal View History

# 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
"""Implementation of the ng_module rule.
"""
load(":rules_typescript.bzl",
"tsc_wrapped_tsconfig",
"COMMON_ATTRIBUTES",
"COMMON_OUTPUTS",
"compile_ts",
"DEPS_ASPECTS",
"ts_providers_dict_to_struct",
)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
def _compile_strategy(ctx):
"""Detect which strategy should be used to implement ng_module.
Depending on the value of the 'compile' define flag or the '_global_mode' attribute, ng_module
can be implemented in various ways. This function reads the configuration passed by the user and
determines which mode is active.
Args:
ctx: skylark rule execution context
Returns:
one of 'legacy', 'local', 'jit', or 'global' depending on the configuration in ctx
"""
strategy = 'legacy'
if 'compile' in ctx.var:
strategy = ctx.var['compile']
if strategy not in ['legacy', 'local', 'jit']:
fail("Unknown --define=compile value '%s'" % strategy)
if strategy == 'legacy' and hasattr(ctx.attr, '_global_mode') and ctx.attr._global_mode:
strategy = 'global'
return strategy
def _compiler_name(ctx):
"""Selects a user-visible name depending on the current compilation strategy.
Args:
ctx: skylark rule execution context
Returns:
the name of the current compiler to be displayed in build output
"""
strategy = _compile_strategy(ctx)
if strategy == 'legacy':
return 'ngc'
elif strategy == 'global':
return 'ngc.ivy'
elif strategy == 'local':
return 'ngtsc'
elif strategy == 'jit':
return 'tsc'
else:
fail('unreachable')
def _enable_ivy_value(ctx):
"""Determines the value of the enableIvy option in the generated tsconfig.
Args:
ctx: skylark rule execution context
Returns:
the value of enableIvy that needs to be set in angularCompilerOptions in the generated tsconfig
"""
strategy = _compile_strategy(ctx)
if strategy == 'legacy':
return False
elif strategy == 'global':
return True
elif strategy == 'local':
return 'ngtsc'
elif strategy == 'jit':
return 'tsc'
else:
fail('unreachable')
def _include_ng_files(ctx):
"""Determines whether Angular outputs will be produced by the current compilation strategy.
Args:
ctx: skylark rule execution context
Returns:
true iff the current compilation strategy will produce View Engine compilation outputs (such as
factory files), false otherwise
"""
strategy = _compile_strategy(ctx)
return strategy == 'legacy' or strategy == 'global'
def _basename_of(ctx, file):
ext_len = len(".ts")
if file.short_path.endswith(".ng.html"):
ext_len = len(".ng.html")
elif file.short_path.endswith(".html"):
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.
We cannot use the default="" parameter of ctx.attr because the value is calculated
from other attributes (name)
Args:
ctx: skylark rule execution context
Returns:
a basename used for the flat module out (no extension)
"""
if hasattr(ctx.attr, "flat_module_out_file") and ctx.attr.flat_module_out_file:
return ctx.attr.flat_module_out_file
return "%s_public_index" % ctx.label.name
def _should_produce_flat_module_outs(ctx):
"""Should we produce flat module outputs.
We only produce flat module outs when we expect the ng_module is meant to be published,
based on the presence of the module_name attribute.
Args:
ctx: skylark rule execution context
Returns:
true iff we should run the bundle_index_host to produce flat module metadata and bundle index
"""
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
# unknown, without parsing, which will be empty.
def _expected_outs(ctx):
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
include_ng_files = _include_ng_files(ctx)
devmode_js_files = []
closure_js_files = []
declaration_files = []
summary_files = []
metadata_files = []
factory_basename_set = depset([_basename_of(ctx, src) for src in ctx.files.factories])
for src in ctx.files.srcs + ctx.files.assets:
package_prefix = ctx.label.package + "/" if ctx.label.package else ""
# Strip external repository name from path if src is from external repository
# If src is from external repository, it's short_path will be ../<external_repo_name>/...
short_path = src.short_path if src.short_path[0:2] != ".." else "/".join(src.short_path.split("/")[2:])
if short_path.endswith(".ts") and not short_path.endswith(".d.ts"):
basename = short_path[len(package_prefix):-len(".ts")]
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
if include_ng_files and (len(factory_basename_set) == 0 or basename in factory_basename_set):
devmode_js = [
".ngfactory.js",
".ngsummary.js",
".js",
]
summaries = [".ngsummary.json"]
metadata = [".metadata.json"]
else:
devmode_js = [".js"]
summaries = []
metadata = []
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
elif include_ng_files and short_path.endswith(".css"):
basename = short_path[len(package_prefix):-len(".css")]
devmode_js = [
".css.shim.ngstyle.js",
".css.ngstyle.js",
]
summaries = []
metadata = []
else:
continue
filter_summaries = ctx.attr.filter_summaries
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.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
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
if include_ng_files and _should_produce_flat_module_outs(ctx):
flat_module_out = _flat_module_out_file(ctx)
devmode_js_files.append(ctx.actions.declare_file("%s.js" % flat_module_out))
closure_js_files.append(ctx.actions.declare_file("%s.closure.js" % flat_module_out))
bundle_index_typings = ctx.actions.declare_file("%s.d.ts" % flat_module_out)
declaration_files.append(bundle_index_typings)
metadata_files.append(ctx.actions.declare_file("%s.metadata.json" % flat_module_out))
else:
bundle_index_typings = None
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
# TODO(alxhub): i18n is only produced by the legacy compiler currently. This should be re-enabled
# when ngtsc can extract messages
if include_ng_files:
i18n_messages_files = [ctx.new_file(ctx.genfiles_dir, ctx.label.name + "_ngc_messages.xmb")]
else:
i18n_messages_files = []
return struct(
closure_js = closure_js_files,
devmode_js = devmode_js_files,
declarations = declaration_files,
summaries = summary_files,
metadata = metadata_files,
bundle_index_typings = bundle_index_typings,
i18n_messages = i18n_messages_files,
)
def _ngc_tsconfig(ctx, files, srcs, **kwargs):
outs = _expected_outs(ctx)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
include_ng_files = _include_ng_files(ctx)
if "devmode_manifest" in kwargs:
expected_outs = outs.devmode_js + outs.declarations + outs.summaries + outs.metadata
else:
expected_outs = outs.closure_js
angular_compiler_options = {
"enableResourceInlining": ctx.attr.inline_resources,
"generateCodeForLibraries": False,
"allowEmptyCodegenFiles": True,
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
# Summaries are only enabled if Angular outputs are to be produced.
"enableSummariesForJit": include_ng_files,
"enableIvy": _enable_ivy_value(ctx),
"fullTemplateTypeCheck": ctx.attr.type_check,
# FIXME: wrong place to de-dupe
"expectedOut": depset([o.path for o in expected_outs]).to_list()
}
if _should_produce_flat_module_outs(ctx):
angular_compiler_options["flatModuleId"] = ctx.attr.module_name
angular_compiler_options["flatModuleOutFile"] = _flat_module_out_file(ctx)
angular_compiler_options["flatModulePrivateSymbolPrefix"] = "_".join(
[ctx.workspace_name] + ctx.label.package.split("/") + [ctx.label.name, ""])
return dict(tsc_wrapped_tsconfig(ctx, files, srcs, **kwargs), **{
"angularCompilerOptions": angular_compiler_options
})
def _collect_summaries_aspect_impl(target, ctx):
results = depset(target.angular.summaries if hasattr(target, "angular") else [])
# If we are visiting empty-srcs ts_library, this is a re-export
srcs = ctx.rule.attr.srcs if hasattr(ctx.rule.attr, "srcs") else []
# "re-export" rules should expose all the files of their deps
if not srcs and hasattr(ctx.rule.attr, "deps"):
for dep in ctx.rule.attr.deps:
if (hasattr(dep, "angular")):
results = depset(dep.angular.summaries, transitive = [results])
return struct(collect_summaries_aspect_result = results)
_collect_summaries_aspect = aspect(
implementation = _collect_summaries_aspect_impl,
attr_aspects = ["deps"],
)
# Extra options passed to Node when running ngc.
_EXTRA_NODE_OPTIONS_FLAGS = [
# Expose the v8 garbage collection API to JS.
"--node_options=--expose-gc"
]
def ngc_compile_action(ctx, label, inputs, outputs, messages_out, tsconfig_file,
node_opts, locale=None, i18n_args=[]):
"""Helper function to create the ngc action.
This is exposed for google3 to wire up i18n replay rules, and is not intended
as part of the public API.
Args:
ctx: skylark context
label: the label of the ng_module being compiled
inputs: passed to the ngc action's inputs
outputs: passed to the ngc action's outputs
messages_out: produced xmb files
tsconfig_file: tsconfig file with settings used for the compilation
node_opts: list of strings, extra nodejs options.
locale: i18n locale, or None
i18n_args: additional command-line arguments to ngc
Returns:
the parameters of the compilation which will be used to replay the ngc action for i18N.
"""
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
include_ng_files = _include_ng_files(ctx)
mnemonic = "AngularTemplateCompile"
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
progress_message = "Compiling Angular templates (%s) %s" % (_compiler_name(ctx), label)
if locale:
mnemonic = "AngularI18NMerging"
supports_workers = "0"
progress_message = ("Recompiling Angular templates (ngc) %s for locale %s" %
(label, locale))
else:
supports_workers = str(int(ctx.attr._supports_workers))
arguments = (list(_EXTRA_NODE_OPTIONS_FLAGS) +
["--node_options=%s" % opt for opt in node_opts])
# One at-sign makes this a params-file, enabling the worker strategy.
# Two at-signs escapes the argument so it's passed through to ngc
# rather than the contents getting expanded.
if supports_workers == "1":
arguments += ["@@" + tsconfig_file.path]
else:
arguments += ["-p", tsconfig_file.path]
arguments += i18n_args
ctx.actions.run(
progress_message = progress_message,
mnemonic = mnemonic,
inputs = inputs,
outputs = outputs,
arguments = arguments,
executable = ctx.executable.compiler,
execution_requirements = {
"supports-workers": supports_workers,
},
)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
if include_ng_files and messages_out != None:
ctx.actions.run(
inputs = list(inputs),
outputs = messages_out,
executable = ctx.executable._ng_xi18n,
arguments = (_EXTRA_NODE_OPTIONS_FLAGS +
[tsconfig_file.path] +
# The base path is bin_dir because of the way the ngc
# compiler host is configured. So we need to explicitly
# point to genfiles/ to redirect the output.
["../genfiles/" + messages_out[0].short_path]),
progress_message = "Extracting Angular 2 messages (ng_xi18n)",
mnemonic = "Angular2MessageExtractor")
if not locale and not ctx.attr.no_i18n:
return struct(
label = label,
tsconfig = tsconfig_file,
inputs = inputs,
outputs = outputs,
compiler = ctx.executable.compiler,
)
return None
def _compile_action(ctx, inputs, outputs, messages_out, tsconfig_file, node_opts):
# Give the Angular compiler all the user-listed assets
file_inputs = list(ctx.files.assets)
# The compiler only needs to see TypeScript sources from the npm dependencies,
# but may need to look at package.json and ngsummary.json files as well.
if hasattr(ctx.attr, "node_modules"):
file_inputs += [f for f in ctx.files.node_modules
if f.path.endswith(".ts") or f.path.endswith(".json")]
# If the user supplies a tsconfig.json file, the Angular compiler needs to read it
if hasattr(ctx.attr, "tsconfig") and ctx.file.tsconfig:
file_inputs.append(ctx.file.tsconfig)
# Collect the inputs and summary files from our deps
action_inputs = depset(file_inputs,
transitive = [inputs] + [dep.collect_summaries_aspect_result for dep in ctx.attr.deps
if hasattr(dep, "collect_summaries_aspect_result")])
return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, tsconfig_file, node_opts)
def _prodmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
outs = _expected_outs(ctx)
return _compile_action(ctx, inputs, outputs + outs.closure_js, outs.i18n_messages, tsconfig_file, node_opts)
def _devmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
outs = _expected_outs(ctx)
compile_action_outputs = outputs + outs.devmode_js + outs.declarations + outs.summaries + outs.metadata
_compile_action(ctx, inputs, compile_action_outputs, None, tsconfig_file, node_opts)
def _ts_expected_outs(ctx, label):
# rules_typescript expects a function with two arguments, but our
# implementation doesn't use the label
_ignored = [label]
return _expected_outs(ctx)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
def ng_module_impl(ctx, ts_compile_actions):
"""Implementation function for the ng_module rule.
This is exposed so that google3 can have its own entry point that re-uses this
and is not meant as a public API.
Args:
ctx: the skylark rule context
ts_compile_actions: generates all the actions to run an ngc compilation
Returns:
the result of the ng_module rule as a dict, suitable for
conversion by ts_providers_dict_to_struct
"""
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
include_ng_files = _include_ng_files(ctx)
providers = ts_compile_actions(
ctx, is_library=True, compile_action=_prodmode_compile_action,
devmode_compile_action=_devmode_compile_action,
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
tsc_wrapped_tsconfig=_ngc_tsconfig,
outputs = _ts_expected_outs)
outs = _expected_outs(ctx)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
if include_ng_files:
providers["angular"] = {
"summaries": outs.summaries,
"metadata": outs.metadata
}
providers["ngc_messages"] = outs.i18n_messages
if include_ng_files and _should_produce_flat_module_outs(ctx):
if len(outs.metadata) > 1:
fail("expecting exactly one metadata output for " + str(ctx.label))
providers["angular"]["flat_module_metadata"] = struct(
module_name = ctx.attr.module_name,
metadata_file = outs.metadata[0],
typings_file = outs.bundle_index_typings,
flat_module_out_file = _flat_module_out_file(ctx),
)
return providers
def _ng_module_impl(ctx):
return ts_providers_dict_to_struct(ng_module_impl(ctx, compile_ts))
NG_MODULE_ATTRIBUTES = {
"srcs": attr.label_list(allow_files = [".ts"]),
"deps": attr.label_list(aspects = DEPS_ASPECTS + [_collect_summaries_aspect]),
"assets": attr.label_list(allow_files = [
".css",
# TODO(alexeagle): change this to ".ng.html" when usages updated
".html",
]),
"factories": attr.label_list(
allow_files = [".ts", ".html"],
mandatory = False),
"filter_summaries": attr.bool(default = False),
"type_check": attr.bool(default = True),
"inline_resources": attr.bool(default = True),
"no_i18n": attr.bool(default = False),
"compiler": attr.label(
default = Label("//packages/bazel/src/ngc-wrapped"),
executable = True,
cfg = "host",
),
"_ng_xi18n": attr.label(
default = Label("//packages/bazel/src/ngc-wrapped:xi18n"),
executable = True,
cfg = "host",
),
"_supports_workers": attr.bool(default = True),
}
NG_MODULE_RULE_ATTRS = dict(dict(COMMON_ATTRIBUTES, **NG_MODULE_ATTRIBUTES), **{
"tsconfig": attr.label(allow_files = True, single_file = True),
# @// is special syntax for the "main" repository
# The default assumes the user specified a target "node_modules" in their
# root BUILD file.
"node_modules": attr.label(
default = Label("@//:node_modules")
),
"entry_point": attr.string(),
# Default is %{name}_public_index
# The suffix points to the generated "bundle index" files that users import from
# The default is intended to avoid collisions with the users input files.
# Later packaging rules will point to these generated files as the entry point
# into the package.
# See the flatModuleOutFile documentation in
# https://github.com/angular/angular/blob/master/packages/compiler-cli/src/transformers/api.ts
"flat_module_out_file": attr.string(),
})
ng_module = rule(
implementation = _ng_module_impl,
attrs = NG_MODULE_RULE_ATTRS,
outputs = COMMON_OUTPUTS,
)
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
# TODO(alxhub): this rule causes legacy ngc to produce Ivy outputs from global analysis information.
# It exists to facilitate testing of the Ivy runtime until ngtsc is mature enough to be used
# instead, and should be removed once ngtsc is capable of fulfilling the same requirements.
build(ivy): support alternate compilation modes to enable Ivy testing (#24056) Bazel has a restriction that a single output (eg. a compiled version of //packages/common) can only be produced by a single rule. This precludes the Angular repo from having multiple rules that build the same code. And the complexity of having a single rule produce multiple outputs (eg. an ngc-compiled version of //packages/common and an Ivy-enabled version) is too high. Additionally, the Angular repo has lots of existing tests which could be executed as-is under Ivy. Such testing is very valuable, and it would be nice to share not only the code, but the dependency graph / build config as well. Thus, this change introduces a --define flag 'compile' with three potential values. When --define=compile=X is set, the entire build system runs in a particular mode - the behavior of all existing targets is controlled by the flag. This allows us to reuse our entire build structure for testing in a variety of different manners. The flag has three possible settings: * legacy (the default): the traditional View Engine (ngc) build * local: runs the prototype ngtsc compiler, which does not rely on global analysis * jit: runs ngtsc in a mode which executes tsickle, but excludes the Angular related transforms, which approximates the behavior of plain tsc. This allows the main packages such as common to be tested with the JIT compiler. Additionally, the ivy_ng_module() rule still exists and runs ngc in a mode where Ivy-compiled output is produced from global analysis information, as a stopgap while ngtsc is being developed. PR Close #24056
2018-05-21 18:48:00 -04:00
internal_global_ng_module = rule(
implementation = _ng_module_impl,
attrs = dict(NG_MODULE_RULE_ATTRS, **{
"_global_mode": attr.bool(
default = True,
),
}),
outputs = COMMON_OUTPUTS,
)