[libc-commits] [libc] [libc] Add public_includes stanza to hdrgen and use it in socket headers (PR #205543)
via libc-commits
libc-commits at lists.llvm.org
Wed Jun 24 05:25:47 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Pavel Labath (labath)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/205543.diff
7 Files Affected:
- (modified) libc/include/CMakeLists.txt (+60-57)
- (modified) libc/include/arpa/inet.yaml (+11)
- (modified) libc/include/netinet/in.yaml (+8-1)
- (modified) libc/utils/hdrgen/hdrgen/header.py (+6-1)
- (modified) libc/utils/hdrgen/hdrgen/yaml_to_classes.py (+1)
- (modified) libc/utils/hdrgen/tests/expected_output/custom.h (+1)
- (modified) libc/utils/hdrgen/tests/input/custom.yaml (+2)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/205543
More information about the libc-commits
mailing list