From 2b9e5b5f02e3ea1cd7e05e81f46878091e6bbd50 Mon Sep 17 00:00:00 2001
From: Mats Kindahl <mats@kindahl.net>
Date: Wed, 1 Jan 2025 14:15:51 +0100
Subject: Add meson build for coccicheck

This commit adds a run target `coccicheck` to meson build files.

Since ninja does not accept parameters the same way make does, there are three
run targets defined---"coccicheck-patch", "coccicheck-report", and
"coccicheck-context"---that you can use to generate a patch, get a report, and
get the context respectively. For example, to patch the tree from the "build"
subdirectory created by the meson run:

    ninja coccicheck-patch | patch -d .. -p1
---
 meson.build               | 29 +++++++++++++++++++++++++++++
 meson_options.txt         |  7 ++++++-
 src/makefiles/meson.build |  6 ++++++
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 13c13748e5d..044171f80e4 100644
--- a/meson.build
+++ b/meson.build
@@ -348,6 +348,7 @@ missing = find_program('config/missing', native: true)
 cp = find_program('cp', required: false, native: true)
 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
+spatch = find_program(get_option('SPATCH'), native: true, required: false)
 
 bison_flags = []
 if bison.found()
@@ -1642,6 +1643,33 @@ else
 endif
 
 
+###############################################################
+# Option: Coccinelle checks
+###############################################################
+
+coccicheck_opt = get_option('coccicheck')
+coccicheck_dep = not_found_dep
+if not coccicheck_opt.disabled()
+  if spatch.found()
+    coccicheck_dep = declare_dependency()
+  elif coccicheck_opt.enabled()
+    error('missing required tools (spatch needed) for Coccinelle checks')
+  endif
+endif
+
+coccicheck_modes = ['context', 'report', 'patch']
+
+foreach mode : coccicheck_modes
+  run_target('coccicheck-' + mode,
+	   command: [python, files('src/tools/coccicheck.py'),
+		     '--mode', mode,
+		     '--spatch', spatch,
+		     '--patchdir', '@SOURCE_ROOT@',
+		     '@SOURCE_ROOT@/cocci/**/*.cocci',
+		     '@SOURCE_ROOT@/src',
+		     '@SOURCE_ROOT@/contrib',
+		    ])
+endforeach
 
 ###############################################################
 # Compiler tests
@@ -3808,6 +3836,7 @@ if meson.version().version_compare('>=0.57')
     {
       'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
       'dtrace': dtrace,
+      'spatch': spatch,
       'flex': '@0@ @1@'.format(flex.full_path(), flex_version),
     },
     section: 'Programs',
diff --git a/meson_options.txt b/meson_options.txt
index 702c4517145..37d6d43af93 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -43,6 +43,9 @@ option('cassert', type: 'boolean', value: false,
 option('tap_tests', type: 'feature', value: 'auto',
   description: 'Enable TAP tests')
 
+option('coccicheck', type: 'feature', value: 'auto',
+       description: 'Enable Coccinelle checks')
+
 option('injection_points', type: 'boolean', value: false,
   description: 'Enable injection points')
 
@@ -52,7 +55,6 @@ option('PG_TEST_EXTRA', type: 'string', value: '',
 option('PG_GIT_REVISION', type: 'string', value: 'HEAD',
   description: 'git revision to be packaged by pgdist target')
 
-
 # Compilation options
 
 option('extra_include_dirs', type: 'array', value: [],
@@ -195,6 +197,9 @@ option('PYTHON', type: 'array', value: ['python3', 'python'],
 option('SED', type: 'string', value: 'gsed',
   description: 'Path to sed binary')
 
+option('SPATCH', type: 'string', value: 'spatch',
+  description: 'Path to spatch binary, used for SmPL patches')
+
 option('STRIP', type: 'string', value: 'strip',
   description: 'Path to strip binary, used for PGXS emulation')
 
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 60e13d50235..c66156d9046 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -57,6 +57,7 @@ pgxs_kv = {
   'enable_injection_points': get_option('injection_points') ? 'yes' : 'no',
   'enable_tap_tests': tap_tests_enabled ? 'yes' : 'no',
   'enable_debug': get_option('debug') ? 'yes' : 'no',
+  'enable_coccicheck': spatch.found() ? 'yes' : 'no',
   'enable_coverage': 'no',
   'enable_dtrace': dtrace.found() ? 'yes' : 'no',
 
@@ -151,6 +152,7 @@ pgxs_bins = {
   'TAR': tar,
   'ZSTD': program_zstd,
   'DTRACE': dtrace,
+  'SPATCH': spatch,
 }
 
 pgxs_empty = [
@@ -166,6 +168,10 @@ pgxs_empty = [
   'DBTOEPUB',
   'FOP',
 
+  # Coccinelle is not supported by pgxs
+  'SPATCH',
+  'SPFLAGS',
+  
   # supporting coverage for pgxs-in-meson build doesn't seem worth it
   'GENHTML',
   'LCOV',
-- 
2.43.0

