-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add compiler info to result directory #1050
Conversation
Add the results of gcc -v like invocations as files to the reult dir. This is needed for later local investigation of any failed analysis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some high level questions and found some nits otherwise looks good.
libcodechecker/analyze/log_parser.py
Outdated
for line in lines.splitlines(True): | ||
line = line.strip() | ||
if line.startswith(end_mark): | ||
do_append = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be multiple occurrences of start_mark? If no, could we just break here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the original code for parsing, unfortunately diff shows this as completely new code.
Still, I think we could just break here.
libcodechecker/analyze/log_parser.py
Outdated
|
||
return target | ||
err = get_compiler_err(cmd) | ||
dump_compiler_info(output_path, "compiler_target.json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to both dump compiler info when getting the target and when getting the includes?
return target | ||
|
||
|
||
def dump_compiler_info(output_path, filename, data): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the file already exists, we just append to it.
Is it ensured that multiple concurrent checks (to different result directories) won't interfere?
When will we clean up this file? If we don't do that, this file will just grow with subsequent checks to the same result directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, as we discussed I modifed the analyze.py to remove these files when starting a new analysis.
libcodechecker/analyze/log_parser.py
Outdated
@@ -208,13 +243,13 @@ def parse_compile_commands_json(logfile, add_compiler_defaults=False): | |||
return actions | |||
|
|||
|
|||
def parse_log(logfilepath, add_compiler_defaults=False): | |||
def parse_log(logfilepath, output_path, add_compiler_defaults=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think output_path
worth a documentation, what this refers to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good. I was wondering if it would be cleaner to have only one json file.
libcodechecker/analyze/log_parser.py
Outdated
return target | ||
def remove_file_if_exists(filename): | ||
try: | ||
os.remove(filename) # throws if file does not exsist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We start comments with capital letters and terminate them with periods.
libcodechecker/analyze/log_parser.py
Outdated
if os.path.exists(filename): | ||
append_write = 'a' | ||
with open(filename, append_write) as f: | ||
f.write(json.dumps(data)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably this will not be a proper json in case of multiple compilers.
We have to
- read the file first with
- then do a
json.loads
on the content - then add the new entry
- then write back
@Xazax-hun, as we discussed two files make the json handling code more compact for our benefit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! But could you squash this into two commit? One for the feature one for the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also, commits are many.)
libcodechecker/analyze/log_parser.py
Outdated
@@ -10,6 +10,8 @@ | |||
import traceback | |||
import subprocess | |||
import shlex | |||
import json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import order has been violated here.
libcodechecker/analyze/log_parser.py
Outdated
""" | ||
|
||
def get_compiler_err(cmd): | ||
''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'''
➡️ """
libcodechecker/analyze/log_parser.py
Outdated
Returns a list of default includes of the given compiler. | ||
""" | ||
|
||
def get_compiler_err(cmd): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, don't we have a method for arbitrary command invocation and output saving somewhere in util
? Or am I mixing it up with the test
library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is util.call_command
but that does not handle the stderr. Also this code is refactored from https://github.com/Ericsson/codechecker/pull/1050/files?diff=split#diff-3edc7a6cc15c42194786d15e8ab5852dL95
# where we need to strip the "(framework directory)" string. | ||
# For instance: | ||
# /System/Library/Frameworks (framework directory) | ||
fpos = line.find("(framework directory)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string::find(substr) == -1
can be replaced with substr not in string
, which is more Pythonic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I agree.
Still, this is again not new code despite it looks like that in the diff; merge conflict resolution brought this in :(
libcodechecker/analyze/log_parser.py
Outdated
return target | ||
def remove_file_if_exists(filename): | ||
try: | ||
os.remove(filename) # Throws if file does not exsist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These comments are unneccessary here. Also, I recall we use the following form almost everywhere in the code.
if os.path.isfile(a): # Or exists()
os.remove(a)
import json | ||
# The add-compiler-defaults is a deprecated argument | ||
# and we always perform target and include auto-detection. | ||
add_compiler_defaults = True | ||
LOG.debug('parse_compile_commands_json: ' + str(add_compiler_defaults)) | ||
|
||
if output_path is not None: | ||
remove_file_if_exists(os.path.join(output_path, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it always applicable for incremental analysis to remove these files? What if analysis configuration changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not a problem. If the analysis configuration changes the compile database still remains the same. Compiler includes and targets do not depend on analysis configuration.
@@ -38,7 +38,7 @@ def setup_class(cls): | |||
cls.src_file_name = "main.cpp" | |||
cls.src_file_path = os.path.join(cls.tmp_dir, | |||
cls.src_file_name) | |||
cls.compiler = "g++" | |||
cls.compiler = "clang++" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this change introduced?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bug which is present since a while. cls.compiler
is called with --target
and gcc7 exits with an error (return value not equal with 0), however older gcc like gcc 4.8 just gives a warning and returns with 0.
|
||
# Create a compilation database. | ||
build_log = [{"directory": self.test_workspace, | ||
"command": "gcc -c " + source_file, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to gcc
not existing on macOS systems, this way of creating a build log on the fly is prone to break macOS tests. See #824.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought gcc is a symbolic link to clang on macOS. https://stackoverflow.com/questions/19535422/os-x-10-9-gcc-links-to-clang
Has this changed in systems newer than El Capitan?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've no macOS machine, so I'm not sure. There was definitely no such thing as gcc
and g++
on the Travis macOS instances a few months ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this is really a problem since there are several other uses like this in other test cases:
tests/functional/analyze/test_analyze.py|102 col 35| "command": "gcc -c " + source_file,
tests/functional/analyze/test_analyze.py|172 col 35| "command": "gcc -c " + source_file,
tests/functional/analyze/test_analyze.py|205 col 35| "command": "gcc -c " + source_file,
tests/functional/analyze/test_analyze.py|240 col 35| "gcc -c " + source_file)
tests/functional/analyze/test_analyze.py|303 col 35| "command": "gcc -c " + source_file,
tests/functional/ctu/test_files/buildlog.json|4 col 17| "command": "gcc -c lib.c -o lib.o",
tests/functional/ctu/test_files/buildlog.json|9 col 17| "command": "gcc -c main.c -o main.o",
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this case compilation.json is not created on the fly, but wired in into the test case. So it will not cause problem on Mac.
5134a67
to
6bb7c51
Compare
if os.path.exists(filename): | ||
with open(filename, 'r') as f: | ||
all_data = json.load(f) | ||
all_data.update(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
be careful, this will not add a new member in the hash, but update an existing one. Thus you will always have one element in the dict such as {'target': 'arm', 'compiler': 'gcc-arm'}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a new squashed commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
On the long term however we may want to perform the compiler detection as a part of log and not analyze. The advantage would be that one would not need the presence of the compilers in the analysis phase (maybe the compilers exist only temporarily in the env).
We could not squash the merge commit 3df5ecd , so for simplicity we keep the 4 commit. |
Add the results of gcc -v like invocations as files to the result dir.
This is needed for later local investigation of any failed analysis.