Skip to content
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

Default compiler standard #1720

Merged
merged 2 commits into from
Sep 7, 2018
Merged

Conversation

bruntib
Copy link
Contributor

@bruntib bruntib commented Aug 27, 2018

No description provided.

@bruntib bruntib added enhancement 🌟 analyzer 📈 Related to the analyze commands (analysis driver) labels Aug 27, 2018
@bruntib bruntib added this to the release 6.8 milestone Aug 27, 2018
test_file = temp_file + ('.c' if lang == 'c' else '.cpp')
os.rename(temp_file, test_file)

with open(test_file, 'w') as f:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use io.open

executable = os.path.join(tempfile.gettempdir(),
next(tempfile._get_candidate_names()))

proc = subprocess.Popen([compiler, '-o', executable, test_file],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle Popen exceptions in case the call fails.


os.chmod(executable, stat.S_IXUSR)

proc = subprocess.Popen([executable], stdout=subprocess.PIPE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle Popen exceptions in case the call fails.

compiler_includes_dump_file))
remove_file_if_exists(os.path.join(output_path,
compiler_target_dump_file))
global compiler_info_dump_file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of global variables, could you change it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I tried some other implementations, but every other solution was much uglier and boilerplate. So I left it like this, maybe we could figure out something more elegant later.

proc = subprocess.Popen([executable], stdout=subprocess.PIPE)
out, _ = proc.communicate()

os.remove(test_file)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle exceptions if the files are already removed for some reason, or use the remove_file_if_exists function.

}
"""

err = ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this named err, the cpp standard argument will be stored in it.

@bruntib bruntib force-pushed the default_compiler_standard branch from 1b2bec4 to b6c960c Compare August 31, 2018 21:21
@bruntib bruntib requested a review from gyorb August 31, 2018 21:22
if parseLogOptions.compiler_info_file is None:
_, temp_file = tempfile.mkstemp()
test_file = temp_file + ('.c' if lang == 'c' else '.cpp')
os.rename(temp_file, test_file)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think removing a temp file should be done in the following form:

_, temp_file = tempfile.mkstemp()
try:
    ...
finally:
    remove_file_if_exists(temp_file)
    remove_file_if_exists(test_file)

What do you think @gyorb?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using NamedTemporaryFile in a with statement with a suffix (no renaming is needed) would be easier and it would remove the file when it is out of context.

Copy link
Contributor

@gyorb gyorb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the temporary file handling.

@bruntib bruntib force-pushed the default_compiler_standard branch from b6c960c to eeebd03 Compare September 3, 2018 16:34
@@ -127,16 +127,24 @@ def add_arguments_to_parser(parser):
dest="compiler_includes_file",
required=False,
default=None,
help="Read the compiler includes from the specified "
"file rather than invoke the compiler "
help="DEPRECATED. Read the compiler includes from the "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated arguments used to have a wrapper somewhere which allowed setting them to behave with emitting a warning that a deprecated argument is used. I think this should be introduced again, or just simply the argument parser round (__handle) written in a way that the user is warned about the deprecated argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to search this wrapper in the git history. However, I'd propose a new policy rule: if there are such changes which involve other parts of the source code requiring their change, and not in the scope of the current pull request, then a new issue should be registered, maybe by additionally providing the assignee. What do you think?

Copy link
Contributor

@whisperity whisperity Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class DeprecatedOptionAction(argparse.Action):

Although yeah, the handling of this should be made more reusable and standard.
(Then again, argparse should also be extended to allow broader cross-argument rules and dependencies for which we use __handle...)

Copy link
Contributor

@whisperity whisperity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure actually compiling something and executing it is the best approach? We could simply use a #pragma GCC error preprocessor macro (both Clang and MSVC understand it too!) and splitting the compiler stderr could also give us the information.

"detector.")

if os.path.isfile(exe):
os.chmod(exe, stat.S_IXUSR)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the user always have the permission to set these bits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea of using preprocessing time error sounds good. Do you know any difference between #error and #pragma GCC error? Isn't the former one more standard?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #pragma version gives me different outputs with different compilers. g++ (5.5.0) seems not to understand it: error: invalid "#pragma GCC error" directive.
By the way can we rely on the error message format between different compilers, or even same compiler and different versions? Wouldn't it complicate the parsing of this output?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about #error.

The output should be sufficiently small: CC_FOUND_STARDARD_VER|23. On that, a simple regex can give us the answer, irrespective to whatever specific compiler and version is used.

@whisperity
Copy link
Contributor

Also, with regards to the temporary file: we could distribute the "prepared" C/C++ code as a resource with the CodeChecker install, instead of creating them at runtime.

@bruntib
Copy link
Contributor Author

bruntib commented Sep 4, 2018

I tried to keep these C++ codes in separate files but it was not possible to reach them from the test code.

@whisperity
Copy link
Contributor

@bruntib That is an ongoing issue (that the tests can rarely pull configuration and other stuff from the deployed environment), see #787.

Until then, I think still putting these into separate files (e.g. config or vendor?) and making the make test command unconditionally copy them over to some well-defined location is a good workaround. When we have some time, as part of #787, we will figure something better out.

@bruntib
Copy link
Contributor Author

bruntib commented Sep 4, 2018

The idea behind this solution was that log_parser.py highly depends on these .cpp files, so delivering them as a vendor would be too far. I think this can also be a reason not to confide the build system managing the file locations. So couldn't we consider this current solution as a workaround?
By the way the problem was in the unit tests of log_parser. It can't (and wouldn't be logical either) to make it rely on a CodeChecker package to find these C++ files through config options.

@whisperity
Copy link
Contributor

Was just an idea, this workaround is good enough for me. However, I think it would be better if the code, if it stays in the Python file, gets moved out of the function's scope? It is... essentially a static const of this function, it is a resource, it is also very long code, it should reside amongst some top-level declarations.

@bruntib
Copy link
Contributor Author

bruntib commented Sep 4, 2018

The outer scope is global scope which we try to fight against, even in this ticket for another variable. Would you suggest to place it there? By the way in an other language I would choose static const as it supports the rule of thumb of keeping the variables in the innermost possible scope. We have even a checker for this :)

@bruntib bruntib force-pushed the default_compiler_standard branch from eeebd03 to 23de4b8 Compare September 4, 2018 16:00
Copy link
Member

@dkrupp dkrupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc accepts -std=c++11 in the following forms
-std=c++11
--std=c++11
--std c++11

Only the first form is handled.
Please handle the other variations too.

@@ -136,6 +136,10 @@ def construct_analyzer_cmd(self, result_handler):

analyzer_cmd.extend(self.buildaction.compiler_includes)

if not next((x for x in analyzer_cmd if x.startswith('-std=')),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc accepts -std=c++11 in the following forms
-std=c++11
--std=c++11
--std c++11

Only the first form is handled.
Please handle the other variations too.

@bruntib bruntib force-pushed the default_compiler_standard branch 3 times, most recently from 9ed0aa6 to 217754b Compare September 6, 2018 12:11
@bruntib bruntib requested a review from dkrupp September 6, 2018 12:12
@bruntib bruntib force-pushed the default_compiler_standard branch from 217754b to 37ce3ec Compare September 6, 2018 13:02
The --compiler-includes and --compiler-target flags are deprecated under
"CodeChecker analyze" command, --compiler-info is introduced instead.
The new compiler info dump file contains the information of these two
merged into one JSON, however, the files with the old format still can
be used for supporting reverse compatibility.
@bruntib bruntib force-pushed the default_compiler_standard branch from 37ce3ec to ce6c56f Compare September 7, 2018 07:54
Copy link
Contributor

@csordasmarton csordasmarton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please extend the New features tab with this feature:

C/C++ standard auto detection
Detect automatically which C/C++ standard was used for compilation by gcc and pass the relevant option to Clang (e.g. -std=c++11)

@bruntib bruntib force-pushed the default_compiler_standard branch from ce6c56f to 133b01d Compare September 7, 2018 09:51
@bruntib bruntib force-pushed the default_compiler_standard branch from 133b01d to 44fc7f7 Compare September 7, 2018 10:17
Some implicit information, like implicit include paths or compiler
targets, may depend on the used C/C++ language standard. This can be
provided by "-std=" flag. However, in some cases this flag is not used
and has a default value which depends on the compiler binary. In this
commit the intention is to detect this default language standard
version.
@bruntib bruntib force-pushed the default_compiler_standard branch from 44fc7f7 to fcd5e85 Compare September 7, 2018 11:13
@dkrupp dkrupp merged commit aa36dcc into Ericsson:master Sep 7, 2018
@bruntib bruntib deleted the default_compiler_standard branch September 7, 2018 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer 📈 Related to the analyze commands (analysis driver) enhancement 🌟
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants