diff --git a/cppwg/input/class_info.py b/cppwg/input/class_info.py index 2971a48..c2edd6e 100644 --- a/cppwg/input/class_info.py +++ b/cppwg/input/class_info.py @@ -235,7 +235,9 @@ def update_from_source(self, source_file_paths: List[str]) -> None: return # Attempt to map class to a source file - if not self.source_file_full_path: + if self.source_file_full_path: + self.source_file = os.path.basename(self.source_file_full_path) + else: for file_path in source_file_paths: file_name = os.path.basename(file_path) # Match file name if set diff --git a/cppwg/input/package_info.py b/cppwg/input/package_info.py index f90f24a..b31ca76 100644 --- a/cppwg/input/package_info.py +++ b/cppwg/input/package_info.py @@ -111,6 +111,9 @@ def collect_source_headers(self, restricted_paths: List[str]) -> None: logger.error(f"No header files found in source root: {self.source_root}") raise FileNotFoundError() + # Sort by filename + self.source_hpp_files.sort(key=lambda x: os.path.basename(x)) + def update_from_source(self) -> None: """ Update modules with information from the source headers. diff --git a/cppwg/parsers/package_info_parser.py b/cppwg/parsers/package_info_parser.py index 8f59f78..e2b62f7 100644 --- a/cppwg/parsers/package_info_parser.py +++ b/cppwg/parsers/package_info_parser.py @@ -215,6 +215,8 @@ def parse(self) -> PackageInfo: class_info.module_info = module_info module_info.class_info_collection.append(class_info) + module_info.class_info_collection.sort(key=lambda x: x.name) + # Parse the free function data and create free function info objects. # Note: if module_config["use_all_free_functions"] == True, free function # info objects will be added later after parsing the C++ source code. @@ -243,6 +245,8 @@ def parse(self) -> PackageInfo: free_function_info ) + module_info.free_function_info_collection.sort(key=lambda x: x.name) + # Parse the variable data if not module_config["use_all_variables"]: for raw_variable_info in module_config["variables"]: diff --git a/cppwg/writers/header_collection_writer.py b/cppwg/writers/header_collection_writer.py index 0c4fdbf..6ddc5c3 100644 --- a/cppwg/writers/header_collection_writer.py +++ b/cppwg/writers/header_collection_writer.py @@ -23,9 +23,9 @@ class CppHeaderCollectionWriter: The package information wrapper_root : str The output directory for the generated wrapper code - hpp_collection_filepath : str + hpp_collection_file : str The path to save the header collection file to - hpp_collection_string : str + hpp_collection : str The output string that gets written to the header collection file class_dict : Dict[str, CppClassInfo] A dictionary of all class info objects @@ -37,13 +37,13 @@ def __init__( self, package_info: PackageInfo, wrapper_root: str, - hpp_collection_filepath: str, + hpp_collection_file: str, ): self.package_info: PackageInfo = package_info self.wrapper_root: str = wrapper_root - self.hpp_collection_filepath: str = hpp_collection_filepath - self.hpp_collection_string: str = "" + self.hpp_collection_file: str = hpp_collection_file + self.hpp_collection: str = "" # For convenience, collect all class and free function info into dicts keyed by name self.class_dict: Dict[str, CppClassInfo] = {} @@ -73,24 +73,23 @@ def should_include_all(self) -> bool: def write(self) -> None: """Generate the header file output string and write it to file.""" # Add the top prefix text - self.hpp_collection_string += self.package_info.prefix_text + "\n" + self.hpp_collection += self.package_info.prefix_text + "\n" # Add opening header guard - self.hpp_collection_string += f"#ifndef {self.package_info.name}_HEADERS_HPP_\n" - self.hpp_collection_string += f"#define {self.package_info.name}_HEADERS_HPP_\n" + self.hpp_collection += f"#ifndef {self.package_info.name}_HEADERS_HPP_\n" + self.hpp_collection += f"#define {self.package_info.name}_HEADERS_HPP_\n" - self.hpp_collection_string += "\n// Includes\n" + self.hpp_collection += "\n// Includes\n" - included_files = set() # Keep track of included files to avoid duplicates + seen_files = set() # Keep track of included files to avoid duplicates if self.should_include_all(): # Include all the headers - for hpp_filepath in self.package_info.source_hpp_files: - hpp_filename = os.path.basename(hpp_filepath) - - if hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + for filepath in self.package_info.source_hpp_files: + filename = os.path.basename(filepath) + if filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) else: # Include specific headers needed by classes @@ -100,30 +99,20 @@ def write(self) -> None: if class_info.excluded: continue - hpp_filename = None - - if class_info.source_file: - hpp_filename = class_info.source_file - - elif class_info.source_file_full_path: - hpp_filename = os.path.basename( - class_info.source_file_full_path - ) - - if hpp_filename and hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + filename = class_info.source_file + if filename and filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) # Include specific headers needed by free functions for free_function_info in module_info.free_function_info_collection: if free_function_info.source_file_full_path: - hpp_filename = os.path.basename( + filename = os.path.basename( free_function_info.source_file_full_path ) - - if hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + if filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) # Add the template instantiations e.g. `template class Foo<2,2>;` # and typdefs e.g. `typedef Foo<2,2> Foo_2_2;` @@ -150,19 +139,17 @@ def write(self) -> None: template_instantiations += f"template class {cpp_name};\n" template_typedefs += f" typedef {cpp_name} {py_name};\n" - self.hpp_collection_string += "\n// Instantiate Template Classes\n" - self.hpp_collection_string += template_instantiations + self.hpp_collection += "\n// Instantiate Template Classes\n" + self.hpp_collection += template_instantiations - self.hpp_collection_string += "\n// Typedefs for nicer naming\n" - self.hpp_collection_string += "namespace cppwg\n{\n" - self.hpp_collection_string += template_typedefs - self.hpp_collection_string += "} // namespace cppwg\n" + self.hpp_collection += "\n// Typedefs for nicer naming\n" + self.hpp_collection += "namespace cppwg\n{\n" + self.hpp_collection += template_typedefs + self.hpp_collection += "} // namespace cppwg\n" # Add closing header guard - self.hpp_collection_string += ( - f"\n#endif // {self.package_info.name}_HEADERS_HPP_\n" - ) + self.hpp_collection += f"\n#endif // {self.package_info.name}_HEADERS_HPP_\n" # Write the header collection string to file - with open(self.hpp_collection_filepath, "w") as hpp_file: - hpp_file.write(self.hpp_collection_string) + with open(self.hpp_collection_file, "w") as hpp_file: + hpp_file.write(self.hpp_collection) diff --git a/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp b/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp index dfad45a..8eb7eb1 100644 --- a/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp +++ b/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp @@ -5,26 +5,26 @@ #define pyshapes_HEADERS_HPP_ // Includes +#include "AbstractMesh.hpp" #include "ConcreteMesh.hpp" +#include "Cuboid.hpp" #include "MeshFactory.hpp" -#include "AbstractMesh.hpp" +#include "Point.hpp" +#include "Rectangle.hpp" +#include "Shape.hpp" #include "SimpleMathFunctions.hpp" #include "Square.hpp" -#include "Shape.hpp" -#include "Cuboid.hpp" #include "Triangle.hpp" -#include "Rectangle.hpp" -#include "Point.hpp" // Instantiate Template Classes template class Point<2>; template class Point<3>; template class Shape<2>; template class Shape<3>; -template class ConcreteMesh<2>; -template class ConcreteMesh<3>; template class AbstractMesh<2, 2>; template class AbstractMesh<3, 3>; +template class ConcreteMesh<2>; +template class ConcreteMesh<3>; // Typedefs for nicer naming namespace cppwg @@ -33,10 +33,10 @@ namespace cppwg typedef Point<3> Point_3; typedef Shape<2> Shape_2; typedef Shape<3> Shape_3; - typedef ConcreteMesh<2> ConcreteMesh_2; - typedef ConcreteMesh<3> ConcreteMesh_3; typedef AbstractMesh<2, 2> AbstractMesh_2_2; typedef AbstractMesh<3, 3> AbstractMesh_3_3; + typedef ConcreteMesh<2> ConcreteMesh_2; + typedef ConcreteMesh<3> ConcreteMesh_3; } // namespace cppwg #endif // pyshapes_HEADERS_HPP_