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 -#include - 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 "