Skip to content

Commit 3b10668

Browse files
committed
feat: add platform-aware D toolchain selection and pin default versions
1 parent 978ddfa commit 3b10668

File tree

4 files changed

+53
-38
lines changed

4 files changed

+53
-38
lines changed

MODULE.bazel

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ bazel_dep(name = "buildifier_prebuilt", version = "8.2.1", dev_dependency = True
1919
bazel_dep(name = "gazelle", version = "0.42.0", dev_dependency = True, repo_name = "bazel_gazelle")
2020
bazel_dep(name = "stardoc", version = "0.7.1", dev_dependency = True)
2121

22-
# NOTE:
23-
# It is recommended to specify the exact d_version (ex. "dmd-2.111.0") for reproducible builds.
24-
# Setting d_version = "auto" here ensures aarch64 CI works out of the box,
25-
# but using "auto" may lead to non-reproducible builds and is not recommended.
22+
# Select first d toolchain available for the current platform.
2623
d = use_extension("//d:extensions.bzl", "d")
27-
d.toolchain(d_version = "auto")
24+
d.toolchain(d_version = "dmd-2.111.0")
25+
d.toolchain(d_version = "ldc-1.41.0")
2826
use_repo(d, "d_toolchains")
2927

3028
register_toolchains("@d_toolchains//:all")

d/extensions.bzl

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ names (the latest version will be picked for each name) and can register them as
1010
effectively overriding the default named toolchain due to toolchain resolution precedence.
1111
"""
1212

13-
load(":repositories.bzl", "d_register_toolchains")
13+
load(":repositories.bzl", "d_register_toolchains", "select_compiler_by_os")
1414

1515
_DEFAULT_NAME = "d"
1616

@@ -20,10 +20,9 @@ Base name for generated repositories, allowing more than one d toolchain to be r
2020
Overriding the default is only permitted in the root module.
2121
""", default = _DEFAULT_NAME),
2222
"d_version": attr.string(doc = """\
23-
Version of the compiler. "auto" will select latest known dmd or ldc compiler available for
24-
the current platform. "dmd" or "ldc" will select the latest known version of the respective
25-
compiler. If a specific version is desired, it can be specified as "dmd-2.100.0" or
26-
"ldc-1.30.0".
23+
Fully qualified compiler version, for example "dmd-2.111.0" or "ldc-1.41.0".
24+
The extension selects the first supplied version compatible with the current platform
25+
and fails if none match.
2726
""", mandatory = True),
2827
})
2928

@@ -40,18 +39,9 @@ def _toolchain_extension(module_ctx):
4039
registrations[toolchain.name] = []
4140
registrations[toolchain.name].append(toolchain.d_version)
4241
for name, versions in registrations.items():
43-
if len(versions) > 1:
44-
# TODO: should be semver-aware, using MVS
45-
selected = sorted(versions, reverse = True)[0]
46-
47-
# buildifier: disable=print
48-
print("NOTE: d toolchain {} has multiple versions {}, selected {}".format(name, versions, selected))
49-
else:
50-
selected = versions[0]
51-
5242
d_register_toolchains(
5343
name = name,
54-
d_version = selected,
44+
d_version = select_compiler_by_os(versions, module_ctx.os),
5545
register = False,
5646
)
5747

d/repositories.bzl

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def rules_d_dependencies():
4141
########
4242
_DOC = "Fetch external tools needed for d toolchain"
4343
_ATTRS = {
44-
"d_version": attr.string(mandatory = True, values = ["auto", "dmd", "ldc"] + SDK_VERSIONS.keys()),
44+
"d_version": attr.string(mandatory = True, values = SDK_VERSIONS.keys()),
4545
"platform": attr.string(mandatory = True, values = PLATFORMS.keys()),
4646
}
4747

@@ -61,20 +61,6 @@ def _d_repo_impl(repository_ctx):
6161
d_version = repository_ctx.attr.d_version
6262
platform = repository_ctx.attr.platform
6363

64-
if d_version == "auto":
65-
for compiler in ["dmd", "ldc"]:
66-
for version, platforms in SDK_VERSIONS.items():
67-
if version.startswith(compiler) and platform in platforms:
68-
d_version = compiler
69-
break
70-
if d_version != "auto":
71-
break
72-
73-
if d_version in ["dmd", "ldc"]:
74-
sdks = [version for version, platforms in SDK_VERSIONS.items() if version.startswith(d_version) and platform in platforms]
75-
sdks = sorted(sdks, key = lambda x: [int(v) if v.isdigit() else v for v in x[4:].split(".")], reverse = True)
76-
d_version = sdks[0] if sdks else d_version
77-
7864
if d_version not in SDK_VERSIONS:
7965
fail("Unknown d_version: %s" % d_version)
8066
if platform not in SDK_VERSIONS[d_version]:
@@ -107,12 +93,15 @@ def d_register_toolchains(name, register = True, **kwargs):
10793
Users can avoid this macro and do these steps themselves, if they want more control.
10894
10995
Args:
110-
name: base name for all created repos, like "d1_14"
96+
name: base name for all created repositories
11197
register: whether to call through to native.register_toolchains.
11298
Should be True for WORKSPACE users, but false when used under bzlmod extension
11399
**kwargs: passed to each d_repositories call
114100
"""
115101
for platform in PLATFORMS.keys():
102+
d_version = kwargs.get("d_version")
103+
if not d_version or d_version not in SDK_VERSIONS or platform not in SDK_VERSIONS[d_version]:
104+
continue
116105
d_repositories(name = name + "_" + platform, platform = platform, **kwargs)
117106
if register:
118107
native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform))
@@ -121,3 +110,36 @@ def d_register_toolchains(name, register = True, **kwargs):
121110
name = name + "_toolchains",
122111
user_repository_name = name,
123112
)
113+
114+
def _get_platform_id(os):
115+
"""Get the platform id for the given os repository_os information."""
116+
if os.name == "linux":
117+
if os.arch in ["amd64", "x86_64"]:
118+
return "x86_64-unknown-linux-gnu"
119+
elif os.arch in ["aarch64", "arm64"]:
120+
return "aarch64-unknown-linux-gnu"
121+
elif os.name in ["darwin", "mac os x", "macos", "osx"]:
122+
if os.arch in ["amd64", "x86_64"]:
123+
return "x86_64-apple-darwin"
124+
elif os.arch in ["aarch64", "arm64"]:
125+
return "aarch64-apple-darwin"
126+
elif "windows" in os.name:
127+
if os.arch in ["amd64", "x86_64"]:
128+
return "x86_64-pc-windows-msvc"
129+
fail("Unsupported OS/arch combination: %s/%s" % (os.name, os.arch))
130+
131+
def select_compiler_by_os(versions, os):
132+
"""Select the most appropriate compiler version for the given OS.
133+
134+
Args:
135+
versions: list of compiler versions
136+
os: repository_os information
137+
138+
Returns:
139+
selected compiler version
140+
"""
141+
platform_id = _get_platform_id(os)
142+
for version in versions:
143+
if platform_id in SDK_VERSIONS.get(version, {}):
144+
return version
145+
fail("No suitable d compiler found for OS %s among versions: %s." % (os, ", ".join(versions)))

e2e/smoke/WORKSPACE.bazel

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ load("@rules_d//d:repositories.bzl", "d_register_toolchains", "rules_d_dependenc
8787
rules_d_dependencies()
8888

8989
d_register_toolchains(
90-
"d_toolchain",
91-
d_version = "auto",
90+
"dmd_toolchain",
91+
d_version = "dmd-2.111.0",
92+
)
93+
94+
d_register_toolchains(
95+
"ldc_toolchain",
96+
d_version = "ldc-1.41.0",
9297
)

0 commit comments

Comments
 (0)