Merge "Add can grabber auto."
diff --git a/aos/build/queues.gypi b/aos/build/queues.gypi
index 7c0343a..4d9fec2 100644
--- a/aos/build/queues.gypi
+++ b/aos/build/queues.gypi
@@ -21,13 +21,10 @@
 # example of how this should work
 {
   'variables': {
-    #'header_path': '>!(python -c "import os.path; print os.path.relpath(\'<(RULE_INPUT_PATH)\', \'<(DEPTH)\')")',
     'prefix_dir': '<(SHARED_INTERMEDIATE_DIR)/<!(echo <(header_path) | sed "s/[^A-Za-z0-9]/_/g")',
     'out_dir': '<(prefix_dir)/<(_target_name)/<(header_path)',
-    'gen_namespace%': '>!(echo >(header_path) | sed "s:\([^/]*\).*:\\1:g")',
     'output_h': '<(out_dir)/<(RULE_INPUT_ROOT).q.h',
     'output_cc': '<(out_dir)/<(RULE_INPUT_ROOT).q.cc',
-    'output_main': '<(out_dir)/<(RULE_INPUT_ROOT)_main.cc',
     'no_rsync': 1,
     'aos_q_dependent_paths%': [],
   },
diff --git a/aos/build/queues/BUILD b/aos/build/queues/BUILD
new file mode 100644
index 0000000..ec51451
--- /dev/null
+++ b/aos/build/queues/BUILD
@@ -0,0 +1,42 @@
+load('/tools/build_rules/ruby', 'ruby_library', 'ruby_binary')
+
+ruby_library(
+  name = 'lib',
+  srcs = [
+    'load.rb',
+    'write_iff_changed.rb',
+  ] + glob(['*/*.rb']),
+)
+
+ruby_binary(
+  name = 'compiler',
+  visibility = ['//visibility:public'],
+  srcs = [
+    'compiler.rb',
+  ],
+  deps = [
+    ':lib',
+  ],
+)
+
+ruby_binary(
+  name = 'queue_primitives',
+  visibility = ['//visibility:public'],
+  srcs = [
+    'queue_primitives.rb',
+  ],
+  deps = [
+    ':lib',
+  ],
+)
+
+ruby_binary(
+  name = 'print_field',
+  visibility = ['//visibility:public'],
+  srcs = [
+    'print_field.rb',
+  ],
+  deps = [
+    ':lib',
+  ],
+)
diff --git a/aos/build/queues/compiler.rb b/aos/build/queues/compiler.rb
index 52c0005..1f739e0 100644
--- a/aos/build/queues/compiler.rb
+++ b/aos/build/queues/compiler.rb
@@ -1,62 +1,79 @@
-require File.dirname(__FILE__) + '/load.rb'
+require_relative "load.rb"
 
 def parse_args(globals,args)
-	i = 0
-	while(i < args.length)
-		if(args[i] == "-I")
-			args.delete_at(i)
-			if(!args[i])
-				$stderr.puts "hey! -I is followed by nothing."
-				$stderr.puts "\tnot a supported usage..."
-				$stderr.puts "\tWot. Wot."
-				exit!(-1)
-			end
-			path = args.delete_at(i)
-			globals.add_path(path)
-		elsif(args[i] == "-cpp_out")
-			args.delete_at(i)
-			path = args.delete_at(i)
-			if(path =~ /\./)
-				$stderr.puts "hey! path #{path} has a \".\" char which is "
-				$stderr.puts "\tnot a supported usage..."
-				$stderr.puts "\tWot. Wot."
-				exit!(-1)
-			elsif(!path)
-				$stderr.puts "hey! No cpp_out path provided."
-				$stderr.puts "\tumm, you could try -cpp_out \"\""
-				$stderr.puts "\tThat might do the trick"
-				$stderr.puts "\tWot. Wot."
-				exit!(-1)
-			end
-			$cpp_out = path.split(/\\|\//)
-		elsif(args[i] == "-cpp_base")
-			args.delete_at(i)
-			path = args.delete_at(i)
-			$cpp_base = File.expand_path(path)
-			if(!File.exists?($cpp_base))
-				$stderr.puts "output directory #{$cpp_base.inspect} does not exist."
-				$stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
-				$stderr.puts "\tWot. Wot."
-				exit!(-1)
-			end
-		elsif(args[i] =~ /^-/)
-			$stderr.puts "hey! unknown argument #{args[i]}."
-			$stderr.puts "\tWot. Wot."
-			exit!(-1)
-		else
-			i += 1
-		end
-	end
-	if(!$cpp_base)
-		$stderr.puts "hey! missing -cpp_base argument."
-		$stderr.puts "\tWot. Wot."
-		exit!(-1)
-	end
-	if(!$cpp_out)
-		$stderr.puts "hey! missing -cpp_out argument."
-		$stderr.puts "\tWot. Wot."
-		exit!(-1)
-	end
+  i = 0
+  while(i < args.length)
+    if(args[i] == "-I")
+      args.delete_at(i)
+      if(!args[i])
+        $stderr.puts "hey! -I is followed by nothing."
+        $stderr.puts "\tnot a supported usage..."
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      end
+      path = args.delete_at(i)
+      globals.add_path(path)
+    elsif(args[i] == "-cpp_out")
+      args.delete_at(i)
+      path = args.delete_at(i)
+      if(path =~ /\./)
+        $stderr.puts "hey! path #{path} has a \".\" char which is "
+        $stderr.puts "\tnot a supported usage..."
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      elsif(!path)
+        $stderr.puts "hey! No cpp_out path provided."
+        $stderr.puts "\tumm, you could try -cpp_out \"\""
+        $stderr.puts "\tThat might do the trick"
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      end
+      $cpp_out = path.split(/\\|\//)
+    elsif(args[i] == "-cpp_base")
+      args.delete_at(i)
+      path = args.delete_at(i)
+      $cpp_base = File.expand_path(path)
+      if(!File.exists?($cpp_base))
+        $stderr.puts "output directory #{$cpp_base.inspect} does not exist."
+        $stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      end
+    elsif(args[i] == "-src_filename")
+      args.delete_at(i)
+      $src_filename = args.delete_at(i)
+    elsif(args[i] == "-h_file_path")
+      args.delete_at(i)
+      path = args.delete_at(i)
+      $h_file_path = File.expand_path(path)
+      if(!File.exists?(File.dirname($h_file_path)))
+        $stderr.puts "directory of output #{$h_file_path.inspect} does not exist."
+        $stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      end
+    elsif(args[i] == "-cc_file_path")
+      args.delete_at(i)
+      path = args.delete_at(i)
+      $cc_file_path = File.expand_path(path)
+      if(!File.exists?(File.dirname($cc_file_path)))
+        $stderr.puts "directory of output #{$cc_file_path.inspect} does not exist."
+        $stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
+        $stderr.puts "\tWot. Wot."
+        exit!(-1)
+      end
+    elsif(args[i] =~ /^-/)
+      $stderr.puts "hey! unknown argument #{args[i]}."
+      $stderr.puts "\tWot. Wot."
+      exit!(-1)
+    else
+      i += 1
+    end
+  end
+  if ($cpp_base && $cpp_out) == ($src_filename && $h_file_path && $cc_file_path)
+    $stderr.puts "hey! I'm not sure where to write the output files!"
+    exit!(-1)
+  end
 end
 def format_pipeline(output)
   read_in, write_in = IO.pipe()
@@ -67,39 +84,41 @@
   [child, write_in]
 end
 def build(filename,globals_template)
-	globals = Globals.new()
-	globals_template.paths.each do |path|
-		globals.add_path(path)
-	end
-	filename = File.expand_path(filename)
-	q_file = QFile.parse(filename)
-	output_file = q_file.q_eval(globals)
-	q_filename = File.basename(filename)
-	rel_path = ($cpp_out + [q_filename]).join("/")
+  globals = Globals.new()
+  globals_template.paths.each do |path|
+    globals.add_path(path)
+  end
+  filename = File.expand_path(filename)
+  q_file = QFile.parse(filename)
+  output_file = q_file.q_eval(globals)
+  q_filename = File.basename(filename)
 
-	FileUtils.mkdir_p(Pathname.new($cpp_base) + $cpp_out.join("/"))
+  if $cpp_base && $cpp_out
+    $src_filename = ($cpp_out + [q_filename]).join("/")
+    $h_file_path = $cpp_base + "/" + $src_filename + ".h"
+    $cc_file_path = $cpp_base + "/" + $src_filename + ".cc"
+    FileUtils.mkdir_p(Pathname.new($cpp_base) + $cpp_out.join("/"))
+  end
 
-	cpp_tree = output_file.make_cpp_tree(rel_path)
+  cpp_tree = output_file.make_cpp_tree($src_filename)
 
-	h_file_path = $cpp_base + "/" + rel_path + ".h"
-	cc_file_path = $cpp_base + "/" + rel_path + ".cc"
-	cpp_tree.add_cc_include((rel_path + ".h").inspect)
-	cpp_tree.add_cc_include("aos/common/byteorder.h".inspect)
-	cpp_tree.add_cc_include("<inttypes.h>")
-	cpp_tree.add_cc_include("aos/common/queue_types.h".inspect)
+  cpp_tree.add_cc_include(($src_filename + ".h").inspect)
+  cpp_tree.add_cc_include("aos/common/byteorder.h".inspect)
+  cpp_tree.add_cc_include("<inttypes.h>")
+  cpp_tree.add_cc_include("aos/common/queue_types.h".inspect)
   cpp_tree.add_cc_include("aos/common/once.h".inspect)
   cpp_tree.add_cc_include("aos/common/logging/logging_printf_formats.h".inspect)
-	cpp_tree.add_cc_using("::aos::to_network")
-	cpp_tree.add_cc_using("::aos::to_host")
+  cpp_tree.add_cc_using("::aos::to_network")
+  cpp_tree.add_cc_using("::aos::to_host")
 
-	header_file = WriteIffChanged.new(h_file_path)
-	cc_file = WriteIffChanged.new(cc_file_path)
+  header_file = WriteIffChanged.new($h_file_path)
+  cc_file = WriteIffChanged.new($cc_file_path)
   header_child, header_output = format_pipeline(header_file)
   cc_child, cc_output = format_pipeline(cc_file)
-	cpp_tree.write_header_file($cpp_base,header_output)
-	cpp_tree.write_cc_file($cpp_base,cc_output)
-	header_output.close()
-	cc_output.close()
+  cpp_tree.write_header_file($cpp_base,header_output)
+  cpp_tree.write_cc_file($cpp_base,cc_output)
+  header_output.close()
+  cc_output.close()
   if !Process.wait2(cc_child)[1].success?
     $stderr.puts "Formatting cc file failed."
     exit 1
@@ -112,20 +131,20 @@
   cc_file.close()
 end
 begin
-	args = ARGV.dup
-	globals = Globals.new()
-	parse_args(globals,args)
-	if(args.length == 0)
-		$stderr.puts "hey! you want me to do something,"
-		$stderr.puts "\tbut you gave me no q files to build!"
-		$stderr.puts "\tWot. Wot."
-		exit!(-1)
-	end
-	args.each do |filename|
-		build(filename,globals)
-	end
-	exit(0)
+  args = ARGV.dup
+  globals = Globals.new()
+  parse_args(globals,args)
+  if(args.length == 0)
+    $stderr.puts "hey! you want me to do something,"
+    $stderr.puts "\tbut you gave me no q files to build!"
+    $stderr.puts "\tWot. Wot."
+    exit!(-1)
+  end
+  args.each do |filename|
+    build(filename,globals)
+  end
+  exit(0)
 rescue QError => e
-	$stderr.print(e.to_s)
-	exit!(-1)
+  $stderr.print(e.to_s)
+  exit!(-1)
 end
diff --git a/aos/build/queues/load.rb b/aos/build/queues/load.rb
index 59a4590..50d59f8 100644
--- a/aos/build/queues/load.rb
+++ b/aos/build/queues/load.rb
@@ -1,15 +1,17 @@
 $LOAD_PATH.unshift(".")
+
 ["tokenizer.rb","q_file.rb","queue_group.rb","queue.rb","namespaces.rb",
-"interface.rb","errors.rb", "q_struct.rb"].each do |name|
-	require File.dirname(__FILE__) + "/objects/" + name
+ "interface.rb","errors.rb", "q_struct.rb"].each do |name|
+  require_relative "objects/" + name
 end
 ["standard_types.rb","auto_gen.rb","file_pair_types.rb",
-"dep_file_pair.rb"].each do |name|
-	require File.dirname(__FILE__) + "/cpp_pretty_print/" + name
+  "dep_file_pair.rb"].each do |name|
+	require_relative "cpp_pretty_print/" + name
 end
 ["q_file.rb","message_dec.rb","queue_dec.rb", "q_struct.rb"].each do |name|
-	require File.dirname(__FILE__) + "/output/" + name
+	require_relative "output/" + name
 end
-require File.dirname(__FILE__) + '/write_iff_changed.rb'
+require_relative "write_iff_changed.rb"
+
 require "fileutils"
 require "pathname"
diff --git a/aos/build/queues/print_field.rb b/aos/build/queues/print_field.rb
index 75cc1da..4f0fe7d 100644
--- a/aos/build/queues/print_field.rb
+++ b/aos/build/queues/print_field.rb
@@ -1,4 +1,4 @@
-require File.dirname(__FILE__) + '/load.rb'
+require_relative 'load.rb'
 
 # TODO(brians): Special-case Time too and float/double if we can find a good way to do it.
 GenericTypeNames = ['float', 'double', 'char', '::aos::time::Time']
diff --git a/aos/build/queues/queue_primitives.rb b/aos/build/queues/queue_primitives.rb
index 421c3b4..801e606 100644
--- a/aos/build/queues/queue_primitives.rb
+++ b/aos/build/queues/queue_primitives.rb
@@ -1,4 +1,4 @@
-require File.dirname(__FILE__) + '/load.rb'
+require_relative 'load.rb'
 
 require 'fileutils'
 
diff --git a/aos/common/BUILD b/aos/common/BUILD
index 55f1a03..919c2a0 100644
--- a/aos/common/BUILD
+++ b/aos/common/BUILD
@@ -117,15 +117,12 @@
 
 cc_library(
   name = 'gtest_prod',
-  deps = [
-    '//third_party/gtest_prod',
-  ],
 )
 
 cc_library(
   name = 'once',
   deps = [
-    '//third_party/gtest_prod',
+    ':gtest_prod',
   ],
 )
 
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index 17df955..54617db 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -167,21 +167,15 @@
     {
       'target_name': 'gtest_prod',
       'type': 'static_library',
-      'dependencies': [
-        '<(EXTERNALS):gtest_prod',
-      ],
-      'export_dependent_settings': [
-        '<(EXTERNALS):gtest_prod',
-      ],
     },
     {
       'target_name': 'once',
       'type': 'static_library',
       'dependencies': [
-        '<(EXTERNALS):gtest_prod',
+        ':gtest_prod',
       ],
       'export_dependent_settings': [
-        '<(EXTERNALS):gtest_prod',
+        ':gtest_prod',
       ],
     },
     {
diff --git a/aos/common/gtest_prod.h b/aos/common/gtest_prod.h
index fe0b056..6c7d96e 100644
--- a/aos/common/gtest_prod.h
+++ b/aos/common/gtest_prod.h
@@ -1,8 +1,6 @@
 #ifndef AOS_COMMON_GTEST_PROD_H_
 #define AOS_COMMON_GTEST_PROD_H_
 
-#include "gtest/gtest_prod.h"
-
 // These macros replace gtest's FRIEND_TEST if the test is in a different
 // namespace than the code that needs to make it a friend.
 // Example:
@@ -34,4 +32,8 @@
 #define FRIEND_TEST_NAMESPACE(test_case_name, test_name, namespace_name) \
     friend class namespace_name::test_case_name##_##test_name##_Test
 
+// Copied from googletest's gtest_prod.h. See that file for documentation.
+#define FRIEND_TEST(test_case_name, test_name) \
+  friend class test_case_name##_##test_name##_Test
+
 #endif  // AOS_COMMON_GTEST_PROD_H_
diff --git a/build_tests/BUILD b/build_tests/BUILD
index e11937b..75198fd 100644
--- a/build_tests/BUILD
+++ b/build_tests/BUILD
@@ -1,3 +1,5 @@
+load('/tools/build_rules/ruby', 'ruby_binary')
+
 cc_test(
   name = 'gflags_build_test',
   srcs = [
@@ -8,3 +10,25 @@
   ],
   size = 'small',
 )
+
+ruby_binary(
+  name = 'ruby_binary',
+  srcs = [
+    'ruby.rb',
+    'ruby_to_require.rb',
+  ],
+  data = [
+    'ruby_to_require.rb',
+  ],
+)
+
+sh_test(
+  name = 'ruby_build_test',
+  srcs = [
+    'ruby_check.sh',
+  ],
+  data = [
+    ':ruby_binary',
+  ],
+  size = 'small',
+)
diff --git a/build_tests/ruby.rb b/build_tests/ruby.rb
new file mode 100644
index 0000000..12af7fe
--- /dev/null
+++ b/build_tests/ruby.rb
@@ -0,0 +1,18 @@
+# ruby_check.sh runs this and verifies the output matches.
+# The first argument is the absolute path to the runfiles directory to use for
+# testing require with an absolute path.
+
+$loaded = false
+raise unless require_relative 'ruby_to_require.rb'
+raise unless $loaded
+
+# We already loaded this above, so it won't happen again.
+raise if require 'build_tests/ruby_to_require'
+
+$loaded = false
+raise unless require ARGV[0] + '/build_tests/ruby_to_require'
+raise unless $loaded
+
+raise unless ''.encoding == Encoding::UTF_8
+
+puts 'Hi from ruby'
diff --git a/build_tests/ruby_check.sh b/build_tests/ruby_check.sh
new file mode 100755
index 0000000..70d3149
--- /dev/null
+++ b/build_tests/ruby_check.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Checks the output from ruby.rb.
+
+set -e
+set -u
+
+OUTPUT="$("./build_tests/ruby_binary" "${PWD}")"
+
+if [[ "${OUTPUT}" != "Hi from ruby" ]]; then
+  echo "Output is actually:" >&2
+  echo "${OUTPUT}" >&2
+  exit 1
+fi
diff --git a/build_tests/ruby_to_require.rb b/build_tests/ruby_to_require.rb
new file mode 100644
index 0000000..b63cda2
--- /dev/null
+++ b/build_tests/ruby_to_require.rb
@@ -0,0 +1,4 @@
+# This file is loaded by ruby.rb through several mechanisms to make sure they
+# all work.
+
+$loaded = true
diff --git a/doc/run_gyp_to_bazel.sh b/doc/run_gyp_to_bazel.sh
index 759caeb..b4688f1 100755
--- a/doc/run_gyp_to_bazel.sh
+++ b/doc/run_gyp_to_bazel.sh
@@ -15,6 +15,12 @@
     echo Need to manually convert {} >&2' \;
 }
 
+run_for_folder bot3
+
+# Manual work on the other folders has started, so we don't want this script to
+# automatically overwrite that work.
+exit 0
+
 run_for_folder aos
 run_for_folder frc971
 run_for_folder y2014
diff --git a/tools/build_rules/ruby.bzl b/tools/build_rules/ruby.bzl
new file mode 100644
index 0000000..7c02745
--- /dev/null
+++ b/tools/build_rules/ruby.bzl
@@ -0,0 +1,93 @@
+ZIP_PATH = '/usr/bin/zip'
+
+ruby_file_types = FileType(['.rb'])
+
+def _collect_transitive_sources(ctx):
+  source_files = set(order='compile')
+  for dep in ctx.attr.deps:
+    source_files += dep.transitive_ruby_files
+
+  source_files += ruby_file_types.filter(ctx.files.srcs)
+  return source_files
+
+def _ruby_library_impl(ctx):
+  transitive_sources = _collect_transitive_sources(ctx)
+  return struct(
+    transitive_ruby_files = transitive_sources,
+  )
+
+def _ruby_binary_impl(ctx):
+  main_file = ctx.files.srcs[0]
+  transitive_sources = _collect_transitive_sources(ctx)
+  executable = ctx.outputs.executable
+  manifest_file = ctx.outputs.manifest
+
+  path_map = '\n'.join([('%s|%s' % (item.short_path, item.path))
+                        for item in transitive_sources])
+  ctx.file_action(output=manifest_file, content=path_map)
+
+  ctx.action(
+    inputs = list(transitive_sources) + [manifest_file],
+    outputs = [ executable ],
+    arguments = [ manifest_file.path, executable.path, main_file.path ],
+    executable = ctx.executable._ruby_linker,
+  )
+
+  return struct(
+    files = set([executable]),
+    runfiles = ctx.runfiles(collect_data = True),
+  )
+
+
+_ruby_attrs = {
+  'srcs': attr.label_list(
+    allow_files = ruby_file_types,
+    mandatory = True,
+    non_empty = True,
+  ),
+  'deps': attr.label_list(
+    providers = ['transitive_ruby_files'],
+    allow_files = False,
+  ),
+  'data': attr.label_list(
+    allow_files = True,
+    cfg = DATA_CFG,
+  ),
+}
+
+'''Packages ruby code into a library.
+
+The files can use require with paths from the base of the workspace and/or
+require_relative with other files that are part of the library.
+require also works from the filesystem as usual.
+
+Attrs:
+  srcs: Ruby source files to include.
+  deps: Other ruby_library rules to include.
+'''
+ruby_library = rule(
+  implementation = _ruby_library_impl,
+  attrs = _ruby_attrs,
+)
+
+'''Packages ruby code into a binary which can be run.
+
+See ruby_library for details on how require works.
+
+Attrs:
+  srcs: Ruby source files to include. The first one is loaded to at startup.
+  deps: ruby_library rules to include.
+'''
+ruby_binary = rule(
+  implementation = _ruby_binary_impl,
+  executable = True,
+  attrs = _ruby_attrs + {
+    '_ruby_linker': attr.label(
+      executable = True,
+      default = Label('//tools/ruby:standalone_ruby'),
+    )
+  },
+  outputs = {
+    'manifest': '%{name}.tar_manifest',
+  },
+)
diff --git a/tools/ruby/BUILD b/tools/ruby/BUILD
new file mode 100644
index 0000000..426a9f1
--- /dev/null
+++ b/tools/ruby/BUILD
@@ -0,0 +1,5 @@
+py_binary(
+  name = 'standalone_ruby',
+  srcs = ['standalone_ruby.py'],
+  visibility = ['//visibility:public'],
+)
diff --git a/tools/ruby/standalone_ruby.py b/tools/ruby/standalone_ruby.py
new file mode 100644
index 0000000..0c574e0
--- /dev/null
+++ b/tools/ruby/standalone_ruby.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+
+import zlib, sys, os, stat
+
+with file(sys.argv[2], "wb+") as outf:
+  outf.write("""#!/usr/bin/env ruby
+require "zlib"
+
+def zip_file_binding()
+  binding()
+end
+
+module Kernel
+  class ZipRequireRecord
+    attr_accessor :fname, :val
+    def initialize(fname, val)
+      @fname = fname
+      @val = val
+    end
+    def do_require()
+      return false if !@val
+      eval(@val, binding = zip_file_binding(), filename="//@bazel/" + @fname)
+      @val = nil
+      return true
+    end
+  end
+  BAZEL_START_ENTRY = "/@bazel/"
+  ZIP_TEMP_OBJS = {}
+  def require_relative(relative_feature)
+    file = caller.first.split(/:\d/,2).first
+    raise LoadError, "require_relative is called in #{$1}" if /\A\((.*)\)/ =~ file
+    require File.expand_path(relative_feature, File.dirname(file))
+  end
+  def require_zip(moduleName)
+    if moduleName.start_with?(BAZEL_START_ENTRY)
+      moduleName = moduleName[BAZEL_START_ENTRY.length..-1]
+    end
+    zip_obj = ZIP_TEMP_OBJS[moduleName]
+    if not zip_obj and !moduleName.end_with?('.rb')
+      zip_obj = ZIP_TEMP_OBJS[moduleName + '.rb']
+    end
+    return zip_obj.do_require() if (zip_obj)
+    return pre_zip_load_require(moduleName)
+  end
+  alias :pre_zip_load_require :require
+  alias :require :require_zip
+  def init_app(main_fname)
+    $0 = "//@bazel/" + main_fname
+    Kernel.require_zip(main_fname)
+  end
+  def register_inline_file(fname, data)
+    raise if ZIP_TEMP_OBJS.has_key?(fname)
+    ZIP_TEMP_OBJS[fname] = Kernel::ZipRequireRecord.new(fname, data.force_encoding("UTF-8"))
+  end
+end
+
+my_data = Zlib.inflate(DATA.read())
+""")
+
+  blob_data = []
+  offset = 0
+  with file(sys.argv[1], 'r') as infile:
+    for line in infile.xreadlines():
+      file_outname, file_binname = line.strip().split('|')
+      with file(file_binname, 'r') as obj_file:
+        obj = obj_file.read()
+      blob_data.append(obj)
+      new_off = offset + len(obj)
+      outf.write("Kernel.register_inline_file(%s, my_data.slice(%s...%s))\n" %
+                 (repr(file_outname), offset, new_off))
+      offset = new_off
+
+  outf.write("Kernel.init_app(%s)\n" % repr(sys.argv[3]))
+  outf.write("__END__\n")
+  outf.write(zlib.compress("".join(blob_data)))