Added ability to use cppcheck from the command line.
authorTeemu Murtola <teemu.murtola@gmail.com>
Tue, 28 May 2013 18:54:46 +0000 (21:54 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 13 Jun 2013 15:10:16 +0000 (17:10 +0200)
CMake now detects cppcheck, and enables "make cppcheck" to run
cppcheck on all source files, generated kernels and some other files
excluded.  Commands are more or less the same as used in Jenkins.
A separate target is produced for each input file, allowing one to use
build system parallelism (tested that it doesn't have much effect on the
overall run time).  This also adds a nice property that after the
initial run, cppcheck gets only run on modified files.  All errors
(including those from unmodified files) are also collected into a single
text file for easier processing.

No effort has been made to make it particularly robust or portable,
e.g., with respect to different cppcheck versions, as it is mostly for
developer convenience to be able to reproduce the runs from Jenkins.

Ideally, Jenkins would also run cppcheck using the generated rules,
which would allow changing the cppcheck configuration in sync with
source code changes if that is necessary.  For this purpose, a CMake
option to switch to XML output files is provided.

Change-Id: Ib88e2ba87cd4f091484fe09beac5ef108b0fad77

tests/.gitignore [new file with mode: 0644]
tests/CMakeLists.txt
tests/CppCheck.cmake [new file with mode: 0644]

diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644 (file)
index 0000000..74064db
--- /dev/null
@@ -0,0 +1,2 @@
+cppcheck-*.txt
+cppcheck-*.xml
index c47b3927c7fbe737bedbbcb1aef690bf9b92f87f..446951f36408f553a311d3435f456af28caa5351 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2012, by the GROMACS development team, led by
+# Copyright (c) 2012,2013, by the GROMACS development team, led by
 # David van der Spoel, Berk Hess, Erik Lindahl, and including many
 # others, as listed in the AUTHORS file in the top-level source
 # directory and at http://www.gromacs.org.
@@ -160,3 +160,5 @@ if(REGRESSIONTEST_PATH)
             ENVIRONMENT "PATH=${PATH}")
     endforeach()
 endif()
+
+include(CppCheck.cmake)
diff --git a/tests/CppCheck.cmake b/tests/CppCheck.cmake
new file mode 100644 (file)
index 0000000..c2cf88c
--- /dev/null
@@ -0,0 +1,136 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2013, by the GROMACS development team, led by
+# David van der Spoel, Berk Hess, Erik Lindahl, and including many
+# others, as listed in the AUTHORS file in the top-level source
+# directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+#
+
+find_program(CPPCHECK_EXECUTABLE
+    NAMES cppcheck
+    DOC "cppcheck executable")
+mark_as_advanced(CPPCHECK_EXECUTABLE)
+option(CPPCHECK_XML_OUTPUT "Whether to produce XML output from cppcheck (mainly for Jenkins)"
+       OFF)
+mark_as_advanced(CPPCHECK_XML_OUTPUT)
+
+# Depends on stderr redirection and cat
+if (CPPCHECK_EXECUTABLE AND UNIX)
+    # Produce the list of files to check
+    file(GLOB_RECURSE _inputfiles RELATIVE ${CMAKE_SOURCE_DIR}
+        ${CMAKE_SOURCE_DIR}/src/*.c
+        ${CMAKE_SOURCE_DIR}/src/*.cpp
+        ${CMAKE_SOURCE_DIR}/src/*.cu)
+    file(GLOB_RECURSE _files_to_ignore RELATIVE ${CMAKE_SOURCE_DIR}
+        ${CMAKE_SOURCE_DIR}/src/nb_kernel_Elec*.c
+        ${CMAKE_SOURCE_DIR}/src/gromacs/linearalgebra/gmx_blas/*.c
+        ${CMAKE_SOURCE_DIR}/src/gromacs/linearalgebra/gmx_lapack/*.c
+        ${CMAKE_SOURCE_DIR}/src/contrib/*.c
+        ${CMAKE_SOURCE_DIR}/src/contrib/*.cpp
+        ${CMAKE_SOURCE_DIR}/src/contrib/*.cu)
+    list(REMOVE_ITEM _inputfiles ${_files_to_ignore})
+
+    # Set flags for cppcheck
+    set(_outputext txt)
+    set(_outputopt --template=gcc)
+    if (CPPCHECK_XML_OUTPUT)
+        set(_outputext xml)
+        set(_outputopt --xml)
+    endif()
+    set(_common_flags
+        --enable=style
+        -DSIZEOF_LONG_LONG_INT=8 -DSIZEOF_INT=4 -DLINUX
+        -I src/gromacs/legacyheaders -I src
+        -I ${CMAKE_BINARY_DIR}/src -I ${CMAKE_BINARY_DIR}/src/gromacs/utility
+        --quiet
+        ${_outputopt})
+    set(_c_flags
+        -I src/gromacs/gmxpreprocess
+        -I src/programs/mdrun -I src/programs/pdb2gmx
+        --suppress=variableScope
+        --suppress=unusedVariable
+        --suppress=unreadVariable
+        --suppress=unusedStructMember
+        --suppress=invalidscanf
+        --suppress=sizeofCalculation
+        --suppress=missingInclude:src/programs/mdrun/gmx_gpu_utils/gmx_gpu_utils.cu
+        --inline-suppr)
+    set(_cxx_flags
+        --suppress=variableScope
+        --suppress=unnecessaryForwardDeclaration
+        --suppress=*:src/gromacs/selection/scanner.cpp)
+
+    # This list will hold the list of all files with cppcheck errors
+    # (one per input file)
+    set(_filelist)
+
+    foreach (_filename ${_inputfiles})
+        set(_target_name cppcheck-${_filename}.${_outputext})
+        string(REPLACE "/" "_" _target_name ${_target_name})
+        list(APPEND _filelist ${_target_name})
+        if (_filename MATCHES "\\.cpp$")
+            set(_lang CXX)
+            set(_lang_flags ${_cxx_flags})
+        else()
+            set(_lang C)
+            set(_lang_flags ${_c_flags})
+        endif()
+        add_custom_command(
+            OUTPUT ${_target_name}
+            COMMAND ${CPPCHECK_EXECUTABLE} ${_common_flags} ${_lang_flags}
+                ${_filename} 2> ${CMAKE_CURRENT_BINARY_DIR}/${_target_name}
+            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+            IMPLICIT_DEPENDS ${_lang} ${CMAKE_SOURCE_DIR}/${_filename}
+            COMMENT "Running cppcheck for ${_filename}"
+            VERBATIM)
+        if (NOT CPPCHECK_XML_OUTPUT)
+            add_custom_command(
+                OUTPUT ${_target_name}
+                COMMAND cat ${CMAKE_CURRENT_BINARY_DIR}/${_target_name}
+                VERBATIM APPEND)
+        endif()
+    endforeach()
+    if (NOT CPPCHECK_XML_OUTPUT)
+        set(_target_name cppcheck-errors.${_outputext})
+        add_custom_command(
+            OUTPUT ${_target_name}
+            COMMAND cat ${_filelist} > ${_target_name}
+            DEPENDS ${_filelist}
+            COMMENT "Combining cppcheck results"
+            VERBATIM)
+        list(APPEND _filelist ${_target_name})
+    endif()
+    add_custom_target(cppcheck DEPENDS ${_filelist})
+else()
+    add_custom_target(cppcheck
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "cppcheck was not found by CMake. Rerun CMake specifying CPPCHECK_EXECUTABLE."
+        VERBATIM)
+endif()