Exporting CMake builds as .deb packages with CPack
Long time without updating. And I have a new computer I’m setting up. I’m giving Ubuntu 20.04 LTS a chance, but I’m already hitting some of its quirks. For example, the official libfmt package being borked. When I try to run a small program I built, I get this:
$ ./matcher test
Failed opening file 'test'
terminate called after throwing an instance of 'fmt::v6::format_error'
what(): missing '}' in format string
Aborted (core dumped)
After some researching, it looked like this was a problem in the library, and that it was fixed in a version higher than the one included in Ubuntu 20.04’s official deb package.
I decided to build the most recent version of libfmt and install it, but I wanted to keep my new installation as clean as possible, so I checked whether I could find a guide on how to (easily) turn a CMake build into a .deb package.
And I was surprised to find CPack and its DEB Generator. It turns out CMake has a module to automatically generate package bundles for the code it builds! It supports producing tarballs, Qt IFW, NSIS. NuGet packages, .rpm and .deb packages, which is just what I was looking for.
By quickly looking at the doc pages, I learned that the DEB generator is not meant to be used directly, and that CPack will use it when configured to do so. Still, using CPack looked complicated: lots of options and no examples, and I also wasn’t able to find any examples or tutorials online, but I still wanted to give it a try.
I was about to add a CPack include in libfmt’s CMakeLists.txt file when I noticed there’s already some configuration in there! Sadly, the config is minimal, and only generates tarballs, but it was easy to extend it to build a .deb file. I just needed to add/edit the following towards the end of the file:
set(CPACK_PACKAGE_NAME libfmt-dev)
set(CPACK_GENERATOR DEB)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "invik")
I wanted the package to have the same name as Ubuntu’s, so that I can find it easily in the future, or, maybe even allow apt to update it automatically whenever I upgrade the dist?.
Setting the generator to “DEB” disables building the tarballs, but that won’t be a problem for me. Enabling the “DEB” generator requires a contact/package maintainer to be specified, so I added myself.
When I ran CMake, among some other options, I made sure to specify
-DBUILD_SHARED_LIBS=ON
, in order to get a shared library (libfmt will build a
static one by default). And then I ran make -j package
, and it worked like a
charm: I got a libfmt-dev-7.1.3-Linux.deb
file in my build directory, which
looked quite good when I inspected it with dpkg -c
libfmt-dev-7.1.3-Linux.deb
, and also installed perfectly!
Leave a comment