forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefaults.bzl
324 lines (288 loc) · 13 KB
/
defaults.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
"""Re-export of some bazel rules with repository-wide defaults."""
load("@npm//@angular/bazel:index.bzl", _ng_module = "ng_module", _ng_package = "ng_package")
load("@npm//@bazel/concatjs:index.bzl", _ts_library = "ts_library")
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin", _js_library = "js_library", _pkg_npm = "pkg_npm")
load("@rules_pkg//:pkg.bzl", "pkg_tar")
load("@npm//@bazel/esbuild:index.bzl", "esbuild")
load("@npm//@angular/build-tooling/bazel:extract_js_module_output.bzl", "extract_js_module_output")
load("@aspect_bazel_lib//lib:utils.bzl", "to_label")
load("@aspect_bazel_lib//lib:jq.bzl", "jq")
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("//tools:link_package_json_to_tarballs.bzl", "link_package_json_to_tarballs")
load("//tools:snapshot_repo_filter.bzl", "SNAPSHOT_REPO_JQ_FILTER")
load("//:constants.bzl", "RELEASE_ENGINES_NODE", "RELEASE_ENGINES_NPM", "RELEASE_ENGINES_YARN")
_DEFAULT_TSCONFIG = "//:tsconfig-build.json"
_DEFAULT_TSCONFIG_NG = "//:tsconfig-build-ng"
_DEFAULT_TSCONFIG_TEST = "//:tsconfig-test.json"
NPM_PACKAGE_SUBSTITUTIONS = {
# Version of the local package being built, generated via the `--workspace_status_command` flag.
"0.0.0-PLACEHOLDER": "{STABLE_PROJECT_VERSION}",
"0.0.0-EXPERIMENTAL-PLACEHOLDER": "{STABLE_PROJECT_EXPERIMENTAL_VERSION}",
"BUILD_SCM_HASH-PLACEHOLDER": "{BUILD_SCM_ABBREV_HASH}",
"0.0.0-ENGINES-NODE": RELEASE_ENGINES_NODE,
"0.0.0-ENGINES-NPM": RELEASE_ENGINES_NPM,
"0.0.0-ENGINES-YARN": RELEASE_ENGINES_YARN,
}
NO_STAMP_PACKAGE_SUBSTITUTIONS = dict(NPM_PACKAGE_SUBSTITUTIONS, **{
"0.0.0-PLACEHOLDER": "0.0.0",
"0.0.0-EXPERIMENTAL-PLACEHOLDER": "0.0.0",
})
def _default_module_name(testonly):
""" Provide better defaults for package names.
e.g. rather than angular/packages/core/testing we want @angular/core/testing
TODO(alexeagle): we ought to supply a default module name for every library in the repo.
But we short-circuit below in cases that are currently not working.
"""
pkg = native.package_name()
if testonly:
# Some tests currently rely on the long-form package names
return None
if pkg.startswith("packages/"):
return "@angular/" + pkg[len("packages/angular/"):]
return None
def ts_library(
name,
tsconfig = None,
testonly = False,
deps = [],
devmode_module = None,
devmode_target = None,
**kwargs):
"""Default values for ts_library"""
if testonly:
# Match the types[] in //packages:tsconfig-test.json
deps.append("@npm//@types/jasmine")
deps.append("@npm//@types/node")
if not tsconfig:
if testonly:
tsconfig = _DEFAULT_TSCONFIG_TEST
else:
tsconfig = _DEFAULT_TSCONFIG
if not devmode_module:
devmode_module = "commonjs"
if not devmode_target:
devmode_target = "es2022"
_ts_library(
name = name,
testonly = testonly,
deps = deps,
# @external_begin
tsconfig = tsconfig,
devmode_module = devmode_module,
devmode_target = devmode_target,
prodmode_target = "es2022",
# @external_end
**kwargs
)
js_library = _js_library
def pkg_npm(name, pkg_deps = [], use_prodmode_output = False, **kwargs):
"""Override of pkg_npm to produce package outputs and version substitutions conventional to the angular-cli project.
Produces a package and a tar of that package. Expects a package.json file
in the same folder to exist.
Args:
name: Name of the pkg_npm rule. '_archive.tgz' is appended to create the tarball.
pkg_deps: package.json files of dependent packages. These are used for local path substitutions when --config=local is set.
use_prodmode_output: False to ship ES5 devmode output, True to ship ESM output. Defaults to False.
**kwargs: Additional arguments passed to the real pkg_npm.
"""
pkg_json = kwargs.pop("pkg_json", ":package.json")
visibility = kwargs.pop("visibility", None)
if pkg_json:
deps = kwargs.pop("deps", [])
# The `pkg_npm` rule brings in devmode (`JSModuleInfo`) and prodmode (`JSEcmaScriptModuleInfo`)
# output into the NPM package We do not intend to ship the prodmode ECMAScript `.mjs`
# files, but the `JSModuleInfo` outputs (which correspond to devmode output). Depending on
# the `use_prodmode_output` macro attribute, we either ship the ESM output of dependencies,
# or continue shipping the devmode ES5 output.
# TODO: Clean this up in the future if we have combined devmode and prodmode output.
# https://github.com/bazelbuild/rules_nodejs/commit/911529fd364eb3ee1b8ecdc568a9fcf38a8b55ca.
# https://github.com/bazelbuild/rules_nodejs/blob/stable/packages/typescript/internal/build_defs.bzl#L334-L337.
extract_js_module_output(
name = "%s_js_module_output" % name,
provider = "JSEcmaScriptModuleInfo" if use_prodmode_output else "JSModuleInfo",
include_declarations = True,
include_default_files = True,
forward_linker_mappings = False,
include_external_npm_packages = False,
deps = deps,
)
# Merge package.json with root package.json and perform various substitutions to
# prepare it for release. For jq docs, see https://stedolan.github.io/jq/manual/.
jq(
name = "basic_substitutions",
# Note: this jq filter relies on the order of the inputs
# buildifier: do not sort
srcs = ["//:package.json", pkg_json],
filter_file = "//tools:package_json_release_filter.jq",
args = ["--slurp"],
out = "substituted/package.json",
)
# Copy package.json files to bazel-out so we can use their bazel-out paths to determine
# the corresponding package npm package tgz path for substitutions.
copy_to_bin(
name = "package_json_copy",
srcs = [pkg_json],
)
pkg_deps_copies = []
for pkg_dep in pkg_deps:
pkg_label = to_label(pkg_dep)
if pkg_label.name != "package.json":
fail("ERROR: only package.json files allowed in pkg_deps of pkg_npm macro")
pkg_deps_copies.append("@%s//%s:package_json_copy" % (pkg_label.workspace_name, pkg_label.package))
# Substitute dependencies on other packages in this repo with tarballs.
link_package_json_to_tarballs(
name = "tar_substitutions",
src = "substituted/package.json",
pkg_deps = [":package_json_copy"] + pkg_deps_copies,
out = "substituted_with_tars/package.json",
)
# Substitute dependencies on other packages in this repo with snapshot repos.
jq(
name = "snapshot_repo_substitutions",
srcs = ["substituted/package.json"],
filter = SNAPSHOT_REPO_JQ_FILTER,
out = "substituted_with_snapshot_repos/package.json",
)
# Move the generated package.json along with other deps into a directory for pkg_npm
# to package up because pkg_npm requires that all inputs be in the same directory.
copy_to_directory(
name = "package",
srcs = select({
# Do tar substitution if config_setting 'package_json_use_tar_deps' is true (local builds)
"//:package_json_use_tar_deps": [":%s_js_module_output" % name, "substituted_with_tars/package.json"],
"//:package_json_use_snapshot_repo_deps": [":%s_js_module_output" % name, "substituted_with_snapshot_repos/package.json"],
"//conditions:default": [":%s_js_module_output" % name, "substituted/package.json"],
}),
replace_prefixes = {
"substituted_with_tars/": "",
"substituted_with_snapshot_repos/": "",
"substituted/": "",
},
exclude_srcs_patterns = [
"packages/**/*", # Exclude compiled outputs of dependent packages
],
allow_overwrites = True,
)
nested_packages = ["package"]
else:
nested_packages = None
_pkg_npm(
name = name,
# We never set a `package_name` for NPM packages, neither do we enable validation.
# This is necessary because the source targets of the NPM packages all have
# package names set and setting a similar `package_name` on the NPM package would
# result in duplicate linker mappings that will conflict. e.g. consider the following
# scenario: We have a `ts_library` for `@angular/core`. We will configure a package
# name for the target so that it can be resolved in NodeJS executions from `node_modules`.
# If we'd also set a `package_name` for the associated `pkg_npm` target, there would be
# two mappings for `@angular/core` and the linker will complain. For a better development
# experience, we want the mapping to resolve to the direct outputs of the `ts_library`
# instead of requiring tests and other targets to assemble the NPM package first.
# TODO(devversion): consider removing this if `rules_nodejs` allows for duplicate
# linker mappings where transitive-determined mappings are skipped on conflicts.
# https://github.com/bazelbuild/rules_nodejs/issues/2810.
package_name = None,
validate = False,
substitutions = select({
"//:stamp": NPM_PACKAGE_SUBSTITUTIONS,
"//conditions:default": NO_STAMP_PACKAGE_SUBSTITUTIONS,
}),
visibility = visibility,
nested_packages = nested_packages,
tgz = None,
**kwargs
)
pkg_tar(
name = name + "_archive",
srcs = [":%s" % name],
extension = "tgz",
strip_prefix = "./%s" % name,
visibility = visibility,
)
def ng_module(name, tsconfig = None, entry_point = None, testonly = False, deps = [], module_name = None, package_name = None, **kwargs):
"""Default values for ng_module"""
deps = deps + ["@npm//tslib"]
if testonly:
# Match the types[] in //packages:tsconfig-test.json
deps.append("@npm//@types/jasmine")
deps.append("@npm//@types/node")
if not tsconfig:
if testonly:
tsconfig = _DEFAULT_TSCONFIG_TEST
else:
tsconfig = _DEFAULT_TSCONFIG_NG
if not module_name:
module_name = _default_module_name(testonly)
# If no `package_name` is explicitly set, we use the default module name as package
# name, so that the target can be resolved within NodeJS executions, by activating
# the Bazel NodeJS linker. See: https://github.com/bazelbuild/rules_nodejs/pull/2799.
if not package_name:
package_name = _default_module_name(testonly)
if not entry_point:
entry_point = "public_api.ts"
_ng_module(
name = name,
flat_module_out_file = name,
tsconfig = tsconfig,
entry_point = entry_point,
testonly = testonly,
deps = deps,
# `module_name` is used for AMD module names within emitted JavaScript files.
module_name = module_name,
# `package_name` can be set to allow for the Bazel NodeJS linker to run. This
# allows for resolution of the given target within the `node_modules/`.
package_name = package_name,
**kwargs
)
def ng_package(deps = [], **kwargs):
_ng_package(
deps = deps,
externals = [
"xhr2",
"critters",
"express-engine",
"express",
],
substitutions = select({
"//:stamp": NPM_PACKAGE_SUBSTITUTIONS,
"//conditions:default": NO_STAMP_PACKAGE_SUBSTITUTIONS,
}),
**kwargs
)
def ng_test_library(name, entry_point = None, deps = [], tsconfig = None, **kwargs):
local_deps = [
# We declare "@angular/core" as default dependencies because
# all Angular component unit tests use the `TestBed` and `Component` exports.
"@npm//@angular/core",
] + deps
if not tsconfig:
tsconfig = _DEFAULT_TSCONFIG_TEST
ts_library_name = name + "_ts_library"
ts_library(
name = ts_library_name,
testonly = 1,
tsconfig = tsconfig,
deps = local_deps,
**kwargs
)
esbuild(
name,
testonly = 1,
args = {
"keepNames": True,
# ensure that esbuild prefers .mjs to .js if both are available
# since ts_library produces both
"resolveExtensions": [
".mjs",
".js",
],
},
output = name + "_spec.js",
entry_point = entry_point,
format = "iife",
# We cannot use `ES2017` or higher as that would result in `async/await` not being downleveled.
# ZoneJS needs to be able to intercept these as otherwise change detection would not work properly.
target = "es2016",
platform = "node",
deps = [":" + ts_library_name],
)