Robust Development Methodologies (II)
Introduction
Thus far, you have created, run and debugged your own application developed with ARM Keil. However, you have little to no knowledge whether this application could be used - from a qualitative standpoint - in a safety environment. This codelab aims at adding this dimension to your project so as to have sound foundations for future work.
What you’ll build
In this codelab, you will understand the required tools and guidelines for building qualitatively good SW - attitude that should be used while creating any type of SW. You will also understand how to interpret the results delivered by the tools used in order to improve your work.
What you’ll learn
- How to set up the tools for ensuring sufficiently good SW quality.
- Continue ensuring quality throughout the development lifecycle.
- Understand the different elements composing quality and to interpret the results provided by the different analysis tools.
What you’ll need
- You need to have completed the getting started with keil codelab.
- You need to have finished the Digging into RTX codelab.
- You need to have finished Scheduling of periodic tasks
Install the SW Quality checkers - cloc
, lizard
, clang-format
and cpplint
You need python3
installed
You likely have it already - but in case you did not, follow the following instructions
During this course, we will use cloc
, lizard
, clang-format
, cpplint
(and
pre-commit
later) for ensuring our code conforms to expected quality.
In order to install the checker tools:
- head to
clang-format
- LLVM Download Page, download and install the appropriate package ( here a direct link ). Important: make sure to ignore the warning during installation and install the tool in the PATH for all users. This tool will be used for formatting the C/C++ code. - enter
pip3 install cpplint
to install a linter for our code. This will be used for ensuring compliancy to Google styleguide . Remember, it is important to have 1 styleguide. Whether this is the best is up to debate (as we should tailor it to C anyhow for instance). - head to
cloc
- releases to download and install the appropriate package ( here a direct link ). Save it on your harddisk and add it to the $PATH.
IMPORTANT: do not yet use version 2.xx (or at your own risk). - issue
pip3 install lizard
to installlizard
.
Note
In case you had a different operating system, you can also issue:
clang-format
:- MacOS:
brew install clang-format
- Linux:
sudo apt install clang-format
- MacOS:
cloc
- MacOS:
brew install cloc
- Linux:
pip3 install cloc
- MacOS:
cpplint
- MacOS:
brew install cpplint
- Linux:
pip3 install cpplint
- MacOS:
Obviously, these tools may be available as plugin in various IDEs ( VsCode, CLion, …) you may use regularly.
Test your tools from the command line before continuing
Ensure that your tools are working by issuing the following commands:
clang-format --version
cpplint --version
cloc --version
Not finding the tool from the command line?
In case Windows did not find the tool, check that it is indeed present
in your $PATH
.
Configure the tools
Now that you have installed the tools, it is time to make use of them. You first start by checking they do work and then move on to test what your code looks like.
Run a first analysis
To test lizard
functionality (and be surprised by the complexity of a
function), go to where your simple car project is located and issue:
lizard RTE/Device/STM32L475VGTx/STCubeGenerated/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c
You should be able to see that HAL_SPI_TransmitReceive
has a whopping cyclomatic
complexity of 62. Open the file and see it yourself what that 62
means as far
understanding a foreign piece of SW.
In order to analyze your own project, head to the root of your simple car
project, run the lizard
tool and inspect the results. You can run the tool
by entering:
// use lizard (note: "Application" is the folder in which you put your own application)
lizard Application RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
Question 1
- With
lizard
, what does the option-C
mean? - What
C
value would you set according to the theory?
Solution
- Threshold for cyclomatic complexity number warning
- Ideally 10 (12 topmost value)
Subsequently, run the cloc
tool and inspect the results. You can run the
tool by entering:
// use cloc (note: "Application" is the folder in which you put your own application)
cloc Application RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
Afterwards, check out what clang-format
does. For doing so, first create a
.clang-format
at the root of your project with the following content:
---
BasedOnStyle: Google
IndentWidth: 4
---
Language: Cpp
ColumnLimit: 100
AlignConsecutiveAssignments: true
DerivePointerAlignment: false
PointerAlignment: Left
BinPackArguments: false
BinPackParameters: false
clang-format -i RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
.
Question 2
Respond to the following questions:
- has the file been modified?
- how can you check that? (write down the command)
- what is the meaning of option
-i
? - what does
ColumnLimit
in.clang-format
mean?
Solution
- Yes, it has
git diff RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
- Inplace edit
file
s, if specified - the maximum length of a line
Lastly, have a look at what cpplint
. Issue:
cpplint Application/* RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
Fixing the issues
You have tested most tools and inspected results. However, the goal is to ensure qualitatively good code. As a result:
- create a dedicated
git branch
for fixing the eventual issues - use
lizard -C 10 Application RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
.
Fix all the functions - if any - crossing the 10 maximal value for the cyclomatic complexity. - commit your changes (
git add *
andgit commit -m "Fixed cyclomatic complecity issues"
) - apply
clang-format -i Application/* RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
- commit your changes (
git add *
andgit commit -m "Fixed formatting issues with clang-format"
) - run
cpplint Application/* RTE/Device/STM32L475VGTx/STCubeGenerated/Core/src/main.c
- commit your changes (
git add *
andgit commit -m "Fixed Google Styleguides issues"
)
REMEMBER: make small commits!
As we learned, small commits are instrumental to a proper way of developing. Make sure to respect it when you are fixing the issues. That is, you will commit only one step at a time - not all changes at once.
Use spaces
, not tabs
Make sure your editor (including ARM Keil) makes use of spaces
instead of
tabs
.
Here the link to ARM Keil’s user manual
to change the behaviour accordingly (and act according to the
chosen styleguide).
Note
There may be issues flagged by cpplint
that may not seem trivial. However:
- check Google’s Styleguide concerning the rationale of the rule
- control the Styleguide Script as it may help the understanding
- be aware of compiler’s behaviours. For instance
const static aVariable
is accepted by the compiler but it is not standard compliant (static const aVariable
is) - although one could disable a rule with
-filter
, it is strongly suggested not to - and if so, only with a written justification
Warning
Be sure you have created a CPPLINT.cfg
file at the root of your project
containing, at least, the line length aligned with .clang-format
.
Moreover, prevent cpplint
from expecting include files in the same
directory.
# Stop searching for additional config files.
set noparent
# Limit line length.
linelength=100
# Header files are not always placed in the same directory
filter=-build/include
cpplint
manual (aka
ccplint.py
😉).
Copyrighting your work
No matter what SW one writes, a copyright shall always be specified - no matter
whether open source or proprietary in its nature. With cpplint
, in case one
forgot, the following error will be shown ”
No copyright message found. You should have a line: Copyright [year] <Copyright Owner>
“. An example of such copyright can be found below:
/**
******************************************************************************
* @file : monnalisa.h
* @brief : pensive woman module
* @author : Leonardo Da Vinci <leo@davinci.net>
* @date : 19. March 1503
******************************************************************************
* @copyright : Copyright (c) 1503
* Haute école de peinture de Florence
* @attention : SPDX-License-Identifier: MIT OR Apache-2.0
******************************************************************************
* @details
* Pensive woman module for impressing mankind
******************************************************************************
*/
Putting all together: pre-commit
Now that you are capable of checking the code, a question arises: how to ensure
to always remember to execute this? One way would be to check it centrally on a
CI/CD pipeline, but that would be late (and consume energy for nothing).
Do not worry!
We got you covered: pre-commit
does exactly what its name
implies. It will run a serie of checks prior to committing. In order to install
it, head to https://pre-commit.com/ and follow the
instructions.
So, once installed, we put all the tools seen so far by following the following instructions:
- create a
.pre-commit-config.yaml
at the root of yourgit
project with the following content:
files: ^(Application)|^(RTE\/Device\/STM32L475VGTx\/STCubeGenerated\/Core\/src\/main\.c)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: check-yaml
args: [--allow-multiple-documents]
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: 'v14.0.6'
hooks:
- id: clang-format
- repo: https://github.com/cpplint/cpplint
rev: '1.6.1'
hooks:
- id: cpplint
- repo: local
hooks:
- id: lizard
name: lizard
entry: lizard
language: system
args: [-C 12]
- add
.pre-commit-config.yaml
to yourgit
repository - install the hooks with
pre-commit install
- run the command manually by issuing
pre-commit run --all-files
- if you did a good job in Fixing the issues, all will be green
- That’s it!. From now on, all code changes will undergo the specified checks
Question 3
Respond to the following questions:
- what does
^(Application)|^(RTE\/Device\/STM32L475VGTx\/STCubeGenerated\/Core\/src\/main\.c)
underfiles
mean? (hint: check https://regex101.com/) - what does
[-C 12]
mean? - what are the implications of
language: system
? - is there a way to ensure that MISRA C:2012 checks are run automatically?
Solution
- It is a regex specifying on what the hooks will be applied
- It specifies the maximum cyclomatic complexity accepted
- One needs to a) ensure the presence of the tool on the machine, b)
handle the updates manually and c) manage the accessibility of the
tool (e.g. tool present in the
$PATH
) - Yes, there is. One can run
pre-commit run cppcheck --all-files
once .pre-commit-config.yaml is configured as follows (or similar):Obviously, it would be best not to rely on- repo: local hooks: - id: cppcheck name: cppcheck entry: cppcheck language: system args: [--addon=misra.json --force --inline-suppr --suppress=*:RTE/Device/STM32L475VGTx/STCubeGenerated/Inc/* -IRTE/Device/STM32L475VGTx/STCubeGenerated/Inc -IApplication]
language: system
;-)
Note
For those who would like to know more about git hooks
and pre-commit
,
here a few interesting links:
Run the analysis on your code
On a dedicated branch, run the analysis on your code to find
eventual issues in your application (including MISRA). Go about fixing
them one at a time and commit the fixes on a dedicated branch (named
going_professional
).
Important: only run the analysis on main.c
contained in
YOUR_PROJECT_LOCATION\RTE\Device\STM32L475VGTx\STCubeGenerated\src
and
Application
(or whatever folder you put your own implementation), not those coming from 3rd party.
pre-commit
will be part of the git
repository and will throw no errors.
Metrics - Going beyond
Although we will use the above tools throughout the course, there is a
multitude of other metrics that will help you assess the code quality.
Scitool Understand, for which
you have now received a license, will offer you a plethora of options under
the “Metrics->Metrics Browser”. You have access to the metrics definitions by
clicking on the following icon: