Browse Source

sca: llvm: add support for clang static analyzer

This commit brings a convenient way to run clang static analyzer on a
project with 'analyze-build' llvm utility.

Signed-off-by: Alex Fabre <alex.fabre@rtone.fr>
pull/90417/head
Alex Fabre 2 months ago committed by Anas Nashif
parent
commit
219fae6946
  1. 42
      cmake/sca/clang/sca.cmake
  2. 99
      doc/develop/sca/clang.rst
  3. 1
      doc/develop/sca/index.rst

42
cmake/sca/clang/sca.cmake

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (c) 2025 Alex Fabre
find_program(CLANG_SCA_EXE NAMES analyze-build REQUIRED)
message(STATUS "Found SCA: clang static analyzer (${CLANG_SCA_EXE})")
# Get clang analyzer user options
zephyr_get(CLANG_SCA_OPTS)
zephyr_get(LLVM_TOOLCHAIN_PATH)
# Check analyzer extra options
if(DEFINED CLANG_SCA_OPTS)
foreach(analyzer_option IN LISTS CLANG_SCA_OPTS)
list(APPEND CLANG_SCA_EXTRA_OPTS ${analyzer_option})
endforeach()
endif()
# clang analyzer uses the compile_commands.json as input
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Create an output directory for clang analyzer results
set(output_dir ${CMAKE_BINARY_DIR}/sca/clang)
file(MAKE_DIRECTORY ${output_dir})
# Use a dummy file to let clang static analyzer know we can start analyzing
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${CMAKE_COMMAND} -E touch ${output_dir}/clang-sca.ready)
set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts
${output_dir}/clang-sca.ready)
# Add a cmake target to run the analyzer after the build is done
add_custom_target(clang-sca ALL
COMMAND ${CLANG_SCA_EXE} --cdb ${CMAKE_BINARY_DIR}/compile_commands.json -o ${CMAKE_BINARY_DIR}/sca/clang/ --analyze-headers --use-analyzer ${LLVM_TOOLCHAIN_PATH}/bin/clang ${CLANG_SCA_EXTRA_OPTS}
DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json ${output_dir}/clang-sca.ready
)
# Cleanup dummy file
add_custom_command(
TARGET clang-sca POST_BUILD
COMMAND ${CMAKE_COMMAND} -E rm ${output_dir}/clang-sca.ready
)

99
doc/develop/sca/clang.rst

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
.. _clang:
Clang static analyzer support
#############################
Clang Static Analyzer is built on top of Clang and LLVM.
Strictly speaking, the analyzer is part of Clang, as Clang
consists of a set of reusable C++ libraries for building
powerful source-level tools. The static analysis engine used by the
Clang Static Analyzer is a Clang library, and has the capability to
be reused in different contexts and by different clients.
LLVM provides various methods to run the analyzer on a codebase,
through either a dedicated set of tools (scan-build and analyze-build),
or via command line arguments when running clang ('--analyze').
- 'scan-build' utility comes as the most convenient way for projects
using a simple $CC makefile variables, as it will wraps and replace
the compiler calls to perform it's analysis.
- 'analyze-build' utility is a sub-tool from 'scan-build', it only
relies on a 'compile_commands.json' database to perform the analysis.
- clang option '--analyze' will run the analyzer alongside the build, but
objects files are not generated, making any link stage impossible. In
our case the first link stage will fail and stop the analysis.
Because of it's complexe build infrastructure, invoking clang analyzer with
'analyze-build' is the most simple way to analyze a Zephyr project.
`Clang static analyzer documentation <https://clang.llvm.org/docs/ClangStaticAnalyzer.html>`__
Installing clang analyzer
*************************
'scan-build' and its sub-tool 'analyze-build' come natively with llvm as part of the binaries.
Make sure to have the binary directory accessible into your PATH.
'scan-build' is also available as a standalone python package available on `pypi <https://pypi.org/project/scan-build/>`__.
.. code-block:: shell
pip install scan-build
Run clang static analyzer
*************************
.. note::
The analyser requires that the project builds with a LLVM toolchain, and
produces a 'compile_commands.json' database.
To run clang static analyzer, :ref:`west build <west-building>` should be
called with a ``-DZEPHYR_SCA_VARIANT=clang`` parameter, alongside the llvm
toolchain parameters, e.g.
.. zephyr-app-commands::
:zephyr-app: samples/userspace/hello_world_user
:board: qemu_x86
:gen-args: -DZEPHYR_TOOLCHAIN_VARIANT=llvm -DLLVM_TOOLCHAIN_PATH=... -DZEPHYR_SCA_VARIANT=clang
:goals: build
:compact:
.. note::
By default, clang static analyzer produces a html report, but various other
outputs can be selected with options (sarif, plist, html)
Configuring clang static analyzer
*********************************
Clang static analyzer can be controlled using specific options.
To get an exaustive list of available options, report to the
'analyze-build' helper and 'scan-build' helper.
.. code-block:: shell
analyze-build --help
Options already activated by default:
* --analyze-headers : Also analyze functions in #included files.
.. list-table::
:header-rows: 1
* - Parameter
- Description
* - ``CLANG_SCA_OPTS``
- A semicolon separated list of 'analyze-build' options.
These parameters can be passed on the command line, or be set as environment variables.
.. zephyr-app-commands::
:zephyr-app: samples/hello_world
:board: stm32h573i_dk
:gen-args: -DZEPHYR_TOOLCHAIN_VARIANT=llvm -DLLVM_TOOLCHAIN_PATH=... -DZEPHYR_SCA_VARIANT=clang -DCLANG_SCA_OPTS="--sarif;--verbose"
:goals: build
:compact:

1
doc/develop/sca/index.rst

@ -64,6 +64,7 @@ The following is a list of SCA tools natively supported by Zephyr build system. @@ -64,6 +64,7 @@ The following is a list of SCA tools natively supported by Zephyr build system.
codechecker
sparse
gcc
clang
cpptest
eclair
polyspace

Loading…
Cancel
Save