Using Catch2 v3 in CMake with DDS and PMM
When the maintainers of Catch2 announced that the next major version (v3) would
be migrating away from its long-standing header-only approach to distribution,
there was much uproar about how this would hurt adoption and migration. After
all: What can be easier than just dropping a header file in your project and
#include
-ing it?
To be completely fair to detractors, there’s much precedent to be upset about
the idea of a migration from header-only to a compiled library: Building,
distributing, and obtaining libraries in C++ has been a longstanding nightmare
throughout the community. This precedent has been the status quo for far too
long. With dds
I am working to change that.
So here I’ll show a simple demo of how to use Catch2 v3 by dropping a single
file in your CMake project and include()
-ing it. Other build systems will not
be discussed here, but I hope to have solutions for them in the future as well.
The Project
Here’s my simple CMake project file:
cmake_minimum_required(VERSION 3.15)
project(MyProject)
add_library(my-library stuff.cpp)
add_executable(my-test test.cpp)
target_link_libraries(my-test PRIVATE my-library)
Suppose I want to use Catch2 v3 with the my-test
executable. To do this with
Catch2 v2, one would need to download and correctly place the header file, then
set the proper preprocessor definitions and custom library targets to use it.
In the case of Catch2 v3, PMM and dds
make it even more trivial.
Adding Catch2 v3 with PMM and dds
First, download
the PMM entrypoint script
and save and commit it to your CMake project. With wget
:
$ wget "https://raw.githubusercontent.com/vector-of-bool/pmm/master/pmm.cmake"
or in PowerShell:
> iwr "https://raw.githubusercontent.com/vector-of-bool/pmm/master/pmm.cmake" `
-OutFile pmm.cmake
Next we include()
the file in our CMakeLists.txt
:
include(pmm.cmake)
then we utter a small magic pmm()
incantation:
pmm(DDS DEPENDS catch2@3.0.0-preview3)
and now we can link Catch2 into our test executable:
target_link_libraries(my-test PRIVATE catch2::catch2)
and that’s all there is to it. With this, can write our tests and use Catch2 as normal:
// - test.cpp -
#include <catch2/catch_test_macros.hpp>
#include <my-library.hpp>
TEST_CASE("This is my test case") {
REQUIRE(my_lib::add_together(3, 5) == 8);
}
That’s All for Now
This post will be short and sweet to exemplify what I am really shooting for
with dds
and PMM, and to emphasize just how simple I believe that tooling
could be. “Just build everything from source” can be viable if we use our
tools to their fullest extent.
I won’t detail here how PMM and dds
do their deeds, but you are always free to
read the source for PMM and
the source for dds
. If there is
sufficient interest in those nitty-gritty details, I may write a follow-up post.
Unfortunately there are a few (temporary) caveats to go along with this: At the
time of writing, dds
is still in a (seemingly eternal) alpha stage, and the
above example does not yet support providing a custom main()
(this is a
limitation to the Catch2 package in the dds
repository, and not due to an
issue in Catch2 or dds
itself). dds
is not fully “production-ready”, but I
encourage readers to experiment and consider that their tools could be doing
more for them.
Happy coding!