Add support for generating a compile_commands.json file for clang-tidy

Change-Id: I3db1a69030f6ba6617ccaf3a1ebc319111145fe1
diff --git a/.gitignore b/.gitignore
index 294a40a..569a6df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 *.pyc
 /bazel-*
+/compile_commands.json
diff --git a/third_party/bazel/BUILD b/third_party/bazel/BUILD
new file mode 100644
index 0000000..4b56a08
--- /dev/null
+++ b/third_party/bazel/BUILD
@@ -0,0 +1,11 @@
+licenses(['notice'])
+
+# Generated from Bazel's
+# 30df02a567cbd8a307b96037f0960fca66a5deaf://src/main/protobuf/extra_actions_base.proto.
+py_library(
+  name = 'extra_actions_proto_py',
+  visibility = ['//visibility:public'],
+  srcs = [
+    'protos/extra_actions_base_pb2.py',
+  ],
+)
diff --git a/third_party/bazel/protos/extra_actions_base_pb2.py b/third_party/bazel/protos/extra_actions_base_pb2.py
new file mode 100644
index 0000000..bbd4ea4
--- /dev/null
+++ b/third_party/bazel/protos/extra_actions_base_pb2.py
@@ -0,0 +1,596 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: extra_actions_base.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf import descriptor_pb2
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='extra_actions_base.proto',
+  package='blaze',
+  serialized_pb=_b('\n\x18\x65xtra_actions_base.proto\x12\x05\x62laze\"D\n\x12\x45xtraActionSummary\x12.\n\x06\x61\x63tion\x18\x01 \x03(\x0b\x32\x1e.blaze.DetailedExtraActionInfo\"Z\n\x17\x44\x65tailedExtraActionInfo\x12\x17\n\x0ftriggering_file\x18\x01 \x01(\t\x12&\n\x06\x61\x63tion\x18\x02 \x02(\x0b\x32\x16.blaze.ExtraActionInfo\"I\n\x0f\x45xtraActionInfo\x12\r\n\x05owner\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x10\n\x08mnemonic\x18\x05 \x01(\t*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"2\n\x13\x45nvironmentVariable\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x02(\t\"\xb3\x01\n\tSpawnInfo\x12\x10\n\x08\x61rgument\x18\x01 \x03(\t\x12,\n\x08variable\x18\x02 \x03(\x0b\x32\x1a.blaze.EnvironmentVariable\x12\x12\n\ninput_file\x18\x04 \x03(\t\x12\x13\n\x0boutput_file\x18\x05 \x03(\t2=\n\nspawn_info\x12\x16.blaze.ExtraActionInfo\x18\xeb\x07 \x01(\x0b\x32\x10.blaze.SpawnInfo\"\xc8\x01\n\x0e\x43ppCompileInfo\x12\x0c\n\x04tool\x18\x01 \x01(\t\x12\x17\n\x0f\x63ompiler_option\x18\x02 \x03(\t\x12\x13\n\x0bsource_file\x18\x03 \x01(\t\x12\x13\n\x0boutput_file\x18\x04 \x01(\t\x12\x1b\n\x13sources_and_headers\x18\x05 \x03(\t2H\n\x10\x63pp_compile_info\x12\x16.blaze.ExtraActionInfo\x18\xe9\x07 \x01(\x0b\x32\x15.blaze.CppCompileInfo\"\x96\x02\n\x0b\x43ppLinkInfo\x12\x12\n\ninput_file\x18\x01 \x03(\t\x12\x13\n\x0boutput_file\x18\x02 \x01(\t\x12\x1d\n\x15interface_output_file\x18\x03 \x01(\t\x12\x18\n\x10link_target_type\x18\x04 \x01(\t\x12\x17\n\x0flink_staticness\x18\x05 \x01(\t\x12\x12\n\nlink_stamp\x18\x06 \x03(\t\x12\"\n\x1a\x62uild_info_header_artifact\x18\x07 \x03(\t\x12\x10\n\x08link_opt\x18\x08 \x03(\t2B\n\rcpp_link_info\x12\x16.blaze.ExtraActionInfo\x18\xea\x07 \x01(\x0b\x32\x12.blaze.CppLinkInfo\"\xe9\x01\n\x0fJavaCompileInfo\x12\x11\n\toutputjar\x18\x01 \x01(\t\x12\x11\n\tclasspath\x18\x02 \x03(\t\x12\x12\n\nsourcepath\x18\x03 \x03(\t\x12\x13\n\x0bsource_file\x18\x04 \x03(\t\x12\x11\n\tjavac_opt\x18\x05 \x03(\t\x12\x11\n\tprocessor\x18\x06 \x03(\t\x12\x15\n\rprocessorpath\x18\x07 \x03(\t2J\n\x11java_compile_info\x12\x16.blaze.ExtraActionInfo\x18\xe8\x07 \x01(\x0b\x32\x16.blaze.JavaCompileInfo\"t\n\nPythonInfo\x12\x13\n\x0bsource_file\x18\x01 \x03(\t\x12\x10\n\x08\x64\x65p_file\x18\x02 \x03(\t2?\n\x0bpython_info\x12\x16.blaze.ExtraActionInfo\x18\xed\x07 \x01(\x0b\x32\x11.blaze.PythonInfoB/\n+com.google.devtools.build.lib.actions.extraP\x01')
+)
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+
+
+
+_EXTRAACTIONSUMMARY = _descriptor.Descriptor(
+  name='ExtraActionSummary',
+  full_name='blaze.ExtraActionSummary',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='action', full_name='blaze.ExtraActionSummary.action', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=35,
+  serialized_end=103,
+)
+
+
+_DETAILEDEXTRAACTIONINFO = _descriptor.Descriptor(
+  name='DetailedExtraActionInfo',
+  full_name='blaze.DetailedExtraActionInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='triggering_file', full_name='blaze.DetailedExtraActionInfo.triggering_file', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='action', full_name='blaze.DetailedExtraActionInfo.action', index=1,
+      number=2, type=11, cpp_type=10, label=2,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=105,
+  serialized_end=195,
+)
+
+
+_EXTRAACTIONINFO = _descriptor.Descriptor(
+  name='ExtraActionInfo',
+  full_name='blaze.ExtraActionInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='owner', full_name='blaze.ExtraActionInfo.owner', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='id', full_name='blaze.ExtraActionInfo.id', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='mnemonic', full_name='blaze.ExtraActionInfo.mnemonic', index=2,
+      number=5, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=197,
+  serialized_end=270,
+)
+
+
+_ENVIRONMENTVARIABLE = _descriptor.Descriptor(
+  name='EnvironmentVariable',
+  full_name='blaze.EnvironmentVariable',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='blaze.EnvironmentVariable.name', index=0,
+      number=1, type=9, cpp_type=9, label=2,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='value', full_name='blaze.EnvironmentVariable.value', index=1,
+      number=2, type=9, cpp_type=9, label=2,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=272,
+  serialized_end=322,
+)
+
+
+_SPAWNINFO = _descriptor.Descriptor(
+  name='SpawnInfo',
+  full_name='blaze.SpawnInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='argument', full_name='blaze.SpawnInfo.argument', index=0,
+      number=1, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='variable', full_name='blaze.SpawnInfo.variable', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='input_file', full_name='blaze.SpawnInfo.input_file', index=2,
+      number=4, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='output_file', full_name='blaze.SpawnInfo.output_file', index=3,
+      number=5, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+    _descriptor.FieldDescriptor(
+      name='spawn_info', full_name='blaze.SpawnInfo.spawn_info', index=0,
+      number=1003, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=True, extension_scope=None,
+      options=None),
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=325,
+  serialized_end=504,
+)
+
+
+_CPPCOMPILEINFO = _descriptor.Descriptor(
+  name='CppCompileInfo',
+  full_name='blaze.CppCompileInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='tool', full_name='blaze.CppCompileInfo.tool', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='compiler_option', full_name='blaze.CppCompileInfo.compiler_option', index=1,
+      number=2, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='source_file', full_name='blaze.CppCompileInfo.source_file', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='output_file', full_name='blaze.CppCompileInfo.output_file', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='sources_and_headers', full_name='blaze.CppCompileInfo.sources_and_headers', index=4,
+      number=5, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+    _descriptor.FieldDescriptor(
+      name='cpp_compile_info', full_name='blaze.CppCompileInfo.cpp_compile_info', index=0,
+      number=1001, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=True, extension_scope=None,
+      options=None),
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=507,
+  serialized_end=707,
+)
+
+
+_CPPLINKINFO = _descriptor.Descriptor(
+  name='CppLinkInfo',
+  full_name='blaze.CppLinkInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='input_file', full_name='blaze.CppLinkInfo.input_file', index=0,
+      number=1, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='output_file', full_name='blaze.CppLinkInfo.output_file', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='interface_output_file', full_name='blaze.CppLinkInfo.interface_output_file', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='link_target_type', full_name='blaze.CppLinkInfo.link_target_type', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='link_staticness', full_name='blaze.CppLinkInfo.link_staticness', index=4,
+      number=5, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='link_stamp', full_name='blaze.CppLinkInfo.link_stamp', index=5,
+      number=6, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='build_info_header_artifact', full_name='blaze.CppLinkInfo.build_info_header_artifact', index=6,
+      number=7, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='link_opt', full_name='blaze.CppLinkInfo.link_opt', index=7,
+      number=8, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+    _descriptor.FieldDescriptor(
+      name='cpp_link_info', full_name='blaze.CppLinkInfo.cpp_link_info', index=0,
+      number=1002, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=True, extension_scope=None,
+      options=None),
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=710,
+  serialized_end=988,
+)
+
+
+_JAVACOMPILEINFO = _descriptor.Descriptor(
+  name='JavaCompileInfo',
+  full_name='blaze.JavaCompileInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='outputjar', full_name='blaze.JavaCompileInfo.outputjar', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='classpath', full_name='blaze.JavaCompileInfo.classpath', index=1,
+      number=2, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='sourcepath', full_name='blaze.JavaCompileInfo.sourcepath', index=2,
+      number=3, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='source_file', full_name='blaze.JavaCompileInfo.source_file', index=3,
+      number=4, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='javac_opt', full_name='blaze.JavaCompileInfo.javac_opt', index=4,
+      number=5, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='processor', full_name='blaze.JavaCompileInfo.processor', index=5,
+      number=6, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='processorpath', full_name='blaze.JavaCompileInfo.processorpath', index=6,
+      number=7, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+    _descriptor.FieldDescriptor(
+      name='java_compile_info', full_name='blaze.JavaCompileInfo.java_compile_info', index=0,
+      number=1000, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=True, extension_scope=None,
+      options=None),
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=991,
+  serialized_end=1224,
+)
+
+
+_PYTHONINFO = _descriptor.Descriptor(
+  name='PythonInfo',
+  full_name='blaze.PythonInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='source_file', full_name='blaze.PythonInfo.source_file', index=0,
+      number=1, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='dep_file', full_name='blaze.PythonInfo.dep_file', index=1,
+      number=2, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+    _descriptor.FieldDescriptor(
+      name='python_info', full_name='blaze.PythonInfo.python_info', index=0,
+      number=1005, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=True, extension_scope=None,
+      options=None),
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1226,
+  serialized_end=1342,
+)
+
+_EXTRAACTIONSUMMARY.fields_by_name['action'].message_type = _DETAILEDEXTRAACTIONINFO
+_DETAILEDEXTRAACTIONINFO.fields_by_name['action'].message_type = _EXTRAACTIONINFO
+_SPAWNINFO.fields_by_name['variable'].message_type = _ENVIRONMENTVARIABLE
+DESCRIPTOR.message_types_by_name['ExtraActionSummary'] = _EXTRAACTIONSUMMARY
+DESCRIPTOR.message_types_by_name['DetailedExtraActionInfo'] = _DETAILEDEXTRAACTIONINFO
+DESCRIPTOR.message_types_by_name['ExtraActionInfo'] = _EXTRAACTIONINFO
+DESCRIPTOR.message_types_by_name['EnvironmentVariable'] = _ENVIRONMENTVARIABLE
+DESCRIPTOR.message_types_by_name['SpawnInfo'] = _SPAWNINFO
+DESCRIPTOR.message_types_by_name['CppCompileInfo'] = _CPPCOMPILEINFO
+DESCRIPTOR.message_types_by_name['CppLinkInfo'] = _CPPLINKINFO
+DESCRIPTOR.message_types_by_name['JavaCompileInfo'] = _JAVACOMPILEINFO
+DESCRIPTOR.message_types_by_name['PythonInfo'] = _PYTHONINFO
+
+ExtraActionSummary = _reflection.GeneratedProtocolMessageType('ExtraActionSummary', (_message.Message,), dict(
+  DESCRIPTOR = _EXTRAACTIONSUMMARY,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.ExtraActionSummary)
+  ))
+_sym_db.RegisterMessage(ExtraActionSummary)
+
+DetailedExtraActionInfo = _reflection.GeneratedProtocolMessageType('DetailedExtraActionInfo', (_message.Message,), dict(
+  DESCRIPTOR = _DETAILEDEXTRAACTIONINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.DetailedExtraActionInfo)
+  ))
+_sym_db.RegisterMessage(DetailedExtraActionInfo)
+
+ExtraActionInfo = _reflection.GeneratedProtocolMessageType('ExtraActionInfo', (_message.Message,), dict(
+  DESCRIPTOR = _EXTRAACTIONINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.ExtraActionInfo)
+  ))
+_sym_db.RegisterMessage(ExtraActionInfo)
+
+EnvironmentVariable = _reflection.GeneratedProtocolMessageType('EnvironmentVariable', (_message.Message,), dict(
+  DESCRIPTOR = _ENVIRONMENTVARIABLE,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.EnvironmentVariable)
+  ))
+_sym_db.RegisterMessage(EnvironmentVariable)
+
+SpawnInfo = _reflection.GeneratedProtocolMessageType('SpawnInfo', (_message.Message,), dict(
+  DESCRIPTOR = _SPAWNINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.SpawnInfo)
+  ))
+_sym_db.RegisterMessage(SpawnInfo)
+
+CppCompileInfo = _reflection.GeneratedProtocolMessageType('CppCompileInfo', (_message.Message,), dict(
+  DESCRIPTOR = _CPPCOMPILEINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.CppCompileInfo)
+  ))
+_sym_db.RegisterMessage(CppCompileInfo)
+
+CppLinkInfo = _reflection.GeneratedProtocolMessageType('CppLinkInfo', (_message.Message,), dict(
+  DESCRIPTOR = _CPPLINKINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.CppLinkInfo)
+  ))
+_sym_db.RegisterMessage(CppLinkInfo)
+
+JavaCompileInfo = _reflection.GeneratedProtocolMessageType('JavaCompileInfo', (_message.Message,), dict(
+  DESCRIPTOR = _JAVACOMPILEINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.JavaCompileInfo)
+  ))
+_sym_db.RegisterMessage(JavaCompileInfo)
+
+PythonInfo = _reflection.GeneratedProtocolMessageType('PythonInfo', (_message.Message,), dict(
+  DESCRIPTOR = _PYTHONINFO,
+  __module__ = 'extra_actions_base_pb2'
+  # @@protoc_insertion_point(class_scope:blaze.PythonInfo)
+  ))
+_sym_db.RegisterMessage(PythonInfo)
+
+_SPAWNINFO.extensions_by_name['spawn_info'].message_type = _SPAWNINFO
+ExtraActionInfo.RegisterExtension(_SPAWNINFO.extensions_by_name['spawn_info'])
+_CPPCOMPILEINFO.extensions_by_name['cpp_compile_info'].message_type = _CPPCOMPILEINFO
+ExtraActionInfo.RegisterExtension(_CPPCOMPILEINFO.extensions_by_name['cpp_compile_info'])
+_CPPLINKINFO.extensions_by_name['cpp_link_info'].message_type = _CPPLINKINFO
+ExtraActionInfo.RegisterExtension(_CPPLINKINFO.extensions_by_name['cpp_link_info'])
+_JAVACOMPILEINFO.extensions_by_name['java_compile_info'].message_type = _JAVACOMPILEINFO
+ExtraActionInfo.RegisterExtension(_JAVACOMPILEINFO.extensions_by_name['java_compile_info'])
+_PYTHONINFO.extensions_by_name['python_info'].message_type = _PYTHONINFO
+ExtraActionInfo.RegisterExtension(_PYTHONINFO.extensions_by_name['python_info'])
+
+DESCRIPTOR.has_options = True
+DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n+com.google.devtools.build.lib.actions.extraP\001'))
+# @@protoc_insertion_point(module_scope)
diff --git a/tools/actions/BUILD b/tools/actions/BUILD
new file mode 100644
index 0000000..2362307
--- /dev/null
+++ b/tools/actions/BUILD
@@ -0,0 +1,30 @@
+py_binary(
+  name = 'generate_compile_command',
+  srcs = [
+    'generate_compile_command.py',
+  ],
+  deps = [
+    '//third_party/bazel:extra_actions_proto_py',
+  ],
+)
+
+action_listener(
+  name = 'generate_compile_commands_listener',
+  visibility = ['//visibility:public'],
+  mnemonics = [
+    'CppCompile',
+  ],
+  extra_actions = [':generate_compile_commands_action'],
+)
+
+extra_action(
+  name = 'generate_compile_commands_action',
+  tools = [
+    ':generate_compile_command',
+  ],
+  out_templates = [
+    '$(ACTION_ID)_compile_command',
+  ],
+  cmd = '$(location :generate_compile_command) $(EXTRA_ACTION_FILE)' +
+        ' $(output $(ACTION_ID)_compile_command)',
+)
diff --git a/tools/actions/generate_compile_command.py b/tools/actions/generate_compile_command.py
new file mode 100755
index 0000000..b41f2fc
--- /dev/null
+++ b/tools/actions/generate_compile_command.py
@@ -0,0 +1,27 @@
+# This is the implementation of a Bazel extra_action which genenerates
+# _compile_command files for generate_compile_commands.py to consume.
+
+import sys
+
+import third_party.bazel.protos.extra_actions_base_pb2 as extra_actions_base_pb2
+
+def _get_cpp_command(cpp_compile_info):
+  compiler = cpp_compile_info.tool
+  options = ' '.join(cpp_compile_info.compiler_option)
+  source = cpp_compile_info.source_file
+  output = cpp_compile_info.output_file
+  return '%s %s -c %s -o %s' % (compiler, options, source, output), source
+
+def main(argv):
+  action = extra_actions_base_pb2.ExtraActionInfo()
+  with open(argv[1], 'rb') as f:
+    action.MergeFromString(f.read())
+  command, source_file = _get_cpp_command(
+      action.Extensions[extra_actions_base_pb2.CppCompileInfo.cpp_compile_info])
+  with open(argv[2], 'w') as f:
+    f.write(command)
+    f.write('\0')
+    f.write(source_file)
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/tools/actions/generate_compile_commands_json.py b/tools/actions/generate_compile_commands_json.py
new file mode 100755
index 0000000..d867698
--- /dev/null
+++ b/tools/actions/generate_compile_commands_json.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python3
+
+# This reads the _compile_command files :generate_compile_commands_action
+# generates a outputs a compile_commands.json file at the top of the source
+# tree for things like clang-tidy to read.
+
+# Overall usage directions: run bazel with
+# --experimental_action_listener=//tools/actions:generate_compile_commands_listener
+# for all the files you want to use clang-tidy with and then run this script.
+# Afer that, `clang-tidy build_tests/gflags.cc` should work.
+
+import sys
+import pathlib
+import os.path
+import subprocess
+
+'''
+Args:
+  path: The pathlib.Path to _compile_command file.
+  command_directory: The directory commands are run from.
+
+Returns a string to stick in compile_commands.json.
+'''
+def _get_command(path, command_directory):
+  with path.open('r') as f:
+    contents = f.read().split('\0')
+    if len(contents) != 2:
+      # Old/incomplete file or something; silently ignore it.
+      return None
+    return '''{
+        "directory": "%s",
+        "command": "%s",
+        "file": "%s",
+      },''' % (command_directory, contents[0].replace('"', '\\"'), contents[1])
+
+'''
+Args:
+  path: A directory pathlib.Path to look for _compile_command files under.
+  command_directory: The directory commands are run from.
+
+Yields strings to stick in compile_commands.json.
+'''
+def _get_compile_commands(path, command_directory):
+  for f in path.iterdir():
+    if f.is_dir():
+      yield from _get_compile_commands(f, command_directory)
+    elif f.name.endswith('_compile_command'):
+      command = _get_command(f, command_directory)
+      if command:
+        yield command
+
+def main(argv):
+  source_path = os.path.join(os.path.dirname(__file__), '../..')
+  action_outs = os.path.join(source_path,
+                             'bazel-bin/../extra_actions',
+                             'tools/actions/generate_compile_commands_action')
+  command_directory = subprocess.check_output(
+      ('bazel', 'info', 'execution_root'),
+      cwd=source_path).decode('utf-8').rstrip()
+  commands = _get_compile_commands(pathlib.Path(action_outs), command_directory)
+  with open(os.path.join(source_path, 'compile_commands.json'), 'w') as f:
+    f.write('[')
+    for command in commands:
+      f.write(command)
+    f.write(']')
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))