Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) #!/usr/bin/env python3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) # Copyright (C) Google LLC, 2018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) # Author: Tom Roeder <tmroeder@google.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) """A tool for generating compile_commands.json in the Linux kernel."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) import json
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) import logging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) import subprocess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) _DEFAULT_OUTPUT = 'compile_commands.json'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) _DEFAULT_LOG_LEVEL = 'WARNING'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) _FILENAME_PATTERN = r'^\..*\.cmd$'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) _LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) def parse_arguments():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)     """Sets up and parses command-line arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)     Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)         log_level: A logging level to filter log output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)         directory: The work directory where the objects were built.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)         ar: Command used for parsing .a archives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)         output: Where to write the compile-commands JSON file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)         paths: The list of files/directories to handle to find .cmd files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)     usage = 'Creates a compile_commands.json database from kernel .cmd files'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)     parser = argparse.ArgumentParser(description=usage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)     directory_help = ('specify the output directory used for the kernel build '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)                       '(defaults to the working directory)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)     parser.add_argument('-d', '--directory', type=str, default='.',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)                         help=directory_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)     output_help = ('path to the output command database (defaults to ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)                    _DEFAULT_OUTPUT + ')')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)     parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)                         help=output_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)     log_level_help = ('the level of log messages to produce (defaults to ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)                       _DEFAULT_LOG_LEVEL + ')')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)     parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)                         default=_DEFAULT_LOG_LEVEL, help=log_level_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)     ar_help = 'command used for parsing .a archives'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)     parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)     paths_help = ('directories to search or files to parse '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)                   '(files should be *.o, *.a, or modules.order). '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)                   'If nothing is specified, the current directory is searched')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)     parser.add_argument('paths', type=str, nargs='*', help=paths_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)     args = parser.parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)     return (args.log_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)             os.path.abspath(args.directory),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)             args.output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)             args.ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)             args.paths if len(args.paths) > 0 else [args.directory])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) def cmdfiles_in_dir(directory):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)     """Generate the iterator of .cmd files found under the directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)     Walk under the given directory, and yield every .cmd file found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)         directory: The directory to search for .cmd files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)     Yields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)         The path to a .cmd file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)     filename_matcher = re.compile(_FILENAME_PATTERN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)     for dirpath, _, filenames in os.walk(directory):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)         for filename in filenames:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)             if filename_matcher.match(filename):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)                 yield os.path.join(dirpath, filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) def to_cmdfile(path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)     """Return the path of .cmd file used for the given build artifact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)         Path: file path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)     Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)         The path to .cmd file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)     dir, base = os.path.split(path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)     return os.path.join(dir, '.' + base + '.cmd')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) def cmdfiles_for_o(obj):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)     """Generate the iterator of .cmd files associated with the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)     Yield the .cmd file used to build the given object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)         obj: The object path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)     Yields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)         The path to .cmd file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)     yield to_cmdfile(obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) def cmdfiles_for_a(archive, ar):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)     """Generate the iterator of .cmd files associated with the archive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)     Parse the given archive, and yield every .cmd file used to build it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)         archive: The archive to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)     Yields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)         The path to every .cmd file found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)     for obj in subprocess.check_output([ar, '-t', archive]).decode().split():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)         yield to_cmdfile(obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) def cmdfiles_for_modorder(modorder):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)     """Generate the iterator of .cmd files associated with the modules.order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     Parse the given modules.order, and yield every .cmd file used to build the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)     contained modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)         modorder: The modules.order file to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)     Yields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)         The path to every .cmd file found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)     with open(modorder) as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)         for line in f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)             ko = line.rstrip()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)             base, ext = os.path.splitext(ko)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)             if ext != '.ko':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)                 sys.exit('{}: module path must end with .ko'.format(ko))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)             mod = base + '.mod'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	    # The first line of *.mod lists the objects that compose the module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)             with open(mod) as m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)                 for obj in m.readline().split():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)                     yield to_cmdfile(obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) def process_line(root_directory, command_prefix, file_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)     """Extracts information from a .cmd line and creates an entry from it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)     Args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)         root_directory: The directory that was searched for .cmd files. Usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)             used directly in the "directory" entry in compile_commands.json.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)         command_prefix: The extracted command line, up to the last element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)         file_path: The .c file from the end of the extracted command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)             Usually relative to root_directory, but sometimes absolute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)     Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)         An entry to append to compile_commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)     Raises:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)         ValueError: Could not find the extracted file based on file_path and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)             root_directory or file_directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)     # The .cmd files are intended to be included directly by Make, so they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)     # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)     # kernel version). The compile_commands.json file is not interepreted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)     # by Make, so this code replaces the escaped version with '#'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)     prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)     # Use os.path.abspath() to normalize the path resolving '.' and '..' .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)     abs_path = os.path.abspath(os.path.join(root_directory, file_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)     if not os.path.exists(abs_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)         raise ValueError('File %s not found' % abs_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)     return {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)         'directory': root_directory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)         'file': abs_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)         'command': prefix + file_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) def main():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)     """Walks through the directory and finds and parses .cmd files."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)     log_level, directory, output, ar, paths = parse_arguments()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)     level = getattr(logging, log_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)     logging.basicConfig(format='%(levelname)s: %(message)s', level=level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)     line_matcher = re.compile(_LINE_PATTERN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)     compile_commands = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)     for path in paths:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)         # If 'path' is a directory, handle all .cmd files under it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)         # Otherwise, handle .cmd files associated with the file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)         # Most of built-in objects are linked via archives (built-in.a or lib.a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)         # but some objects are linked to vmlinux directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)         # Modules are listed in modules.order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)         if os.path.isdir(path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)             cmdfiles = cmdfiles_in_dir(path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)         elif path.endswith('.o'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)             cmdfiles = cmdfiles_for_o(path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)         elif path.endswith('.a'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)             cmdfiles = cmdfiles_for_a(path, ar)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)         elif path.endswith('modules.order'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)             cmdfiles = cmdfiles_for_modorder(path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)             sys.exit('{}: unknown file type'.format(path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)         for cmdfile in cmdfiles:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)             with open(cmdfile, 'rt') as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)                 result = line_matcher.match(f.readline())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)                 if result:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)                     try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)                         entry = process_line(directory, result.group(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)                                              result.group(2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)                         compile_commands.append(entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)                     except ValueError as err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)                         logging.info('Could not add line from %s: %s',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)                                      cmdfile, err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)     with open(output, 'wt') as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)         json.dump(compile_commands, f, indent=2, sort_keys=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if __name__ == '__main__':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)     main()