diff --git a/Makefile b/Makefile
index 432d6fcf5d6b134b92a05c2ac3053c74cb6198df..bde14ca1c5917537fc81e6a1d408bd0534b4aa77 100644
--- a/Makefile
+++ b/Makefile
@@ -87,6 +87,10 @@ format: all
 tidy: all
 	$(NINJA) -C build clang-tidy
 
+.PHONY: cppcheck
+cppcheck: all
+	$(NINJA) -C build $@
+
 PHONY: iwyu
 iwyu: all
 	$(NINJA) -C build $@
diff --git a/cppcheck-suppressions.xml b/cppcheck-suppressions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1153b807e9f6a20b11a84e6fce77aeaeb84e9c4f
--- /dev/null
+++ b/cppcheck-suppressions.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<suppressions>
+  <suppress>
+	<id>syntaxError</id>
+  </suppress>
+</suppressions>
diff --git a/meson.build b/meson.build
index a73194416adeac577574d39bdcce9e66e4e77316..520e9a1897b957e94d789136fa92751b585ee709 100644
--- a/meson.build
+++ b/meson.build
@@ -16,9 +16,20 @@ boost_thread_dep = dependency('boost', modules : ['thread'], required: false)
 
 tools_dir = join_paths(meson.source_root(), 'tools')
 
+compile_commands_json = join_paths(meson.build_root(), 'compile_commands.json')
+
 run_target('iwyu',
 		   command: join_paths(tools_dir, 'check-iwyu'))
 
+run_target('cppcheck',
+		   command: [
+			 'cppcheck',
+			 '--project=' + compile_commands_json,
+			 '--suppress-xml=' + join_paths(meson.source_root(), 'cppcheck-suppressions.xml'),
+			 '--error-exitcode=2',
+			 '--quiet',
+		   ], )
+
 conf_data = configuration_data()
 option_urcu = get_option('userspace_rcu')
 conf_data.set('EMPER_LIBURCU', option_urcu)