Packaging libbpf with vcpkg
by Mike Przybylski
Previously
Managing dependencies with vcpkg
libbpf
: the missing package
In the interest of maintainability, I want vcpkg to be bpf-iotrace’s one-stop shop for managing third-party code. Since vcpkg’s default registry doesn’t include libbpf, I will need to package it myself the vcpkg way.
I’ll make an educated guess that the biggest reason libbpf
isn’t already in the default vcpkg
registry is that its
build procedure diverges pretty sharply from what is typical for a Makefile-based open source project.
Most Makefile-based open source projects use
GNU autotools
to generate a Makefile tailored for the build environment and the target system.
Those projects also typically separate the source and build directories, also known as an out-of-source build.
libbpf
doesn’t require this level of complexity
and uses a manually written Makefile
located in the same directory as the library source.
Also, make
must be called from the source directory, (an in-source build).
This has the advantage of fewer dependencies and faster build times.
The disadvantage is that
vcpkg_configure_make() and
vcpkg_build_make() aren’t
written to work with a project that is structured this way.
Adapting the libbpf
build to be compatible with vcpkg
conventions
As I noted in my previous article,
an overlay ports directory is an excellent
place to keep a library while developing and testing because it enables rapid iteration.
So I created the tools/vcpkg-overlays/ports/libbpf
and its parents in the bpf-iotrace
project and referenced
tools/vcpkg-overlays/ports
in
vcpkg-configuration.json.
Then I added the following files to tools/vcpkg-overlays/ports/libbpf
:
-
vcpkg.json: The manifest file that describes the port and declares
libbpf
’s direct dependency on elfutils libelf. - CMakeLists.txt:
This file wraps the
libbpf
build system to make it look from the outside like a typical CMake project.vcpkg
works really easily with CMake projects. - portfile.cmake that
fetches and unpacks the specified version of
libbpf
, calls vcpkg_cmake_configure(), vcpkg_cmake_build(), and vcpkg_cmake_install() to build and installlibbpf
.
vcpkg
ports like bzip2
use a
CMakeLists.txt file that completely bypasses the upstream project’s build system.
While this may be a good fit for projects that rarely change, it is not a good fit for libbpf
,
which is constantly evolving. It is highly likely that new releases of libbpf
would break a CMakeLists.txt
that attempts to bypass the existing Makefile
.
This breakage can easily happen if libbpf
adds new source files or refactors existing ones.
Keeping those parallel build systems in sync would simply be more trouble than it’s worth.
Fortunately, CMake has a module called
ExternalProject
that allows a CMake project to wrap project builds involving non-CMake build systems.
Even more fortunately, libbpf
’s Makefile follows
GNU Makefile conventions
which give me a stable interface to use when wrapping libbpf’s build with ExternalProject_Add()
.
CMakeLists.txt
also translates the “implicit options” vcpkg
passes via
vcpkg_cmake_configure()
to Makefile variables and installation paths.
Brushing off the lint
After my first successful build of libbpf
, in vcpkg
, I noticed the following warnings in CMake’s output:
...
-- Performing post-build validation
warning: The software license must be available at ${CURRENT_PACKAGES_DIR}/share/libbpf/copyright
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}//IdeaProjects/bpf-iotrace/tools/vcpkg/buildtrees/libbpf//LICENSE")
warning: There should be no absolute paths, such as the following, in an installed package:
/IdeaProjects/bpf-iotrace/tools/vcpkg/packages/libbpf_x64-linux
/IdeaProjects/bpf-iotrace/cmake-build-debug/vcpkg_installed
/IdeaProjects/bpf-iotrace/tools/vcpkg/buildtrees/libbpf
/IdeaProjects/bpf-iotrace/tools/vcpkg/downloads
Absolute paths were found in the following files:
/IdeaProjects/bpf-iotrace/tools/vcpkg/packages/libbpf_x64-linux/debug/lib/pkgconfig/libbpf.pc
/IdeaProjects/bpf-iotrace/tools/vcpkg/packages/libbpf_x64-linux/lib/pkgconfig/libbpf.pc
error: Found 2 post-build check problem(s). To submit these ports to curated catalogs, please first correct the portfile: /IdeaProjects/bpf-iotrace/./tools/vcpkg-overlays/ports/libbpf/portfile.cmake
...
Thankfully, vcpkg
provides a pair of functions I can call from portfile.cmake
to easily resolve these issues:
- vcpkg_install_copyright()
takes a list of paths to license files and legal notices for the upstream project, and places them in
vcpkg
’s preferred location. - vcpkg_fixup_pkgconfig()
transforms any absolute paths in a library’s pkg-config
file to relative paths which are preferred by
vcpkg
.
Graduating from the overlay directory
Once a library has been packaged successfully, it can be graduated to a public or private registry to facilitate its use in other projects.
Currently, only an empty .gitignore
file exists in bpf-iotrace/tools/vcpkg-overlays/ports
to make sure the directory
gets created by git clone ...
.
However, I will still temporarily copy in
any-port-in-a-storm/ports/libbpf when
I want to test changes or fixes my libbpf
vcpkg
port.