[libc-commits] [libc] [libc] Make hdrgen emit correct relative paths for llvm-libc-types (PR #127150)

Roland McGrath via libc-commits libc-commits at lists.llvm.org
Thu Feb 13 18:41:38 PST 2025


https://github.com/frobtech updated https://github.com/llvm/llvm-project/pull/127150

>From 6ea03b4875cb9d6d720c292410f5afe26fb31b2e Mon Sep 17 00:00:00 2001
From: Roland McGrath <mcgrathr at google.com>
Date: Thu, 13 Feb 2025 16:42:45 -0800
Subject: [PATCH 1/2] [libc] Make hdrgen emit correct relative paths for
 llvm-libc-types

This makes hdrgen emit `#include "..."` lines using the correct
relative path (number of `../` steps, if any) for the containing
header, and includes this in the sorted block of `#include` lines
also used for the macro headers.
---
 libc/utils/hdrgen/header.py                   | 25 ++++++++++++-------
 .../tests/expected_output/subdir/test.h       | 23 +++++++++++++++++
 .../tests/expected_output/test_header.h       |  5 ++--
 .../hdrgen/tests/input/subdir/test.h.def      | 16 ++++++++++++
 .../utils/hdrgen/tests/input/subdir/test.yaml | 12 +++++++++
 libc/utils/hdrgen/tests/test_integration.py   |  9 ++++++-
 libc/utils/hdrgen/type.py                     |  3 ---
 7 files changed, 77 insertions(+), 16 deletions(-)
 create mode 100644 libc/utils/hdrgen/tests/expected_output/subdir/test.h
 create mode 100644 libc/utils/hdrgen/tests/input/subdir/test.h.def
 create mode 100644 libc/utils/hdrgen/tests/input/subdir/test.yaml

diff --git a/libc/utils/hdrgen/header.py b/libc/utils/hdrgen/header.py
index 85d3c54892f89..6bbe37156201a 100644
--- a/libc/utils/hdrgen/header.py
+++ b/libc/utils/hdrgen/header.py
@@ -6,7 +6,7 @@
 #
 # ==-------------------------------------------------------------------------==#
 
-from pathlib import PurePath
+from pathlib import PurePosixPath
 
 
 class HeaderFile:
@@ -37,26 +37,33 @@ def add_function(self, function):
     def includes(self):
         return sorted(
             {
-                PurePath("llvm-libc-macros") / macro.header
+                PurePosixPath("llvm-libc-macros") / macro.header
                 for macro in self.macros
                 if macro.header is not None
             }
+            | {PurePosixPath("llvm-libc-types") / f"{typ.type_name}.h" for typ in self.types}
         )
 
     def public_api(self):
-        header_dir = PurePath(self.name).parent
+        # Python 3.12 has .relative_to(dir, walk_up=True) for this.
+        path_prefix = PurePosixPath("../" * (len(PurePosixPath(self.name).parents) - 1))
+
+        def relpath(file):
+            return path_prefix / file
+
         content = [
-            f'#include "{file.relative_to(header_dir)}"' for file in self.includes()
-        ] + [""]
+            f"#include {file}"
+            for file in sorted(
+                f'"{relpath(file)!s}"'
+                for file in self.includes()
+            )
+        ]
 
         for macro in self.macros:
             # When there is nothing to define, the Macro object converts to str
             # as an empty string.  Don't emit a blank line for those cases.
             if str(macro):
-                content.append(f"{macro}\n")
-
-        for type_ in self.types:
-            content.append(f"{type_}")
+                content.extend(["", f"{macro}"])
 
         if self.enumerations:
             combined_enum_content = ",\n  ".join(
diff --git a/libc/utils/hdrgen/tests/expected_output/subdir/test.h b/libc/utils/hdrgen/tests/expected_output/subdir/test.h
new file mode 100644
index 0000000000000..53d28e8430104
--- /dev/null
+++ b/libc/utils/hdrgen/tests/expected_output/subdir/test.h
@@ -0,0 +1,23 @@
+//===-- C standard library header subdir/test.h --------------------------===//
+//
+// Part of the LLVM Project, 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
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SUBDIR_TEST_H
+#define LLVM_LIBC_SUBDIR_TEST_H
+
+#include "../__llvm-libc-common.h"
+
+#include "../llvm-libc-types/type_a.h"
+#include "../llvm-libc-types/type_b.h"
+
+__BEGIN_C_DECLS
+
+type_a func(type_b) __NOEXCEPT;
+
+__END_C_DECLS
+
+#endif // LLVM_LIBC_SUBDIR_TEST_H
diff --git a/libc/utils/hdrgen/tests/expected_output/test_header.h b/libc/utils/hdrgen/tests/expected_output/test_header.h
index ca9439982d66b..838b6d7728150 100644
--- a/libc/utils/hdrgen/tests/expected_output/test_header.h
+++ b/libc/utils/hdrgen/tests/expected_output/test_header.h
@@ -15,6 +15,8 @@
 
 #include "llvm-libc-macros/test_more-macros.h"
 #include "llvm-libc-macros/test_small-macros.h"
+#include "llvm-libc-types/type_a.h"
+#include "llvm-libc-types/type_b.h"
 
 #define MACRO_A 1
 
@@ -22,9 +24,6 @@
 
 #define MACRO_C
 
-#include <llvm-libc-types/type_a.h>
-#include <llvm-libc-types/type_b.h>
-
 enum {
   enum_a = value_1,
   enum_b = value_2,
diff --git a/libc/utils/hdrgen/tests/input/subdir/test.h.def b/libc/utils/hdrgen/tests/input/subdir/test.h.def
new file mode 100644
index 0000000000000..ded06082a51be
--- /dev/null
+++ b/libc/utils/hdrgen/tests/input/subdir/test.h.def
@@ -0,0 +1,16 @@
+//===-- C standard library header subdir/test.h --------------------------===//
+//
+// Part of the LLVM Project, 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
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SUBDIR_TEST_H
+#define LLVM_LIBC_SUBDIR_TEST_H
+
+#include "../__llvm-libc-common.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_SUBDIR_TEST_H
diff --git a/libc/utils/hdrgen/tests/input/subdir/test.yaml b/libc/utils/hdrgen/tests/input/subdir/test.yaml
new file mode 100644
index 0000000000000..a414b6f387ccb
--- /dev/null
+++ b/libc/utils/hdrgen/tests/input/subdir/test.yaml
@@ -0,0 +1,12 @@
+header: subdir/test.h
+header_template: test.h.def
+types:
+  - type_name: type_a
+  - type_name: type_b
+functions:
+  - name: func
+    return_type: type_a
+    arguments:
+      - type: type_b
+    standards:
+      - stdc
diff --git a/libc/utils/hdrgen/tests/test_integration.py b/libc/utils/hdrgen/tests/test_integration.py
index 7789c9c0a1316..4f3d2a939520a 100644
--- a/libc/utils/hdrgen/tests/test_integration.py
+++ b/libc/utils/hdrgen/tests/test_integration.py
@@ -12,7 +12,7 @@ def setUp(self):
         self.main_script = self.source_dir.parent / "main.py"
         self.maxDiff = 80 * 100
 
-    def run_script(self, yaml_file, output_file, entry_points):
+    def run_script(self, yaml_file, output_file, entry_points=[]):
         command = [
             "python3",
             str(self.main_script),
@@ -52,6 +52,13 @@ def test_generate_header(self):
 
         self.compare_files(output_file, expected_output_file)
 
+    def test_generate_subdir_header(self):
+        yaml_file = self.source_dir / "input" / "subdir" / "test.yaml"
+        expected_output_file = self.source_dir / "expected_output" / "subdir" / "test.h"
+        output_file = self.output_dir / "subdir" / "test.h"
+        self.run_script(yaml_file, output_file)
+        self.compare_files(output_file, expected_output_file)
+
 
 def main():
     parser = argparse.ArgumentParser(description="TestHeaderGenIntegration arguments")
diff --git a/libc/utils/hdrgen/type.py b/libc/utils/hdrgen/type.py
index 4ebf8034a4543..b90480267d8d5 100644
--- a/libc/utils/hdrgen/type.py
+++ b/libc/utils/hdrgen/type.py
@@ -10,6 +10,3 @@
 class Type:
     def __init__(self, type_name):
         self.type_name = type_name
-
-    def __str__(self):
-        return f"#include <llvm-libc-types/{self.type_name}.h>"

>From b74d39f833a66ae90a409a7410f74e1547afed81 Mon Sep 17 00:00:00 2001
From: Roland McGrath <mcgrathr at google.com>
Date: Thu, 13 Feb 2025 18:41:02 -0800
Subject: [PATCH 2/2] Reformat Python

---
 libc/utils/hdrgen/header.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/utils/hdrgen/header.py b/libc/utils/hdrgen/header.py
index 6bbe37156201a..f94cb8e628fa6 100644
--- a/libc/utils/hdrgen/header.py
+++ b/libc/utils/hdrgen/header.py
@@ -41,7 +41,10 @@ def includes(self):
                 for macro in self.macros
                 if macro.header is not None
             }
-            | {PurePosixPath("llvm-libc-types") / f"{typ.type_name}.h" for typ in self.types}
+            | {
+                PurePosixPath("llvm-libc-types") / f"{typ.type_name}.h"
+                for typ in self.types
+            }
         )
 
     def public_api(self):
@@ -53,10 +56,7 @@ def relpath(file):
 
         content = [
             f"#include {file}"
-            for file in sorted(
-                f'"{relpath(file)!s}"'
-                for file in self.includes()
-            )
+            for file in sorted(f'"{relpath(file)!s}"' for file in self.includes())
         ]
 
         for macro in self.macros:



More information about the libc-commits mailing list