[libc-commits] [libc] 2bd8d73 - [libc] Add public_includes stanza to hdrgen and use it in socket headers (#205543)

via libc-commits libc-commits at lists.llvm.org
Sun Jun 28 23:13:22 PDT 2026


Author: Pavel Labath
Date: 2026-06-29T08:13:17+02:00
New Revision: 2bd8d73902bacaa8b8540bc0eb7a6604d6b5f1ed

URL: https://github.com/llvm/llvm-project/commit/2bd8d73902bacaa8b8540bc0eb7a6604d6b5f1ed
DIFF: https://github.com/llvm/llvm-project/commit/2bd8d73902bacaa8b8540bc0eb7a6604d6b5f1ed.diff

LOG: [libc] Add public_includes stanza to hdrgen and use it in socket headers (#205543)

This patch adds support for a public_includes stanza in header YAML
files, allowing generated public headers to include other public
headers.

I use this to make arpa/inet.h include netinet/in.h, and netinet/in.h
include sys/socket.h. While POSIX doesn't strictly require these headers
to include each other, it permits it, and many real-world applications
depend on this behavior.

To make this work, I also needed to reorder the header targets in
include/CMakeLists.txt so that targets sys_socket and netinet_in are
defined before targets declare dependencies on them.

There are a couple of other files that could use this feature (right now
they handle it through the header template), but I'll do that as a
separate patch.

Assisted by Gemini.

Added: 
    

Modified: 
    libc/include/CMakeLists.txt
    libc/include/arpa/inet.yaml
    libc/include/netinet/in.yaml
    libc/utils/hdrgen/hdrgen/header.py
    libc/utils/hdrgen/hdrgen/yaml_to_classes.py
    libc/utils/hdrgen/tests/expected_output/custom.h
    libc/utils/hdrgen/tests/input/custom.yaml

Removed: 
    


################################################################################
diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index bb670b614742a..caf5d61dfc1cb 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -203,63 +203,6 @@ add_header_macro(
     .llvm-libc-macros.sysexits_macros
 )
 
-
-# TODO: This should be conditional on POSIX networking being included.
-file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/arpa)
-
-add_header_macro(
-  arpa_inet
-  ../libc/include/arpa/inet.yaml
-  arpa/inet.h
-  DEPENDS
-    .llvm_libc_common_h
-    .inttypes
-    .llvm-libc-types.in_addr_t
-    .llvm-libc-types.struct_in_addr
-    .llvm-libc-macros.inet_address_macros
-)
-
-file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/netinet)
-
-add_header_macro(
-  netinet_in
-  ../libc/include/netinet/in.yaml
-  netinet/in.h
-  DEPENDS
-    .llvm-libc-macros.netinet_in_macros
-    .llvm-libc-macros.inet_address_macros
-    .llvm-libc-types.in_addr_t
-    .llvm-libc-types.in_port_t
-    .llvm-libc-types.sa_family_t
-    .llvm-libc-types.struct_sockaddr_in
-    .llvm-libc-types.struct_sockaddr_in6
-    .llvm-libc-types.struct_in_addr
-    .llvm-libc-types.struct_in6_addr
-    .llvm-libc-types.struct_ip_mreq
-    .llvm-libc-types.struct_ip_mreq_source
-    .llvm-libc-types.struct_ip_mreqn
-    .llvm-libc-types.struct_ip_msfilter
-    .llvm-libc-types.struct_ip_opts
-    .llvm_libc_common_h
-)
-
-add_header_macro(
-  netinet_tcp
-  ../libc/include/netinet/tcp.yaml
-  netinet/tcp.h
-  DEPENDS
-    .llvm_libc_common_h
-)
-
-add_header_macro(
-  netinet_udp
-  ../libc/include/netinet/udp.yaml
-  netinet/udp.h
-  DEPENDS
-    .llvm-libc-types.struct_udphdr
-    .llvm_libc_common_h
-)
-
 add_header_macro(
   assert
   ../libc/include/assert.yaml
@@ -952,6 +895,66 @@ add_header_macro(
     .llvm-libc-types.siginfo_t
 )
 
+# TODO: This should be conditional on POSIX networking being included.
+file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/netinet)
+
+add_header_macro(
+  netinet_in
+  ../libc/include/netinet/in.yaml
+  netinet/in.h
+  DEPENDS
+    .llvm-libc-macros.netinet_in_macros
+    .llvm-libc-macros.inet_address_macros
+    .llvm-libc-types.in_addr_t
+    .llvm-libc-types.in_port_t
+    .llvm-libc-types.sa_family_t
+    .llvm-libc-types.struct_sockaddr_in
+    .llvm-libc-types.struct_sockaddr_in6
+    .llvm-libc-types.struct_in_addr
+    .llvm-libc-types.struct_in6_addr
+    .llvm-libc-types.struct_ip_mreq
+    .llvm-libc-types.struct_ip_mreq_source
+    .llvm-libc-types.struct_ip_mreqn
+    .llvm-libc-types.struct_ip_msfilter
+    .llvm-libc-types.struct_ip_opts
+    .llvm_libc_common_h
+    .sys_socket
+)
+
+add_header_macro(
+  netinet_tcp
+  ../libc/include/netinet/tcp.yaml
+  netinet/tcp.h
+  DEPENDS
+    .llvm_libc_common_h
+)
+
+add_header_macro(
+  netinet_udp
+  ../libc/include/netinet/udp.yaml
+  netinet/udp.h
+  DEPENDS
+    .llvm-libc-types.struct_udphdr
+    .llvm_libc_common_h
+)
+
+file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/arpa)
+
+add_header_macro(
+  arpa_inet
+  ../libc/include/arpa/inet.yaml
+  arpa/inet.h
+  DEPENDS
+    .inttypes
+    .llvm_libc_common_h
+    .llvm-libc-types.in_addr_t
+    .llvm-libc-types.in_port_t
+    .llvm-libc-types.socklen_t
+    .llvm-libc-types.struct_in_addr
+    .llvm-libc-macros.inet_address_macros
+    .netinet_in
+)
+
 add_header_macro(
   termios
   ../libc/include/termios.yaml

diff  --git a/libc/include/arpa/inet.yaml b/libc/include/arpa/inet.yaml
index 38e975c3dfbfd..8e7d57b5104c5 100644
--- a/libc/include/arpa/inet.yaml
+++ b/libc/include/arpa/inet.yaml
@@ -3,13 +3,24 @@ standards:
   - posix
 merge_yaml_files:
   - ../htons-family.yaml
+public_includes:
+  # This is permitted (but not required) by POSIX and many applications depend
+  # on it. If we have a "pedantic" mode in the future, we might want to exclude
+  # it there.
+  - netinet/in.h
 macros:
+  # Macros also defined by netinet/in.h, but listing them explicitly as they are
+  # required by POSIX.
   - macro_name: INET_ADDRSTRLEN
     macro_header: inet-address-macros.h
   - macro_name: INET6_ADDRSTRLEN
     macro_header: inet-address-macros.h
 types:
+  # Types also defined by netinet/in.h, but listing them explicitly as they are
+  # required by POSIX.
+  - type_name: in_port_t
   - type_name: in_addr_t
+  - type_name: socklen_t
   - type_name: struct_in_addr
 enums: []
 objects: []

diff  --git a/libc/include/netinet/in.yaml b/libc/include/netinet/in.yaml
index 0244b160cb601..b78efacbbfe0f 100644
--- a/libc/include/netinet/in.yaml
+++ b/libc/include/netinet/in.yaml
@@ -3,6 +3,11 @@ standards:
   - posix
 merge_yaml_files:
   - ../htons-family.yaml
+public_includes:
+  # This is permitted (but not required) by POSIX and many applications depend
+  # on it. If we have a "pedantic" mode in the future, we might want to exclude
+  # it there.
+  - sys/socket.h
 macros:
   - macro_name: IPPROTO_IP
     macro_header: netinet-in-macros.h
@@ -103,7 +108,6 @@ macros:
 types:
   - type_name: in_port_t
   - type_name: in_addr_t
-  - type_name: sa_family_t
   - type_name: struct_sockaddr_in
   - type_name: struct_sockaddr_in6
   - type_name: struct_in_addr
@@ -113,6 +117,9 @@ types:
   - type_name: struct_ip_mreqn
   - type_name: struct_ip_msfilter
   - type_name: struct_ip_opts
+  # Type also defined by sys/socket.h, but listing it explicitly as it is
+  # required by POSIX.
+  - type_name: sa_family_t
 enums: []
 objects:
   - object_name: in6addr_any

diff  --git a/libc/utils/hdrgen/hdrgen/header.py b/libc/utils/hdrgen/hdrgen/header.py
index 1063e161e36c1..db6a064aaf7f3 100644
--- a/libc/utils/hdrgen/hdrgen/header.py
+++ b/libc/utils/hdrgen/hdrgen/header.py
@@ -116,6 +116,7 @@ def __init__(self, name):
         self.standards = []
         self.merge_yaml_files = []
         self.license_text = []
+        self.public_includes = []
 
     def add_macro(self, macro):
         self.macros.append(macro)
@@ -139,6 +140,9 @@ def merge(self, other):
         self.objects = sorted(set(self.objects) | set(other.objects))
         self.functions = sorted(set(self.functions) | set(other.functions))
         self.extra_standards |= other.extra_standards
+        self.public_includes = sorted(
+            set(self.public_includes) | set(other.public_includes)
+        )
         if self.license_text:
             assert not other.license_text, "only one `license_text` allowed"
         else:
@@ -183,7 +187,8 @@ def all_standards(self):
 
     def includes(self):
         return (
-            {
+            {f"<{inc}>" for inc in self.public_includes}
+            | {
                 PurePosixPath("llvm-libc-macros") / macro.header
                 for macro in self.macros
                 if macro.header is not None

diff  --git a/libc/utils/hdrgen/hdrgen/yaml_to_classes.py b/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
index ca71408c92036..dcbb52c8ce99c 100644
--- a/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
+++ b/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
@@ -39,6 +39,7 @@ def yaml_to_classes(yaml_data, header_class, entry_points=None):
     header.extra_standards = yaml_data.get("extra_standards", {})
     header.license_text = yaml_data.get("license_text", [])
     header.merge_yaml_files = yaml_data.get("merge_yaml_files", [])
+    header.public_includes = yaml_data.get("public_includes", [])
 
     for macro_data in yaml_data.get("macros", []):
         macro = Macro(

diff  --git a/libc/utils/hdrgen/tests/expected_output/custom.h b/libc/utils/hdrgen/tests/expected_output/custom.h
index 5f9ed231490fd..b78e91201d7b2 100644
--- a/libc/utils/hdrgen/tests/expected_output/custom.h
+++ b/libc/utils/hdrgen/tests/expected_output/custom.h
@@ -11,6 +11,7 @@
 #include "__llvm-libc-common.h"
 #include "llvm-libc-types/meep.h"
 #include "llvm-libc-types/road.h"
+#include <acme/anvil.h>
 
 __BEGIN_C_DECLS
 

diff  --git a/libc/utils/hdrgen/tests/input/custom.yaml b/libc/utils/hdrgen/tests/input/custom.yaml
index 7d3ff8ec421dd..fe1e69301afdf 100644
--- a/libc/utils/hdrgen/tests/input/custom.yaml
+++ b/libc/utils/hdrgen/tests/input/custom.yaml
@@ -4,6 +4,8 @@ merge_yaml_files:
 header: custom.h
 standards:
   - acme
+public_includes:
+  - acme/anvil.h
 
 functions:
   - name: runner


        


More information about the libc-commits mailing list