@@ -154,10 +154,6 @@ def initialize(inputter, outputter, config)
154154 @incomplete_iterators = Hash . new
155155 # Iterator names per class (for aliasing each_const -> each)
156156 @class_iterator_names = Hash . new { |h , k | h [ k ] = Set . new }
157- # Template classes with no bindable content (all methods deprecated/skipped)
158- @empty_builders = Set . new
159- # Maps builder function name -> -rb.ipp basename (persists across files for cross-file deps)
160- @builder_ipps = { }
161157 end
162158
163159 def generate
@@ -245,6 +241,13 @@ def rice_include_header
245241 @include_header || "#{ @project || 'rice' } _include.hpp"
246242 end
247243
244+ # Compute the .ipp path for a template defined in a different file.
245+ def ipp_path_for_cursor ( cursor )
246+ template_file = cursor . file_location . file
247+ relative = Pathname . new ( template_file ) . relative_path_from ( Pathname . new ( @inputter . base_path ) ) . to_s
248+ File . join ( File . dirname ( relative ) , "#{ File . basename ( relative , '.*' ) } -rb.ipp" )
249+ end
250+
248251 # Generate default Rice include header if user didn't specify one
249252 def create_rice_include_header
250253 return if @include_header # User specified their own header
@@ -535,12 +538,6 @@ def visit_class_template_builder(cursor)
535538 only_kinds : [ :cursor_cxx_method , :cursor_constructor , :cursor_field_decl , :cursor_variable ,
536539 :cursor_enum_decl , :cursor_conversion_function ] )
537540
538- # If no children (all methods deprecated/skipped), don't generate builder
539- if children . empty?
540- @empty_builders . add ( cursor . spelling )
541- return ""
542- end
543-
544541 # TODO: Calling get_base_spelling crashes libclang on certain templates.
545542 # Fix the instantiate functions by hand for now.
546543 #base_spelling = get_base_spelling(cursor)
@@ -564,12 +561,6 @@ def visit_class_template_builder(cursor)
564561 param_names = template_parameters . map ( &:spelling ) . join ( ", " )
565562 fully_qualified_type = "#{ cursor . qualified_name } <#{ param_names } >"
566563
567- # Track builder for cross-file dependency detection.
568- # Store the full relative path (e.g., "opencv2/core/cvstd_wrapper-rb.ipp")
569- # so consumers in different directories can compute the correct include path.
570- builder_name = "#{ cursor . spelling } _instantiate"
571- @builder_ipps [ builder_name ] = File . join ( @relative_dir , "#{ @basename } .ipp" )
572-
573564 children_content = merge_children ( children , :indentation => 4 , :separator => ".\n " ,
574565 :terminator => ";" , :strip => true )
575566
@@ -1898,14 +1889,14 @@ def visit_template_specialization(cursor, cursor_template, underlying_type)
18981889
18991890 template_specialization = type_spelling ( underlying_type )
19001891
1901- # Check if the template's _instantiate builder was generated in a different file
1902- builder_name = " #{ cursor_template . spelling } _instantiate"
1903- builder_ipp = @builder_ipps [ builder_name ]
1904- current_ipp = File . join ( @relative_dir , "#{ @basename } .ipp" )
1905- if builder_ipp && builder_ipp != current_ipp
1906- # Compute relative path from current file's directory to the ipp file
1907- ipp_relative = Pathname . new ( builder_ipp ) . relative_path_from ( Pathname . new ( @relative_dir ) ) . to_s
1908- @includes << "#include \" #{ ipp_relative } \" "
1892+ # If template is defined in a different file, include its .ipp for the _instantiate builder
1893+ unless cursor_template . file_location . file == cursor_template . translation_unit . file . name
1894+ builder_ipp = ipp_path_for_cursor ( cursor_template )
1895+ current_ipp = File . join ( @relative_dir , "#{ @basename } .ipp" )
1896+ if builder_ipp != current_ipp
1897+ ipp_relative = Pathname . new ( builder_ipp ) . relative_path_from ( Pathname . new ( @relative_dir ) ) . to_s
1898+ @includes << "#include \" #{ ipp_relative } \" "
1899+ end
19091900 end
19101901
19111902 @classes [ cursor . cruby_name ] = template_specialization
0 commit comments