homebrew-core/Formula/cppcheck.rb

129 lines
4.6 KiB
Ruby

class Cppcheck < Formula
desc "Static analysis of C and C++ code"
homepage "https://sourceforge.net/projects/cppcheck/"
url "https://github.com/danmar/cppcheck/archive/2.9.2.tar.gz"
sha256 "93920d24d4442856bf7916ee0e3fc31308bc23948e7029b4fd332e01cac63c3e"
license "GPL-3.0-or-later"
head "https://github.com/danmar/cppcheck.git", branch: "main"
bottle do
sha256 arm64_ventura: "e9d950c1bbec3fe3372d72b27705620cad11e9d8fc38ee592e7f94ad9e025ca2"
sha256 arm64_monterey: "c7f0d86f54fbc5fed6264a28df44015e176a8facebaea61148f8420ed92bdb83"
sha256 arm64_big_sur: "bac58add5429a917d42799ec0cb8f4223ed067fd50afad3c61e8c286a3287f9d"
sha256 ventura: "9ea806e20f1542cebc84f8f9b46b1d3624dc9bbc2fb0ef1e9ee113d9955e956d"
sha256 monterey: "bdc32662ec9878ab061b35006246109399b23f9b02affd3a695cc5d826aeae05"
sha256 big_sur: "0f458144275d0059202b57213d978e233630a49eebb107f6f0809c5a0b7aef31"
sha256 catalina: "7181d937a674ab82d22357c864d336f1f4ff42d8be40878d654961b7b4bd5d3e"
sha256 x86_64_linux: "7610f1666fb79bcce237bc9931e5ea5f7d97efb28efd07cb1589bcc39eeef557"
end
depends_on "cmake" => :build
depends_on "python@3.10" => [:build, :test]
depends_on "pcre"
depends_on "tinyxml2"
uses_from_macos "libxml2"
def python3
which("python3.10")
end
def install
args = std_cmake_args + %W[
-DHAVE_RULES=ON
-DUSE_MATCHCOMPILER=ON
-DUSE_BUNDLED_TINYXML2=OFF
-DENABLE_OSS_FUZZ=OFF
-DPYTHON_EXECUTABLE=#{python3}
]
system "cmake", "-S", ".", "-B", "build", *args
system "cmake", "--build", "build"
system "cmake", "--install", "build"
# Move the python addons to the cppcheck pkgshare folder
(pkgshare/"addons").install Dir.glob("addons/*.py")
end
test do
# Execution test with an input .cpp file
test_cpp_file = testpath/"test.cpp"
test_cpp_file.write <<~EOS
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
class Example
{
public:
int GetNumber() const;
explicit Example(int initialNumber);
private:
int number;
};
Example::Example(int initialNumber)
{
number = initialNumber;
}
EOS
system "#{bin}/cppcheck", test_cpp_file
# Test the "out of bounds" check
test_cpp_file_check = testpath/"testcheck.cpp"
test_cpp_file_check.write <<~EOS
int main()
{
char a[10];
a[10] = 0;
return 0;
}
EOS
output = shell_output("#{bin}/cppcheck #{test_cpp_file_check} 2>&1")
assert_match "out of bounds", output
# Test the addon functionality: sampleaddon.py imports the cppcheckdata python
# module and uses it to parse a cppcheck dump into an OOP structure. We then
# check the correct number of detected tokens and function names.
addons_dir = pkgshare/"addons"
cppcheck_module = "#{name}data"
expect_token_count = 55
expect_function_names = "main,GetNumber,Example"
assert_parse_message = "Error: sampleaddon.py: failed: can't parse the #{name} dump."
sample_addon_file = testpath/"sampleaddon.py"
sample_addon_file.write <<~EOS
#!/usr/bin/env #{python3}
"""A simple test addon for #{name}, prints function names and token count"""
import sys
from importlib import machinery, util
# Manually import the '#{cppcheck_module}' module
spec = machinery.PathFinder().find_spec("#{cppcheck_module}", ["#{addons_dir}"])
cpp_check_data = util.module_from_spec(spec)
spec.loader.exec_module(cpp_check_data)
for arg in sys.argv[1:]:
# Parse the dump file generated by #{name}
configKlass = cpp_check_data.parsedump(arg)
if len(configKlass.configurations) == 0:
sys.exit("#{assert_parse_message}") # Parse failure
fConfig = configKlass.configurations[0]
# Pick and join the function names in a string, separated by ','
detected_functions = ','.join(fn.name for fn in fConfig.functions)
detected_token_count = len(fConfig.tokenlist)
# Print the function names on the first line and the token count on the second
print("%s\\n%s" %(detected_functions, detected_token_count))
EOS
system "#{bin}/cppcheck", "--dump", test_cpp_file
test_cpp_file_dump = "#{test_cpp_file}.dump"
assert_predicate testpath/test_cpp_file_dump, :exist?
output = shell_output("#{python3} #{sample_addon_file} #{test_cpp_file_dump}")
assert_match "#{expect_function_names}\n#{expect_token_count}", output
end
end