Make CODEQL_PLATFORM architecture-aware for linux-arm64

CODEQL_PLATFORM is OS-only today (linux->linux64, macos->osx64,
windows->win64). ELF has no fat-binary equivalent, so Linux arm64 needs
its own string. Add `linux-arm64` for os:linux AND cpu:arm64 while
keeping every existing string byte-identical.

- Add a public `//misc/bazel:linux_arm64` config_setting (os:linux +
  cpu:arm64).
- Turn `os_select` into `codeql_platform_select`, a full selector over
  the four CodeQL platforms (`linux64`, `linux_arm64`, `osx64`, `win64`,
  plus `otherwise`), working in both macro (select) and rule
  (target_platform_has_constraint) contexts. There is deliberately no
  fallback between the two Linux slots.
- Re-express `os_select` as a thin OS-only wrapper around it (Linux maps
  to both `linux64` and `linux_arm64`), so its existing swift/xcode
  callers keep working unchanged.
- Add an `_arm64_constraint` entry to OS_DETECTION_ATTRS.
- Drive the platform string from `codeql_platform_select` in pkg.bzl's
  `_detect_platform` and defs.bzl's `codeql_platform`.

macOS keeps osx64 for both arch slices (universal binary): the
linux_arm64 key requires both constraints, so the OS discriminator
dominates. The new branch is dormant on existing CI (no job builds
linux-on-arm64), so all current configs produce byte-identical outputs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5c5b0bf-4afa-468c-b2dd-197d80932b4b
This commit is contained in:
Paolo Tranquilli
2026-07-29 14:01:25 +02:00
parent 478878cfb7
commit d0b6e96e5b
4 changed files with 86 additions and 28 deletions

View File

@@ -1,5 +1,8 @@
codeql_platform = select({
"@platforms//os:linux": "linux64",
"@platforms//os:macos": "osx64",
"@platforms//os:windows": "win64",
})
load("//misc/bazel:os.bzl", "codeql_platform_select")
codeql_platform = codeql_platform_select(
linux64 = "linux64",
linux_arm64 = "linux-arm64",
osx64 = "osx64",
win64 = "win64",
)

View File

@@ -1,5 +1,16 @@
load("@rules_shell//shell:sh_library.bzl", "sh_library")
# Matches the Linux arm64 target, used to give it a distinct `CODEQL_PLATFORM` string
# (`linux-arm64`). Every other configuration keeps its OS-only string.
config_setting(
name = "linux_arm64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm64",
],
visibility = ["//visibility:public"],
)
sh_library(
name = "sh_runfiles",
srcs = ["runfiles.sh"],

View File

@@ -1,5 +1,52 @@
""" Os detection facilities. """
def codeql_platform_select(
ctx = None,
*,
linux64 = None,
linux_arm64 = None,
osx64 = None,
win64 = None,
otherwise = None):
"""
Choose a value based on the target CodeQL platform, discriminating the four platforms CodeQL
knows about: `linux64` (Linux on x86_64), `linux_arm64` (Linux on arm64), `osx64` (macOS, any
architecture) and `win64` (Windows on x86_64). Any platform left unspecified uses `otherwise`.
There is deliberately no fallback between `linux64` and `linux_arm64`: if you want the same value
for both (i.e. you only care about the OS, not the architecture), use `os_select` instead.
This works both in a macro context (`ctx = None`, returning a `select`) and in a rule context
(passing `ctx`, which then needs `OS_DETECTION_ATTRS` on the rule attributes).
"""
choices = {
"//misc/bazel:linux_arm64": linux_arm64 or otherwise,
"@platforms//os:linux": linux64 or otherwise,
"@platforms//os:macos": osx64 or otherwise,
"@platforms//os:windows": win64 or otherwise,
}
if not ctx:
return select({
setting: v
for setting, v in choices.items()
if v != None
})
def has(constraint):
return ctx.target_platform_has_constraint(getattr(ctx.attr, "_%s_constraint" % constraint)[platform_common.ConstraintValueInfo])
if has("linux"):
result = choices["//misc/bazel:linux_arm64"] if has("arm64") else choices["@platforms//os:linux"]
elif has("macos"):
result = choices["@platforms//os:macos"]
elif has("windows"):
result = choices["@platforms//os:windows"]
else:
fail("Unknown OS detected")
if result == None:
fail("platform not supported by %s" % ctx.label)
return result
def os_select(
ctx = None,
*,
@@ -8,31 +55,22 @@ def os_select(
macos = None,
default = None):
"""
This can work both in a macro and a rule context to choose something based on the current OS.
If used in a rule implementation, you need to pass `ctx` and add `OS_DETECTION_ATTRS` to the
rule attributes.
Choose a value based on the target OS, ignoring the architecture. This is a thin, OS-only wrapper
around `codeql_platform_select` (Linux gets the same value on both x86_64 and arm64).
See `codeql_platform_select` for macro vs rule usage.
"""
choices = {
"linux": linux or default,
"windows": windows or default,
"macos": macos or default,
}
if not ctx:
return select({
"@platforms//os:%s" % os: v
for os, v in choices.items()
if v != None
})
for os, v in choices.items():
if ctx.target_platform_has_constraint(getattr(ctx.attr, "_%s_constraint" % os)[platform_common.ConstraintValueInfo]):
if v == None:
fail("%s not supported by %s" % (os, ctx.label))
return v
fail("Unknown OS detected")
return codeql_platform_select(
ctx,
linux64 = linux,
linux_arm64 = linux,
osx64 = macos,
win64 = windows,
otherwise = default,
)
OS_DETECTION_ATTRS = {
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
"_macos_constraint": attr.label(default = "@platforms//os:macos"),
"_linux_constraint": attr.label(default = "@platforms//os:linux"),
"_arm64_constraint": attr.label(default = "@platforms//cpu:arm64"),
}

View File

@@ -8,7 +8,7 @@ load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_fil
load("@rules_pkg//pkg:pkg.bzl", "pkg_zip")
load("@rules_pkg//pkg:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo")
load("@rules_python//python:defs.bzl", "py_binary", "py_test")
load("//misc/bazel:os.bzl", "OS_DETECTION_ATTRS", "os_select")
load("//misc/bazel:os.bzl", "OS_DETECTION_ATTRS", "codeql_platform_select")
def _make_internal(name):
def internal(suffix = "internal", *args):
@@ -26,7 +26,13 @@ def _expand_path(path, platform):
return ("common", path)
def _detect_platform(ctx = None):
return os_select(ctx, linux = "linux64", macos = "osx64", windows = "win64")
return codeql_platform_select(
ctx,
linux64 = "linux64",
linux_arm64 = "linux-arm64",
osx64 = "osx64",
win64 = "win64",
)
def codeql_pkg_files(
*,