class RbPlusPlus::Writers::MultipleFilesWriter
Writer that takes a builder and writes out the code in multiple files.
Public Instance Methods
Writing out a multiple-file built is a multi-stage process. This writer first builds a [working_dir]/.build directory, where new code initially goes. Once the writing is complete, each file in .build/ is diff-checked by the files in [working_dir]. If the files are different, the new file is copied into place. Then, the .build dir is removed.
We do this to allow for easy and quick-ish work on large wrapping projects. Because Rice code takes so long to compile, the fewer files one has to compile per change the better.
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 16 def write build_working_dir write_files process_diffs cleanup end
Private Instance Methods
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 25 def build_working_dir @build_dir = File.join(working_dir, ".build") # Build our temp dir FileUtils.mkdir_p @build_dir end
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 50 def cleanup FileUtils.rm_rf @build_dir end
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 41 def files_differ(file) filename = File.basename(file) existing = File.expand_path(File.join(working_dir, filename)) new = File.expand_path(File.join(@build_dir, filename)) return true if !File.exists?(existing) !system("diff #{existing} #{new} > #{@build_dir}/diff_info 2>&1") end
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 96 def new_file_for(node, parent = nil) file_writer = FileWriter.new(node, parent) @file_writers << file_writer process_file(file_writer, node) end
Go through each file in @build_dir and check them against the files in @working_dir, copying over only the ones that differ
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 35 def process_diffs Dir["#{@build_dir}/*.{cpp,hpp}"].each do |file| FileUtils.cp file, working_dir if files_differ(file) end end
Recursively run through this node's children adding them to the given file_writer or spawning off another file writer depending on the type of node we hit
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 107 def process_file(file_writer, node) node.nodes.each do |child| if child.is_a?(Builders::ModuleNode) || child.is_a?(Builders::ClassNode) new_file_for(child, file_writer) else file_writer << child process_file(file_writer, child) if child.has_children? end end end
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 83 def process_globals(node) # Process the globals node.global_nodes.each do |g| next if @globals_handled.include?(g.qualified_name) @globals_handled << g.qualified_name @global_writer << g end node.nodes.each do |b| process_globals(b) end end
Given our builder, go through nodes and write out files
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 55 def write_files # Couple of steps here: # - Split up the code into files according to Modules and Classes # - Header files need a register_#{name} prototype, source needs # register_#{name}(#{parent}) method definition # - All includes for this node go in the header. # - Source gets an include for the related header # - Save up all data from global_children and at the end write out # our rbpp_custom files, making sure all header files include # rbpp_custom.hpp @file_writers = [] @global_writer = RbppCustomFileWriter.new @globals_handled = [] new_file_for(self.builder) process_globals(self.builder) @global_writer.with_includes(self.builder.additional_includes) @global_writer.write(@build_dir) # Write out from the bottom up, makes sure that children file writers # update their parents as needed @file_writers.each do |fw| fw.write(@build_dir, self.builder.additional_includes) end end