style: format .bzl files with buildifier (#23544)

PR Close #23544
This commit is contained in:
Alex Eagle 2018-08-07 16:15:45 -07:00 committed by Kara Erickson
parent 090824526b
commit a3f1e2cb42
16 changed files with 1329 additions and 1239 deletions

View File

@ -12,11 +12,13 @@ from source downstream. Alternately, this API is available from the
used in a downstream project.
"""
load("//packages/bazel:index.bzl",
load(
"//packages/bazel:index.bzl",
_ng_module = "ng_module",
_ng_package = "ng_package",
_protractor_web_test = "protractor_web_test",
_protractor_web_test_suite = "protractor_web_test_suite")
_protractor_web_test_suite = "protractor_web_test_suite",
)
load("//tools:ng_setup_workspace.bzl", _ng_setup_workspace = "ng_setup_workspace")
ng_module = _ng_module

View File

@ -10,9 +10,11 @@ Users should not load files under "/src"
load("//packages/bazel/src:ng_module.bzl", _ng_module = "ng_module")
load("//packages/bazel/src:ng_setup_workspace.bzl", _ng_setup_workspace = "ng_setup_workspace")
load("//packages/bazel/src/ng_package:ng_package.bzl", _ng_package = "ng_package")
load("//packages/bazel/src/protractor:protractor_web_test.bzl",
_protractor_web_test = "protractor_web_test",
_protractor_web_test_suite = "protractor_web_test_suite")
load(
"//packages/bazel/src/protractor:protractor_web_test.bzl",
_protractor_web_test = "protractor_web_test",
_protractor_web_test_suite = "protractor_web_test_suite",
)
ng_module = _ng_module
ng_package = _ng_package

View File

@ -28,75 +28,78 @@ ESM5Info = provider(
)
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"
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])
return "/".join([p for p in array if p])
def _esm5_outputs_aspect(target, ctx):
if not hasattr(target, "typescript"):
return []
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)
# 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 ""
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
# 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")]
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.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.actions.run(
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 = {
# TODO(alexeagle): enable worker mode for these compilations
"supports-workers": "0",
},
)
ctx.actions.run(
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 = {
# TODO(alexeagle): enable worker mode for these compilations
"supports-workers": "0",
},
)
root_dir = _join([
ctx.bin_dir.path,
workspace,
target.label.package,
ctx.label.name + ".esm5",
])
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)
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,
)]
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
@ -104,12 +107,13 @@ def _esm5_outputs_aspect(target, ctx):
esm5_outputs_aspect = aspect(
implementation = _esm5_outputs_aspect,
# Recurse to the deps of any target we visit
attr_aspects = ['deps'],
attr_aspects = ["deps"],
attrs = {
"_modify_tsconfig": attr.label(
default = Label("//packages/bazel/src:modify_tsconfig"),
executable = True,
cfg = "host"),
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.
@ -128,43 +132,44 @@ esm5_outputs_aspect = aspect(
)
def esm5_root_dir(ctx):
return ctx.label.name + ".esm5"
return ctx.label.name + ".esm5"
def flatten_esm5(ctx):
"""Merge together the .esm5 folders from the dependencies.
"""Merge together the .esm5 folders from the dependencies.
Two different dependencies A and B may have outputs like
`bazel-bin/path/to/A.esm5/path/to/lib.js`
`bazel-bin/path/to/B.esm5/path/to/main.js`
Two different dependencies A and B may have outputs like
`bazel-bin/path/to/A.esm5/path/to/lib.js`
`bazel-bin/path/to/B.esm5/path/to/main.js`
In order to run rollup on this app, in case main.js contains `import from './lib'`
they need to be together in the same root directory, so if we depend on both A and B
we need the outputs to be
`bazel-bin/path/to/my_rule.esm5/path/to/lib.js`
`bazel-bin/path/to/my_rule.esm5/path/to/main.js`
In order to run rollup on this app, in case main.js contains `import from './lib'`
they need to be together in the same root directory, so if we depend on both A and B
we need the outputs to be
`bazel-bin/path/to/my_rule.esm5/path/to/lib.js`
`bazel-bin/path/to/my_rule.esm5/path/to/main.js`
Args:
ctx: the skylark rule execution context
Args:
ctx: the skylark rule execution context
Returns:
list of flattened files
"""
esm5_sources = []
result = []
for dep in ctx.attr.deps:
if ESM5Info in dep:
transitive_output = dep[ESM5Info].transitive_output
esm5_sources.extend(transitive_output.values())
for f in depset(transitive = esm5_sources).to_list():
path = f.short_path[f.short_path.find(".esm5") + len(".esm5"):]
if (path.startswith("../")):
path = "external/" + path[3:]
rerooted_file = ctx.actions.declare_file("/".join([esm5_root_dir(ctx), path]))
result.append(rerooted_file)
# print("copy", f.short_path, "to", rerooted_file.short_path)
ctx.actions.expand_template(
output = rerooted_file,
template = f,
substitutions = {},
)
return result
Returns:
list of flattened files
"""
esm5_sources = []
result = []
for dep in ctx.attr.deps:
if ESM5Info in dep:
transitive_output = dep[ESM5Info].transitive_output
esm5_sources.extend(transitive_output.values())
for f in depset(transitive = esm5_sources).to_list():
path = f.short_path[f.short_path.find(".esm5") + len(".esm5"):]
if (path.startswith("../")):
path = "external/" + path[3:]
rerooted_file = ctx.actions.declare_file("/".join([esm5_root_dir(ctx), path]))
result.append(rerooted_file)
# print("copy", f.short_path, "to", rerooted_file.short_path)
ctx.actions.expand_template(
output = rerooted_file,
template = f,
substitutions = {},
)
return result

View File

@ -5,270 +5,272 @@
"""Run Angular's AOT template compiler
"""
load(":rules_typescript.bzl",
"tsc_wrapped_tsconfig",
load(
":rules_typescript.bzl",
"COMMON_ATTRIBUTES",
"COMMON_OUTPUTS",
"compile_ts",
"DEPS_ASPECTS",
"compile_ts",
"ts_providers_dict_to_struct",
"tsc_wrapped_tsconfig",
)
def compile_strategy(ctx):
"""Detect which strategy should be used to implement ng_module.
"""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.
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
Args:
ctx: skylark rule execution context
Returns:
one of 'legacy', 'local', 'jit', or 'global' depending on the configuration in ctx
"""
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']
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 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'
if strategy == "legacy" and hasattr(ctx.attr, "_global_mode") and ctx.attr._global_mode:
strategy = "global"
return strategy
return strategy
def _compiler_name(ctx):
"""Selects a user-visible name depending on the current compilation strategy.
"""Selects a user-visible name depending on the current compilation strategy.
Args:
ctx: skylark rule execution context
Args:
ctx: skylark rule execution context
Returns:
the name of the current compiler to be displayed in build output
"""
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')
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.
"""Determines the value of the enableIvy option in the generated tsconfig.
Args:
ctx: skylark rule execution context
Args:
ctx: skylark rule execution context
Returns:
the value of enableIvy that needs to be set in angularCompilerOptions in the generated tsconfig
"""
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')
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.
"""Determines whether Angular outputs will be produced by the current compilation strategy.
Args:
ctx: skylark rule execution context
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
"""
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'
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]
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")
return not hasattr(native, "genmpm")
def _flat_module_out_file(ctx):
"""Provide a default for the flat_module_out_file attribute.
"""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)
We cannot use the default="" parameter of ctx.attr because the value is calculated
from other attributes (name)
Args:
ctx: skylark rule execution context
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
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.
"""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.
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
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
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):
include_ng_files = _include_ng_files(ctx)
include_ng_files = _include_ng_files(ctx)
devmode_js_files = []
closure_js_files = []
declaration_files = []
summary_files = []
metadata_files = []
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])
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 ""
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:])
# 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")]
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 = []
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 = []
if short_path.endswith(".ts") and not short_path.endswith(".d.ts"):
basename = short_path[len(package_prefix):-len(".ts")]
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 = []
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
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:
continue
bundle_index_typings = None
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]
# 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 = []
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 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
# 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,
)
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)
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
outs = _expected_outs(ctx)
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,
# 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()
}
angular_compiler_options = {
"enableResourceInlining": ctx.attr.inline_resources,
"generateCodeForLibraries": False,
"allowEmptyCodegenFiles": True,
# 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, ""])
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
})
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 [])
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 []
# 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])
# "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)
return struct(collect_summaries_aspect_result = results)
_collect_summaries_aspect = aspect(
implementation = _collect_summaries_aspect_impl,
@ -278,177 +280,197 @@ _collect_summaries_aspect = aspect(
# Extra options passed to Node when running ngc.
_EXTRA_NODE_OPTIONS_FLAGS = [
# Expose the v8 garbage collection API to JS.
"--node_options=--expose-gc"
"--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.
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.
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
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.
"""
Returns:
the parameters of the compilation which will be used to replay the ngc action for i18N.
"""
include_ng_files = _include_ng_files(ctx)
include_ng_files = _include_ng_files(ctx)
mnemonic = "AngularTemplateCompile"
progress_message = "Compiling Angular templates (%s) %s" % (_compiler_name(ctx), label)
mnemonic = "AngularTemplateCompile"
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))
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 = (list(_EXTRA_NODE_OPTIONS_FLAGS) +
["--node_options=%s" % opt for opt in node_opts])
arguments += i18n_args
# 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]
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,
},
)
arguments += i18n_args
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,
progress_message = progress_message,
mnemonic = mnemonic,
inputs = inputs,
outputs = outputs,
compiler = ctx.executable.compiler,
arguments = arguments,
executable = ctx.executable.compiler,
execution_requirements = {
"supports-workers": supports_workers,
},
)
return None
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)
# 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")]
# 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)
# 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)
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
"""
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,
tsc_wrapped_tsconfig=_ngc_tsconfig,
outputs = _ts_expected_outs)
outs = _expected_outs(ctx)
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),
# 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 providers
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)
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
"""
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,
tsc_wrapped_tsconfig = _ngc_tsconfig,
outputs = _ts_expected_outs,
)
outs = _expected_outs(ctx)
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))
return ts_providers_dict_to_struct(ng_module_impl(ctx, compile_ts))
NG_MODULE_ATTRIBUTES = {
"srcs": attr.label_list(allow_files = [".ts"]),
@ -457,9 +479,8 @@ NG_MODULE_ATTRIBUTES = {
# https://github.com/bazelbuild/skydoc/issues/21
"deps": attr.label_list(
doc = "Targets that are imported by this target",
aspects = list(DEPS_ASPECTS) + [_collect_summaries_aspect]
aspects = list(DEPS_ASPECTS) + [_collect_summaries_aspect],
),
"assets": attr.label_list(
doc = ".html and .css files needed by the Angular compiler",
allow_files = [
@ -468,31 +489,24 @@ NG_MODULE_ATTRIBUTES = {
".html",
],
),
"factories": attr.label_list(
allow_files = [".ts", ".html"],
mandatory = False),
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),
}
@ -503,9 +517,8 @@ NG_MODULE_RULE_ATTRS = dict(dict(COMMON_ATTRIBUTES, **NG_MODULE_ATTRIBUTES), **{
# The default assumes the user specified a target "node_modules" in their
# root BUILD file.
"node_modules": attr.label(
default = Label("@//:node_modules")
default = Label("@//:node_modules"),
),
"entry_point": attr.string(),
# Default is %{name}_public_index

View File

@ -14,41 +14,46 @@ specification of this format at https://goo.gl/jB3GVv
"""
load("@build_bazel_rules_nodejs//:internal/collect_es6_sources.bzl", "collect_es6_sources")
load("@build_bazel_rules_nodejs//:internal/rollup/rollup_bundle.bzl",
"write_rollup_config",
"rollup_module_mappings_aspect",
"run_uglify",
"ROLLUP_ATTRS")
load("@build_bazel_rules_nodejs//:internal/npm_package/npm_package.bzl",
"NPM_PACKAGE_ATTRS",
"NPM_PACKAGE_OUTPUTS",
"create_package")
load(
"@build_bazel_rules_nodejs//:internal/rollup/rollup_bundle.bzl",
"ROLLUP_ATTRS",
"rollup_module_mappings_aspect",
"run_uglify",
"write_rollup_config",
)
load(
"@build_bazel_rules_nodejs//:internal/npm_package/npm_package.bzl",
"NPM_PACKAGE_ATTRS",
"NPM_PACKAGE_OUTPUTS",
"create_package",
)
load("@build_bazel_rules_nodejs//:internal/node.bzl", "sources_aspect")
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "flatten_esm5", "esm5_root_dir")
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5")
# Convert from some-dash-case to someCamelCase
def _convert_dash_case_to_camel_case(s):
parts = s.split("-")
# First letter in the result is always unchanged
return s[0] + "".join([p.title() for p in parts])[1:]
parts = s.split("-")
# First letter in the result is always unchanged
return s[0] + "".join([p.title() for p in parts])[1:]
# Convert from a package name on npm to an identifier that's a legal global symbol
# @angular/core -> ng.core
# @angular/platform-browser-dynamic/testing -> ng.platformBrowserDynamic.testing
def _global_name(package_name):
# strip npm scoped package qualifier
start = 1 if package_name.startswith("@") else 0
parts = package_name[start:].split("/")
result_parts = []
for p in parts:
# Special case for angular's short name
if p == "angular":
result_parts.append("ng")
else:
result_parts.append(_convert_dash_case_to_camel_case(p))
return ".".join(result_parts)
# strip npm scoped package qualifier
start = 1 if package_name.startswith("@") else 0
parts = package_name[start:].split("/")
result_parts = []
for p in parts:
# Special case for angular's short name
if p == "angular":
result_parts.append("ng")
else:
result_parts.append(_convert_dash_case_to_camel_case(p))
return ".".join(result_parts)
WELL_KNOWN_GLOBALS = { p: _global_name(p) for p in [
WELL_KNOWN_GLOBALS = {p: _global_name(p) for p in [
"@angular/upgrade",
"@angular/upgrade/static",
"@angular/forms",
@ -85,242 +90,259 @@ WELL_KNOWN_GLOBALS = { p: _global_name(p) for p in [
]}
def _rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, format = "es", package_name = "", include_tslib = False):
map_output = ctx.actions.declare_file(js_output.basename + ".map", sibling = js_output)
map_output = ctx.actions.declare_file(js_output.basename + ".map", sibling = js_output)
args = ctx.actions.args()
args.add("--config", rollup_config)
args = ctx.actions.args()
args.add("--config", rollup_config)
args.add("--input", entry_point)
args.add("--output.file", js_output)
args.add("--output.format", format)
if package_name:
args.add("--output.name", _global_name(package_name))
args.add("--amd.id", package_name)
args.add("--input", entry_point)
args.add("--output.file", js_output)
args.add("--output.format", format)
if package_name:
args.add("--output.name", _global_name(package_name))
args.add("--amd.id", package_name)
# Note: if the input has external source maps then we need to also install and use
# `rollup-plugin-sourcemaps`, which will require us to use rollup.config.js file instead
# of command line args
args.add("--sourcemap")
# Note: if the input has external source maps then we need to also install and use
# `rollup-plugin-sourcemaps`, which will require us to use rollup.config.js file instead
# of command line args
args.add("--sourcemap")
globals = dict(WELL_KNOWN_GLOBALS, **ctx.attr.globals)
external = globals.keys()
if not include_tslib:
external.append("tslib")
args.add_joined("--external", external, join_with=",")
globals = dict(WELL_KNOWN_GLOBALS, **ctx.attr.globals)
external = globals.keys()
if not include_tslib:
external.append("tslib")
args.add_joined("--external", external, join_with = ",")
args.add_joined(
"--globals",
["%s:%s" % g for g in globals.items()],
join_with=",")
args.add_joined(
"--globals",
["%s:%s" % g for g in globals.items()],
join_with = ",",
)
args.add("--silent")
args.add("--silent")
other_inputs = [ctx.executable._rollup, rollup_config]
if ctx.file.license_banner:
other_inputs.append(ctx.file.license_banner)
if ctx.version_file:
other_inputs.append(ctx.version_file)
ctx.actions.run(
progress_message = "ng_package: Rollup %s %s" % (bundle_name, ctx.label),
mnemonic = "AngularPackageRollup",
inputs = inputs.to_list() + other_inputs,
outputs = [js_output, map_output],
executable = ctx.executable._rollup,
arguments = [args],
)
return struct(
js = js_output,
map = map_output,
)
other_inputs = [ctx.executable._rollup, rollup_config]
if ctx.file.license_banner:
other_inputs.append(ctx.file.license_banner)
if ctx.version_file:
other_inputs.append(ctx.version_file)
ctx.actions.run(
progress_message = "ng_package: Rollup %s %s" % (bundle_name, ctx.label),
mnemonic = "AngularPackageRollup",
inputs = inputs.to_list() + other_inputs,
outputs = [js_output, map_output],
executable = ctx.executable._rollup,
arguments = [args],
)
return struct(
js = js_output,
map = map_output,
)
# convert from [{js: js_file1, map: map_file1}, ...] to
# [js_filepath1, map_filepath1, ...]
def _flatten_paths(directory):
result = []
for f in directory:
result.append(f.js.path)
if f.map:
result.append(f.map.path)
return result
result = []
for f in directory:
result.append(f.js.path)
if f.map:
result.append(f.map.path)
return result
# takes an depset of files and returns an array that doesn't contain any generated files by ngc
def _filter_out_generated_files(files):
result = []
for file in files:
if (not(file.path.endswith(".ngfactory.js") or file.path.endswith(".ngsummary.js") or file.path.endswith(".ngstyle.js"))):
result.append(file)
return depset(result)
result = []
for file in files:
if (not (file.path.endswith(".ngfactory.js") or file.path.endswith(".ngsummary.js") or file.path.endswith(".ngstyle.js"))):
result.append(file)
return depset(result)
def _esm2015_root_dir(ctx):
return ctx.label.name + ".es6"
return ctx.label.name + ".es6"
# ng_package produces package that is npm-ready.
def _ng_package_impl(ctx):
npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name)
npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name)
esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx))
esm5_sources = _filter_out_generated_files(flatten_esm5(ctx))
esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx))
esm5_sources = _filter_out_generated_files(flatten_esm5(ctx))
# These accumulators match the directory names where the files live in the
# Angular package format.
fesm2015 = []
fesm5 = []
esm2015 = []
esm5 = []
bundles = []
# These accumulators match the directory names where the files live in the
# Angular package format.
fesm2015 = []
fesm5 = []
esm2015 = []
esm5 = []
bundles = []
# For Angular Package Format v6, we put all the individual .js files in the
# esm5/ and esm2015/ folders.
for f in esm5_sources.to_list():
if f.path.endswith(".js"):
esm5.append(struct(js = f, map = None))
for f in esm_2015_files.to_list():
if f.path.endswith(".js"):
esm2015.append(struct(js = f, map = None))
# For Angular Package Format v6, we put all the individual .js files in the
# esm5/ and esm2015/ folders.
for f in esm5_sources.to_list():
if f.path.endswith(".js"):
esm5.append(struct(js = f, map = None))
for f in esm_2015_files.to_list():
if f.path.endswith(".js"):
esm2015.append(struct(js = f, map = None))
# We infer the entry points to be:
# - ng_module rules in the deps (they have an "angular" provider)
# - in this package or a subpackage
# - those that have a module_name attribute (they produce flat module metadata)
flat_module_metadata = []
# Name given in the package.json name field, eg. @angular/core/testing
package_name = ""
deps_in_package = [d for d in ctx.attr.deps if d.label.package.startswith(ctx.label.package)]
for dep in deps_in_package:
# Intentionally evaluates to empty string for the main entry point
entry_point = dep.label.package[len(ctx.label.package) + 1:]
if hasattr(dep, "module_name"):
package_name = dep.module_name
if hasattr(dep, "angular") and hasattr(dep.angular, "flat_module_metadata"):
flat_module_metadata.append(dep.angular.flat_module_metadata)
flat_module_out_file = dep.angular.flat_module_metadata.flat_module_out_file + ".js"
# We infer the entry points to be:
# - ng_module rules in the deps (they have an "angular" provider)
# - in this package or a subpackage
# - those that have a module_name attribute (they produce flat module metadata)
flat_module_metadata = []
# Name given in the package.json name field, eg. @angular/core/testing
package_name = ""
deps_in_package = [d for d in ctx.attr.deps if d.label.package.startswith(ctx.label.package)]
for dep in deps_in_package:
# Intentionally evaluates to empty string for the main entry point
entry_point = dep.label.package[len(ctx.label.package) + 1:]
if hasattr(dep, "module_name"):
package_name = dep.module_name
if hasattr(dep, "angular") and hasattr(dep.angular, "flat_module_metadata"):
flat_module_metadata.append(dep.angular.flat_module_metadata)
flat_module_out_file = dep.angular.flat_module_metadata.flat_module_out_file + ".js"
else:
# fallback to a reasonable default
flat_module_out_file = "index.js"
es2015_entry_point = "/".join([p for p in [
ctx.bin_dir.path,
ctx.label.package,
_esm2015_root_dir(ctx),
ctx.label.package,
entry_point,
flat_module_out_file,
] if p])
es5_entry_point = "/".join([p for p in [
ctx.label.package,
entry_point,
flat_module_out_file,
] if p])
if entry_point:
# TODO jasonaden says there is no particular reason these filenames differ
prefix = primary_entry_point_name(ctx.attr.name, ctx.attr.entry_point, ctx.attr.entry_point_name)
umd_output_filename = "-".join([prefix] + entry_point.split("/"))
fesm_output_filename = entry_point.replace("/", "__")
fesm2015_output = ctx.actions.declare_file("fesm2015/%s.js" % fesm_output_filename)
fesm5_output = ctx.actions.declare_file("%s.js" % fesm_output_filename)
umd_output = ctx.actions.declare_file("%s.umd.js" % umd_output_filename)
min_output = ctx.actions.declare_file("%s.umd.min.js" % umd_output_filename)
else:
fesm2015_output = ctx.outputs.fesm2015
fesm5_output = ctx.outputs.fesm5
umd_output = ctx.outputs.umd
min_output = ctx.outputs.umd_min
esm2015_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, _esm2015_root_dir(ctx)]), filename = "_%s.rollup_esm2015.conf.js")
esm5_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]), filename = "_%s.rollup_esm5.conf.js")
fesm2015.append(_rollup(ctx, "fesm2015", esm2015_config, es2015_entry_point, esm_2015_files + ctx.files.node_modules, fesm2015_output))
fesm5.append(_rollup(ctx, "fesm5", esm5_config, es5_entry_point, esm5_sources + ctx.files.node_modules, fesm5_output))
bundles.append(
_rollup(
ctx,
"umd",
esm5_config,
es5_entry_point,
esm5_sources + ctx.files.node_modules,
umd_output,
format = "umd",
package_name = package_name,
include_tslib = True,
),
)
uglify_sourcemap = run_uglify(
ctx,
umd_output,
min_output,
config_name = entry_point.replace("/", "_"),
)
bundles.append(struct(js = min_output, map = uglify_sourcemap))
packager_inputs = (
ctx.files.srcs +
ctx.files.data +
esm5_sources.to_list() +
depset(transitive = [
d.typescript.transitive_declarations
for d in ctx.attr.deps
if hasattr(d, "typescript")
]).to_list() +
[f.js for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles] +
[f.map for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles if f.map]
)
packager_args = ctx.actions.args()
packager_args.use_param_file("%s", use_always = True)
# The order of arguments matters here, as they are read in order in packager.ts.
packager_args.add(npm_package_directory.path)
packager_args.add(ctx.label.package)
packager_args.add_joined([ctx.bin_dir.path, ctx.label.package], join_with = "/")
packager_args.add_joined([ctx.genfiles_dir.path, ctx.label.package], join_with = "/")
# Marshal the metadata into a JSON string so we can parse the data structure
# in the TypeScript program easily.
metadata_arg = {}
for m in flat_module_metadata:
packager_inputs.extend([m.metadata_file])
metadata_arg[m.module_name] = {
"index": m.typings_file.path.replace(".d.ts", ".js"),
"typings": m.typings_file.path,
"metadata": m.metadata_file.path,
}
packager_args.add(str(metadata_arg))
if ctx.file.readme_md:
packager_inputs.append(ctx.file.readme_md)
packager_args.add(ctx.file.readme_md.path)
else:
# fallback to a reasonable default
flat_module_out_file = "index.js"
# placeholder
packager_args.add("")
es2015_entry_point = "/".join([p for p in [
ctx.bin_dir.path,
ctx.label.package,
_esm2015_root_dir(ctx),
ctx.label.package,
entry_point,
flat_module_out_file,
] if p])
packager_args.add_joined(_flatten_paths(fesm2015), join_with = ",")
packager_args.add_joined(_flatten_paths(fesm5), join_with = ",")
packager_args.add_joined(_flatten_paths(esm2015), join_with = ",")
packager_args.add_joined(_flatten_paths(esm5), join_with = ",")
packager_args.add_joined(_flatten_paths(bundles), join_with = ",")
packager_args.add_joined([s.path for s in ctx.files.srcs], join_with = ",")
es5_entry_point = "/".join([p for p in [
ctx.label.package,
entry_point,
flat_module_out_file,
] if p])
# TODO: figure out a better way to gather runfiles providers from the transitive closure.
packager_args.add_joined([d.path for d in ctx.files.data], join_with = ",")
if entry_point:
# TODO jasonaden says there is no particular reason these filenames differ
prefix = primary_entry_point_name(ctx.attr.name, ctx.attr.entry_point, ctx.attr.entry_point_name)
umd_output_filename = "-".join([prefix] + entry_point.split("/"))
fesm_output_filename = entry_point.replace("/", "__")
fesm2015_output = ctx.actions.declare_file("fesm2015/%s.js" % fesm_output_filename)
fesm5_output = ctx.actions.declare_file("%s.js" % fesm_output_filename)
umd_output = ctx.actions.declare_file("%s.umd.js" % umd_output_filename)
min_output = ctx.actions.declare_file("%s.umd.min.js" % umd_output_filename)
if ctx.file.license_banner:
packager_inputs.append(ctx.file.license_banner)
packager_args.add(ctx.file.license_banner)
else:
fesm2015_output = ctx.outputs.fesm2015
fesm5_output = ctx.outputs.fesm5
umd_output = ctx.outputs.umd
min_output = ctx.outputs.umd_min
# placeholder
packager_args.add("")
esm2015_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, _esm2015_root_dir(ctx)]), filename="_%s.rollup_esm2015.conf.js")
esm5_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]), filename="_%s.rollup_esm5.conf.js")
ctx.actions.run(
progress_message = "Angular Packaging: building npm package %s" % str(ctx.label),
mnemonic = "AngularPackage",
inputs = packager_inputs,
outputs = [npm_package_directory],
executable = ctx.executable._ng_packager,
arguments = [packager_args],
)
fesm2015.append(_rollup(ctx, "fesm2015", esm2015_config, es2015_entry_point, esm_2015_files + ctx.files.node_modules, fesm2015_output))
fesm5.append(_rollup(ctx, "fesm5", esm5_config, es5_entry_point, esm5_sources + ctx.files.node_modules, fesm5_output))
devfiles = depset()
if ctx.attr.include_devmode_srcs:
for d in ctx.attr.deps:
devfiles = depset(transitive = [devfiles, d.files, d.node_sources])
bundles.append(
_rollup(ctx, "umd", esm5_config, es5_entry_point, esm5_sources + ctx.files.node_modules, umd_output,
format = "umd", package_name = package_name, include_tslib = True))
uglify_sourcemap = run_uglify(ctx, umd_output, min_output,
config_name = entry_point.replace("/", "_"))
bundles.append(struct(js = min_output, map = uglify_sourcemap))
packager_inputs = (
ctx.files.srcs +
ctx.files.data +
esm5_sources.to_list() +
depset(transitive = [d.typescript.transitive_declarations
for d in ctx.attr.deps
if hasattr(d, "typescript")]).to_list() +
[f.js for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles] +
[f.map for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles if f.map])
packager_args = ctx.actions.args()
packager_args.use_param_file("%s", use_always = True)
# The order of arguments matters here, as they are read in order in packager.ts.
packager_args.add(npm_package_directory.path)
packager_args.add(ctx.label.package)
packager_args.add_joined([ctx.bin_dir.path, ctx.label.package], join_with="/")
packager_args.add_joined([ctx.genfiles_dir.path, ctx.label.package], join_with="/")
# Marshal the metadata into a JSON string so we can parse the data structure
# in the TypeScript program easily.
metadata_arg = {}
for m in flat_module_metadata:
packager_inputs.extend([m.metadata_file])
metadata_arg[m.module_name] = {
"index": m.typings_file.path.replace(".d.ts", ".js"),
"typings": m.typings_file.path,
"metadata": m.metadata_file.path,
}
packager_args.add(str(metadata_arg))
if ctx.file.readme_md:
packager_inputs.append(ctx.file.readme_md)
packager_args.add(ctx.file.readme_md.path)
else:
# placeholder
packager_args.add("")
packager_args.add_joined(_flatten_paths(fesm2015), join_with=",")
packager_args.add_joined(_flatten_paths(fesm5), join_with=",")
packager_args.add_joined(_flatten_paths(esm2015), join_with=",")
packager_args.add_joined(_flatten_paths(esm5), join_with=",")
packager_args.add_joined(_flatten_paths(bundles), join_with=",")
packager_args.add_joined([s.path for s in ctx.files.srcs], join_with=",")
# TODO: figure out a better way to gather runfiles providers from the transitive closure.
packager_args.add_joined([d.path for d in ctx.files.data], join_with=",")
if ctx.file.license_banner:
packager_inputs.append(ctx.file.license_banner)
packager_args.add(ctx.file.license_banner)
else:
# placeholder
packager_args.add("")
ctx.actions.run(
progress_message = "Angular Packaging: building npm package %s" % str(ctx.label),
mnemonic = "AngularPackage",
inputs = packager_inputs,
outputs = [npm_package_directory],
executable = ctx.executable._ng_packager,
arguments = [packager_args],
)
devfiles = depset()
if ctx.attr.include_devmode_srcs:
for d in ctx.attr.deps:
devfiles = depset(transitive = [devfiles, d.files, d.node_sources])
# Re-use the create_package function from the nodejs npm_package rule.
package_dir = create_package(
ctx,
devfiles.to_list(),
[npm_package_directory] + ctx.files.packages)
return [DefaultInfo(
files = depset([package_dir])
)]
# Re-use the create_package function from the nodejs npm_package rule.
package_dir = create_package(
ctx,
devfiles.to_list(),
[npm_package_directory] + ctx.files.packages,
)
return [DefaultInfo(
files = depset([package_dir]),
)]
NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{
"srcs": attr.label_list(allow_files = True),
@ -335,22 +357,29 @@ NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{
),
"include_devmode_srcs": attr.bool(default = False),
"readme_md": attr.label(allow_single_file = FileType([".md"])),
"globals": attr.string_dict(default={}),
"globals": attr.string_dict(default = {}),
"entry_point_name": attr.string(
doc = "Name to use when generating bundle files for the primary entry-point.",
doc = "Name to use when generating bundle files for the primary entry-point.",
),
"_ng_packager": attr.label(
default=Label("//packages/bazel/src/ng_package:packager"),
executable=True, cfg="host"),
default = Label("//packages/bazel/src/ng_package:packager"),
executable = True,
cfg = "host",
),
"_rollup": attr.label(
default=Label("@build_bazel_rules_nodejs//internal/rollup"),
executable=True, cfg="host"),
default = Label("@build_bazel_rules_nodejs//internal/rollup"),
executable = True,
cfg = "host",
),
"_rollup_config_tmpl": attr.label(
default=Label("@build_bazel_rules_nodejs//internal/rollup:rollup.config.js"),
allow_single_file=True),
default = Label("@build_bazel_rules_nodejs//internal/rollup:rollup.config.js"),
allow_single_file = True,
),
"_uglify": attr.label(
default=Label("@build_bazel_rules_nodejs//internal/rollup:uglify"),
executable=True, cfg="host"),
default = Label("@build_bazel_rules_nodejs//internal/rollup:uglify"),
executable = True,
cfg = "host",
),
}))
# Angular wants these named after the entry_point,
@ -360,57 +389,57 @@ NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{
# some/path/to/my/package/index.js
# we assume the files should be named "package.*.js"
def primary_entry_point_name(name, entry_point, entry_point_name):
"""This is not a public API.
"""This is not a public API.
Compute the name of the primary entry point in the library.
Compute the name of the primary entry point in the library.
Args:
name: the name of the `ng_package` rule, as a fallback.
entry_point: The starting point of the application, see rollup_bundle.
entry_point_name: if set, this is the returned value.
Args:
name: the name of the `ng_package` rule, as a fallback.
entry_point: The starting point of the application, see rollup_bundle.
entry_point_name: if set, this is the returned value.
Returns:
name of the entry point, which will appear in the name of generated bundles
"""
if entry_point_name:
# If an explicit entry_point_name is given, use that.
return entry_point_name
elif entry_point.find("/") >= 0:
# If the entry_point has multiple path segments, use the second one.
# E.g., for "@angular/cdk/a11y", use "cdk".
return entry_point.split("/")[-2]
else:
# Fall back to the name of the ng_package rule.
return name
Returns:
name of the entry point, which will appear in the name of generated bundles
"""
if entry_point_name:
# If an explicit entry_point_name is given, use that.
return entry_point_name
elif entry_point.find("/") >= 0:
# If the entry_point has multiple path segments, use the second one.
# E.g., for "@angular/cdk/a11y", use "cdk".
return entry_point.split("/")[-2]
else:
# Fall back to the name of the ng_package rule.
return name
def ng_package_outputs(name, entry_point, entry_point_name):
"""This is not a public API.
"""This is not a public API.
This function computes the named outputs for an ng_package rule.
This function computes the named outputs for an ng_package rule.
Args:
name: value of the name attribute
entry_point: value of the entry_point attribute
entry_point_name: value of the entry_point_name attribute
Args:
name: value of the name attribute
entry_point: value of the entry_point attribute
entry_point_name: value of the entry_point_name attribute
Returns:
dict of named outputs of the rule
"""
Returns:
dict of named outputs of the rule
"""
basename = primary_entry_point_name(name, entry_point, entry_point_name)
outputs = {
"fesm5": "fesm5/%s.js" % basename,
"fesm2015": "fesm2015/%s.js" % basename,
"umd": "%s.umd.js" % basename,
"umd_min": "%s.umd.min.js" % basename,
}
for key in NPM_PACKAGE_OUTPUTS:
# NPM_PACKAGE_OUTPUTS is a "normal" dict-valued outputs so it looks like
# "pack": "%{name}.pack",
# But this is a function-valued outputs.
# Bazel won't replace the %{name} token so we have to do it.
outputs[key] = NPM_PACKAGE_OUTPUTS[key].replace("%{name}", name)
return outputs
basename = primary_entry_point_name(name, entry_point, entry_point_name)
outputs = {
"fesm5": "fesm5/%s.js" % basename,
"fesm2015": "fesm2015/%s.js" % basename,
"umd": "%s.umd.js" % basename,
"umd_min": "%s.umd.min.js" % basename,
}
for key in NPM_PACKAGE_OUTPUTS:
# NPM_PACKAGE_OUTPUTS is a "normal" dict-valued outputs so it looks like
# "pack": "%{name}.pack",
# But this is a function-valued outputs.
# Bazel won't replace the %{name} token so we have to do it.
outputs[key] = NPM_PACKAGE_OUTPUTS[key].replace("%{name}", name)
return outputs
ng_package = rule(
implementation = _ng_package_impl,
@ -419,4 +448,4 @@ ng_package = rule(
)
"""
ng_package produces an npm-ready package from an Angular library.
"""
"""

View File

@ -14,125 +14,132 @@
[rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html
"""
load("@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
"rollup_module_mappings_aspect",
load(
"@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
"ROLLUP_ATTRS",
"ROLLUP_OUTPUTS",
"write_rollup_config",
"rollup_module_mappings_aspect",
"run_rollup",
"run_sourcemapexplorer",
"run_uglify",
"run_sourcemapexplorer")
"write_rollup_config",
)
load("@build_bazel_rules_nodejs//internal:collect_es6_sources.bzl", collect_es2015_sources = "collect_es6_sources")
load(":esm5.bzl", "esm5_outputs_aspect", "flatten_esm5", "esm5_root_dir")
load(":esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5")
PACKAGES=["packages/core/src", "packages/common/src", "packages/compiler/src", "external/rxjs"]
PLUGIN_CONFIG="{sideEffectFreeModules: [\n%s]}" % ",\n".join(
[" '.esm5/{0}'".format(p) for p in PACKAGES])
BO_ROLLUP="angular_cli/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
BO_PLUGIN="require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG)
PACKAGES = ["packages/core/src", "packages/common/src", "packages/compiler/src", "external/rxjs"]
PLUGIN_CONFIG = "{sideEffectFreeModules: [\n%s]}" % ",\n".join(
[" '.esm5/{0}'".format(p) for p in PACKAGES],
)
BO_ROLLUP = "angular_cli/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
BO_PLUGIN = "require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG)
def _use_plain_rollup(ctx):
"""Determine whether to use the Angular or upstream versions of the rollup_bundle rule.
"""Determine whether to use the Angular or upstream versions of the rollup_bundle rule.
In most modes, the Angular version of rollup is used. This runs build optimizer as part of its
processing, which affects decorators and annotations.
In most modes, the Angular version of rollup is used. This runs build optimizer as part of its
processing, which affects decorators and annotations.
In JIT modes, an emulation of the upstream rollup_bundle rule is used. This avoids running
build optimizer on code which isn't designed to be optimized by it.
In JIT modes, an emulation of the upstream rollup_bundle rule is used. This avoids running
build optimizer on code which isn't designed to be optimized by it.
Args:
ctx: skylark rule execution context
Args:
ctx: skylark rule execution context
Returns:
true iff the Angular version of rollup with build optimizer should be used, false otherwise
"""
Returns:
true iff the Angular version of rollup with build optimizer should be used, false otherwise
"""
if 'compile' not in ctx.var:
return False
strategy = ctx.var['compile']
return strategy == 'jit'
if "compile" not in ctx.var:
return False
strategy = ctx.var["compile"]
return strategy == "jit"
def run_brotli(ctx, input, output):
"""Execute the Brotli compression utility.
"""Execute the Brotli compression utility.
Args:
ctx: Bazel's rule execution context
input: any file
output: the compressed file
"""
ctx.actions.run(
executable = ctx.executable._brotli,
inputs = [input],
outputs = [output],
arguments = ["--output=%s" % output.path, input.path],
)
Args:
ctx: Bazel's rule execution context
input: any file
output: the compressed file
"""
ctx.actions.run(
executable = ctx.executable._brotli,
inputs = [input],
outputs = [output],
arguments = ["--output=%s" % output.path, input.path],
)
# Borrowed from bazelbuild/rules_nodejs
def _run_tsc(ctx, input, output):
args = ctx.actions.args()
args.add("--target", "es5")
args.add("--allowJS")
args.add(input)
args.add("--outFile", output)
args = ctx.actions.args()
args.add("--target", "es5")
args.add("--allowJS")
args.add(input)
args.add("--outFile", output)
ctx.action(
executable = ctx.executable._tsc,
inputs = [input],
outputs = [output],
arguments = [args]
)
ctx.action(
executable = ctx.executable._tsc,
inputs = [input],
outputs = [output],
arguments = [args],
)
# Borrowed from bazelbuild/rules_nodejs, with the addition of brotli compression output
def _plain_rollup_bundle(ctx):
rollup_config = write_rollup_config(ctx)
run_rollup(ctx, collect_es2015_sources(ctx), rollup_config, ctx.outputs.build_es6)
_run_tsc(ctx, ctx.outputs.build_es6, ctx.outputs.build_es5)
source_map = run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min)
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min_debug, debug = True)
umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd")
run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd)
run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, source_map, ctx.outputs.explore_html)
rollup_config = write_rollup_config(ctx)
run_rollup(ctx, collect_es2015_sources(ctx), rollup_config, ctx.outputs.build_es6)
_run_tsc(ctx, ctx.outputs.build_es6, ctx.outputs.build_es5)
source_map = run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min)
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min_debug, debug = True)
umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd")
run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd)
run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, source_map, ctx.outputs.explore_html)
run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed)
files = [ctx.outputs.build_es5_min, source_map]
return DefaultInfo(files = depset(files), runfiles = ctx.runfiles(files))
run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed)
files = [ctx.outputs.build_es5_min, source_map]
return DefaultInfo(files = depset(files), runfiles = ctx.runfiles(files))
def _ng_rollup_bundle(ctx):
# Escape and use the plain rollup rule if the compilation strategy requires it
if _use_plain_rollup(ctx):
return _plain_rollup_bundle(ctx)
# Escape and use the plain rollup rule if the compilation strategy requires it
if _use_plain_rollup(ctx):
return _plain_rollup_bundle(ctx)
# We don't expect anyone to make use of this bundle yet, but it makes this rule
# compatible with rollup_bundle which allows them to be easily swapped back and
# forth.
esm2015_rollup_config = write_rollup_config(ctx, filename = "_%s.rollup_es6.conf.js")
run_rollup(ctx, collect_es2015_sources(ctx), esm2015_rollup_config, ctx.outputs.build_es6)
# We don't expect anyone to make use of this bundle yet, but it makes this rule
# compatible with rollup_bundle which allows them to be easily swapped back and
# forth.
esm2015_rollup_config = write_rollup_config(ctx, filename = "_%s.rollup_es6.conf.js")
run_rollup(ctx, collect_es2015_sources(ctx), esm2015_rollup_config, ctx.outputs.build_es6)
esm5_sources = flatten_esm5(ctx)
esm5_sources = flatten_esm5(ctx)
rollup_config = write_rollup_config(ctx, [BO_PLUGIN], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]))
rollup_sourcemap = run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_es5)
rollup_config = write_rollup_config(ctx, [BO_PLUGIN], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]))
rollup_sourcemap = run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_es5)
sourcemap = run_uglify(ctx,
ctx.outputs.build_es5,
ctx.outputs.build_es5_min,
comments = False,
in_source_map = rollup_sourcemap)
run_uglify(ctx,
ctx.outputs.build_es5,
ctx.outputs.build_es5_min_debug,
debug = True, comments = False)
sourcemap = run_uglify(
ctx,
ctx.outputs.build_es5,
ctx.outputs.build_es5_min,
comments = False,
in_source_map = rollup_sourcemap,
)
run_uglify(
ctx,
ctx.outputs.build_es5,
ctx.outputs.build_es5_min_debug,
debug = True,
comments = False,
)
umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd")
run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd)
umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd")
run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd)
run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed)
run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed)
run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, sourcemap, ctx.outputs.explore_html)
run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, sourcemap, ctx.outputs.explore_html)
return DefaultInfo(files=depset([ctx.outputs.build_es5_min, sourcemap]))
return DefaultInfo(files = depset([ctx.outputs.build_es5_min, sourcemap]))
ng_rollup_bundle = rule(
implementation = _ng_rollup_bundle,
@ -143,16 +150,18 @@ ng_rollup_bundle = rule(
aspects = [
rollup_module_mappings_aspect,
esm5_outputs_aspect,
]
],
),
"_rollup": attr.label(
executable = True,
cfg = "host",
default = Label("@angular//packages/bazel/src:rollup_with_build_optimizer")),
default = Label("@angular//packages/bazel/src:rollup_with_build_optimizer"),
),
"_brotli": attr.label(
executable = True,
cfg = "host",
default = Label("@org_brotli//:brotli")),
default = Label("@org_brotli//:brotli"),
),
}),
outputs = dict(ROLLUP_OUTPUTS, **{
"build_es5_min_compressed": "%{name}.min.js.br",
@ -167,4 +176,4 @@ that rule are used here too.
[Rollup]: https://rollupjs.org/
[Build Optimizer]: https://www.npmjs.com/package/@angular-devkit/build-optimizer
[rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html
"""
"""

View File

@ -8,13 +8,13 @@
load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install")
def ng_setup_workspace():
"""This repository rule should be called from your WORKSPACE file.
"""This repository rule should be called from your WORKSPACE file.
It creates some additional Bazel external repositories that are used internally
by the Angular rules.
"""
yarn_install(
name = "angular_packager_deps",
package_json = "@angular//packages/bazel/src/ng_package:package.json",
yarn_lock = "@angular//packages/bazel/src/ng_package:yarn.lock",
)
It creates some additional Bazel external repositories that are used internally
by the Angular rules.
"""
yarn_install(
name = "angular_packager_deps",
package_json = "@angular//packages/bazel/src/ng_package:package.json",
yarn_lock = "@angular//packages/bazel/src/ng_package:yarn.lock",
)

View File

@ -4,9 +4,10 @@
# found in the LICENSE file at https://angular.io/license
"Run end-to-end tests with Protractor"
load("@build_bazel_rules_nodejs//internal:node.bzl",
"sources_aspect",
load(
"@build_bazel_rules_nodejs//internal:node.bzl",
"expand_path_into_runfiles",
"sources_aspect",
)
load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite")
load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS")
@ -15,69 +16,71 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
_CONF_TMPL = "//packages/bazel/src/protractor:protractor.conf.js"
def _protractor_web_test_impl(ctx):
configuration = ctx.actions.declare_file(
"%s.conf.js" % ctx.label.name,
sibling=ctx.outputs.executable)
configuration = ctx.actions.declare_file(
"%s.conf.js" % ctx.label.name,
sibling = ctx.outputs.executable,
)
files = depset(ctx.files.srcs)
for d in ctx.attr.deps:
if hasattr(d, "node_sources"):
files = depset(transitive = [files, d.node_sources])
elif hasattr(d, "files"):
files = depset(transitive = [files, d.files])
files = depset(ctx.files.srcs)
for d in ctx.attr.deps:
if hasattr(d, "node_sources"):
files = depset(transitive = [files, d.node_sources])
elif hasattr(d, "files"):
files = depset(transitive = [files, d.files])
specs = [
expand_path_into_runfiles(ctx, f.short_path)
for f in files
]
specs = [
expand_path_into_runfiles(ctx, f.short_path)
for f in files
]
configuration_sources = []
if ctx.file.configuration:
configuration_sources = [ctx.file.configuration]
if hasattr(ctx.attr.configuration, "node_sources"):
configuration_sources = ctx.attr.configuration.node_sources.to_list()
configuration_sources = []
if ctx.file.configuration:
configuration_sources = [ctx.file.configuration]
if hasattr(ctx.attr.configuration, "node_sources"):
configuration_sources = ctx.attr.configuration.node_sources.to_list()
configuration_file = ctx.file.configuration
if hasattr(ctx.attr.configuration, "typescript"):
configuration_file = ctx.attr.configuration.typescript.es5_sources.to_list()[0]
configuration_file = ctx.file.configuration
if hasattr(ctx.attr.configuration, "typescript"):
configuration_file = ctx.attr.configuration.typescript.es5_sources.to_list()[0]
on_prepare_sources = []
if ctx.file.on_prepare:
on_prepare_sources = [ctx.file.on_prepare]
if hasattr(ctx.attr.on_prepare, "node_sources"):
on_prepare_sources = ctx.attr.on_prepare.node_sources.to_list()
on_prepare_sources = []
if ctx.file.on_prepare:
on_prepare_sources = [ctx.file.on_prepare]
if hasattr(ctx.attr.on_prepare, "node_sources"):
on_prepare_sources = ctx.attr.on_prepare.node_sources.to_list()
on_prepare_file = ctx.file.on_prepare
if hasattr(ctx.attr.on_prepare, "typescript"):
on_prepare_file = ctx.attr.on_prepare.typescript.es5_sources.to_list()[0]
on_prepare_file = ctx.file.on_prepare
if hasattr(ctx.attr.on_prepare, "typescript"):
on_prepare_file = ctx.attr.on_prepare.typescript.es5_sources.to_list()[0]
protractor_executable_path = ctx.executable.protractor.short_path
if protractor_executable_path.startswith('..'):
protractor_executable_path = "external" + protractor_executable_path[2:]
protractor_executable_path = ctx.executable.protractor.short_path
if protractor_executable_path.startswith(".."):
protractor_executable_path = "external" + protractor_executable_path[2:]
server_executable_path = ''
if ctx.executable.server:
server_executable_path = ctx.executable.server.short_path
if server_executable_path.startswith('..'):
server_executable_path = "external" + protractor_executable_path[2:]
server_executable_path = ""
if ctx.executable.server:
server_executable_path = ctx.executable.server.short_path
if server_executable_path.startswith(".."):
server_executable_path = "external" + protractor_executable_path[2:]
ctx.actions.expand_template(
output = configuration,
template = ctx.file._conf_tmpl,
substitutions = {
"TMPL_config": expand_path_into_runfiles(ctx, configuration_file.short_path) if configuration_file else "",
"TMPL_on_prepare": expand_path_into_runfiles(ctx, on_prepare_file.short_path) if on_prepare_file else "",
"TMPL_workspace": ctx.workspace_name,
"TMPL_server": server_executable_path,
"TMPL_specs": "\n".join([" '%s'," % e for e in specs]),
})
ctx.actions.expand_template(
output = configuration,
template = ctx.file._conf_tmpl,
substitutions = {
"TMPL_config": expand_path_into_runfiles(ctx, configuration_file.short_path) if configuration_file else "",
"TMPL_on_prepare": expand_path_into_runfiles(ctx, on_prepare_file.short_path) if on_prepare_file else "",
"TMPL_workspace": ctx.workspace_name,
"TMPL_server": server_executable_path,
"TMPL_specs": "\n".join([" '%s'," % e for e in specs]),
},
)
runfiles = [configuration] + configuration_sources + on_prepare_sources
runfiles = [configuration] + configuration_sources + on_prepare_sources
ctx.actions.write(
output = ctx.outputs.executable,
is_executable = True,
content = """#!/usr/bin/env bash
ctx.actions.write(
output = ctx.outputs.executable,
is_executable = True,
content = """#!/usr/bin/env bash
if [ -e "$RUNFILE_MANIFEST_FILE" ]; then
while read line; do
declare -a PARTS=($line)
@ -100,19 +103,22 @@ echo "Protractor $PROTRACTOR_VERSION"
# Run the protractor binary
$PROTRACTOR $CONF
""".format(TMPL_protractor = protractor_executable_path,
TMPL_conf = configuration.short_path))
return [DefaultInfo(
files = depset([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = runfiles,
transitive_files = files,
# Propagate protractor_bin and its runfiles
collect_data = True,
collect_default = True,
),
executable = ctx.outputs.executable,
)]
""".format(
TMPL_protractor = protractor_executable_path,
TMPL_conf = configuration.short_path,
),
)
return [DefaultInfo(
files = depset([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = runfiles,
transitive_files = files,
# Propagate protractor_bin and its runfiles
collect_data = True,
collect_default = True,
),
executable = ctx.outputs.executable,
)]
_protractor_web_test = rule(
implementation = _protractor_web_test_impl,
@ -123,36 +129,43 @@ _protractor_web_test = rule(
doc = "Protractor configuration file",
allow_single_file = True,
cfg = "data",
aspects = [sources_aspect]),
aspects = [sources_aspect],
),
"srcs": attr.label_list(
doc = "A list of JavaScript test files",
allow_files = [".js"]),
allow_files = [".js"],
),
"on_prepare": attr.label(
doc = """A file with a node.js script to run once before all tests run.
If the script exports a function which returns a promise, protractor
will wait for the promise to resolve before beginning tests.""",
allow_single_file = True,
cfg = "data",
aspects = [sources_aspect]),
aspects = [sources_aspect],
),
"deps": attr.label_list(
doc = "Other targets which produce JavaScript such as `ts_library`",
allow_files = True,
aspects = [sources_aspect]),
aspects = [sources_aspect],
),
"data": attr.label_list(
doc = "Runtime dependencies",
cfg = "data"),
cfg = "data",
),
"server": attr.label(
doc = "Optional server executable target",
executable = True,
cfg = "data",
single_file = False,
allow_files = True),
allow_files = True,
),
"protractor": attr.label(
doc = "Protractor executable target (set by protractor_web_test macro)",
executable = True,
cfg = "data",
single_file = False,
allow_files = True),
allow_files = True,
),
"_conf_tmpl": attr.label(
default = Label(_CONF_TMPL),
allow_single_file = True,
@ -161,180 +174,184 @@ _protractor_web_test = rule(
)
def protractor_web_test(
name,
configuration = None,
on_prepare = None,
srcs = [],
deps = [],
data = [],
server = None,
tags = [],
**kwargs):
"""Runs a protractor test in a browser.
name,
configuration = None,
on_prepare = None,
srcs = [],
deps = [],
data = [],
server = None,
tags = [],
**kwargs):
"""Runs a protractor test in a browser.
Args:
name: The name of the test
configuration: Protractor configuration file.
on_prepare: A file with a node.js script to run once before all tests run.
If the script exports a function which returns a promise, protractor
will wait for the promise to resolve before beginning tests.
srcs: JavaScript source files
deps: Other targets which produce JavaScript such as `ts_library`
data: Runtime dependencies
server: Optional server executable target
tags: Standard Bazel tags, this macro adds one for ibazel
**kwargs: passed through to `_protractor_web_test`
"""
Args:
name: The name of the test
configuration: Protractor configuration file.
on_prepare: A file with a node.js script to run once before all tests run.
If the script exports a function which returns a promise, protractor
will wait for the promise to resolve before beginning tests.
srcs: JavaScript source files
deps: Other targets which produce JavaScript such as `ts_library`
data: Runtime dependencies
server: Optional server executable target
tags: Standard Bazel tags, this macro adds one for ibazel
**kwargs: passed through to `_protractor_web_test`
"""
protractor_bin_name = name + "_protractor_bin"
protractor_bin_name = name + "_protractor_bin"
nodejs_binary(
name = protractor_bin_name,
entry_point = "protractor/bin/protractor",
data = srcs + deps + data,
node_modules = "@//:node_modules",
testonly = 1,
visibility = ["//visibility:private"],
)
nodejs_binary(
name = protractor_bin_name,
entry_point = "protractor/bin/protractor",
data = srcs + deps + data,
node_modules = "@//:node_modules",
testonly = 1,
visibility = ["//visibility:private"],
)
# Our binary dependency must be in data[] for collect_data to pick it up
# FIXME: maybe we can just ask :protractor_bin_name for its runfiles attr
web_test_data = data + [":" + protractor_bin_name]
if server:
web_test_data += [server]
# Our binary dependency must be in data[] for collect_data to pick it up
# FIXME: maybe we can just ask :protractor_bin_name for its runfiles attr
web_test_data = data + [":" + protractor_bin_name]
if server:
web_test_data += [server]
_protractor_web_test(
name = name,
configuration = configuration,
on_prepare=on_prepare,
srcs = srcs,
deps = deps,
data = web_test_data,
server = server,
protractor = protractor_bin_name,
tags = tags + [
# Users don't need to know that this tag is required to run under ibazel
"ibazel_notify_changes",
],
**kwargs)
_protractor_web_test(
name = name,
configuration = configuration,
on_prepare = on_prepare,
srcs = srcs,
deps = deps,
data = web_test_data,
server = server,
protractor = protractor_bin_name,
tags = tags + [
# Users don't need to know that this tag is required to run under ibazel
"ibazel_notify_changes",
],
**kwargs
)
def protractor_web_test_suite(
name,
configuration = None,
on_prepare = None,
srcs = [],
deps = [],
data = [],
server = None,
browsers=["@io_bazel_rules_webtesting//browsers:chromium-local"],
args=None,
browser_overrides=None,
config=None,
flaky=None,
local=None,
shard_count=None,
size=None,
tags = [],
test_suite_tags=None,
timeout=None,
visibility=None,
web_test_data=[],
wrapped_test_tags=None,
**remaining_keyword_args):
"""Defines a test_suite of web_test targets that wrap a protractor_web_test target.
name,
configuration = None,
on_prepare = None,
srcs = [],
deps = [],
data = [],
server = None,
browsers = ["@io_bazel_rules_webtesting//browsers:chromium-local"],
args = None,
browser_overrides = None,
config = None,
flaky = None,
local = None,
shard_count = None,
size = None,
tags = [],
test_suite_tags = None,
timeout = None,
visibility = None,
web_test_data = [],
wrapped_test_tags = None,
**remaining_keyword_args):
"""Defines a test_suite of web_test targets that wrap a protractor_web_test target.
Args:
name: The base name of the test.
configuration: Protractor configuration file.
on_prepare: A file with a node.js script to run once before all tests run.
If the script exports a function which returns a promise, protractor
will wait for the promise to resolve before beginning tests.
srcs: JavaScript source files
deps: Other targets which produce JavaScript such as `ts_library`
data: Runtime dependencies
server: Optional server executable target
browsers: A sequence of labels specifying the browsers to use.
args: Args for web_test targets generated by this extension.
browser_overrides: Dictionary; optional; default is an empty dictionary. A
dictionary mapping from browser names to browser-specific web_test
attributes, such as shard_count, flakiness, timeout, etc. For example:
{'//browsers:chrome-native': {'shard_count': 3, 'flaky': 1}
'//browsers:firefox-native': {'shard_count': 1, 'timeout': 100}}.
config: Label; optional; Configuration of web test features.
flaky: A boolean specifying that the test is flaky. If set, the test will
be retried up to 3 times (default: 0)
local: boolean; optional.
shard_count: The number of test shards to use per browser. (default: 1)
size: A string specifying the test size. (default: 'large')
tags: A list of test tag strings to apply to each generated web_test target.
This macro adds a couple for ibazel.
test_suite_tags: A list of tag strings for the generated test_suite.
timeout: A string specifying the test timeout (default: computed from size)
visibility: List of labels; optional.
web_test_data: Data dependencies for the web_test.
wrapped_test_tags: A list of test tag strings to use for the wrapped test
**remaining_keyword_args: Arguments for the wrapped test target.
"""
# Check explicitly for None so that users can set this to the empty list
if wrapped_test_tags == None:
wrapped_test_tags = DEFAULT_WRAPPED_TEST_TAGS
Args:
name: The base name of the test.
configuration: Protractor configuration file.
on_prepare: A file with a node.js script to run once before all tests run.
If the script exports a function which returns a promise, protractor
will wait for the promise to resolve before beginning tests.
srcs: JavaScript source files
deps: Other targets which produce JavaScript such as `ts_library`
data: Runtime dependencies
server: Optional server executable target
browsers: A sequence of labels specifying the browsers to use.
args: Args for web_test targets generated by this extension.
browser_overrides: Dictionary; optional; default is an empty dictionary. A
dictionary mapping from browser names to browser-specific web_test
attributes, such as shard_count, flakiness, timeout, etc. For example:
{'//browsers:chrome-native': {'shard_count': 3, 'flaky': 1}
'//browsers:firefox-native': {'shard_count': 1, 'timeout': 100}}.
config: Label; optional; Configuration of web test features.
flaky: A boolean specifying that the test is flaky. If set, the test will
be retried up to 3 times (default: 0)
local: boolean; optional.
shard_count: The number of test shards to use per browser. (default: 1)
size: A string specifying the test size. (default: 'large')
tags: A list of test tag strings to apply to each generated web_test target.
This macro adds a couple for ibazel.
test_suite_tags: A list of tag strings for the generated test_suite.
timeout: A string specifying the test timeout (default: computed from size)
visibility: List of labels; optional.
web_test_data: Data dependencies for the web_test.
wrapped_test_tags: A list of test tag strings to use for the wrapped test
**remaining_keyword_args: Arguments for the wrapped test target.
"""
size = size or "large"
# Check explicitly for None so that users can set this to the empty list
if wrapped_test_tags == None:
wrapped_test_tags = DEFAULT_WRAPPED_TEST_TAGS
wrapped_test_name = name + "_wrapped_test"
protractor_bin_name = name + "_protractor_bin"
size = size or "large"
# Users don't need to know that this tag is required to run under ibazel
tags = tags + ["ibazel_notify_changes"]
wrapped_test_name = name + "_wrapped_test"
protractor_bin_name = name + "_protractor_bin"
nodejs_binary(
name = protractor_bin_name,
entry_point = "protractor/bin/protractor",
data = srcs + deps + data,
node_modules = "@//:node_modules",
testonly = 1,
visibility = ["//visibility:private"],
)
# Users don't need to know that this tag is required to run under ibazel
tags = tags + ["ibazel_notify_changes"]
# Our binary dependency must be in data[] for collect_data to pick it up
# FIXME: maybe we can just ask the :protractor_bin_name for its runfiles attr
web_test_data = web_test_data + [":" + protractor_bin_name]
if server:
web_test_data += [server]
nodejs_binary(
name = protractor_bin_name,
entry_point = "protractor/bin/protractor",
data = srcs + deps + data,
node_modules = "@//:node_modules",
testonly = 1,
visibility = ["//visibility:private"],
)
_protractor_web_test(
name=wrapped_test_name,
configuration=configuration,
on_prepare=on_prepare,
srcs=srcs,
deps=deps,
data=web_test_data,
server=server,
protractor=protractor_bin_name,
args=args,
flaky=flaky,
local=local,
shard_count=shard_count,
size=size,
tags=wrapped_test_tags,
timeout=timeout,
visibility=["//visibility:private"],
**remaining_keyword_args)
# Our binary dependency must be in data[] for collect_data to pick it up
# FIXME: maybe we can just ask the :protractor_bin_name for its runfiles attr
web_test_data = web_test_data + [":" + protractor_bin_name]
if server:
web_test_data += [server]
web_test_suite(
name=name,
launcher=":"+wrapped_test_name,
args=args,
browsers=browsers,
browser_overrides=browser_overrides,
config=config,
data=web_test_data,
flaky=flaky,
local=local,
shard_count=shard_count,
size=size,
tags=tags,
test=wrapped_test_name,
test_suite_tags=test_suite_tags,
timeout=timeout,
visibility=visibility)
_protractor_web_test(
name = wrapped_test_name,
configuration = configuration,
on_prepare = on_prepare,
srcs = srcs,
deps = deps,
data = web_test_data,
server = server,
protractor = protractor_bin_name,
args = args,
flaky = flaky,
local = local,
shard_count = shard_count,
size = size,
tags = wrapped_test_tags,
timeout = timeout,
visibility = ["//visibility:private"],
**remaining_keyword_args
)
web_test_suite(
name = name,
launcher = ":" + wrapped_test_name,
args = args,
browsers = browsers,
browser_overrides = browser_overrides,
config = config,
data = web_test_data,
flaky = flaky,
local = local,
shard_count = shard_count,
size = size,
tags = tags,
test = wrapped_test_name,
test_suite_tags = test_suite_tags,
timeout = timeout,
visibility = visibility,
)

View File

@ -1,19 +1,20 @@
"""Allows different paths for these imports in google3.
"""
load("@build_bazel_rules_typescript//internal:build_defs.bzl",
load(
"@build_bazel_rules_typescript//internal:build_defs.bzl",
_tsc_wrapped_tsconfig = "tsc_wrapped_tsconfig",
)
load("@build_bazel_rules_typescript//internal:common/compilation.bzl",
load(
"@build_bazel_rules_typescript//internal:common/compilation.bzl",
_COMMON_ATTRIBUTES = "COMMON_ATTRIBUTES",
_COMMON_OUTPUTS = "COMMON_OUTPUTS",
_compile_ts = "compile_ts",
_DEPS_ASPECTS = "DEPS_ASPECTS",
_compile_ts = "compile_ts",
_ts_providers_dict_to_struct = "ts_providers_dict_to_struct",
)
load("@build_bazel_rules_typescript//internal:common/json_marshal.bzl",
load(
"@build_bazel_rules_typescript//internal:common/json_marshal.bzl",
_json_marshal = "json_marshal",
)

View File

@ -6,16 +6,16 @@
"""
def _extract_flat_module_index(ctx):
files = []
for dep in ctx.attr.deps:
if hasattr(dep, "angular"):
metadata = dep.angular.flat_module_metadata
files.extend([metadata.metadata_file, metadata.typings_file])
return [DefaultInfo(files = depset(files))]
files = []
for dep in ctx.attr.deps:
if hasattr(dep, "angular"):
metadata = dep.angular.flat_module_metadata
files.extend([metadata.metadata_file, metadata.typings_file])
return [DefaultInfo(files = depset(files))]
extract_flat_module_index = rule(
implementation = _extract_flat_module_index,
attrs = {
"deps": attr.label_list(),
"deps": attr.label_list(),
},
)

View File

@ -9,14 +9,15 @@ This allows editors and other tools to easily use the language service bundle
without having to provide all of the angular specific peer dependencies.
"""
load("@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
load(
"@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
"ROLLUP_ATTRS",
"rollup_module_mappings_aspect",
"write_rollup_config",
"run_rollup",
"run_uglify"
"run_uglify",
"write_rollup_config",
)
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "flatten_esm5", "esm5_root_dir")
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5")
# Note: the file is called "umd.js" and "umd.min.js" because of historical
# reasons. The format is actually amd and not umd, but we are afraid to rename
@ -28,13 +29,15 @@ _ROLLUP_OUTPUTS = {
}
def _ls_rollup_bundle(ctx):
esm5_sources = flatten_esm5(ctx)
rollup_config = write_rollup_config(ctx,
root_dir = "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]),
output_format = "amd")
run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_umd)
source_map = run_uglify(ctx, ctx.outputs.build_umd, ctx.outputs.build_umd_min)
return DefaultInfo(files=depset([ctx.outputs.build_umd, ctx.outputs.build_umd_min, source_map]))
esm5_sources = flatten_esm5(ctx)
rollup_config = write_rollup_config(
ctx,
root_dir = "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]),
output_format = "amd",
)
run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_umd)
source_map = run_uglify(ctx, ctx.outputs.build_umd, ctx.outputs.build_umd_min)
return DefaultInfo(files = depset([ctx.outputs.build_umd, ctx.outputs.build_umd_min, source_map]))
ls_rollup_bundle = rule(
implementation = _ls_rollup_bundle,
@ -45,4 +48,4 @@ ls_rollup_bundle = rule(
]),
}),
outputs = _ROLLUP_OUTPUTS,
)
)

View File

@ -1,4 +1,5 @@
"""Re-export of some bazel rules with repository-wide defaults."""
load("@build_bazel_rules_nodejs//:defs.bzl", _npm_package = "npm_package")
load("@build_bazel_rules_typescript//:defs.bzl", _ts_library = "ts_library", _ts_web_test_suite = "ts_web_test_suite")
load("//packages/bazel:index.bzl", _ng_module = "ng_module", _ng_package = "ng_package")
@ -9,96 +10,99 @@ DEFAULT_NODE_MODULES = "@angular_deps//:node_modules"
# Packages which are versioned together on npm
ANGULAR_SCOPED_PACKAGES = ["@angular/%s" % p for p in [
# core should be the first package because it's the main package in the group
# this is significant for Angular CLI and "ng update" specifically, @angular/core
# is considered the identifier of the group by these tools.
"core",
"bazel",
"common",
"compiler",
"compiler-cli",
"animations",
"elements",
"platform-browser",
"platform-browser-dynamic",
"forms",
"http",
"platform-server",
"platform-webworker",
"platform-webworker-dynamic",
"upgrade",
"router",
"language-service",
"service-worker",
# core should be the first package because it's the main package in the group
# this is significant for Angular CLI and "ng update" specifically, @angular/core
# is considered the identifier of the group by these tools.
"core",
"bazel",
"common",
"compiler",
"compiler-cli",
"animations",
"elements",
"platform-browser",
"platform-browser-dynamic",
"forms",
"http",
"platform-server",
"platform-webworker",
"platform-webworker-dynamic",
"upgrade",
"router",
"language-service",
"service-worker",
]]
PKG_GROUP_REPLACEMENTS = {
"\"NG_UPDATE_PACKAGE_GROUP\"": """[
%s
]""" % ",\n ".join(["\"%s\"" % s for s in ANGULAR_SCOPED_PACKAGES])
]""" % ",\n ".join(["\"%s\"" % s for s in ANGULAR_SCOPED_PACKAGES]),
}
def ts_library(tsconfig = None, node_modules = DEFAULT_NODE_MODULES, **kwargs):
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
_ts_library(tsconfig = tsconfig, node_modules = node_modules, **kwargs)
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
_ts_library(tsconfig = tsconfig, node_modules = node_modules, **kwargs)
def ng_module(name, tsconfig = None, entry_point = None, node_modules = DEFAULT_NODE_MODULES, **kwargs):
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
if not entry_point:
entry_point = "public_api.ts"
_ng_module(name = name, flat_module_out_file = name, tsconfig = tsconfig, entry_point = entry_point, node_modules = node_modules, **kwargs)
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
if not entry_point:
entry_point = "public_api.ts"
_ng_module(name = name, flat_module_out_file = name, tsconfig = tsconfig, entry_point = entry_point, node_modules = node_modules, **kwargs)
# ivy_ng_module behaves like ng_module, and under --define=compile=legacy it runs ngc with global
# analysis but produces Ivy outputs. Under other compile modes, it behaves as ng_module.
# TODO(alxhub): remove when ngtsc supports the same use cases.
def ivy_ng_module(name, tsconfig = None, entry_point = None, **kwargs):
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
if not entry_point:
entry_point = "public_api.ts"
_internal_global_ng_module(name = name, flat_module_out_file = name, tsconfig = tsconfig, entry_point = entry_point, **kwargs)
if not tsconfig:
tsconfig = DEFAULT_TSCONFIG
if not entry_point:
entry_point = "public_api.ts"
_internal_global_ng_module(name = name, flat_module_out_file = name, tsconfig = tsconfig, entry_point = entry_point, **kwargs)
def ng_package(name, readme_md = None, license_banner = None, **kwargs):
if not readme_md:
readme_md = "//packages:README.md"
if not license_banner:
license_banner = "//packages:license-banner.txt"
if not readme_md:
readme_md = "//packages:README.md"
if not license_banner:
license_banner = "//packages:license-banner.txt"
_ng_package(
name = name,
readme_md = readme_md,
license_banner = license_banner,
replacements = PKG_GROUP_REPLACEMENTS,
**kwargs)
_ng_package(
name = name,
readme_md = readme_md,
license_banner = license_banner,
replacements = PKG_GROUP_REPLACEMENTS,
**kwargs
)
def npm_package(name, replacements = {}, **kwargs):
_npm_package(
name = name,
replacements = dict(replacements, **PKG_GROUP_REPLACEMENTS),
**kwargs)
_npm_package(
name = name,
replacements = dict(replacements, **PKG_GROUP_REPLACEMENTS),
**kwargs
)
def ts_web_test_suite(bootstrap = [], deps = [], **kwargs):
if not bootstrap:
bootstrap = ["//:web_test_bootstrap_scripts"]
local_deps = [
"@angular_deps//:node_modules/tslib/tslib.js",
"//tools/testing:browser",
] + deps
if not bootstrap:
bootstrap = ["//:web_test_bootstrap_scripts"]
local_deps = [
"@angular_deps//:node_modules/tslib/tslib.js",
"//tools/testing:browser",
] + deps
_ts_web_test_suite(
bootstrap = bootstrap,
deps = local_deps,
# Run unit tests on local Chromium by default.
# You can exclude tests based on tags, e.g. to skip Firefox testing,
# `bazel test --test_tag_filters=-browser:firefox-local [targets]`
browsers = [
"@io_bazel_rules_webtesting//browsers:chromium-local",
# Don't test on local Firefox by default, for faster builds.
# We think that bugs in Angular tend to be caught the same in any
# evergreen browser.
# "@io_bazel_rules_webtesting//browsers:firefox-local",
# TODO(alexeagle): add remote browsers on SauceLabs
],
**kwargs)
_ts_web_test_suite(
bootstrap = bootstrap,
deps = local_deps,
# Run unit tests on local Chromium by default.
# You can exclude tests based on tags, e.g. to skip Firefox testing,
# `bazel test --test_tag_filters=-browser:firefox-local [targets]`
browsers = [
"@io_bazel_rules_webtesting//browsers:chromium-local",
# Don't test on local Firefox by default, for faster builds.
# We think that bugs in Angular tend to be caught the same in any
# evergreen browser.
# "@io_bazel_rules_webtesting//browsers:firefox-local",
# TODO(alexeagle): add remote browsers on SauceLabs
],
**kwargs
)

View File

@ -2,17 +2,19 @@
See https://www.npmjs.com/package/http-server
"""
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
def http_server(templated_args = [], **kwargs):
# By default, we pass an argument pointing the http server to the
# package of the caller.
# This assumes there is an index.html in the package directory.
if not templated_args:
templated_args = [native.package_name()]
# By default, we pass an argument pointing the http server to the
# package of the caller.
# This assumes there is an index.html in the package directory.
if not templated_args:
templated_args = [native.package_name()]
nodejs_binary(
node_modules = "@http-server_runtime_deps//:node_modules",
entry_point = "http-server/bin/http-server",
templated_args = templated_args,
**kwargs)
nodejs_binary(
node_modules = "@http-server_runtime_deps//:node_modules",
entry_point = "http-server/bin/http-server",
templated_args = templated_args,
**kwargs
)

View File

@ -9,17 +9,17 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install")
load("@angular//packages/bazel/src:ng_setup_workspace.bzl", _ng_setup_workspace = "ng_setup_workspace")
def ng_setup_workspace():
"""This repository rule should be called from your WORKSPACE file.
"""This repository rule should be called from your WORKSPACE file.
It creates some additional Bazel external repositories that are used internally
to build angular
"""
yarn_install(
name = "angular_deps",
package_json = "@angular//:package.json",
yarn_lock = "@angular//:yarn.lock",
data = ["@angular//:tools/yarn/check-yarn.js", "@angular//:tools/postinstall-patches.js"],
node_modules_filegroup = """
It creates some additional Bazel external repositories that are used internally
to build angular
"""
yarn_install(
name = "angular_deps",
package_json = "@angular//:package.json",
yarn_lock = "@angular//:yarn.lock",
data = ["@angular//:tools/yarn/check-yarn.js", "@angular//:tools/postinstall-patches.js"],
node_modules_filegroup = """
filegroup(
name = "node_modules",
srcs = glob(["/".join([
@ -239,6 +239,7 @@ filegroup(
"node_modules/protractor/**",
"node_modules/@schematics/angular/**",
]))
""")
""",
)
_ng_setup_workspace()
_ng_setup_workspace()

View File

@ -6,30 +6,30 @@
"""This test verifies that a set of top level symbols from a javascript file match a gold file.
"""
# This does a deep import under //internal because of not wanting the wrapper macro
# This does a deep import under //internal because of not wanting the wrapper macro
# because it introduces an extra target_bin target.
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_test", "nodejs_binary")
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_binary", "nodejs_test")
def js_expected_symbol_test(name, src, golden, **kwargs):
"""This test verifies that a set of top level symbols from a javascript file match a gold file.
"""
all_data = [src, golden]
all_data += [Label("//tools/symbol-extractor:lib")]
all_data += [Label("@bazel_tools//tools/bash/runfiles")]
entry_point = "angular/tools/symbol-extractor/cli.js"
"""This test verifies that a set of top level symbols from a javascript file match a gold file.
"""
all_data = [src, golden]
all_data += [Label("//tools/symbol-extractor:lib")]
all_data += [Label("@bazel_tools//tools/bash/runfiles")]
entry_point = "angular/tools/symbol-extractor/cli.js"
nodejs_test(
name = name,
data = all_data,
entry_point = entry_point,
templated_args = ["$(location %s)" % src, "$(location %s)" % golden],
**kwargs
)
nodejs_test(
name = name,
data = all_data,
entry_point = entry_point,
templated_args = ["$(location %s)" % src, "$(location %s)" % golden],
**kwargs
)
nodejs_binary(
name = name + '.accept',
data = all_data,
entry_point = entry_point,
templated_args = ["$(location %s)" % src, "$(location %s)" % golden, '--accept'],
**kwargs
)
nodejs_binary(
name = name + ".accept",
data = all_data,
entry_point = entry_point,
templated_args = ["$(location %s)" % src, "$(location %s)" % golden, "--accept"],
**kwargs
)

View File

@ -14,43 +14,45 @@
"""Runs ts_api_guardian
"""
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_test", "nodejs_binary")
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_binary", "nodejs_test")
COMMON_MODULE_IDENTIFIERS = ["angular", "jasmine", "protractor"]
def ts_api_guardian_test(name, golden, actual, data = [], **kwargs):
"""Runs ts_api_guardian
"""
data += [
"//tools/ts-api-guardian:lib",
"//tools/ts-api-guardian:bin/ts-api-guardian",
"@bazel_tools//tools/bash/runfiles",
]
"""Runs ts_api_guardian
"""
data += [
"//tools/ts-api-guardian:lib",
"//tools/ts-api-guardian:bin/ts-api-guardian",
"@bazel_tools//tools/bash/runfiles",
]
args = [
# Needed so that node doesn't walk back to the source directory.
# From there, the relative imports would point to .ts files.
"--node_options=--preserve-symlinks",
"--stripExportPattern", "^\(__\\)",
]
for i in COMMON_MODULE_IDENTIFIERS:
args += ["--allowModuleIdentifiers", i]
args = [
# Needed so that node doesn't walk back to the source directory.
# From there, the relative imports would point to .ts files.
"--node_options=--preserve-symlinks",
"--stripExportPattern",
"^\(__\\)",
]
for i in COMMON_MODULE_IDENTIFIERS:
args += ["--allowModuleIdentifiers", i]
nodejs_test(
name = name,
data = data,
node_modules = "@ts-api-guardian_runtime_deps//:node_modules",
entry_point = "angular/tools/ts-api-guardian/bin/ts-api-guardian",
templated_args = args + ["--verify", golden, actual],
testonly = 1,
**kwargs
)
nodejs_test(
name = name,
data = data,
node_modules = "@ts-api-guardian_runtime_deps//:node_modules",
entry_point = "angular/tools/ts-api-guardian/bin/ts-api-guardian",
templated_args = args + ["--verify", golden, actual],
testonly = 1,
**kwargs
)
nodejs_binary(
name = name + ".accept",
data = data,
node_modules = "@ts-api-guardian_runtime_deps//:node_modules",
entry_point = "angular/tools/ts-api-guardian/bin/ts-api-guardian",
templated_args = args + ["--out", golden, actual],
**kwargs
)
nodejs_binary(
name = name + ".accept",
data = data,
node_modules = "@ts-api-guardian_runtime_deps//:node_modules",
entry_point = "angular/tools/ts-api-guardian/bin/ts-api-guardian",
templated_args = args + ["--out", golden, actual],
**kwargs
)