Skip to content

cppcheck options: add --output-file-type option #3365

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

Closed
wants to merge 8 commits into from

Conversation

RobertWak
Copy link

When used with tools such as cmake, cppcheck doesn't provide an convenient way to output into files.

I've added two values for new --output-file-type option:

     uniq: this will create a output file name based on the --output-file and the current file(s) that are analyzed
     append: this will open the --output-file file in append mode and add the content to it

        example:
                Not using the new option:

                    $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml cli/cmdlineparser.cpp
                    $ ls -la output_files/
                    total 12
                    drwxrwxr-x  2 user user 4096 Jul 22 14:47 .
                    drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                    -rw-rw-r--  1 user user 1283 Jul 22 14:47 cppcheck.xml

                Using the option with value "uniq" for one file:

                    $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp
                    $ ls -la output_files/
                    total 12
                    drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                    drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                    -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp.xml

                Using the option with value "uniq" for one file without extension:

                    $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck --output-file-type=uniq cli/cmdlineparser.cpp
                    $ ls -la output_files/
                    total 12
                    drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                    drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                    -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp

	    Using the option with value "uniq" for two files:

                    $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                    $ ls -la output_files/
                    total 16
                    drwxrwxr-x  2 user user 4096 Jul 22 14:49 .
                    drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                    -rw-rw-r--  1 user user 4308 Jul 22 14:49 cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

                Using the option with value "append" for one file on a empty/non-existing file:

                   $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                   $ ls -la output_files/
                   total 12
                   drwxrwxr-x  2 user user 4096 Jul 22 14:51 .
                   drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                   -rw-rw-r--  1 user user 1283 Jul 22 14:51 cppcheck.xml

                Using the option with value "append" for two files on a empty/non-existing file:

                   $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                   $ ls -la output_files/
                   total 16
                   drwxrwxr-x  2 user user 4096 Jul 22 14:53 .
                   drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                   -rw-rw-r--  1 user user 4308 Jul 22 14:53 cppcheck.xml

                Using the option with value twise "append" for one file on a empty/non-existing file:

                   $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                   $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cppcheckexecutor.cpp
                   $ ls -la output_files/
                   total 16
                   drwxrwxr-x  2 user user 4096 Jul 22 14:54 .
                   drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                   -rw-rw-r--  1 user user 5613 Jul 22 14:55 cppcheck.xml

                /!\ the file is a pure concatenation of the files created without the "append" value which means that it's no more a valid XML file as it will have twice the "<?xml version="1.0" encoding="UTF-8"?>" entry
                  $ cat output_files/cppcheck.xml
                  <?xml version="1.0" encoding="UTF-8"?>
                  <results version="2">
                    [...]
                  </results>
                  <?xml version="1.0" encoding="UTF-8"?>
                  <results version="2">
                    [...]
                  </results>

Signed-off-by: Robert Wakim robert.wakim@arm.com

    When used with tools such as cmake, cppcheck doesn't provide an convenient way to output into files.

    I've added two values for new --output-file-type option:

         uniq: this will create a output file name based on the --output-file and the current file(s) that are analyzed
         append: this will open the --output-file file in append mode and add the content to it

            example:
                    Not using the new option:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:47 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:47 cppcheck.xml

                    Using the option with value "uniq" for one file:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp.xml

                    Using the option with value "uniq" for two files:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                        $ ls -la output_files/
                        total 16
                        drwxrwxr-x  2 user user 4096 Jul 22 14:49 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 4308 Jul 22 14:49 cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

                    Using the option with value "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ ls -la output_files/
                       total 12
                       drwxrwxr-x  2 user user 4096 Jul 22 14:51 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 1283 Jul 22 14:51 cppcheck.xml

                    Using the option with value "append" for two files on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:53 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 4308 Jul 22 14:53 cppcheck.xml

                    Using the option with value twise "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:54 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 5613 Jul 22 14:55 cppcheck.xml

                    /!\ the file is a pure concatenation of the files created without the "append" value which means that it's no more a valid XML file as it will have twice the "<?xml version="1.0" encoding="UTF-8"?>" entry
                      $ cat output_files/cppcheck.xml
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>

Signed-off-by: Robert Wakim <robert.wakim@arm.com>
    When used with tools such as cmake, cppcheck doesn't provide an convenient way to output into files.

    I've added two values for new --output-file-type option:

         uniq: this will create a output file name based on the --output-file and the current file(s) that are analyzed
         append: this will open the --output-file file in append mode and add the content to it

            example:
                    Not using the new option:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:47 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:47 cppcheck.xml

                    Using the option with value "uniq" for one file:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp.xml

                    Using the option with value "uniq" for two files:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                        $ ls -la output_files/
                        total 16
                        drwxrwxr-x  2 user user 4096 Jul 22 14:49 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 4308 Jul 22 14:49 cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

                    Using the option with value "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ ls -la output_files/
                       total 12
                       drwxrwxr-x  2 user user 4096 Jul 22 14:51 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 1283 Jul 22 14:51 cppcheck.xml

                    Using the option with value "append" for two files on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:53 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 4308 Jul 22 14:53 cppcheck.xml

                    Using the option with value twise "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:54 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 5613 Jul 22 14:55 cppcheck.xml

                    /!\ the file is a pure concatenation of the files created without the "append" value which means that it's no more a valid XML file as it will have twice the "<?xml version="1.0" encoding="UTF-8"?>" entry
                      $ cat output_files/cppcheck.xml
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>

Signed-off-by: Robert Wakim <robert.wakim@arm.com>
    When used with tools such as cmake, cppcheck doesn't provide an convenient way to output into files.

    I've added two values for new --output-file-type option:

         uniq: this will create a output file name based on the --output-file and the current file(s) that are analyzed
         append: this will open the --output-file file in append mode and add the content to it

            example:
                    Not using the new option:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:47 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:47 cppcheck.xml

                    Using the option with value "uniq" for one file:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp.xml

                    Using the option with value "uniq" for one file without extension:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp

		    Using the option with value "uniq" for two files:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                        $ ls -la output_files/
                        total 16
                        drwxrwxr-x  2 user user 4096 Jul 22 14:49 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 4308 Jul 22 14:49 cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

                    Using the option with value "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ ls -la output_files/
                       total 12
                       drwxrwxr-x  2 user user 4096 Jul 22 14:51 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 1283 Jul 22 14:51 cppcheck.xml

                    Using the option with value "append" for two files on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:53 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 4308 Jul 22 14:53 cppcheck.xml

                    Using the option with value twise "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:54 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 5613 Jul 22 14:55 cppcheck.xml

                    /!\ the file is a pure concatenation of the files created without the "append" value which means that it's no more a valid XML file as it will have twice the "<?xml version="1.0" encoding="UTF-8"?>" entry
                      $ cat output_files/cppcheck.xml
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>

Signed-off-by: Robert Wakim <robert.wakim@arm.com>
    When used with tools such as cmake, cppcheck doesn't provide an convenient way to output into files.

    I've added two values for new --output-file-type option:

         uniq: this will create a output file name based on the --output-file and the current file(s) that are analyzed
         append: this will open the --output-file file in append mode and add the content to it

            example:
                    Not using the new option:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:47 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:47 cppcheck.xml

                    Using the option with value "uniq" for one file:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp.xml

                    Using the option with value "uniq" for one file without extension:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck --output-file-type=uniq cli/cmdlineparser.cpp
                        $ ls -la output_files/
                        total 12
                        drwxrwxr-x  2 user user 4096 Jul 22 14:48 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 1283 Jul 22 14:48 cppcheck_cmdlineparser_cpp

		    Using the option with value "uniq" for two files:

                        $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                        $ ls -la output_files/
                        total 16
                        drwxrwxr-x  2 user user 4096 Jul 22 14:49 .
                        drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                        -rw-rw-r--  1 user user 4308 Jul 22 14:49 cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

                    Using the option with value "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ ls -la output_files/
                       total 12
                       drwxrwxr-x  2 user user 4096 Jul 22 14:51 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 1283 Jul 22 14:51 cppcheck.xml

                    Using the option with value "append" for two files on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:53 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 4308 Jul 22 14:53 cppcheck.xml

                    Using the option with value twise "append" for one file on a empty/non-existing file:

                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cmdlineparser.cpp
                       $ cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=append cli/cppcheckexecutor.cpp
                       $ ls -la output_files/
                       total 16
                       drwxrwxr-x  2 user user 4096 Jul 22 14:54 .
                       drwxrwxr-x 26 user user 4096 Jul 22 14:36 ..
                       -rw-rw-r--  1 user user 5613 Jul 22 14:55 cppcheck.xml

                    /!\ the file is a pure concatenation of the files created without the "append" value which means that it's no more a valid XML file as it will have twice the "<?xml version="1.0" encoding="UTF-8"?>" entry
                      $ cat output_files/cppcheck.xml
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>
                      <?xml version="1.0" encoding="UTF-8"?>
                      <results version="2">
                        [...]
                      </results>

Signed-off-by: Robert Wakim <robert.wakim@arm.com>
@danmar
Copy link
Owner

danmar commented Jul 30, 2021

hi sorry for late reply. I am not convinced about the use case.

I believe you should run cppcheck on all the files to get the whole program analysis.

With a command such as cppcheck --output-file=cppcheck.xml <path> I would expect that cppcheck overwrites the xml file.

What do you think about creating the compile_commands.json with cmake and then run cppcheck like this:

cppcheck --project=compile_commands.json --xml 2> cppcheck.xml

I really recommend to use a cppcheck build dir also but it does not always work well in CI.

@RobertWak
Copy link
Author

RobertWak commented Aug 2, 2021

hi sorry for late reply. I am not convinced about the use case.

I believe you should run cppcheck on all the files to get the whole program analysis.

With a command such as cppcheck --output-file=cppcheck.xml <path> I would expect that cppcheck overwrites the xml file.

What do you think about creating the compile_commands.json with cmake and then run cppcheck like this:

cppcheck --project=compile_commands.json --xml 2> cppcheck.xml

I really recommend to use a cppcheck build dir also but it does not always work well in CI.

Hi,

I'm sorry you're not convinced, unfortunately we have very little solutions otherwise.

First a project may be build by blocks which are organized as libraries, these libraries are not always under the responsibility of one sole team, and therefore having all the files mixed up will require a triage overhead. This triage is useless as a cmake project is already taking care of it.
Secondly, CMake has made a great work integrating the call of cppcheck as part of it's generation process. I feel sorry that you seem to ignore the benefits it brings (see bellow how we call cppcheck from our CMakeLists.txt)
Third, the use of compile_commands.json was studied, but once again, CMake did a great integration job so the overhead of creating the json files becomes useless, plus needless to say it will still require the triage to happen.
Fourth, if possible, I would like to understand why the addition of a parameter that allows the user to decide the output type is something you don't want? In the current situation, I come to the conclusion that the CMake integration of cppcheck is very close to totally useless unless one's ok to just output to STDOUT and redirect everything into a file from the CMake command line, which then will mix up useless information, with compilers warnings/errors, with cppcheck errors.

CMakeLists.txt:
#
# Set up checkers.
#

set(cppcheck-flags)

list(APPEND cppcheck-flags "--enable=all")
list(APPEND cppcheck-flags "--xml")
list(APPEND cppcheck-flags "--xml-version=2")
list(APPEND cppcheck-flags "--output-file=${CMAKE_CURRENT_BINARY_DIR}/cppcheck.xml")
list(APPEND cppcheck-flags "--output-file-type=uniq")

if(PROJECT_STATIC_ANALYSIS_CPPCHECK_CHECKER_CERT_C)
    list(APPEND cppcheck-flags "--addon=cert")
endif()

if(PROJECT_STATIC_ANALYSIS_CPPCHECK_CHECKER_MISRA)
    list(APPEND cppcheck-flags "--addon=${CMAKE_CURRENT_SOURCE_DIR}/misra.json")
endif()

if(PROJECT_STATIC_ANALYSIS_CPPCHECK_CHECKER_THREAD_SAFETY)
    list(APPEND cppcheck-flags "--addon=threadsafety")
endif()

#
# Determine implicit C compiler definitions by pulling them from the
# compiler and dumping them into a header file. This is for those situations
# where we're relying on compiler implementation details, but Cppcheck
# doesn't expose them.
#

file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/null.txt")

separate_arguments(cflags NATIVE_COMMAND "${CMAKE_C_FLAGS}")

execute_process(
    COMMAND ${CMAKE_C_COMPILER} ${cflags} -dM -E -
    INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/null.txt"
    OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/implicit-defines.h")

list(APPEND cppcheck-flags
    "--include=${CMAKE_CURRENT_BINARY_DIR}/implicit-defines.h"
    "--suppress=*:${CMAKE_CURRENT_BINARY_DIR}/implicit-defines.h")

#
# Traditionally we would let Cppcheck use its own standard library headers,
# but it appears to be lacking some critical symbols like `CHAR_BIT` from
# `<limits.h>`. Luckily, CMake makes this relatively easy for us to do. We
# don't analyze these headers, we just make them available for inclusion.
#

foreach(include IN LISTS CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
    list(APPEND cppcheck-flags "-I${include}")
    list(APPEND cppcheck-flags "--suppress=*:${include}/*")
endforeach()

#
# Configure the platform file. This is done based on the current compiler,
# if possible, so that we can communicate certain implementation details to
# Cppcheck and avoid false positives.
#

set(platform-xml
    "${CMAKE_CURRENT_SOURCE_DIR}/compilers/${CMAKE_C_COMPILER_ID}.xml")

if(EXISTS "${platform-xml}")
    list(APPEND cppcheck-flags "--platform=${platform-xml}")
else()
    message(WARNING
        "No Cppcheck platform file is available for this compiler. Static "
        "analysis results may be inaccurate.")
endif()

separate_arguments(cppcheck-flags-user
    NATIVE_COMMAND "${PROJECT_STATIC_ANALYSIS_CPPCHECK_FLAGS}")

set(CMAKE_C_CPPCHECK
    "${PROJECT_STATIC_ANALYSIS_CPPCHECK_PATH}"
        ${cppcheck-flags} ${cppcheck-flags-user}
    CACHE INTERNAL "Cppcheck command line." FORCE)

@danmar
Copy link
Owner

danmar commented Aug 3, 2021

First of all I am trying to have an open mind and I want cppcheck to work for everybody. I do not intend to insult you but I don't blindly add features if I don't understand the use case a bit so would appreciate more info.

First a project may be build by blocks which are organized as libraries, these libraries are not always under the responsibility of one sole team, and therefore having all the files mixed up will require a triage overhead. This triage is useless as a cmake project is already taking care of it.

ok.

are all files in the library mixed together? or do each team have for instance its own folder with files? Do you have 1 common cmake file then how/where do you intend to separate the results? how does uniq/append fit in here?

I still believe that a whole program analysis for the whole library would make sense but that should be a separate step then.

Secondly, CMake has made a great work integrating the call of cppcheck as part of it's generation process. I feel sorry that you seem to ignore the benefits it brings (see bellow how we call cppcheck from our CMakeLists.txt)

I am a newbie when it comes to cmake. So I'll just trust you when you say they have made some great work. however if you ran cppcheck in a command line script then you would not have significant problems piping the results properly to arbitrary results file(s) so imho the cmake integration lack some handling of that.

you have probably messed with the cppcheck integration a lot and have a good feeling about it but I don't. And I do not really understand why "uniq" and "append" will be so useful. Hope you can clarify a bit..

Third, the use of compile_commands.json was studied, but once again, CMake did a great integration job so the overhead of creating the json files becomes useless, plus needless to say it will still require the triage to happen.

there are some ways around the triage problem. For instance if your team have its own folder you can use cppcheck --project=compile_commands.json --file-filter=teamx-path.

@RobertWak
Copy link
Author

First of all I am trying to have an open mind and I want cppcheck to work for everybody. I do not intend to insult you but I don't blindly add features if I don't understand the use case a bit so would appreciate more info.

Sorry, no problem. I will do my best to clarify the use case

First a project may be build by blocks which are organized as libraries, these libraries are not always under the responsibility of one sole team, and therefore having all the files mixed up will require a triage overhead. This triage is useless as a cmake project is already taking care of it.

ok.

are all files in the library mixed together? or do each team have for instance its own folder with files? Do you have 1 common cmake file then how/where do you intend to separate the results? how does uniq/append fit in here?

I still believe that a whole program analysis for the whole library would make sense but that should be a separate step then.

As many project, this project is organized in folders and subfolders depending on the goal of software.
CMake simplify this type of architecture by allowing you to (very) easily link together "parts" of the software.

So for example lets say you have 1 project build upon 3 useful "libraries"
Project A/
Core/
Lib1/
Lib2/
Lib3/

each of these being folders, then you would have
Project A:
CMakeLists.txt (the CMake "file")
Core/
CMakeLists.txt
Lib1/
CMakeLists.txt
Lib2/
CMakeLists.txt
Lib3/
CMakeLists.txt

Each CMakeLists.txt file live "on their own", meaning that they don't need to know who is going to call them, and each "library" can be used in other projects as long as they are self-sufficient.

What CMake will end-up building is static libraries for each sub-folder and linking all of them with the core code.

I'll be answering how uniq/append fits below.

Secondly, CMake has made a great work integrating the call of cppcheck as part of it's generation process. I feel sorry that you seem to ignore the benefits it brings (see bellow how we call cppcheck from our CMakeLists.txt)

I am a newbie when it comes to cmake. So I'll just trust you when you say they have made some great work. however if you ran cppcheck in a command line script then you would not have significant problems piping the results properly to arbitrary results file(s) so imho the cmake integration lack some handling of that.

I didn't know/expected that you weren't fully aware of the CMake integration, sorry.
CMake documentation is pretty bad, but here is the entry point for their cppcheck integration:
https://cmake.org/cmake/help/latest/prop_tgt/LANG_CPPCHECK.html

Basically what they did is that if you define CMAKE__CPPCHECK (CMAKE_C_CPPCHECK or CMAKE_CPP_CPPCHECK) then cmake will generate the Makefile/Ninja code that will run cppcheck alongside with the compiler. And what you can easily see is that in the CMake integration, they didn't follow your recommendation to check all the files at once, CMake does it on a file per file basis.

This is the Makefile generated for Cppcheck call:

runtime/CMakeFiles/proj-runtime.dir/core/handler.c.obj: runtime/CMakeFiles/proj-runtime.dir/flags.make
runtime/CMakeFiles/proj-runtime.dir/core/handler.c.obj: /home/user/work/PROJ/proj/runtime/core/handler.c
runtime/CMakeFiles/proj-runtime.dir/core/handler.c.obj: runtime/CMakeFiles/proj-runtime.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/tmp/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building C object runtime/CMakeFiles/proj-runtime.dir/core/handler.c.obj"
cd /tmp/build/runtime && $(CMAKE_COMMAND) -E __run_co_compile --cppcheck="/usr/local/bin/cppcheck;--enable=all;--xml;--xml-version=2;--output-file=/tmp/build/tools/cppcheck/cppcheck.xml;--output-file-type=uniq;--addon=cert;--addon=/home/user/work/PROJ/proj/tools/cppcheck/misra.json;--addon=threadsafety;--inline-suppr;--suppressions-list=/home/user/work/PROJ/proj/tools/cppcheck/suppressions.txt;--include=/tmp/build/tools/cppcheck/implicit-defines.h;--suppress=:/tmp/build/tools/cppcheck/implicit-defines.h;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include/;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include-fixed;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include-fixed/;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/aarch64-none-elf/include;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/aarch64-none-elf/include/*;--platform=/home/user/work/PROJ/proj/tools/cppcheck/compilers/GNU.xml" --source=/home/user/work/PROJ/proj/runtime/core/handler.c -- /opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT runtime/CMakeFiles/proj-runtime.dir/core/handler.c.obj -MF CMakeFiles/proj-runtime.dir/core/handler.c.obj.d -o CMakeFiles/proj-runtime.dir/core/handler.c.obj -c /home/user/work/PROJ/proj/runtime/core/handler.c

[...]removed useless lines[...]

runtime/CMakeFiles/proj-runtime.dir/core/interrupts.c.obj: runtime/CMakeFiles/proj-runtime.dir/flags.make
runtime/CMakeFiles/proj-runtime.dir/core/interrupts.c.obj: /home/user/work/PROJ/proj/runtime/core/interrupts.c
runtime/CMakeFiles/proj-runtime.dir/core/interrupts.c.obj: runtime/CMakeFiles/proj-runtime.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/tmp/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_11) "Building C object runtime/CMakeFiles/proj-runtime.dir/core/interrupts.c.obj"
cd /tmp/build/runtime && $(CMAKE_COMMAND) -E __run_co_compile --cppcheck="/usr/local/bin/cppcheck;--enable=all;--xml;--xml-version=2;--output-file=/tmp/build/tools/cppcheck/cppcheck.xml;--output-file-type=uniq;--addon=cert;--addon=/home/user/work/PROJ/proj/tools/cppcheck/misra.json;--addon=threadsafety;--inline-suppr;--suppressions-list=/home/user/work/PROJ/proj/tools/cppcheck/suppressions.txt;--include=/tmp/build/tools/cppcheck/implicit-defines.h;--suppress=:/tmp/build/tools/cppcheck/implicit-defines.h;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include/;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include-fixed;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1/include-fixed/;-I/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/aarch64-none-elf/include;--suppress=:/opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/aarch64-none-elf/include/*;--platform=/home/user/work/PROJ/proj/tools/cppcheck/compilers/GNU.xml" --source=/home/user/work/PROJ/proj/runtime/core/interrupts.c -- /opt/arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT runtime/CMakeFiles/proj-runtime.dir/core/interrupts.c.obj -MF CMakeFiles/proj-runtime.dir/core/interrupts.c.obj.d -o CMakeFiles/proj-runtime.dir/core/interrupts.c.obj -c /home/user/work/PROJ/proj/runtime/core/interrupts.c

The way they imagine cppcheck to be used is that the warning/errors are at the same level than the compiler and therefore you could have both "mixed up" on the output.

We tend to not fully align with the mixing of the outputs, as we already have a working/compiling software and we are integrating/adding cppcheck, the compiler already has no error/warning, and a developer is not allowed to put into review code that generate compiler warnings/errors. We intend to use cppcheck mainly for it's Misra-C support, and most (if not all) of the cppcheck/misra checks aren't trap by the compiler.

you have probably messed with the cppcheck integration a lot and have a good feeling about it but I don't. And I do not really understand why "uniq" and "append" will be so useful. Hope you can clarify a bit..

uniq (we don't plan to use append, but I added it as I thought it be logical to have it alongside with uniq and it removes the hassle of the redirection based on the type of shell you're using) in our case will allow us mainly to add the file to the ticket that we would end up creating to fix the issues reported by cppcheck. As we intend to run our build in CI, having a file per c-file allow us to split the work more easily. Without uniq, and with CMake integration (see bellow) we would end-up redirecting all the errors in a text file, then splitting it by hand. Using a file-filter is useless in our case as we would still need cppcheck to do its job on the files, but not "mixing" the results.

Third, the use of compile_commands.json was studied, but once again, CMake did a great integration job so the overhead of creating the json files becomes useless, plus needless to say it will still require the triage to happen.

there are some ways around the triage problem. For instance if your team have its own folder you can use cppcheck --project=compile_commands.json --file-filter=teamx-path.

As I wrote earlier, the file-filter option is useless to us, we need the file to be checked, but we would need the output to be separated from the other outputs.

So to try to summarize, the "uniq" (I can agree that it may not be the best naming), would allow use to the Cppcheck CMake integration while allowing us to dispatch more easily the errors to the proper people/team.

I totally agree that if we don't use the Cppcheck CMake integration, then uniq/append looses value.
But we would most certainly try not to use the compile_commands.json as it just output in json something that CMake already has and knows internally and therefore we would like to avoid doing the job twice.

BTW another way of doing this, would be to have special characters in the --file-output value (something like --file-output=cppcheck_%s.xml) that would replace the %s with the name of the file(s) being checked. This would be neater but I thought it would be too much of a change, and this is the reason why I added an option.

@danmar
Copy link
Owner

danmar commented Aug 4, 2021

Using the option with value "uniq" for two files

I would suggest that two result files was created then? I fear the scenario when somebody checks thousands of files and uses such option. I assume that would not make a difference for you as cmake only checks one file at a time? and it would fit the name "uniq" better.

Sometimes files in lib1 and lib2 might have the same name. not sure how to avoid getting the same name of the results files.

I wonder if we could ensure that;

  • cppcheck is executed using cmake, on each file.
  • it would be preferable that team1 and team2 will get separate results files. right? to me it seems it would be nice to pipe certain results to team1.xml and other results to team2.xml?
  • even though cppcheck is executed per-file I would like to make it possible to use a cppcheck build folder to speed up analysis and to get whole program analysis.
  • misra whole program analysis

Do you use the Cppcheck GUI to triage results?

BTW another way of doing this, would be to have special characters in the --file-output value (something like --file-output=cppcheck_%s.xml) that would replace the %s with the name of the file(s) being checked. This would be neater but I thought it would be too much of a change, and this is the reason why I added an option.

Yes

We intend to use cppcheck mainly for it's Misra-C support, and most (if not all) of the cppcheck/misra checks aren't trap by the compiler.

For information.. there are a number of misra rules that require whole program analysis. These were not implemented in cppcheck-2.5 but they will be implemented in cppcheck-2.6. If you want to use these you can't just run misra addon on a per-file basis. A final step in the build process that executes the misra addon could solve that but this step would generate warnings in all the related files.

@RobertWak
Copy link
Author

Using the option with value "uniq" for two files

I would suggest that two result files was created then? I fear the scenario when somebody checks thousands of files and uses such option. I assume that would not make a difference for you as cmake only checks one file at a time? and it would fit the name "uniq" better.

True, my naming is not the best. The "uniq" option means that each output file is uniq, because I add the name of the source file in the output file name (see the commit message)
cppcheck --output-file-option=uniq --output-file=cppcheck.xml file.c -> cppcheck_file_c.xml
cppcheck --output-file-option=uniq --output-file=cppcheck.xml file1.c -> cppcheck_file1_c.xml

Sometimes files in lib1 and lib2 might have the same name. not sure how to avoid getting the same name of the results files.

Yes correct, I didn't cover this use case, and it's a must have so we (I) need to come with some solutions here.

I wonder if we could ensure that;

  • cppcheck is executed using cmake, on each file.
  • it would be preferable that team1 and team2 will get separate results files. right? to me it seems it would be nice to pipe certain results to team1.xml and other results to team2.xml?
  • even though cppcheck is executed per-file I would like to make it possible to use a cppcheck build folder to speed up analysis and to get whole program analysis.
  • misra whole program analysis

Hum should be possible if we have a --output-file-prefix type of parameter, that would take, in the case of CMAKE, the "library" name automatically, I'm not sure we can do it with the current version of CMake, let me have a try at that and come back to you

I wasn't aware of the build folder mechanism, I will have a look at it.

Do you use the Cppcheck GUI to triage results?

No, I didn't know there is a Cppcheck GUI, but I'm don't see how it would help, as we intended to the triage out of the CI, without any (or very little) human interaction

We intend to use cppcheck mainly for it's Misra-C support, and most (if not all) of the cppcheck/misra checks aren't trap by the compiler.

For information.. there are a number of misra rules that require whole program analysis. These were not implemented in cppcheck-2.5 but they will be implemented in cppcheck-2.6. If you want to use these you can't just run misra addon on a per-file basis. A final step in the build process that executes the misra addon could solve that but this step would generate warnings in all the related files.

Our project doesn't require to be Misra-C compliant, so we don't need all the rules to be checked, and after reviewing Cppcheck Misra coverage, it covers almost all of our rule subsets. But your point if more than valid and has to be solved, but it must be done on the CMake side as CMake is the tool doing the per file analysis.

The more I think about it, and the more it becomes tricky.
Imagine a CMake project, with a core and 2 libs, each lib have a common.h header file, in CMake that wouldn't be an issue as each lib would be built (compiled and linked) independently, and then the .so/a would be linked together with the core to generate the final object.
if you want Cppcheck to run on the whole project you will end up with 2 -I , and you wouldn't know which one to pick for which .c file. On the other side, rules like: there shouldn't be unused XXX can't be checked without doing it on the whole project, i.e. if core does or doesn't call function xxx from lib1, can only be done if you check both core and lib1 at the same time.
And my final thought about this is that you can't either rely on executing the build object, as it may just not run on your host computer.

Maybe we should tackle each issue independently, I fear we might always refuse any improvement as we will always find a something new that can prove it to become not fulfilling the objective(as the objective changed since we added something).

@danmar
Copy link
Owner

danmar commented Aug 6, 2021

True, my naming is not the best. The "uniq" option means that each output file is uniq, because I add the name of the source file in the output file name (see the commit message)
cppcheck --output-file-option=uniq --output-file=cppcheck.xml file.c -> cppcheck_file_c.xml

I agree about that. But your commit message also said:

cppcheck --enable=all --xml --xml-version=2 --output-file=output_files/cppcheck.xml --output-file-type=uniq cli/cmdlineparser.cpp cli/cppcheckexecutor.cpp

=> cppcheck_cmdlineparser_cpp_cppcheckexecutor_cpp.xml

I suggest that 2 output files are created:

cppcheck_cmdlineparser_cpp.xml
cppcheck_cppcheckexecutor_cpp.xml

even though cppcheck is executed per-file I would like to make it possible to use a cppcheck build folder to speed up analysis and to get whole program analysis.

We can wait with implementing a solution for this in my opinion, but it's good to think about this now.

But it seems to me that a pre-build step is needed where cppcheck initialize the build dir. then a post-build step is needed where cppcheck perform the whole program analysis.

For information, when cppcheck initializes the build dir, a unique id "filename.aX" is created for each source file (X is 1,2,3,..) . With that X "uniq" can generate a unique output filename for every source file. If all files have unique names then X will always be 1. The "X" for a file might change when files are added/removed.

No, I didn't know there is a Cppcheck GUI, but I'm don't see how it would help, as we intended to the triage out of the CI, without any (or very little) human interaction

ok.

Maybe we should tackle each issue independently, I fear we might always refuse any improvement as we will always find a something new that can prove it to become not fulfilling the objective(as the objective changed since we added something).

Yes certainly. I do believe we can solve a piece of the problem to start with. But would like to have a overall goal for later so it will make sense later also. it will hurt a lot to change existing behavior later.

@danmar
Copy link
Owner

danmar commented Aug 6, 2021

if you want Cppcheck to run on the whole project you will end up with 2 -I , and you wouldn't know which one to pick for which .c file.

No. With cppcheck --project=compile_commands.json you get whole program analysis and during the analysis each file has unique options..

@danmar
Copy link
Owner

danmar commented Aug 6, 2021

If you use a cppcheck build dir then the generated "filename.a1" files will contain all the error messages. You could extract all results from those. However the format of the "filename.a1" file might be changed in the future so it's not a good idea that users parse those directly. Cppcheck project could provide a tool to extract certain results from the cppcheck build dir.

i.e. in your build script there could be a post build step with such command:

cppcheck-get-results --output team1.xml --from=build lib1/*.c

@RobertWak
Copy link
Author

Sorry Daniel, I had to focus on other topics.

I've had a deeper look at the build folder, the feature is very nice, but create new problems.

The Build folder will generate the xml files (named .aX) but without (rightfully) applying any of the suppressions. I fully understand that this is intentional. But because each file contains all the errors, even the ones you would want to ignore/remove it looses all of it advantage.

But this is very close to want I wanted, and if we could have a way to merge the build folder capabilities with the rest of the config/arguments, then I would have a working solution.

My current goal is to have an output folder, with 1 file per filename (made unique if 2 C file have the same names), which would be the final .xml file (with all the arguments applied, e.g. --suppression). Maybe we could just create a --cppcheck-output-dir option that would do this? If you agree, I can take the time to write the code and push a new PR

BTW: why don't you let cppcheck create (if not exist) the --cppcheck-build-folder?

@danmar
Copy link
Owner

danmar commented Aug 16, 2021

I am very happy that I didn't scare you off with my comments.

Maybe we could just create a --cppcheck-output-dir option

Sounds ok to me. So how do you suggest it will work.

I imagine:

  1. a PRE-BUILD step will create the output/build dir and write the filelist.txt. In the PRE-BUILD step it will be determined what the filename will be for each source file.
  2. Cppcheck is executed on each file, it will use the filelist.txt in the output/build dir to determine what the output filename will be.
  3. You can add an optional POST-BUILD step that performs the whole program analysis. If --cppcheck-output-dir has been used it would be good to separate results according to filelist.txt so whole program analysis results for foo.cpp is stored in a output file for foo.cpp.

So maybe we need some additional --cppcheck-step=pre|file|post option.

Normally Cppcheck is executed on a whole project at once and then it just executes all the pre+file+post steps automatically. So that will remain the default behavior.

@RobertWak
Copy link
Author

I am very happy that I didn't scare you off with my comments.

No worries.

Maybe we could just create a --cppcheck-output-dir option

Sounds ok to me. So how do you suggest it will work.

I imagine:

  1. a PRE-BUILD step will create the output/build dir and write the filelist.txt. In the PRE-BUILD step it will be determined what the filename will be for each source file.
  2. Cppcheck is executed on each file, it will use the filelist.txt in the output/build dir to determine what the output filename will be.
  3. You can add an optional POST-BUILD step that performs the whole program analysis. If --cppcheck-output-dir has been used it would be good to separate results according to filelist.txt so whole program analysis results for foo.cpp is stored in a output file for foo.cpp.

Yes this sounds very good.

So maybe we need some additional --cppcheck-step=pre|file|post option.

From a usage/user point of view, I don't see the point of just running the pre BUILD step alone (i.e. never running the file step).
For now, as a user, the minimum I'm looking for is the file step, and at one point I will also want/need the post step as some of the checks can't happen if not run on the full program.

what about an additional --cppcheck-scope=file|full, the default being full, but you can limit the scope to a file base only.

Normally Cppcheck is executed on a whole project at once and then it just executes all the pre+file+post steps automatically. So that will remain the default behavior.

yes.

@danmar
Copy link
Owner

danmar commented Aug 17, 2021

From a usage/user point of view, I don't see the point of just running the pre BUILD step alone (i.e. never running the file step).
For now, as a user, the minimum I'm looking for is the file step, and at one point I will also want/need the post step as some of the checks can't happen if not run on the full program.

Yes.. but at some point you need to map source file => output file

In default Cppcheck checking we do this mapping first. Cppcheck collects all files that will be checked in a list and then create unique output filenames.

During the "file" step Cppcheck will only know 1 file that will be checked, won't it? I guess the check path(s) could also be provided. Otherwise.. how will you map source file => output file in the "file" step if source files can have the same names.

@RobertWak
Copy link
Author

From a usage/user point of view, I don't see the point of just running the pre BUILD step alone (i.e. never running the file step).
For now, as a user, the minimum I'm looking for is the file step, and at one point I will also want/need the post step as some of the checks can't happen if not run on the full program.

Yes.. but at some point you need to map source file => output file

In default Cppcheck checking we do this mapping first. Cppcheck collects all files that will be checked in a list and then create unique output filenames.

During the "file" step Cppcheck will only know 1 file that will be checked, won't it? I guess the check path(s) could also be provided. Otherwise.. how will you map source file => output file in the "file" step if source files can have the same names.

Sorry I think I didn't make myself clear enough, my bad.

What I was saying is that --cppcheck-step=pre on it's own, to my usage/opinion, has very little interest.
So I was suggesting that we group "pre" and "file" into one single --cppcheck-xxxx=file, and that we group "pre", "file" and "post" into one single "full".

so the mapping will happen for both values, "file" and "full", as being a common "pre" processing.

I hope this clarify what I was thing off.

@danmar
Copy link
Owner

danmar commented Aug 17, 2021

That does not clarify it. Imagine a small project with 2 files source files:

/foo/file.c
/bar/file.c

So if cppcheck will be executed like this:

cppcheck --cppcheck-scope=file --cppcheck-output-folder=out/ /foo/file.c
cppcheck --cppcheck-scope=file --cppcheck-output-folder=out/ /bar/file.c 

what will the output filename be when /foo/file.c is checked? And when /bar/file.c is checked?

@RobertWak
Copy link
Author

That does not clarify it. Imagine a small project with 2 files source files:

hum sorry :(

/foo/file.c
/bar/file.c

So if cppcheck will be executed like this:

cppcheck --cppcheck-scope=file --cppcheck-output-folder=out/ /foo/file.c
cppcheck --cppcheck-scope=file --cppcheck-output-folder=out/ /bar/file.c 

So after the first run since --cppcheck-scope=file is the equivalent of your proposed --cppcheck-build=pre + --cppcheck-build=file I expect to have a "build-folder like" folder with the files.txt that will have:

file.a1::/foo/file.c

and (proposal) we have a file.a1.xml which is the result of the cppcheck checks with the proper arguments parsed (so without any of the --suppressions)

when you run it again a second time, then cppcheck will notice that there is already an entry for a file.c but not the same path, so either it enough or with a hash of the file we confirm that they are different, so we do again a pre and we update the files.txt

file.a1::/foo/file.c
file.a2::/bar/file.c

what will the output filename be when /foo/file.c is checked? And when /bar/file.c is checked?

I believe that we have a
file.a1.xml and a file.a2.xml and a files.txt

Maybe the confusion I have, is that I expect the "pre" to be always run, and to update the files.txt at each run:

  • create if doesn't exist
  • check if current file is or is not in the files.txt

Am I wrong in the expectation?

@danmar
Copy link
Owner

danmar commented Aug 17, 2021

when you run it again a second time

when you run with -j2 it seems possible that both cppcheck will try to open the file for write at the same time.

with a proper "pre" step the order will be the same so unless you rename/remove/add files, a source file would always get the same output file.

@RobertWak
Copy link
Author

when you run it again a second time

when you run with -j2 it seems possible that both cppcheck will try to open the file for write at the same time.

I'm not keen on the idea, but the only file we need to protect against concurrent access is files.txt. I didn't have a look, but are you forking or using threads for -jX ? if you're using threads then we could have the files.txt handled by the main, and access to the file can only be done via thread protected calls to it.

Anyway this isn't a good solution, it feels like trying to put a square peg into a round hole.

with a proper "pre" step the order will be the same so unless you rename/remove/add files, a source file would always get the same output file.

Now I understand, but then we're running again into the way CMake is using cppcheck...
CMake is calling cppcheck on each file individually, which collides with the way you designed cppcheck usage. From our discussion, I understand why this is not optimal. And from my understanding of how CMake is designed, I fear we're in a dead-end.

I will need to talk to some of the CMake experts at work to see if we can come up with a solution from the CMake end.

@chrchr-github
Copy link
Collaborator

Closing due to long time of inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants