Skip to content

[libc][bazel] Support generating public libc headers in Bazel builds. #145381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 26, 2025

Conversation

jtstogel
Copy link
Contributor

Running hdrgen in Bazel hermetically requires adding a new dependency on PyYAML. This PR uses PyYAML version 5.1 due to keep in line with the docs:

See #134780.

Generated headers are placed in a staging/ directory so that they have the opportunity to be treated differently from non-generated headers. This is a follow-up to #141256, which was reverted in #143001 because it caused downstream failures when bootstrapping builds.

@llvmbot llvmbot added libc bazel "Peripheral" support tier build system: utils/bazel labels Jun 23, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 23, 2025

@llvm/pr-subscribers-libc

Author: None (jtstogel)

Changes

Running hdrgen in Bazel hermetically requires adding a new dependency on PyYAML. This PR uses PyYAML version 5.1 due to keep in line with the docs:

See #134780.

Generated headers are placed in a staging/ directory so that they have the opportunity to be treated differently from non-generated headers. This is a follow-up to #141256, which was reverted in #143001 because it caused downstream failures when bootstrapping builds.


Full diff: https://github.com/llvm/llvm-project/pull/145381.diff

4 Files Affected:

  • (modified) utils/bazel/WORKSPACE (+9)
  • (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+9)
  • (modified) utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl (+30)
  • (added) utils/bazel/third_party_build/pyyaml.BUILD (+16)
diff --git a/utils/bazel/WORKSPACE b/utils/bazel/WORKSPACE
index 84e65e6f67b5a..5e28c3b67fc3b 100644
--- a/utils/bazel/WORKSPACE
+++ b/utils/bazel/WORKSPACE
@@ -164,6 +164,15 @@ maybe(
     url = "https://github.com/pybind/pybind11/archive/v2.10.3.zip",
 )
 
+maybe(
+    http_archive,
+    name = "pyyaml",
+    build_file = "@llvm-raw//utils/bazel/third_party_build:pyyaml.BUILD",
+    sha256 = "f0a35d7f282a6d6b1a4f3f3965ef5c124e30ed27a0088efb97c0977268fd671f",
+    strip_prefix = "pyyaml-5.1/lib3",
+    url = "https://github.com/yaml/pyyaml/archive/refs/tags/5.1.zip",
+)
+
 maybe(
     http_archive,
     name = "robin_map",
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 8e629270c89d2..a351b525965c8 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -9,6 +9,7 @@ load("@rules_python//python:defs.bzl", "py_binary")
 load(
     ":libc_build_rules.bzl",
     "libc_function",
+    "libc_generated_header",
     "libc_header_library",
     "libc_math_function",
     "libc_support_library",
@@ -88,6 +89,14 @@ py_binary(
     srcs = glob(["utils/hdrgen/hdrgen/**/*.py"]),
     imports = ["utils/hdrgen"],
     main = "utils/hdrgen/hdrgen/main.py",
+    deps = ["@pyyaml//:yaml"],
+)
+
+libc_generated_header(
+    name = "include_stdbit_h",
+    hdr = "staging/include/stdbit.h",
+    other_srcs = ["include/stdbit.h.def"],
+    yaml_template = "include/stdbit.yaml",
 )
 
 # Library containing all headers that can be transitively included by generated llvm-libc
diff --git a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
index 7fe263ab08f71..e123e4d32b785 100644
--- a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
+++ b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
@@ -248,6 +248,36 @@ def libc_header_library(name, hdrs, deps = [], **kwargs):
         **kwargs
     )
 
+def libc_generated_header(name, hdr, yaml_template, other_srcs = []):
+    """Generates a libc header file from YAML template.
+
+    Args:
+      name: Name of the genrule target.
+      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.
+    """
+    hdrgen = "//libc:hdrgen"
+    cmd = "$(location {hdrgen}) $(location {yaml}) -o $@".format(
+        hdrgen = hdrgen,
+        yaml = yaml_template,
+    )
+
+    if not hdr.startswith("staging/"):
+        fail(
+            "Generated headers should be placed in a 'staging/' directory " +
+            "so that they can be treated differently from constant source files " +
+            "when bootstrapping builds.",
+        )
+
+    native.genrule(
+        name = name,
+        outs = [hdr],
+        srcs = [yaml_template] + other_srcs,
+        cmd = cmd,
+        tools = [hdrgen],
+    )
+
 def libc_math_function(
         name,
         additional_deps = None):
diff --git a/utils/bazel/third_party_build/pyyaml.BUILD b/utils/bazel/third_party_build/pyyaml.BUILD
new file mode 100644
index 0000000000000..78261a7f60d9b
--- /dev/null
+++ b/utils/bazel/third_party_build/pyyaml.BUILD
@@ -0,0 +1,16 @@
+# 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
+
+load("@rules_python//python:defs.bzl", "py_library")
+
+package(
+    default_visibility = ["//visibility:public"],
+    # BSD/MIT-like license (for PyYAML)
+    licenses = ["notice"],
+)
+
+py_library(
+    name = "yaml",
+    srcs = glob(["yaml/*.py"]),
+)

Running `hdrgen` in Bazel hermetically requires adding a new dependency on PyYAML. This PR uses PyYAML version 5.1 due to keep in line with the docs: https://github.com/llvm/llvm-project/blob/b878e0d11874a898bbaa1daf58007dfd232005f2/libc/docs/dev/header_generation.rst?plain=1#L22

See llvm#134780.

Generated headers are placed in a `staging/` directory so that they have the opportunity to be treated differently from non-generated headers. This is a follow-up to llvm#141256, which was reverted in llvm#143001 because it caused downstream failures when bootstrapping builds.
@jtstogel jtstogel force-pushed the generated-headers-in-staging branch from 73c1762 to d3bcdec Compare June 26, 2025 17:59
@vonosmas
Copy link
Contributor

Thank you for working on this! Merging per offline request.

@vonosmas vonosmas merged commit 442c417 into llvm:main Jun 26, 2025
7 checks passed
anthonyhatran pushed a commit to anthonyhatran/llvm-project that referenced this pull request Jun 26, 2025
…llvm#145381)

Running `hdrgen` in Bazel hermetically requires adding a new dependency
on PyYAML. This PR uses PyYAML version 5.1 due to keep in line with the
docs:
https://github.com/llvm/llvm-project/blob/b878e0d11874a898bbaa1daf58007dfd232005f2/libc/docs/dev/header_generation.rst?plain=1#L22

See llvm#134780.

Generated headers are placed in a `staging/` directory so that they have
the opportunity to be treated differently from non-generated headers.
This is a follow-up to llvm#141256,
which was reverted in llvm#143001
because it caused downstream failures when bootstrapping builds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bazel "Peripheral" support tier build system: utils/bazel libc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants