Open-source project
coccinelle/coccinelle avatar
coccinelle/coccinelle

Coccinelle: semantic source to source rewriting for C

Source code of the Coccinelle project (mirror of the main Coccinelle repository located at Inria)

821 stars120 forksOCamlGPL-2.0

At a glance

What is it?
Coccinelle is an OCaml implementation of a semantic patch language for style preserving source to source transformations on C code, driven by the spatch command line tool. It is aimed at large C codebases where a refactoring has to be applied consistently without reformatting everything it touches.
Who is it for?
Adopt Coccinelle if you maintain a large C codebase, mostly inherited or vendored, and need to change a pattern across hundreds of files while keeping the diff small and the formatting intact. Do not adopt it for small edits, for C++ codebases beyond what the C front end covers, or as a replacement for a compiler aware refactoring tool, since the semantic matching has limits that a full C++ model does not.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 51 days ago.
What is it written in?
Mainly OCaml, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Refactoring C without reformatting it

Coccinelle allows programmers to write style preserving source to source transformations on C source code, for instance to perform some refactorings. That combination of words carries the design.

The style preserving part is the hard constraint. A tool that parses C and prints it back out will normalise whitespace, reorder declarations and change line breaks, so a change intended to affect one function arrives as a diff touching every line of the file. Coccinelle's own C front end keeps the original layout and rewrites only the matched regions, which is what makes the output reviewable and what makes the tool usable on codebases where a huge diff is not acceptable.

The transformations are written in a semantic pattern language, referred to as SmPL in the README when it discusses the scripting features, and the patterns match on program meaning rather than on text. That is the difference between matching an identifier or a call shape and matching a specific function name in a specific file.

The audience is therefore kernel and driver maintainers, embedded C projects and anyone looking at a large inherited C tree. The project is written in OCaml, and this GitHub repository is a mirror of the main Coccinelle repository located at Inria, with the project site hosted at coccinelle.gitlabpages.inria.fr.

spatch, the script you actually run

Once Coccinelle is installed there is a script called spatch in /usr/bin or /usr/local/bin that invokes the Coccinelle program. The installed entry point is a single binary, and the README gives a complete example of a run:

bash
spatch --sp-file demos/simple.cocci demos/simple.c -o /tmp/new_simple.c

That invocation names the semantic patch file with --sp-file, the C file to transform, and an output path with -o. The demonstration patches live in the demos/ directory, so the repository ships runnable examples rather than only documentation.

There is a second tool in the build, spgen, which the Makefile lists alongside spatch in its TOOLS variable.

You can also run Coccinelle without installing it at all. The README says the program can be run directly from the download or build directory, and that you may then need to set up a few environment variables so the program knows where to find its configuration files. Those are provided as two shell snippets in the repository root, env.sh for bash and env.csh for tcsh, and the bash usage is a single line:

bash
source env.sh

When you have not installed Coccinelle, the README says to run ./spatch or ./spatch.opt instead of the installed script. There is also a bytecode flavour: if you downloaded the bytecode version of spatch you may first have to install OCaml, which contains the ocamlrun bytecode interpreter, and then invoke it directly:

bash
ocamlrun spatch --sp-file demos/simple.cocci demos/simple.c -o /tmp/new_simple.c

Building from source and the OCaml library layout

The build instructions live in install.txt, and the Makefile enforces the order. If Makefile.config is missing and there is no configure script, the build stops with an error telling you to run ./autogen and ./configure first, and if configure exists but Makefile.config does not, it asks for ./configure. The top level tree shows the usual autotools pieces, configure.ac, Makefile.am, Makefile.config.in and an autogen script, plus a Makefile.dev for development builds and a Makefile.release with a make-release.sh script.

What matters for understanding the codebase is how the OCaml libraries are arranged. The Makefile names a set of core libraries, commons, globals, parsing_cocci and parsing_c, and a larger set that adds ctl, ocaml, python, engine, popl09 and extra. The dependency method is multifile, so the libraries are compiled as separate units rather than one binary blob.

The source lists give a map of the internals. The parsing_cocci library holds the semantic pattern compiler and the semantic AST machinery, with iso_pattern.ml and iso_compile.ml for the isomorphism patterns that make matching semantic rather than textual, and the parser written with menhir alongside hand written lexers. The globals library holds the configuration, flags and iteration logic, and ctl carries the control language, the pretty printer and the engine wrapper. The python directory is the Python scripting feature, and popl09 is the older popl implementation kept alongside the current one.

Documentation is built with make docs into the docs/ directory, and the README warns that some of the LaTeX documents need the texlive-fonts-extra and hevea packages from your distribution.

Scripting features and their runtime dependencies

Coccinelle can run scripts from inside a semantic patch, and the README lists the runtime dependencies for those features under Debian and Ubuntu.

For the OCaml scripting feature in SmPL you need ocaml-native-compilers or ocaml-nox. For the Python scripting feature in SmPL you need python3-dev, and the README is precise about one point: python3-dev is only a runtime dependency and is not required for building Coccinelle itself.

That distinction has a practical consequence for packaging. A build container does not need the scripting runtimes, but a machine running patches that call out to OCaml or Python code does, and a CI image that builds Coccinelle and then runs patches against real code may need both sets of packages.

The repository also carries a Dockerfile for containerised builds. It is based on the ocaml/opam2 image at tag 4.07, and the build pins the local source as an opam package and installs its dependencies:

dockerfile
FROM ocaml/opam2:4.07

The remaining steps copy the tree into /coccinelle, pin it with opam pin add -n file:///coccinelle and run opam depext -i coccinelle. The coccinelle.opam file in the root is the opam package definition, and the same opam packaging means the project can be installed through the normal OCaml package route rather than only from this tarball.

Contributions require a sign-off

The contribution rules are the strictest thing in the README, and they are borrowed wholesale from the Linux kernel.

The README asks contributors to sign their changes according to the text extracted from Documentation/SubmittingPatches.txt of the kernel, and reproduces the Developer's Certificate of Origin 1.1 in full. The four clauses cover a contribution you created in whole or in part, a contribution derived from previous work under an appropriate open source licence, a contribution passed to you by someone else who certified it, and the acknowledgement that the contribution and its sign-off are public and kept indefinitely.

The sign-off itself is a single line appended to the explanation of the patch:

bash
Signed-off-by: Random J Developer <[email protected]>

and the README insists on a real name, explicitly ruling out pseudonyms and anonymous contributions.

This is not ceremony for its own sake. The sign-off is what makes a GPL contribution chain auditable, and for a project whose licence is GPL-2.0 and whose community overlaps heavily with the kernel, it is how provenance is tracked. The repository also keeps authors.txt, credits.txt, changes.txt, copyright.txt and license.txt, and ships a debian/ directory for distribution packaging, a Jenkinsfile and a .gitlab-ci.yml for continuous integration.

Where Coccinelle is the wrong tool

There are clear cases for something else.

If the change is small and localised, a text substitution is faster. Coccinelle earns its setup cost when the same pattern appears in hundreds of places and the pattern is semantic, for instance a particular lock discipline or an API call with a particular argument shape. For a one line rename or a config tweak, a regular expression or a sed script is the right tool and Coccinelle is overkill.

Second, C++ projects are outside the comfortable range. The tool is described as operating on C source code, and the pattern language is built around a C model. A compiler front end built for C++ has a fuller model of the language, templates, overload resolution and the standard library, and a refactoring tool that uses it can reason about things the C front end cannot.

Third, the cost of the approach is that matching is the hard part. Writing a semantic pattern that matches your code takes iteration, because a pattern that seems right often fails to match real code where the types are different, the expression is spelled differently, or the statement appears inside a conditional. The tool's job is easy once the pattern is right, and the pattern is where the engineering effort goes.

Finally, there is the fact that Coccinelle rewrites files in place. That is what makes the diff small, and it is also what makes it risky to point at a tree you cannot revert. The repository publishes no GitHub releases, so there is no tagged version to pin either, and the last push to this mirror was on 2026-09-02, which means the Inria repository is where to look for the current state of the code.

Editorial conclusion

Adopt Coccinelle if you maintain a large C codebase, mostly inherited or vendored, and need to change a pattern across hundreds of files while keeping the diff small and the formatting intact. Do not adopt it for small edits, for C++ codebases beyond what the C front end covers, or as a replacement for a compiler aware refactoring tool, since the semantic matching has limits that a full C++ model does not. Verify three things first: that the pattern you want to match actually exists in your code in the shape the semantic engine expects, which is where most of the iteration time goes; that your build does not depend on byte for byte identical files elsewhere in the tree, since spatch rewrites only what it matches; and how you will handle the OCaml and Python scripting features, which need ocaml-native-compilers or ocaml-nox and python3-dev installed as runtime dependencies. The licence is GPL-2.0, the repository is a mirror of the Inria main repository, and the last push was on 2026-09-02.

Frequently asked questions

What is Coccinelle used for?

It writes style preserving source to source transformations on C source code, for instance refactorings. The transformations are described in a semantic pattern language and applied with the spatch command line tool.

How do I try Coccinelle without installing it?

Run the program directly from the download or build directory and source the environment file so it finds its configuration files, with source env.sh for bash or source env.csh for tcsh. Then run ./spatch or ./spatch.opt rather than the installed script.

What does spatch do in a Coccinelle run?

It is the script that invokes the Coccinelle program. A run names the semantic patch with --sp-file, the source file to transform, and an output path with -o, for example spatch --sp-file demos/simple.cocci demos/simple.c -o /tmp/new_simple.c.

What does building Coccinelle from source require?

The README points to install.txt, and the Makefile refuses to build until ./autogen and ./configure have produced Makefile.config. The runtime dependencies for the scripting features are ocaml-native-compilers or ocaml-nox for OCaml scripting and python3-dev for Python scripting, and python3-dev is not needed to build.

What are the requirements for contributing to Coccinelle?

Contributions must be signed off with a Signed-off-by line using your real name, following the Developer's Certificate of Origin 1.1 text taken from the Linux kernel's patch submission guide. The README explicitly rules out pseudonyms and anonymous contributions.

Official sources

  1. coccinelle/coccinelle on GitHub
  2. Issues
  3. License: GPL-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/coccinelle-coccinelle.svg)](https://hysenlabs.com/projects/coccinelle-coccinelle)

Was this useful?