Generate compile_commands.json as part of build/gen.py

This makes it easy to keep updating out/compile_commands.json.
It also adds `.clangd` to `.gitignore`.

Change-Id: I2d395e68282b81ab06adea1145c10af73f402afe
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/18640
Commit-Queue: Takuto Ikuta <tikuta@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
diff --git a/build/gen.py b/build/gen.py
index 8470373..5d07459 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -209,6 +209,10 @@
                             'with <ZOSLIB_DIR>/lib/libzoslib.a, and ' +
                             'add -I<ZOSLIB_DIR>/include to the compile ' +
                             'commands. See README.md for details.'))
+  args_list.add('--generate-compilation-database',
+                    action='store_true',
+                    help=('Generate compile_commands.json with ' +
+                          '`ninja -t compdb`.'))
 
   args_list.add_to_parser(parser)
   options = parser.parse_args(argv)
@@ -383,12 +387,17 @@
     f.write(ninja_template)
     f.write('\n'.join(ninja_lines))
 
+  build_dir = os.path.dirname(path)
   with open(path + '.d', 'w') as f:
     f.write('build.ninja: ' +
             os.path.relpath(os.path.join(SCRIPT_DIR, 'gen.py'),
-                            os.path.dirname(path)) + ' ' +
-            os.path.relpath(template_filename, os.path.dirname(path)) + '\n')
+                            build_dir) + ' ' +
+            os.path.relpath(template_filename, build_dir) + '\n')
 
+  if options.generate_compilation_database:
+    with open(os.path.join(REPO_ROOT, 'compile_commands.json'), 'w') as f:
+      subprocess.run(
+          ['ninja', '-C', build_dir, '-t', 'compdb'], stdout=f, check=True)
 
 def WriteGNNinja(path, platform, host, options, args_list):
   if platform.is_msvc():