This was asked of me again, by Adam Conrad of Canonical: “Why isn’t CCAN a shared library?”. Distributions prefer shared libraries, for simplicity of updating (especially for security fixes), so I thought I’d answer canonically, once.
- Most CCAN modules are small; many are just headers.
- You can’t librify something which doesn’t have a stable API or ABI.
- CCAN’s alternative is not a library, it’s cut-n-paste.
To illustrate what I mean, consider ccan/hash: it’s a convenient wrapper around the Jenkins lookup3 code. It could be a library, but in practice it’s not. For something as simple as that, people cut & paste the lookup3 code into their own. It already exists in two places in Samba, for example. It’s this level of code snippet which is served beautifully by CCAN: you drop it in a ccan/ dir in your project and you get nice, documented and tested code, with optional updates if you want them later.
You could still make ccan/hash into a shared library. But if the upstream doesn’t do it for you, you have to check the ABI and update the version number every time it changes. This, unfortunately, means you can no longer share it: if library A uses version 11 and library B uses version 12, you can’t link against both library A and library B. Yet there’s nothing wrong with either: you have to change them because you librified it.
This kind of pain isn’t worth it for small snippets of code, so people cut & paste instead, and that makes our code worse, not better. That’s what CCAN tries to fix.
Now, there may one day be modules which could be shared libraries: that’s a good thing, if the maintainer is prepared to support the ABI and API. I’m not going to kick a module out of CCAN for being too successful. But I’d like to explicitly label such a module, and make sure ccanlint does the appropriate checks for ABI compatibility and symbol hiding.