Skip to content

Commit a7ac851

Browse files
committed
Rework erlang version constraints
When the erlang_major and erlang_minor constraint settings were folded into erlang_version, selects.config_setting_group instances were used to define platforms for an erlang major with any available minor. Unfortunately in some cases this causes a cycle in the analysis graph to fail the analysis phase of some builds (probably depending on a host erlang's degree of overlap with internal erlangs). selects.config_setting_group expands to a chain of `alias` instances, where a `select` statement chooses the actual value. How exactly this causes a (potential) cycle isn't fully clear, but this commit works around the issue by declaring extra toolchains in a manner that allows the same match any minor without the use of selects.
1 parent a673b97 commit a7ac851

File tree

5 files changed

+58
-74
lines changed

5 files changed

+58
-74
lines changed

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ use_repo(
3737

3838
register_toolchains(
3939
"@erlang_config//external:toolchain",
40+
"@erlang_config//external:toolchain2",
4041
)

repositories/BUILD_external.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,20 @@ toolchain(
2727
"//:erlang_external",
2828
],
2929
target_compatible_with = [
30-
"%{TARGET_COMPATIBLE_WITH}",
30+
"//:erlang_%{ERLANG_MAJOR}",
31+
],
32+
toolchain = ":erlang",
33+
toolchain_type = "%{RULES_ERLANG_WORKSPACE}//tools:toolchain_type",
34+
visibility = ["//visibility:public"],
35+
)
36+
37+
toolchain(
38+
name = "toolchain2",
39+
exec_compatible_with = [
40+
"//:erlang_external",
41+
],
42+
target_compatible_with = [
43+
"//:erlang_%{ERLANG_MAJOR}_%{ERLANG_MINOR}",
3144
],
3245
toolchain = ":erlang",
3346
toolchain_type = "%{RULES_ERLANG_WORKSPACE}//tools:toolchain_type",

repositories/BUILD_internal.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,22 @@ toolchain(
2929
"//:erlang_internal",
3030
],
3131
target_compatible_with = [
32-
"%{TARGET_COMPATIBLE_WITH}",
32+
"//:erlang_%{ERLANG_MAJOR}",
3333
],
3434
toolchain = ":erlang",
3535
toolchain_type = "%{RULES_ERLANG_WORKSPACE}//tools:toolchain_type",
3636
visibility = ["//visibility:public"],
3737
)
38+
39+
toolchain(
40+
name = "toolchain2",
41+
exec_compatible_with = [
42+
"//:erlang_internal",
43+
],
44+
target_compatible_with = [
45+
"//:erlang_%{ERLANG_MAJOR}_%{ERLANG_MINOR}",
46+
],
47+
toolchain = ":erlang",
48+
toolchain_type = "%{RULES_ERLANG_WORKSPACE}//tools:toolchain_type",
49+
visibility = ["//visibility:public"],
50+
)

repositories/erlang_config.bzl

Lines changed: 28 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def _parse_maybe_semver(version_string):
1717
if len(parts) > 1:
1818
return (parts[0], parts[1])
1919
else:
20-
return (parts[0], None)
20+
return (parts[0], _ERLANG_VERSION_UNKNOWN.lower())
2121

2222
def _impl(repository_ctx):
2323
rules_erlang_workspace = repository_ctx.attr.rules_erlang_workspace
@@ -42,19 +42,15 @@ def _impl(repository_ctx):
4242
)
4343

4444
for (name, props) in erlang_installations.items():
45-
if props.minor != None:
46-
target_compatible_with = "//:erlang_{}_{}".format(props.major, props.minor)
47-
else:
48-
target_compatible_with = "//:erlang_{}".format(props.major)
49-
5045
if props.type == INSTALLATION_TYPE_EXTERNAL:
5146
repository_ctx.template(
5247
"{}/BUILD.bazel".format(name),
5348
Label("//repositories:BUILD_external.tpl"),
5449
{
5550
"%{ERLANG_HOME}": props.erlang_home,
5651
"%{ERLANG_VERSION}": props.version,
57-
"%{TARGET_COMPATIBLE_WITH}": target_compatible_with,
52+
"%{ERLANG_MAJOR}": props.major,
53+
"%{ERLANG_MINOR}": props.minor,
5854
"%{RULES_ERLANG_WORKSPACE}": rules_erlang_workspace,
5955
},
6056
False,
@@ -68,7 +64,8 @@ def _impl(repository_ctx):
6864
"%{URL}": props.url,
6965
"%{STRIP_PREFIX}": props.strip_prefix or "",
7066
"%{SHA_256}": props.sha256 or "",
71-
"%{TARGET_COMPATIBLE_WITH}": target_compatible_with,
67+
"%{ERLANG_MAJOR}": props.major,
68+
"%{ERLANG_MINOR}": props.minor,
7269
"%{RULES_ERLANG_WORKSPACE}": rules_erlang_workspace,
7370
},
7471
False,
@@ -83,10 +80,12 @@ def _impl(repository_ctx):
8380
False,
8481
)
8582

86-
toolchains = [
87-
"@{}//{}:toolchain".format(repository_ctx.name, name)
88-
for name in erlang_installations.keys()
89-
]
83+
toolchains = []
84+
for name in erlang_installations.keys():
85+
toolchains.extend([
86+
"@{}//{}:toolchain".format(repository_ctx.name, name),
87+
"@{}//{}:toolchain2".format(repository_ctx.name, name),
88+
])
9089

9190
repository_ctx.template(
9291
"defaults.bzl",
@@ -186,25 +185,13 @@ def _default_erlang_dict(repository_ctx):
186185
type = INSTALLATION_TYPE_EXTERNAL,
187186
version = _ERLANG_VERSION_UNKNOWN,
188187
major = _ERLANG_VERSION_UNKNOWN.lower(),
189-
minor = None,
188+
minor = _ERLANG_VERSION_UNKNOWN.lower(),
190189
erlang_home = erlang_home,
191190
),
192191
}
193192

194193
def _build_file_content(erlang_installations):
195-
default_installation = erlang_installations[_DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME]
196-
197-
if default_installation.minor != None:
198-
default_identifier = "{}_{}".format(
199-
default_installation.major,
200-
default_installation.minor,
201-
)
202-
else:
203-
default_identifier = default_installation.major
204-
205194
build_file_content = """\
206-
load("@bazel_skylib//lib:selects.bzl", "selects")
207-
208195
package(
209196
default_visibility = ["//visibility:public"],
210197
)
@@ -214,44 +201,37 @@ constraint_setting(
214201
default_constraint_value = ":erlang_external",
215202
)
216203
217-
constraint_setting(
218-
name = "erlang_version",
219-
default_constraint_value = ":erlang_{default_identifier}",
220-
)
221-
222204
constraint_value(
223205
name = "erlang_external",
224206
constraint_setting = ":erlang_internal_external",
225207
)
226208
227-
""".format(
228-
default_identifier = default_identifier,
229-
)
230-
231-
external_installations = {
232-
name: props
233-
for (name, props) in erlang_installations.items()
234-
if props.type == INSTALLATION_TYPE_EXTERNAL
235-
}
236-
if len(erlang_installations) > len(external_installations):
237-
build_file_content += """\
238209
constraint_value(
239210
name = "erlang_internal",
240211
constraint_setting = ":erlang_internal_external",
241212
)
242213
243214
"""
244215

216+
default_installation = erlang_installations[_DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME]
217+
218+
build_file_content += """\
219+
constraint_setting(
220+
name = "erlang_version",
221+
default_constraint_value = ":erlang_{}_{}",
222+
)
223+
224+
""".format(default_installation.major, default_installation.minor)
225+
245226
major_by_minors = {}
246227
for (name, props) in erlang_installations.items():
247228
minors = major_by_minors.get(props.major, [])
248-
if props.minor != None and props.minor not in minors:
229+
if props.minor not in minors:
249230
minors.append(props.minor)
250231
major_by_minors[props.major] = minors
251232

252233
for (major, minors) in major_by_minors.items():
253-
if len(minors) == 0:
254-
build_file_content += """\
234+
build_file_content += """\
255235
constraint_value(
256236
name = "erlang_{major}",
257237
constraint_setting = ":erlang_version",
@@ -264,16 +244,10 @@ platform(
264244
],
265245
)
266246
267-
""".format(
268-
major = major,
269-
)
270-
else:
271-
constraints = []
272-
for minor in minors:
273-
constraints.append(
274-
":erlang_{}_{}".format(major, minor),
275-
)
276-
build_file_content += """\
247+
""".format(major = major)
248+
249+
for minor in minors:
250+
build_file_content += """\
277251
constraint_value(
278252
name = "erlang_{major}_{minor}",
279253
constraint_setting = ":erlang_version",
@@ -288,22 +262,4 @@ platform(
288262
289263
""".format(major = major, minor = minor)
290264

291-
build_file_content += """\
292-
selects.config_setting_group(
293-
name = "erlang_{major}",
294-
match_any = {constraints},
295-
)
296-
297-
platform(
298-
name = "erlang_{major}_platform",
299-
constraint_values = [
300-
":erlang_{major}",
301-
],
302-
)
303-
304-
""".format(
305-
major = major,
306-
constraints = constraints,
307-
)
308-
309265
return build_file_content

test/MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ use_repo(
2828

2929
register_toolchains(
3030
"@erlang_config//internal:toolchain",
31+
"@erlang_config//internal:toolchain2",
3132
)

0 commit comments

Comments
 (0)