meson: wire up static analysis via Coccinelle
Wire up static analysis via Coccinelle via a new test target "coccicheck". This target can be executed via `meson compile coccicheck` and generates the semantic patch for us. Note that we don't hardcode the list of source and header files that shall be analyzed, and instead use git-ls-files(1) to find them for us. This is because we also want to analyze files that may not get built on the current platform, so finding all sources at configure time is easier than introducing a new variable that tracks all sources, including those which aren't being built. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Feb 18, 2025 at 08:45 UTC
c1d6628c9433c09ff62f916f2b933ee12995e9d8
3 files changed
+92
contrib/coccinelle/meson.build
new
+89
@@ -0,0 +1,89 @@
1
+spatch = find_program('spatch', required: get_option('coccinelle'))
2
+if not spatch.found()
3
+ subdir_done()
4
+endif
5
+
6
+third_party_sources = [
7
+ ':!contrib',
8
+ ':!compat/inet_ntop.c',
9
+ ':!compat/inet_pton.c',
10
+ ':!compat/nedmalloc',
11
+ ':!compat/obstack.*',
12
+ ':!compat/poll',
13
+ ':!compat/regex',
14
+ ':!sha1collisiondetection',
15
+ ':!sha1dc',
16
+ ':!t/unit-tests/clar',
17
+ ':!t/unit-tests/clar',
18
+ ':!t/t[0-9][0-9][0-9][0-9]*',
19
+]
20
+
21
+rules = [
22
+ 'array.cocci',
23
+ 'commit.cocci',
24
+ 'config_fn_ctx.pending.cocci',
25
+ 'equals-null.cocci',
26
+ 'flex_alloc.cocci',
27
+ 'free.cocci',
28
+ 'git_config_number.cocci',
29
+ 'hashmap.cocci',
30
+ 'index-compatibility.cocci',
31
+ 'object_id.cocci',
32
+ 'preincr.cocci',
33
+ 'qsort.cocci',
34
+ 'refs.cocci',
35
+ 'strbuf.cocci',
36
+ 'swap.cocci',
37
+ 'the_repository.cocci',
38
+ 'xcalloc.cocci',
39
+ 'xopen.cocci',
40
+ 'xstrdup_or_null.cocci',
41
+ 'xstrncmpz.cocci',
42
+]
43
+
44
+concatenated_rules = custom_target(
45
+ command: [
46
+ 'cat', '@INPUT@',
47
+ ],
48
+ input: rules,
49
+ output: 'rules.cocci',
50
+ capture: true,
51
+)
52
+
53
+sources = [ ]
54
+foreach source : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.c', third_party_sources, check: true).stdout().split()
55
+ sources += source
56
+endforeach
57
+
58
+headers = [ ]
59
+foreach header : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.h', third_party_sources, check: true).stdout().split()
60
+ headers += meson.project_source_root() / header
61
+endforeach
62
+
63
+patches = [ ]
64
+foreach source : sources
65
+ patches += custom_target(
66
+ command: [
67
+ spatch,
68
+ '--all-includes',
69
+ '--sp-file', concatenated_rules,
70
+ '--patch', meson.project_source_root(),
71
+ '@INPUT@',
72
+ ],
73
+ input: meson.project_source_root() / source,
74
+ output: source.underscorify() + '.patch',
75
+ capture: true,
76
+ depend_files: headers,
77
+ )
78
+endforeach
79
+
80
+concatenated_patch = custom_target(
81
+ command: [
82
+ 'cat', '@INPUT@',
83
+ ],
84
+ input: patches,
85
+ output: 'cocci.patch',
86
+ capture: true,
87
+)
88
+
89
+alias_target('coccicheck', concatenated_patch)
contrib/meson.build
+1
@@ -2,4 +2,5 @@ foreach feature : get_option('contrib')
2
subdir(feature)
3
endforeach
4
5
+subdir('coccinelle')
6
subdir('credential')
meson_options.txt
+2
@@ -101,6 +101,8 @@ option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto
101
description: 'Which backend to use to generate documentation.')
102
103
# Testing.
104
+option('coccinelle', type: 'feature', value: 'auto',
105
+ description: 'Provide a coccicheck target that generates a Coccinelle patch.')
106
option('tests', type: 'boolean', value: true,
107
description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.')
108
option('test_output_directory', type: 'string',