class RbPlusPlus::Writers::MultipleFilesWriter

Writer that takes a builder and writes out the code in multiple files.

Public Instance Methods

write() click to toggle source

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

build_working_dir() click to toggle source
# 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
cleanup() click to toggle source
# File lib/rbplusplus/writers/multiple_files_writer.rb, line 50
def cleanup
  FileUtils.rm_rf @build_dir
end
files_differ(file) click to toggle source
# 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
new_file_for(node, parent = nil) click to toggle source
# 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
process_diffs() click to toggle source

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
process_file(file_writer, node) click to toggle source

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
process_globals(node) click to toggle source
# 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
write_files() click to toggle source

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