| """Compilation of utility functions for working with Android.mk and make.""" |
| |
| from __future__ import absolute_import |
| import collections |
| import os |
| import re |
| |
| # Example: path/to/file.c:123:4: error: this is an error |
| _MAKE_ERROR_PATTERN = (r'^(?P<filename>[^:]+):(?P<linenum>\d+):(?P<column>\d+):' |
| r' error: (?P<err_msg>.*)$') |
| _MAKE_TOO_MANY_ERRORS_MSG = 'Too many errors! See the logs for the rest.' |
| |
| |
| def make_error_to_comments(make_output, directory): |
| """Convert a make failure message to comments for a gerrit review. |
| |
| In general, a when make has an error it prints to stderr and it looks like: |
| |
| [...snip...] |
| external/iw/wowlan.c:27:3: error: expected ')' before 'return' |
| return 1; |
| ^ |
| external/iw/wowlan.c:182:1: error: expected expression before '}' token |
| } |
| ^ |
| cc1.elf: some warnings being treated as errors |
| make: *** [out/obj/EXECUTABLES/iw_intermediates/wowlan.o] Error 1 |
| [...snip...] |
| |
| And this extracts out the 'error' lines from the rest of the log. |
| |
| Args: |
| make_output: stderr output from a make build command. (Note: it's possible |
| this may contain output from other commands. In general though, make |
| errors occur early in the build process and stop the build.) |
| directory: The path to strip off of the beginning of filenames in the |
| make output. Example: |
| make errors are for "path/to/your/files.cc" |
| directory == "path/to" => comments are for "your/files.cc" |
| |
| Returns: |
| A dictionary of file comments to be added to a review. |
| Keys are filenames and values are lists of dictionaries with 'line' and |
| 'message' entries. |
| { 'path/to/file.cc': [{'line': 5, 'message': 'error!'}, ...]} |
| An empty dict is returned if no comments are found. |
| """ |
| comments = collections.defaultdict(list) |
| |
| for line in make_output.splitlines(): |
| match = re.match(_MAKE_ERROR_PATTERN, line) |
| if match: |
| filename = match.group('filename') |
| # Strip off directory name and slash |
| if directory and filename.startswith(directory): |
| filename = filename[len(directory) + len(os.path.sep):] |
| linenum = int(match.group('linenum')) |
| comments[filename].append({'line': linenum, 'message': line}) |
| |
| return comments |