-
-
Notifications
You must be signed in to change notification settings - Fork 320
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
Documentation should provide an example of C++ static code analysis #4637
Comments
Here's an example I came up with: #!/usr/bin/env python3
from SCons.Script import *
from pathlib import Path
from subprocess import run, DEVNULL, PIPE
env = Environment()
env.Tool("compilation_db")
compilation_db = env.CompilationDatabase()[0]
cpp_sources = Split(
"""
main.cpp
another.cpp
"""
)
program = env.Program("prog", cpp_sources)
AddOption(
"--no-clang-tidy",
action="store_true",
help="Don't run clang-tidy static code analysis automatically",
)
AddOption(
"--no-clazy",
action="store_true",
help="Don't run clazy static code analysis automatically",
)
AddOption(
"--no-cppcheck",
action="store_true",
help="Don't run cppcheck static code analysis automatically",
)
def run_clang_tidy(target, source, env):
cpp_source = str(source[0])
compilation_db = Path(str(source[1]))
result = run(
[
"clang-tidy",
"-p",
compilation_db.parent,
"--checks=readability-*",
cpp_source,
],
env=env["ENV"],
stdout=PIPE,
stderr=DEVNULL,
text=True,
)
with open(str(target[0]), "w") as target_fh:
target_fh.write(result.stdout)
good = result.returncode == 0 and not result.stdout
if not good:
print(result.stdout)
return 1
return 0
def run_clazy(target, source, env):
cpp_source = str(source[0])
compilation_db = Path(str(source[1]))
result = run(
["clazy-standalone", "-p", compilation_db.parent, cpp_source],
env={**env["ENV"], "CLAZY_CHECKS": "level2"},
stdout=PIPE,
stderr=PIPE,
text=True,
)
with open(str(target[0]), "w") as target_fh:
target_fh.write(result.stdout)
target_fh.write(result.stderr)
good = result.returncode == 0 and not result.stderr
if not good:
print(result.stderr)
return 1
return 0
def run_cppcheck(target, source, env):
result = run(
["cppcheck", str(source[0])],
env=env["ENV"],
stdout=DEVNULL,
stderr=PIPE,
text=True,
)
with open(str(target[0]), "w") as target_fh:
target_fh.write(result.stderr)
good = result.returncode == 0 and not result.stderr
if not good:
print(result.stderr)
return 1
return 0
clang_tidy_reports = [
env.Command(
source=[cpp_source, compilation_db],
action=Action(run_clang_tidy, cmdstr="Running clang-tidy on ${SOURCE}"),
target=f"{Path(cpp_source).stem}.clang-tidy.log",
)
for cpp_source in cpp_sources
]
clazy_reports = [
env.Command(
source=[cpp_source, compilation_db],
action=Action(run_clazy, cmdstr="Running clazy on ${SOURCE}"),
target=f"{Path(cpp_source).stem}.clazy.log",
)
for cpp_source in cpp_sources
]
cppcheck_reports = [
env.Command(
source=cpp_source,
action=Action(run_cppcheck, cmdstr="Running cppcheck on ${SOURCE}"),
target=f"{Path(cpp_source).stem}.cppcheck.log",
)
for cpp_source in cpp_sources
]
env.Default(
[program]
+ ([] if GetOption("no_clang_tidy") else clang_tidy_reports)
+ ([] if GetOption("no_cppcheck") else cppcheck_reports)
+ ([] if GetOption("no_clazy") else clazy_reports)
) It takes ~2.2 seconds clean on a single core, and ~0.16 seconds when C++/SCons files are unchanged. Most notably, it only takes ~0.7 seconds when one of the two C++ files changed, due to parallelization and caching. Header dependencies are tracked, and a change is detected and leads to a precisely minimal run of the SCA tools. Feel free to take the idea further, I am not familiar with the docbook format (I like AsciiDoc very much, though ;-)). |
This is not something we'd put in the users guide, but it should fit in the cook book.. |
C++ is a complex beast, and there is a number of static code analysis (SCA) tools which aim to help developers tame this complexity. The tools are run best as part of the build, but they can be slow.
Documentation should provide an example of running a set of SCA tools as part of the build. It can show SCons' abilities of automatic dependency tracking and caching which enable users to run precise SCA scans as part of the inner development loop without sacrificing development performance.
The text was updated successfully, but these errors were encountered: