From d0b6e96e5bb2914d1fb298daadbe1846d40a76f8 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Jul 2026 14:01:25 +0200 Subject: [PATCH 1/4] 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 --- defs.bzl | 13 ++++--- misc/bazel/BUILD.bazel | 11 ++++++ misc/bazel/os.bzl | 80 +++++++++++++++++++++++++++++++----------- misc/bazel/pkg.bzl | 10 ++++-- 4 files changed, 86 insertions(+), 28 deletions(-) diff --git a/defs.bzl b/defs.bzl index d6748d83176..d4c5ea5e262 100644 --- a/defs.bzl +++ b/defs.bzl @@ -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", +) diff --git a/misc/bazel/BUILD.bazel b/misc/bazel/BUILD.bazel index e00a6f7a64c..b71a9b6ca6a 100644 --- a/misc/bazel/BUILD.bazel +++ b/misc/bazel/BUILD.bazel @@ -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"], diff --git a/misc/bazel/os.bzl b/misc/bazel/os.bzl index 34093e76331..f8e5c13cfe1 100644 --- a/misc/bazel/os.bzl +++ b/misc/bazel/os.bzl @@ -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"), } diff --git a/misc/bazel/pkg.bzl b/misc/bazel/pkg.bzl index 25f2bf3577d..efec21e761f 100644 --- a/misc/bazel/pkg.bzl +++ b/misc/bazel/pkg.bzl @@ -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( *, From b6e7464da20bbb8b5d0c60cf993ff79f7bebeae2 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Jul 2026 14:25:13 +0200 Subject: [PATCH 2/4] Address review: linux-arm64 docs + None-vs-falsey fallback - codeql_pack docstring: include `linux-arm64` in the exhaustive list of values the `{CODEQL_PLATFORM}` placeholder expands to (both mentions). - codeql_platform_select: only fall back to `otherwise` on `None`, not on any falsey value, via a small `_or_otherwise` helper, matching the documented `None` defaults. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c5c5b0bf-4afa-468c-b2dd-197d80932b4b --- misc/bazel/os.bzl | 12 ++++++++---- misc/bazel/pkg.bzl | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/misc/bazel/os.bzl b/misc/bazel/os.bzl index f8e5c13cfe1..a3fee479dbc 100644 --- a/misc/bazel/os.bzl +++ b/misc/bazel/os.bzl @@ -19,11 +19,15 @@ def codeql_platform_select( 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). """ + + def _or_otherwise(value): + return value if value != None else otherwise + 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, + "//misc/bazel:linux_arm64": _or_otherwise(linux_arm64), + "@platforms//os:linux": _or_otherwise(linux64), + "@platforms//os:macos": _or_otherwise(osx64), + "@platforms//os:windows": _or_otherwise(win64), } if not ctx: return select({ diff --git a/misc/bazel/pkg.bzl b/misc/bazel/pkg.bzl index efec21e761f..684bcbb8c3b 100644 --- a/misc/bazel/pkg.bzl +++ b/misc/bazel/pkg.bzl @@ -464,12 +464,12 @@ def codeql_pack( `zips` is a map from `.zip` files to prefixes to import. The distinction between arch-specific and common contents is made based on whether the paths (including possible prefixes added by rules) contain the special `{CODEQL_PLATFORM}` placeholder, which in case it is present will also - be replaced by the appropriate platform (`linux64`, `win64` or `osx64`). + be replaced by the appropriate platform (`linux64`, `linux-arm64`, `win64` or `osx64`). Specific file paths can be placed in the arch-specific package by adding them to `arch_overrides`, even if their path doesn't contain the `CODEQL_PLATFORM` placeholder. The codeql pack rules will expand the `{CODEQL_PLATFORM}` marker in paths, and use that to split the files into a common and an arch-specific part. - This placeholder will be replaced by the appropriate platform (`linux64`, `win64` or `osx64`). + This placeholder will be replaced by the appropriate platform (`linux64`, `linux-arm64`, `win64` or `osx64`). `arch_overrides` is a list of files that should be included in the arch-specific bits of the pack, even if their path doesn't contain the `{CODEQL_PLATFORM}` marker. All files in the pack will be prefixed with `name`, unless `pack_prefix` is set, then is used instead. From ba3fce17df72408e8289ddc7f07ef607be1b426e Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Jul 2026 14:50:21 +0200 Subject: [PATCH 3/4] Add `posix` convenience to os_select `posix` sets the shared value for both `linux` and `macos`. It is mutually exclusive with either of them and fails if supplied together with `linux` or `macos`. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c5c5b0bf-4afa-468c-b2dd-197d80932b4b --- misc/bazel/os.bzl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/misc/bazel/os.bzl b/misc/bazel/os.bzl index a3fee479dbc..6b9b71cb016 100644 --- a/misc/bazel/os.bzl +++ b/misc/bazel/os.bzl @@ -57,12 +57,19 @@ def os_select( linux = None, windows = None, macos = None, + posix = None, default = None): """ 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. + `posix` is a convenience for the value shared by `linux` and `macos`; it is mutually exclusive + with both. See `codeql_platform_select` for macro vs rule usage. """ + if posix != None: + if linux != None or macos != None: + fail("`posix` is mutually exclusive with `linux` and `macos`") + linux = posix + macos = posix return codeql_platform_select( ctx, linux64 = linux, From 0c20a33bc249698b47af059c9c57b497e569f09d Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Jul 2026 16:03:39 +0200 Subject: [PATCH 4/4] Anchor linux_arm64 select key to the codeql repo When `codeql_platform_select` builds its `select` from a macro invoked in another workspace (e.g. semmle-code consuming this repo as `@codeql`), a bare `//misc/bazel:linux_arm64` string key resolves against the consuming repo and fails with "no such package 'misc/bazel'". Use `Label(...)`, which resolves relative to this file's own repo, so the key always binds to `@codeql//misc/bazel:linux_arm64` regardless of the calling workspace. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c5c5b0bf-4afa-468c-b2dd-197d80932b4b --- misc/bazel/os.bzl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/misc/bazel/os.bzl b/misc/bazel/os.bzl index 6b9b71cb016..39b12773c78 100644 --- a/misc/bazel/os.bzl +++ b/misc/bazel/os.bzl @@ -23,8 +23,9 @@ def codeql_platform_select( def _or_otherwise(value): return value if value != None else otherwise + linux_arm64_setting = Label("//misc/bazel:linux_arm64") choices = { - "//misc/bazel:linux_arm64": _or_otherwise(linux_arm64), + linux_arm64_setting: _or_otherwise(linux_arm64), "@platforms//os:linux": _or_otherwise(linux64), "@platforms//os:macos": _or_otherwise(osx64), "@platforms//os:windows": _or_otherwise(win64), @@ -40,7 +41,7 @@ def codeql_platform_select( 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"] + result = choices[linux_arm64_setting] if has("arm64") else choices["@platforms//os:linux"] elif has("macos"): result = choices["@platforms//os:macos"] elif has("windows"):