[llvm] [libc][bazel] Add an option to build linux UAPI headers from source (PR #216868)

Jackson Stogel via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 16:53:49 PDT 2026


https://github.com/jtstogel updated https://github.com/llvm/llvm-project/pull/216868

>From 27cdcfd922da410711e09896f96c6ce770c0c48f Mon Sep 17 00:00:00 2001
From: jtstogel <jtstogel at gmail.com>
Date: Thu, 16 Jul 2026 13:19:07 -0700
Subject: [PATCH] [libc][bazel] Pull UAPI headers from debain repository when
 unset

---
 utils/bazel/MODULE.bazel.lock |   2 +-
 utils/bazel/linux_uapi.bzl    | 105 ++++++++++++++++++++--------------
 2 files changed, 63 insertions(+), 44 deletions(-)

diff --git a/utils/bazel/MODULE.bazel.lock b/utils/bazel/MODULE.bazel.lock
index 7536f45680484..2fb696ee8254c 100644
--- a/utils/bazel/MODULE.bazel.lock
+++ b/utils/bazel/MODULE.bazel.lock
@@ -334,7 +334,7 @@
   "moduleExtensions": {
     "//:extensions.bzl%llvm_repos_extension": {
       "general": {
-        "bzlTransitiveDigest": "9GsOS6+zNAQam7hiO44NfnT7MQsd1QbAqkfqojQ0pWc=",
+        "bzlTransitiveDigest": "WRH8TXJA/9+bdJ2N+h0EcRGjV/fPZ0z8DZBJAHox+6U=",
         "usagesDigest": "X0yUkkWyxQ2Y5oZVDkRSE/K4YkDWo1IjhHsL+1weKyU=",
         "recordedInputs": [
           "REPO_MAPPING:,bazel_tools bazel_tools"
diff --git a/utils/bazel/linux_uapi.bzl b/utils/bazel/linux_uapi.bzl
index aa0a764d2e1e4..444ead386b169 100644
--- a/utils/bazel/linux_uapi.bzl
+++ b/utils/bazel/linux_uapi.bzl
@@ -6,28 +6,6 @@
 
 _SYSTEM_HEADERS_PATH_ENV_VAR = "LINUX_UAPI_INCLUDE_DIR"
 
-_ERROR_MESSAGE_BZL = """\
-def _error_message_impl(ctx):
-    fail(ctx.attr.message)
-
-error_message = rule(
-    implementation = _error_message_impl,
-    attrs = {"message": attr.string()},
-)
-"""
-
-_ERROR_BUILD = """\
-load(":error_message.bzl", "error_message")
-
-error_message(
-    name = "linux_uapi_headers",
-    message = \"""System linux UAPI headers not found.
-
-Pass --repo_env={var_name}=/path/to/your/linux/include to bazel build.
-\"""
-)
-""".format(var_name = _SYSTEM_HEADERS_PATH_ENV_VAR)
-
 _SYSTEM_BUILD = """\
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
@@ -41,34 +19,75 @@ cc_library(
 )
 """
 
-def _default_include_dir(repository_ctx):
-    """Returns a default include dir if it looks to have Linux UAPI headers."""
-    include_dir = "/usr/include"
-    if not repository_ctx.path(include_dir + "/linux").exists:
-        return None
-    return include_dir
-
-def _linux_uapi_setup_impl(repository_ctx):
-    """Sets up a repository of UAPI headers from a system directory."""
-    include_dir = repository_ctx.getenv(_SYSTEM_HEADERS_PATH_ENV_VAR, "")
-    if not include_dir:
-        include_dir = _default_include_dir(repository_ctx)
-
-    # If the directory doesn't exist, then set up a dummy rule that just errors.
-    # This defers the error message until an actual build,
-    # rather than failing during repository setup.
-    if not include_dir:
-        repository_ctx.file("error_message.bzl", _ERROR_MESSAGE_BZL)
-        repository_ctx.file("BUILD.bazel", _ERROR_BUILD)
-        return
-
+def _setup_from_system(repository_ctx, include_dir):
+    """Sets up the repository from a user-provided include directory."""
     if not include_dir.startswith("/"):
         fail("{} must be absolute, was {}".format(
             _SYSTEM_HEADERS_PATH_ENV_VAR,
             include_dir,
         ))
 
+    if not repository_ctx.path(include_dir + "/linux").exists:
+        fail(
+            "{} does not contain Linux UAPI headers (no linux/ subdirectory)"
+                .format(include_dir),
+        )
+
     repository_ctx.symlink(include_dir, "include")
     repository_ctx.file("BUILD.bazel", _SYSTEM_BUILD)
 
+    return None
+
+_LIBC_DEV_PACKAGE_BUILD = """\
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+cc_library(
+    name = "linux_uapi_headers",
+    # The linux-libc-dev package has headers for many platforms.
+    # These may not compile, so use `textual_hdrs` instead of `hdrs`.
+    textual_hdrs = glob(["usr/include/**/*.h"]),
+    includes = [
+        "usr/include",
+    ] + select(
+        {{
+            # LLVM-libc requires the `asm` directory to exist,
+            # so include the arch-specific directory.
+            "@platforms//cpu:x86_64": ["usr/include/x86_64-linux-gnu"],
+            "@platforms//cpu:arm64": ["usr/include/aarch64-linux-gnu"],
+            "@platforms//cpu:riscv64": ["usr/include/riscv64-linux-gnu"],
+        }},
+        no_match_error = \"""Unsupported CPU for the Linux UAPI headers.
+
+Use --repo_env={var_name}=/path/to/uapi/include to load from system headers,
+or add support for your architecture.
+\""",
+    ),
+    visibility = ["//visibility:public"],
+)
+""".format(var_name = _SYSTEM_HEADERS_PATH_ENV_VAR)
+
+def _setup_from_libc_dev_package(repository_ctx):
+    """Sets up linux UAPI headers from Debian's linux-libc-dev package."""
+
+    # Pulling from Linux sources and generating the headers ourselves would
+    # provide more control, but downloading from linux-libc-dev is much faster.
+    repository_ctx.download_and_extract(
+        url = "https://snapshot.debian.org/archive/debian/20260501T022911Z/pool/main/l/linux/linux-libc-dev_7.0.3-1_all.deb",
+        sha256 = "02eb444940d2e8aee116b9b1525ca2618e48b025aff75e0b75515812af121c59",
+    )
+    repository_ctx.extract(archive = "data.tar.xz")
+    repository_ctx.delete("data.tar.xz")
+    repository_ctx.file("BUILD.bazel", _LIBC_DEV_PACKAGE_BUILD)
+
+    return repository_ctx.repo_metadata(reproducible = True)
+
+def _linux_uapi_setup_impl(repository_ctx):
+    """Sets up a repository of Linux UAPI headers."""
+
+    include_dir = repository_ctx.getenv(_SYSTEM_HEADERS_PATH_ENV_VAR, "")
+    if include_dir:
+        return _setup_from_system(repository_ctx, include_dir)
+
+    return _setup_from_libc_dev_package(repository_ctx)
+
 linux_uapi_setup = repository_rule(implementation = _linux_uapi_setup_impl)



More information about the llvm-commits mailing list