stopped rebuilding everything when generated code doesn't change
diff --git a/aos/build/queues.gypi b/aos/build/queues.gypi
index 07f1ed7..7c0343a 100644
--- a/aos/build/queues.gypi
+++ b/aos/build/queues.gypi
@@ -56,7 +56,7 @@
         '<(header_path)',
         '-cpp_base',
         '<(prefix_dir)/<(_target_name)'],
-      'message': 'Generating C++ code from <(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).q',
+      'message': 'Generating C++ code for <(header_path)/<(RULE_INPUT_PATH)',
       'process_outputs_as_sources': 1,
     },
   ],
diff --git a/aos/build/queues/compiler.rb b/aos/build/queues/compiler.rb
index 899ba85..e4312fd 100644
--- a/aos/build/queues/compiler.rb
+++ b/aos/build/queues/compiler.rb
@@ -62,7 +62,7 @@
   read_in, write_in = IO.pipe()
   child = Process.spawn('clang-format-3.4 --style=google',
                         {:in=>read_in, write_in=>:close,
-                         :out=>output})
+                         :out=>output.fileno})
   read_in.close
   [child, write_in]
 end
@@ -91,14 +91,14 @@
 	cpp_tree.add_cc_using("::aos::to_network")
 	cpp_tree.add_cc_using("::aos::to_host")
 
-	header_file = File.open(h_file_path,"w+")
-	cc_file = File.open(cc_file_path,"w+")
+	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)
-	cc_output.close()
 	header_output.close()
+	cc_output.close()
   if !Process.wait2(cc_child)[1].success?
     $stderr.puts "Formatting cc file failed."
     exit 1
@@ -107,6 +107,8 @@
     $stderr.puts "Formatting header file failed."
     exit 1
   end
+  header_file.close()
+  cc_file.close()
 end
 begin
 	args = ARGV.dup
diff --git a/aos/build/queues/load.rb b/aos/build/queues/load.rb
index c299d80..59a4590 100644
--- a/aos/build/queues/load.rb
+++ b/aos/build/queues/load.rb
@@ -10,5 +10,6 @@
 ["q_file.rb","message_dec.rb","queue_dec.rb", "q_struct.rb"].each do |name|
 	require File.dirname(__FILE__) + "/output/" + name
 end
+require File.dirname(__FILE__) + '/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 7a9fbb4..a86140f 100644
--- a/aos/build/queues/print_field.rb
+++ b/aos/build/queues/print_field.rb
@@ -4,7 +4,7 @@
   ["uint#{size}_t", "int#{size}_t"]
 end.flatten + ['bool', 'float', 'char', 'double']
 
-File.open(ARGV[0], 'w') do |output|
+WriteIffChanged.open(ARGV[0]) do |output|
   output.puts <<END
 // This file is generated by #{File.expand_path(__FILE__)}.
 // DO NOT EDIT BY HAND!
diff --git a/aos/build/queues/write_iff_changed.rb b/aos/build/queues/write_iff_changed.rb
new file mode 100644
index 0000000..74373a9
--- /dev/null
+++ b/aos/build/queues/write_iff_changed.rb
@@ -0,0 +1,30 @@
+require 'tempfile'
+
+# Writes a file like normal except doesn't do anything if the new contents are
+# the same as what's already there. Useful for helping build tools not rebuild
+# if generated files are re-generated but don't change.
+# Usable as a standard File, including to redirect to with IO.popen etc.
+class WriteIffChanged < Tempfile
+  def initialize(filename)
+    super('write_iff_changed')
+    @filename = filename
+  end
+  def WriteIffChanged.open(filename)
+    out = WriteIffChanged.new(filename)
+    yield out
+    out.close
+  end
+  def close
+    flush
+    contents = File.open(path, 'r') do |f|
+      f.readlines(nil)
+    end
+    if !File.exists?(@filename) ||
+        File.new(@filename, 'r').readlines(nil) != contents
+      File.open(@filename, 'w') do |out|
+        out.write(contents[0])
+      end
+    end
+    super
+  end
+end