Add Bazel support for queue files.

Change-Id: I69921edb654765364bc1333b16fd4583446fd88c
diff --git a/aos/build/queues.bzl b/aos/build/queues.bzl
new file mode 100644
index 0000000..7c67a6b
--- /dev/null
+++ b/aos/build/queues.bzl
@@ -0,0 +1,107 @@
+def _single_queue_file_impl(ctx):
+  args = [
+    '-h_file_path', ctx.outputs.header.path,
+    '-cc_file_path', ctx.outputs.cc.path,
+    '-src_filename', ctx.file.src.short_path,
+    '-I', '.',
+    ctx.file.src.path,
+  ]
+  ctx.action(
+    outputs = [
+      ctx.outputs.header,
+      ctx.outputs.cc,
+    ],
+    inputs = [ ctx.file.src ] + ctx.attr.q_deps.transitive_q_files,
+    executable = ctx.executable._queue_compiler,
+    arguments = args,
+    mnemonic = 'QGen',
+    progress_message = 'Generating C++ code for %s' % ctx.file.src.short_path,
+  )
+
+def _single_queue_file_outputs(attrs):
+  return {
+    'header': attrs.src.name + '.h',
+    'cc': attrs.src.name + '.cc',
+  }
+
+_single_queue_file = rule(
+  implementation = _single_queue_file_impl,
+  attrs = {
+    'src': attr.label(
+      mandatory = True,
+      single_file = True,
+      allow_files = FileType(['.q']),
+    ),
+    'q_deps': attr.label(
+      providers = ['transitive_q_files'],
+      mandatory = True,
+    ),
+    'package_name': attr.string(
+      mandatory = True,
+    ),
+    '_queue_compiler': attr.label(
+      executable = True,
+      default = Label('//aos/build/queues:compiler'),
+    ),
+  },
+  outputs = _single_queue_file_outputs,
+  output_to_genfiles = True,
+)
+
+def _q_deps_impl(ctx):
+  transitive_q_files = ctx.files.srcs
+  for dep in ctx.attr.deps:
+    transitive_q_files += dep.transitive_q_files
+  return struct(transitive_q_files = transitive_q_files)
+
+_q_deps = rule(
+  implementation = _q_deps_impl,
+  attrs = {
+    'srcs': attr.label_list(
+      mandatory = True,
+      non_empty = True,
+      allow_files = FileType(['.q']),
+    ),
+    'deps': attr.label_list(
+      mandatory = True,
+      non_empty = False,
+      providers = ['transitive_q_files'],
+    ),
+  },
+)
+
+'''Creates a C++ library from a set of .q files.
+
+Attrs:
+  srcs: A list of .q files.
+  deps: Other queue_library rules this one depends on.
+'''
+def queue_library(name, srcs, deps = [],
+                  visibility = None):
+  q_deps = _q_deps(
+    name = name + '__q_deps',
+    srcs = srcs,
+    deps = [dep + '__q_deps' for dep in deps],
+    visibility = visibility,
+  )
+
+  for src in srcs:
+    _single_queue_file(
+      name = name + '_' + src,
+      src = src,
+      q_deps = ':%s__q_deps' % name,
+      package_name = PACKAGE_NAME,
+      visibility = ['//visibility:private'],
+    )
+
+  native.cc_library(
+    name = name,
+    srcs = [src + '.cc' for src in srcs],
+    hdrs = [src + '.h' for src in srcs],
+    deps = deps + [
+      '//aos/common:once',
+      '//aos/common:queues',
+      '//aos/common:queue_types',
+    ],
+    visibility = visibility,
+  )
diff --git a/build_tests/BUILD b/build_tests/BUILD
index 75198fd..cae87f0 100644
--- a/build_tests/BUILD
+++ b/build_tests/BUILD
@@ -1,4 +1,5 @@
 load('/tools/build_rules/ruby', 'ruby_binary')
+load('/aos/build/queues', 'queue_library')
 
 cc_test(
   name = 'gflags_build_test',
@@ -32,3 +33,21 @@
   ],
   size = 'small',
 )
+
+queue_library(
+  name = 'queue_library',
+  srcs = [
+    'queue.q',
+  ],
+)
+
+cc_test(
+  name = 'queue_build_test',
+  srcs = [
+    'queue.cc',
+  ],
+  deps = [
+    ':queue_library',
+  ],
+  size = 'small',
+)
diff --git a/build_tests/queue.cc b/build_tests/queue.cc
new file mode 100644
index 0000000..3be667e
--- /dev/null
+++ b/build_tests/queue.cc
@@ -0,0 +1,7 @@
+#include "build_tests/queue.q.h"
+
+int main() {
+  ::build_tests::TestStruct s;
+  s.field = 971;
+  return (s.field == 971) ? 0 : 1;
+}
diff --git a/build_tests/queue.q b/build_tests/queue.q
new file mode 100644
index 0000000..df1b7db
--- /dev/null
+++ b/build_tests/queue.q
@@ -0,0 +1,5 @@
+package build_tests;
+
+struct TestStruct {
+  int32_t field;
+};