[libc][bazel] Add generation for public headers (#184889)

Previously there was a single rule for stdbit, this PR adds generated
header targets for the rest of the linux headers. It also adds a
cc_library
for all of the public headers which also includes the types and macros
headers.
This commit is contained in:
Michael Jones 2026-03-27 09:44:32 -07:00 committed by GitHub
parent 5688aca96e
commit 166f996c44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 290 additions and 15 deletions

View File

@ -18,7 +18,7 @@ functions:
return_type: int
arguments:
- type: int
- type: sockaddr *__restrict
- type: struct sockaddr *__restrict
- type: socklen_t *__restrict
- name: bind
standards:

View File

@ -5,11 +5,13 @@
# LLVM libc project.
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@rules_python//python:defs.bzl", "py_binary")
load(
":libc_build_rules.bzl",
"libc_function",
"libc_generated_header",
"libc_header_info",
"libc_header_library",
"libc_math_function",
"libc_support_library",
@ -83,6 +85,22 @@ config_setting(
flag_values = {":mpc": "system"},
)
# A flag to enable modular format for printf.
# Usage: `--@llvm-project//libc:modular_format=<disable|enable>`.
string_flag(
name = "modular_format",
build_setting_default = "disable",
values = [
"disable",
"enable",
],
)
config_setting(
name = "modular_format_enable",
flag_values = {":modular_format": "enable"},
)
########################### Header Generation ##################################
py_binary(
@ -93,23 +111,268 @@ py_binary(
deps = ["@pyyaml//:yaml"],
)
LLVM_LIBC_HEADERS = [
libc_header_info(
"arpa/inet",
has_def_template = True,
),
libc_header_info(
"assert",
has_def_template = True,
),
libc_header_info(
"complex",
has_def_template = True,
),
libc_header_info(
"elf",
has_def_template = True,
),
libc_header_info(
"endian",
has_def_template = True,
),
libc_header_info(
"errno",
has_def_template = True,
),
libc_header_info(
"fcntl",
has_def_template = True,
),
libc_header_info(
"features",
has_def_template = True,
),
libc_header_info(
"float",
has_def_template = True,
),
libc_header_info(
"inttypes",
has_def_template = True,
),
libc_header_info(
"limits",
has_def_template = True,
),
libc_header_info(
"link",
has_def_template = True,
),
libc_header_info(
"locale",
has_def_template = True,
),
libc_header_info(
"math",
has_def_template = True,
),
libc_header_info(
"netinet/in",
has_def_template = True,
),
libc_header_info(
"poll",
has_def_template = True,
),
libc_header_info(
"sched",
has_def_template = True,
),
libc_header_info(
"signal",
has_def_template = True,
),
libc_header_info(
"stdbit",
has_def_template = True,
),
libc_header_info(
"stdckdint",
has_def_template = True,
),
libc_header_info(
"stdfix",
has_def_template = True,
),
libc_header_info(
"stdint",
has_def_template = True,
),
libc_header_info(
"stdio",
has_def_template = True,
),
libc_header_info(
"sysexits",
has_def_template = True,
),
libc_header_info(
"sys/auxv",
has_def_template = True,
),
libc_header_info(
"sys/epoll",
has_def_template = True,
),
libc_header_info(
"sys/ioctl",
has_def_template = True,
),
libc_header_info(
"sys/mman",
has_def_template = True,
),
libc_header_info(
"sys/prctl",
has_def_template = True,
),
libc_header_info(
"sys/random",
has_def_template = True,
),
libc_header_info(
"sys/resource",
has_def_template = True,
),
libc_header_info(
"sys/select",
has_def_template = True,
),
libc_header_info(
"sys/socket",
has_def_template = True,
),
libc_header_info(
"sys/stat",
has_def_template = True,
),
libc_header_info(
"sys/syscall",
has_def_template = True,
),
libc_header_info(
"sys/time",
has_def_template = True,
),
libc_header_info(
"sys/types",
has_def_template = True,
),
libc_header_info(
"sys/wait",
has_def_template = True,
),
libc_header_info(
"termios",
has_def_template = True,
),
libc_header_info(
"time",
has_def_template = True,
),
libc_header_info(
"unistd",
has_def_template = True,
),
libc_header_info(
"wchar",
has_def_template = True,
),
libc_header_info("ctype"),
libc_header_info("dirent"),
libc_header_info("dlfcn"),
libc_header_info("fenv"),
libc_header_info("nl_types"),
libc_header_info("pthread"),
libc_header_info("search"),
libc_header_info("setjmp"),
libc_header_info("spawn"),
libc_header_info("string"),
libc_header_info("strings"),
libc_header_info("sys/ipc"),
libc_header_info("sys/statvfs"),
libc_header_info("sys/utsname"),
libc_header_info("threads"),
libc_header_info("uchar"),
libc_header_info("wctype"),
libc_header_info(
"stdlib",
has_def_template = True,
other_srcs = ["include/stdlib-malloc.yaml"],
),
libc_header_info(
"malloc",
other_srcs = ["include/stdlib-malloc.yaml"],
),
]
[
libc_generated_header(
name = info.target_name,
hdr = info.staging_path,
other_srcs = info.other_srcs,
yaml_template = info.yaml_template,
)
for info in LLVM_LIBC_HEADERS
]
# needed for startup and VDSO. Doesn't get placed in /include so is handled separately.
libc_generated_header(
name = "include_stdbit_h",
hdr = "staging/include/stdbit.h",
other_srcs = ["include/stdbit.h.def"],
yaml_template = "include/stdbit.yaml",
name = "hdr_elf_proxy_h",
hdr = "staging/hdr/elf_proxy.h",
proxy = True,
yaml_template = "include/elf.yaml",
)
# Library containing all headers that can be transitively included by generated llvm-libc
# public headers (or by the unit tests).
# Static headers that need to be in staging/include
STATIC_HEADERS = glob(
["include/llvm-libc-types/**/*.h"],
) + glob(
["include/llvm-libc-macros/**/*.h"],
exclude = [
"include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h",
"include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h",
],
) + ["include/__llvm-libc-common.h"]
genrule(
name = "copy_llvm_libc_static_headers",
srcs = STATIC_HEADERS,
outs = ["staging/" + f for f in STATIC_HEADERS],
cmd = """srcs=($(SRCS))\n outs=($(OUTS))\n for i in "$${!srcs[@]}"; do cp "$${srcs[$$i]}" "$${outs[$$i]}"; done""",
)
genrule(
name = "copy_modular_format_header",
srcs = select({
":modular_format_enable": ["include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h"],
"//conditions:default": ["include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h"],
}),
outs = ["staging/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h"],
cmd = "cp $< $@",
)
STATIC_AND_CONDITIONAL_HEADERS = STATIC_HEADERS + ["include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h"]
cc_library(
name = "public_headers",
hdrs = [header.target_name for header in LLVM_LIBC_HEADERS],
includes = ["staging/include"],
textual_hdrs = ["staging/" + f for f in STATIC_AND_CONDITIONAL_HEADERS],
deps = [
":copy_llvm_libc_static_headers",
":copy_modular_format_header",
],
)
# Textual versions of the static headers. These are taken from the source tree
# and are separate from the generated headers above. They are used for
# testing purposes.
libc_support_library(
name = "public_headers_deps",
textual_hdrs = [
"include/__llvm-libc-common.h",
] + glob([
"include/llvm-libc-types/**/*.h",
"include/llvm-libc-macros/**/*.h",
]),
textual_hdrs = STATIC_AND_CONDITIONAL_HEADERS,
)
################################## Base Config #################################

View File

@ -255,7 +255,7 @@ def libc_header_library(name, hdrs, deps = [], **kwargs):
enforce_headers_only = True,
)
def libc_generated_header(name, hdr, yaml_template, other_srcs = []):
def libc_generated_header(name, hdr, yaml_template, other_srcs = [], proxy = False):
"""Generates a libc header file from YAML template.
Args:
@ -263,12 +263,13 @@ def libc_generated_header(name, hdr, yaml_template, other_srcs = []):
hdr: Path of the header file to generate.
yaml_template: Path of the YAML template file.
other_srcs: Other files required to generate the header, if any.
proxy: Whether this is a proxy header with slightly different generation results.
"""
hdrgen = "//libc:hdrgen"
cmd = "$(location {hdrgen}) $(location {yaml}) -o $@".format(
hdrgen = hdrgen,
yaml = yaml_template,
)
) + (" --proxy" if proxy else "")
if not hdr.startswith("staging/"):
fail(
@ -285,6 +286,17 @@ def libc_generated_header(name, hdr, yaml_template, other_srcs = []):
tools = [hdrgen],
)
def libc_header_info(
name,
has_def_template = False,
other_srcs = []):
return struct(
target_name = "include_{}_h".format(name.replace("/", "_")),
staging_path = "staging/include/{}.h".format(name),
yaml_template = "include/{}.yaml".format(name),
other_srcs = other_srcs + (["include/{}.h.def".format(name)] if has_def_template else []),
)
def libc_math_function(
name,
additional_deps = None):