blob: 444ead386b169921d5b54ea793967bba8f131ec3 [file]
# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""bzlmod extension for making Linux kernel UAPI headers available in Bazel."""
_SYSTEM_HEADERS_PATH_ENV_VAR = "LINUX_UAPI_INCLUDE_DIR"
_SYSTEM_BUILD = """\
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "linux_uapi_headers",
# Builds using /usr/include may have a lot of junk that does not cleanly
# compile, so use `textual_hdrs` instead of `hdrs`.
textual_hdrs = glob(["include/**"]),
includes = ["include"],
visibility = ["//visibility:public"],
)
"""
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)