| # 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" | |
| _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") | |
| 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 _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 | |
| if not include_dir.startswith("/"): | |
| fail("{} must be absolute, was {}".format( | |
| _SYSTEM_HEADERS_PATH_ENV_VAR, | |
| include_dir, | |
| )) | |
| repository_ctx.symlink(include_dir, "include") | |
| repository_ctx.file("BUILD.bazel", _SYSTEM_BUILD) | |
| linux_uapi_setup = repository_rule(implementation = _linux_uapi_setup_impl) |