Tools: add OUTPUT_DIR option to the "check_cppcheck" target

- Add optional `--build-dir` & `--output-dir` arguments to
  "static_check_cppcheck.py".
- Support using `project_source_info.py` without the CWD having
  to be the build-directory.
- Make the script executable.
This commit is contained in:
Campbell Barton
2025-02-11 13:07:36 +11:00
parent 60ef321e6d
commit ad4eb66fdf
3 changed files with 103 additions and 15 deletions

View File

@@ -56,7 +56,12 @@ Testing Targets
Static Source Code Checking Static Source Code Checking
Not associated with building Blender. Not associated with building Blender.
* check_cppcheck: Run blender source through cppcheck (C & C++). * check_cppcheck:
Run blender source through cppcheck (C & C++).
To write log files into a user defined location append 'OUTPUT_DIR',
e.g. 'OUTPUT_DIR=/example/path'
* check_clang_array: Run blender source through clang array checking script (C & C++). * check_clang_array: Run blender source through clang array checking script (C & C++).
* check_struct_comments: Check struct member comments are correct (C & C++). * check_struct_comments: Check struct member comments are correct (C & C++).
* check_deprecated: Check if there is any deprecated code to remove. * check_deprecated: Check if there is any deprecated code to remove.
@@ -474,9 +479,10 @@ project_eclipse: .FORCE
check_cppcheck: .FORCE check_cppcheck: .FORCE
@$(CMAKE_CONFIG) @$(CMAKE_CONFIG)
@cd "$(BUILD_DIR)" ; \
$(PYTHON) \ $(PYTHON) \
"$(BLENDER_DIR)/tools/check_source/static_check_cppcheck.py" "$(BLENDER_DIR)/tools/check_source/static_check_cppcheck.py" \
--build-dir=$(BUILD_DIR) \
--output-dir=$(OUTPUT_DIR)
check_struct_comments: .FORCE check_struct_comments: .FORCE
@$(CMAKE_CONFIG) @$(CMAKE_CONFIG)

View File

@@ -4,8 +4,10 @@
__all__ = ( __all__ = (
"cmake_dir_set",
"build_info", "build_info",
"SOURCE_DIR", "SOURCE_DIR",
"CMAKE_DIR",
) )
@@ -38,6 +40,19 @@ SOURCE_DIR = join(dirname(__file__), "..", "..")
SOURCE_DIR = normpath(SOURCE_DIR) SOURCE_DIR = normpath(SOURCE_DIR)
SOURCE_DIR = abspath(SOURCE_DIR) SOURCE_DIR = abspath(SOURCE_DIR)
# copied from project_info.py
CMAKE_DIR = "."
def cmake_dir_set(cmake_dir: str) -> None:
"""
Callers may not run this tool from the CWD, in this case,
allow the value to be set.
"""
# Use a method in case any other values need to be updated in the future.
global CMAKE_DIR
CMAKE_DIR = cmake_dir
def is_c_header(filename: str) -> bool: def is_c_header(filename: str) -> bool:
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
@@ -53,10 +68,6 @@ def is_c_any(filename: str) -> bool:
return is_c(filename) or is_c_header(filename) return is_c(filename) or is_c_header(filename)
# copied from project_info.py
CMAKE_DIR = "."
def cmake_cache_var_iter() -> Iterator[tuple[str, str, str]]: def cmake_cache_var_iter() -> Iterator[tuple[str, str, str]]:
import re import re
re_cache = re.compile(r'([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$') re_cache = re.compile(r'([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$')
@@ -102,14 +113,27 @@ def makefile_log() -> list[str]:
if make_exe_basename.startswith(("make", "gmake")): if make_exe_basename.startswith(("make", "gmake")):
print("running 'make' with --dry-run ...") print("running 'make' with --dry-run ...")
process = subprocess.Popen([make_exe, "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"], process = subprocess.Popen(
stdout=subprocess.PIPE, (
) make_exe,
"-C", CMAKE_DIR,
"--always-make",
"--dry-run",
"--keep-going",
"VERBOSE=1",
),
stdout=subprocess.PIPE,
)
elif make_exe_basename.startswith("ninja"): elif make_exe_basename.startswith("ninja"):
print("running 'ninja' with -t commands ...") print("running 'ninja' with -t commands ...")
process = subprocess.Popen([make_exe, "-t", "commands"], process = subprocess.Popen(
stdout=subprocess.PIPE, (
) make_exe,
"-C", CMAKE_DIR,
"-t", "commands",
),
stdout=subprocess.PIPE,
)
if process is None: if process is None:
print("Can't execute process") print("Can't execute process")

62
tools/check_source/static_check_cppcheck.py Normal file → Executable file
View File

@@ -3,10 +3,18 @@
# #
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
"""
Run CPPCHECK on Blender's source files,
writing results to a log as well as a summary of all checks.
Existing logs are renamed to ``.old.log`` so they can be compared.
"""
__all__ = ( __all__ = (
"main", "main",
) )
import argparse
import project_source_info import project_source_info
import subprocess import subprocess
import sys import sys
@@ -352,9 +360,59 @@ def cppcheck_generate_summary(
log_summary_fh.write(line) log_summary_fh.write(line)
def argparse_create() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawTextHelpFormatter,
)
parser.add_argument(
"--build-dir",
dest="build_dir",
metavar='BUILD_DIR',
type=str,
help=(
"The build directory (containing CMakeCache.txt).\n"
"\n"
"Defaults to the \".\"."
),
default=".",
required=False,
)
parser.add_argument(
"--output-dir",
dest="output_dir",
metavar='OUTPUT_DIR',
type=str,
help=(
"Specify the directory where CPPCHECK logs will be written to.\n"
"Using this may be preferred so the build directory can be cleared\n"
"without loosing the result of previous checks.\n"
"\n"
"Defaults to {BUILD_DIR}/cppcheck/"
),
default="",
required=False,
)
return parser
def main() -> None: def main() -> None:
cmake_dir = os.path.normpath(os.path.abspath(project_source_info.CMAKE_DIR)) args = argparse_create().parse_args()
cppcheck_dir = os.path.join(cmake_dir, "cppcheck")
project_source_info.cmake_dir_set(args.build_dir)
cppcheck_dir = args.output_dir
if cppcheck_dir:
cppcheck_dir = os.path.normpath(os.path.abspath(cppcheck_dir))
else:
cppcheck_dir = os.path.join(os.path.normpath(os.path.abspath(project_source_info.CMAKE_DIR)), "cppcheck")
del args
filepath_output_log = os.path.join(cppcheck_dir, "cppcheck.part.log") filepath_output_log = os.path.join(cppcheck_dir, "cppcheck.part.log")
filepath_output_summary_log = os.path.join(cppcheck_dir, "cppcheck_summary.part.log") filepath_output_summary_log = os.path.join(cppcheck_dir, "cppcheck_summary.part.log")