add new cppcheck example with updated dockerfiles
This commit is contained in:
parent
59159c4c38
commit
ef0d61aa0e
17
04-static-analysis/cppcheck-compile-commands/CMakeLists.txt
Normal file
17
04-static-analysis/cppcheck-compile-commands/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
cmake_minimum_required (VERSION 3.0)
|
||||
|
||||
project(cppcheck_analysis)
|
||||
|
||||
# Have cmake create a compile database
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Add a custom CMake Modules directory
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules
|
||||
${CMAKE_MODULE_PATH})
|
||||
|
||||
# find the cppcheck binary
|
||||
find_package(CppCheck)
|
||||
|
||||
# Add sub directories
|
||||
add_subdirectory(subproject1)
|
||||
add_subdirectory(subproject2)
|
183
04-static-analysis/cppcheck-compile-commands/README.adoc
Normal file
183
04-static-analysis/cppcheck-compile-commands/README.adoc
Normal file
@ -0,0 +1,183 @@
|
||||
= CppCheck Static Analysis using Compile Commands
|
||||
:toc:
|
||||
:toc-placement!:
|
||||
|
||||
toc::[]
|
||||
|
||||
# Introduction
|
||||
|
||||
This example shows how to call the
|
||||
http://cppcheck.sourceforge.net/[CppCheck] tool to do static analysis.
|
||||
This shows how to use projects and a compile database.
|
||||
Projects are available from cppcheck v1.77
|
||||
|
||||
It includes code to
|
||||
|
||||
* Find the cppcheck binary
|
||||
* Generate an overall `make cppcheck-analysis` target to do static
|
||||
analysis on all sub-projects.
|
||||
|
||||
The files included in this example are:
|
||||
|
||||
```
|
||||
$ tree
|
||||
.
|
||||
├── cmake
|
||||
│ └── modules
|
||||
│ └── FindCppCheck.cmake
|
||||
├── CMakeLists.txt
|
||||
├── subproject1
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── main1.cpp
|
||||
└── subproject2
|
||||
├── CMakeLists.txt
|
||||
└── main2.cpp
|
||||
```
|
||||
|
||||
* link:CMakeLists.txt[] - Top level CMakeLists.txt
|
||||
* link:cmake/modules/FindCppCheck.cmake[] - A custom package module to find CppCheck
|
||||
* link:subproject1/CMakeLists.txt[] - CMake commands for subproject 1
|
||||
* link:subproject1/main.cpp[] - source for a subproject with no errors
|
||||
* link:subproject2/CMakeLists.txt[] - CMake commands for subproject 2
|
||||
* link:subproject2/main2.cpp[] - source for a subproject that includes errors
|
||||
|
||||
# Requirements
|
||||
|
||||
To run this example you must have CppCheck of at least v1.77 installed. This is not
|
||||
available by default on Ubuntu but can be compiled using the following command.
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
$ wget https://github.com/danmar/cppcheck/archive/1.79.tar.gz \
|
||||
&& tar xvf 1.79.tar.gz \
|
||||
&& cd cppcheck-1.79 \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake .. \
|
||||
&& sudo make install
|
||||
----
|
||||
|
||||
# Concepts
|
||||
|
||||
## Adding Custom Package Modules
|
||||
|
||||
As with the previous example I use a custom module to find CppCheck. This version is slightly different to the pervious one and
|
||||
will automatically add a `make cppcheck-analysis` target.
|
||||
|
||||
[source,cmake]
|
||||
----
|
||||
if(CPPCHECK_FOUND)
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/analysis/cppcheck)
|
||||
add_custom_target(cppcheck-analysis
|
||||
COMMAND ${CPPCHECK_COMMAND})
|
||||
message("cppcheck found. Use cppccheck-analysis targets to run it")
|
||||
else()
|
||||
message("cppcheck not found. No cppccheck-analysis targets")
|
||||
endif()
|
||||
----
|
||||
|
||||
The variables available have also changed. For full details on the commands see the `FindCppCheck.cmake` module. Below are a subset of the available options:
|
||||
|
||||
### Suppressions
|
||||
|
||||
Adding a suppression file called `.cppcheck-suppressions` which must be in your +CMAKE_SOURCE_DIR+
|
||||
|
||||
### Error Exitcode
|
||||
|
||||
When cppcheck finds an error it can cause it to exit with a specific error. In this
|
||||
example, by default, it will exit with `1`. To change this you can set the
|
||||
+CPPCHECK_ERROR_EXITCODE_ARG+ argument when running CMake.
|
||||
|
||||
### CppCheck build dir
|
||||
|
||||
In this example, we set +CPPCHECK_BUILD_DIR_ARG+, to `${PROJECT_BINARY_DIR}/analysis/cppcheck`. This will output details of the build to this folder and can be used to
|
||||
increase the speed of rechecks if a file hasn't changed
|
||||
|
||||
## Compile Database
|
||||
|
||||
CMake allows you to export all https://cmake.org/cmake/help/v3.5/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html[compile commands]
|
||||
that are used to build the project into a file called `compile_commands.json`
|
||||
|
||||
This can be done by setting the +CMAKE_EXPORT_COMPILE_COMMANDS+ variable to +ON+
|
||||
as below:
|
||||
|
||||
[source,cmake]
|
||||
----
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
----
|
||||
|
||||
The JSON file will look like:
|
||||
|
||||
[source,json]
|
||||
----
|
||||
[
|
||||
{
|
||||
"directory": "/home/user/development/project",
|
||||
"command": "/usr/bin/c++ ... -c ../foo/foo.cc",
|
||||
"file": "../foo/foo.cc"
|
||||
},
|
||||
|
||||
...
|
||||
|
||||
{
|
||||
"directory": "/home/user/development/project",
|
||||
"command": "/usr/bin/c++ ... -c ../foo/bar.cc",
|
||||
"file": "../foo/bar.cc"
|
||||
}
|
||||
]
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
----
|
||||
This is only available for the `Makefile` and `ninja` generators.
|
||||
----
|
||||
|
||||
## CppCheck Projects
|
||||
|
||||
Starting with CppCheck v1.77, you can pass the `--project` flag pointing to the
|
||||
compile database. This will cause CppCheck to run on al your cpp files using the same
|
||||
include directories and compiler flags as your normal build.
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
cppcheck --project=compile_comands.json
|
||||
----
|
||||
|
||||
This will check all files in your project and sub-projects. There will be no analysis target per sub-project as with our previous example.
|
||||
|
||||
# Building the example
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
$ mkdir build
|
||||
|
||||
$ cd build/
|
||||
|
||||
$ cmake ..
|
||||
-- The C compiler identification is GNU 4.8.4
|
||||
-- The CXX compiler identification is GNU 4.8.4
|
||||
-- Check for working C compiler: /usr/bin/cc
|
||||
-- Check for working C compiler: /usr/bin/cc -- works
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Check for working CXX compiler: /usr/bin/c++
|
||||
-- Check for working CXX compiler: /usr/bin/c++ -- works
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Found CPPCHECK: /usr/local/bin/cppcheck
|
||||
cppcheck found. Use cppccheck-analysis targets to run it
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /data/code/04-static-analysis/cppcheck-compile-commands/build
|
||||
|
||||
$ make cppcheck-analysis
|
||||
Scanning dependencies of target cppcheck-analysis
|
||||
[/data/code/04-static-analysis/cppcheck-compile-commands/subproject2/main2.cpp:7]: (error) Array 'tmp[10]' accessed at index 11, which is out of bounds.
|
||||
make[3]: *** [CMakeFiles/cppcheck-analysis] Error 1
|
||||
make[2]: *** [CMakeFiles/cppcheck-analysis.dir/all] Error 2
|
||||
make[1]: *** [CMakeFiles/cppcheck-analysis.dir/rule] Error 2
|
||||
make: *** [cppcheck-analysis] Error 2
|
@ -0,0 +1,94 @@
|
||||
# Locate cppcheck
|
||||
#
|
||||
# This module defines
|
||||
# CPPCHECK_BIN, where to find cppcheck
|
||||
#
|
||||
# To help find the binary you can set CPPCHECK_ROOT_DIR to search a custom path
|
||||
# Exported argumets include
|
||||
# CPPCHECK_FOUND, if false, do not try to link to cppcheck --- if (CPPCHECK_FOUND)
|
||||
#
|
||||
# CPPCHECK_THREADS_ARG - Number of threads to use (e.g. -j 3)
|
||||
# CPPCHECK_PROJECT_ARG - The project to use (compile_comands.json)
|
||||
# CPPCHECK_BUILD_DIR_ARG - The build output directory
|
||||
# CPPCHECK_ERROR_EXITCODE_ARG - The exit code if an error is found
|
||||
# CPPCHECK_SUPPRESSIONS - A suppressiosn file to use
|
||||
# CPPCHECK_CHECKS_ARGS - The checks to run
|
||||
# CPPCHECK_OTHER_ARGS - Any other arguments
|
||||
# CPPCHECK_COMMAND - The full command to run the default cppcheck configuration
|
||||
#
|
||||
# find the cppcheck binary
|
||||
|
||||
# if custom path check there first
|
||||
if(CPPCHECK_ROOT_DIR)
|
||||
find_program(CPPCHECK_BIN
|
||||
NAMES
|
||||
cppcheck
|
||||
PATHS
|
||||
"${CPPCHECK_ROOT_DIR}"
|
||||
NO_DEFAULT_PATH)
|
||||
endif()
|
||||
|
||||
find_program(CPPCHECK_BIN NAMES cppcheck)
|
||||
|
||||
if(CPPCHECK_BIN)
|
||||
execute_process(COMMAND ${CPPCHECK_BIN} --version
|
||||
OUTPUT_VARIABLE CPPCHECK_VERSION
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(CPPCHECK_THREADS_ARG "-j4" CACHE STRING "The number of threads to use")
|
||||
set(CPPCHECK_PROJECT_ARG "--project=${PROJECT_BINARY_DIR}/compile_commands.json")
|
||||
set(CPPCHECK_BUILD_DIR_ARG "--cppcheck-build-dir=${PROJECT_BINARY_DIR}/analysis/cppcheck" CACHE STRING "The build directory to use")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.cppcheck_suppressions")
|
||||
set(CPPCHECK_SUPPRESSIONS "--suppressions-list=${CMAKE_SOURCE_DIR}/.cppcheck_suppressions" CACHE STRING "The suppressions file to use")
|
||||
else()
|
||||
set(CPPCHECK_SUPPRESSIONS "" CACHE STRING "The suppressions file to use")
|
||||
endif()
|
||||
set(CPPCHECK_ERROR_EXITCODE_ARG "--error-exitcode=1" CACHE STRING "The exitcode to use if an error is found")
|
||||
set(CPPCHECK_CHECKS_ARGS "" CACHE STRING "Arguments for the checks to run")
|
||||
set(CPPCHECK_OTHER_ARGS "--quiet" CACHE STRING "Other arguments")
|
||||
|
||||
set(CPPCHECK_ALL_ARGS
|
||||
${CPPCHECK_THREADS_ARG}
|
||||
${CPPCHECK_PROJECT_ARG}
|
||||
${CPPCHECK_BUILD_DIR_ARG}
|
||||
${CPPCHECK_ERROR_EXITCODE_ARG}
|
||||
${CPPCHECK_SUPPRESSIONS}
|
||||
${CPPCHECK_CHECKS_ARGS}
|
||||
${CPPCHECK_OTHER_ARGS}
|
||||
)
|
||||
|
||||
set(CPPCHECK_COMMAND
|
||||
${CPPCHECK_BIN}
|
||||
${CPPCHECK_ALL_ARGS}
|
||||
)
|
||||
|
||||
#TODO add version check on the binary
|
||||
endif()
|
||||
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
|
||||
CPPCHECK
|
||||
DEFAULT_MSG
|
||||
CPPCHECK_BIN)
|
||||
|
||||
mark_as_advanced(
|
||||
CPPCHECK_BIN
|
||||
CPPCHECK_THREADS_ARG
|
||||
CPPCHECK_PROJECT_ARG
|
||||
CPPCHECK_BUILD_DIR_ARG
|
||||
CPPCHECK_ERROR_EXITCODE_ARG
|
||||
CPPCHECK_SUPPRESSIONS
|
||||
CPPCHECK_CHECKS_ARGS
|
||||
CPPCHECK_OTHER_ARGS)
|
||||
|
||||
if(CPPCHECK_FOUND)
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/analysis/cppcheck)
|
||||
add_custom_target(cppcheck-analysis
|
||||
COMMAND ${CPPCHECK_COMMAND})
|
||||
message("cppcheck found. Use cppccheck-analysis targets to run it")
|
||||
else()
|
||||
message("cppcheck not found. No cppccheck-analysis targets")
|
||||
endif()
|
2
04-static-analysis/cppcheck-compile-commands/run_test.sh
Executable file
2
04-static-analysis/cppcheck-compile-commands/run_test.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
mkdir -p build && cd build && cmake -DCPPCHECK_ERROR_EXITCODE_ARG="" .. && make cppcheck-analysis
|
@ -0,0 +1,10 @@
|
||||
# Set the project name
|
||||
project (subproject1)
|
||||
|
||||
# Create a sources variable with a link to all cpp files to compile
|
||||
set(SOURCES
|
||||
main1.cpp
|
||||
)
|
||||
|
||||
# Add an executable with the above sources
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
@ -0,0 +1,7 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout << "Hello Main1!" << std::endl;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# Set the project name
|
||||
project (subproject2)
|
||||
|
||||
# Create a sources variable with a link to all cpp files to compile
|
||||
set(SOURCES
|
||||
main2.cpp
|
||||
)
|
||||
|
||||
# Add an executable with the above sources
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
@ -0,0 +1,9 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout << "Hello Main2!" << std::endl;
|
||||
char tmp[10];
|
||||
tmp[11] = 's';
|
||||
return 0;
|
||||
}
|
@ -8,6 +8,7 @@ toc::[]
|
||||
|
||||
This example shows how to call the
|
||||
http://cppcheck.sourceforge.net/[CppCheck] tool to do static analysis.
|
||||
This shows how to make an analysis target for each project in your repository.
|
||||
|
||||
It includes code to
|
||||
|
||||
@ -318,6 +319,8 @@ make: *** [analysis] Error 2
|
||||
|
||||
# Extra Notes
|
||||
|
||||
## Multiple Folders
|
||||
|
||||
If you have a multiple folders levels, where one folder just points to
|
||||
sub folders, such as below:
|
||||
|
||||
@ -343,3 +346,20 @@ add_subdirectory(project1)
|
||||
add_subdirectory(project2)
|
||||
set(ALL_ANALYSIS_TARGETS "${ALL_ANALYSIS_TARGETS}" PARENT_SCOPE)
|
||||
----
|
||||
|
||||
## Include Directories
|
||||
|
||||
In the +add_analysis+ macro in `analysis.cmake` we extract the +INCLUDE_DIRECTORIES+ from the
|
||||
target and add them to the call to cppcheck.
|
||||
|
||||
[source,cmake]
|
||||
----
|
||||
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
foreach(dir ${dirs})
|
||||
LIST(APPEND cppcheck_includes "-I${dir}")
|
||||
endforeach()
|
||||
----
|
||||
|
||||
This works for basic examples but if you use some CMake features such as
|
||||
generator expressions this will not add the include directory.
|
||||
|
||||
|
2
04-static-analysis/cppcheck/run_test.sh
Executable file
2
04-static-analysis/cppcheck/run_test.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
mkdir -p build && cd build && cmake .. && make analysis
|
@ -4,7 +4,7 @@
|
||||
# variables and give them sudo access
|
||||
#
|
||||
ret=false
|
||||
output=`getent passwd devuser 2&>1`
|
||||
output=`getent passwd devuser 2>&1`
|
||||
result=$?
|
||||
if [ $result -ne 0 ] ; then
|
||||
echo "Creating devuser"
|
||||
@ -23,4 +23,4 @@ if [ $result -ne 0 ] ; then
|
||||
echo "%sudo ALL=NOPASSWD: ALL" >> /etc/sudoers
|
||||
fi
|
||||
|
||||
exec /bin/su - devuser -c "$@"
|
||||
exec gosu devuser "$@"
|
||||
|
@ -7,7 +7,6 @@ RUN apt-get update && apt-get install -y build-essential \
|
||||
libboost-all-dev \
|
||||
libprotobuf-dev \
|
||||
protobuf-compiler \
|
||||
cppcheck \
|
||||
clang-3.6 \
|
||||
ninja-build \
|
||||
wget \
|
||||
@ -16,6 +15,11 @@ RUN apt-get update && apt-get install -y build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
|
||||
&& apt-get autoremove -y
|
||||
|
||||
RUN cd /usr/local/src \
|
||||
&& wget https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64 \
|
||||
&& mv gosu-amd64 /usr/local/bin/gosu \
|
||||
&& chmod +x /usr/local/bin/gosu
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
RUN chmod +x /setup.sh
|
||||
|
||||
@ -29,6 +33,18 @@ RUN cd /usr/local/src \
|
||||
&& cd .. \
|
||||
&& rm -rf cmake*
|
||||
|
||||
# cppcheck
|
||||
RUN cd /usr/local/src \
|
||||
&& wget https://github.com/danmar/cppcheck/archive/1.79.tar.gz \
|
||||
&& tar xvf 1.79.tar.gz \
|
||||
&& cd cppcheck-1.79 \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake .. \
|
||||
&& make install \
|
||||
&& cd ../.. && rm -rf cppcheck*
|
||||
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
ENTRYPOINT ["/setup.sh"]
|
||||
|
@ -28,6 +28,10 @@ RUN cd /usr/local/src \
|
||||
&& rm -rf tini-* \
|
||||
&& rm -rf v0.9.0.tar.gz
|
||||
|
||||
RUN cd /usr/local/src \
|
||||
&& wget https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64 \
|
||||
&& mv gosu-amd64 /usr/local/bin/gosu \
|
||||
&& chmod +x /usr/local/bin/gosu
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
RUN chmod +x /setup.sh
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Container for building and testing cmake-examples with default cmake v2.8.12.2
|
||||
# Container for building and testing cmake-examples with default cmake v3.5.1
|
||||
FROM ubuntu:16.04
|
||||
MAINTAINER Thom Troy
|
||||
|
||||
@ -8,7 +8,6 @@ RUN apt-get update && apt-get install -y build-essential \
|
||||
libboost-all-dev \
|
||||
libprotobuf-dev \
|
||||
protobuf-compiler \
|
||||
cppcheck \
|
||||
clang-3.6 \
|
||||
ninja-build \
|
||||
wget \
|
||||
@ -16,6 +15,22 @@ RUN apt-get update && apt-get install -y build-essential \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# cppcheck
|
||||
RUN cd /usr/local/src \
|
||||
&& wget https://github.com/danmar/cppcheck/archive/1.79.tar.gz \
|
||||
&& tar xvf 1.79.tar.gz \
|
||||
&& cd cppcheck-1.79 \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake .. \
|
||||
&& make install \
|
||||
&& cd ../.. && rm -rf cppcheck*
|
||||
|
||||
RUN cd /usr/local/src \
|
||||
&& wget https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64 \
|
||||
&& mv gosu-amd64 /usr/local/bin/gosu \
|
||||
&& chmod +x /usr/local/bin/gosu
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
RUN chmod +x /setup.sh
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user