Skip to content

[libc] Make hdrgen emit correct relative paths for llvm-libc-types #127150

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 3 commits into from
Feb 14, 2025

Conversation

frobtech
Copy link
Contributor

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.

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.
@frobtech frobtech requested review from Caslyn and fabio-d February 14, 2025 00:48
Copy link

github-actions bot commented Feb 14, 2025

✅ With the latest revision this PR passed the Python code formatter.

@frobtech frobtech marked this pull request as ready for review February 14, 2025 02:42
@llvmbot llvmbot added the libc label Feb 14, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 14, 2025

@llvm/pr-subscribers-libc

Author: Roland McGrath (frobtech)

Changes

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.


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

7 Files Affected:

  • (modified) libc/utils/hdrgen/header.py (+16-9)
  • (added) libc/utils/hdrgen/tests/expected_output/subdir/test.h (+23)
  • (modified) libc/utils/hdrgen/tests/expected_output/test_header.h (+2-3)
  • (added) libc/utils/hdrgen/tests/input/subdir/test.h.def (+16)
  • (added) libc/utils/hdrgen/tests/input/subdir/test.yaml (+12)
  • (modified) libc/utils/hdrgen/tests/test_integration.py (+8-1)
  • (modified) libc/utils/hdrgen/type.py (-3)
diff --git a/libc/utils/hdrgen/header.py b/libc/utils/hdrgen/header.py
index 85d3c54892f89..f94cb8e628fa6 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>"

@frobtech frobtech merged commit d2dd802 into llvm:main Feb 14, 2025
14 checks passed
@frobtech frobtech deleted the p/libc-hdrgen-type-relpath branch February 14, 2025 19:01
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Feb 14, 2025
…lvm#127150)

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.
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
…lvm#127150)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants