MKBuild is a small utility to simplify managing Measurement Kit builds. This tool performs two main tasks:
-
generates or updates a
CMakeLists.txtthat downloads required dependencies, configures strict compiler flags, builds libraries and executables, and run tests; -
generates or updates the
docker.shthat runs a CMake based build inside a specific Docker container, with specific compiler flags (e.g. forasan).
MKBuild is driven by the configuration contained in the
MKBuild.yml YAML file. Read on for more info.
go get -v github.com/measurement-kit/mkbuild
Create MKBuild.yaml in the toplevel directory of your project. This
file should look like this:
name: mkcurl
docker: bassosimone/mk-debian
dependencies:
- curl.haxx.se/ca
- github.com/adishavit/argh
- github.com/catchorg/catch2
- github.com/curl/curl
- github.com/measurement-kit/mkmock
targets:
libraries:
mkcurl:
compile: [mkcurl.cpp]
executables:
mkcurl-client:
compile: [mkcurl-client.cpp]
link: [mkcurl]
tests:
compile: [tests.cpp]
integration-tests:
compile: [integration-tests.cpp]
link: [mkcurl]
tests:
mocked_tests:
command: tests
integration_tests:
command: integration-tests
redirect_test:
command: mkcurl-client --follow-redirect http://google.comWhere name is the name of the project, docker is the name of the
docker container to use, dependencies lists the IDs of the dependencies
you want to download and install, targets tells us what artifacts you
want to build, and tests what tests to executed.
See cmake/deps/deps.go for all the available deps IDs. Dependencies
that compile to static/shared libraries (e.g. libcurl) will be downloaded
automatically on Windows, and must be already installed on Unix systems. If a
dependency is not already installed on Unix, the related cmake check will
fail when running cmake later on. The build flags will be automatically
adjusted to account for a dependency (e.g. CXXFLAGS and LDFLAGS will be
updated to use cURL's headers and libraries).
The libraries key specifies what libraries to build and the
executables key what executables to build. Both contain maps where the
target name maps to build information. Depending on the system, proper
file extensions and prefixes will be added. In the above example, the
instructions require us to build a library called mkcurl, which will
become libmkcurl.a on Unix and mkcurl.lib on Windows. (This is
done for us by CMake and is actually how CMake works.)
The build information is composed of two keys, compile, which indicates which
sources to compile, and link, which indicates which libraries to link. You
do not need to list here the dependencies, since they're already added
automatically, as mentioned above. But you can list here libraries built as part
of the current build. In the above example, the integration-tests binary
will link with the (static) library called mkcurl, in addition to linking
to all the libraries implied by the declared dependencies.
The tests key indicates what test to run. Each key inside tests is the name
of a test. The command key indicates what command to execute. Of course, the
command line arguments can be quoted, if required.
One you've written (or updated) MKBuild.yaml, just run
mkbuild
This will generate (or update) CMakeLists.txt and docker.sh.
You should commit these files to the repository.
Since mkbuild generates a CMakeLists.txt and we suggest to commit
it to your repository, the build instructions are the standard build
instructions of any CMake based software project (we tend to use
ninja, so the following instructions use ninja):
mkdir build
cd build
cmake -GNinja ..
cmake --build .
ctest -a -j8 --output-on-failure
Provided that you have Docker installed, running a docker based build is as simple as running:
./docker.sh <build-type>
Run docker.sh without arguments to see the available build types. The
names of the build types should be self explanatory.
The .travis.yml file should look like:
language: c++
services:
- docker
sudo: required
matrix:
include:
- env: BUILD_TYPE="asan"
- env: BUILD_TYPE="clang"
- env: BUILD_TYPE="coverage"
- env: BUILD_TYPE="ubsan"
- env: BUILD_TYPE="vanilla"
script:
- ./docker.sh $BUILD_TYPEThis is equal to what we have now, except that the name of the script to run docker is now different.
The .appveyor.yml is quite like the one that we use now:
image: Visual Studio 2017
environment:
matrix:
- CMAKE_GENERATOR: "Visual Studio 15 2017 Win64"
- CMAKE_GENERATOR: "Visual Studio 15 2017"
build_script:
- cmd: cmake -G "%CMAKE_GENERATOR%" .
- cmd: cmake --build . -- /nologo /property:Configuration=Release
- cmd: ctest --output-on-failure -C Release -aThe main difference is that we don't need to force git to update
the subrepos anymore.
This software is meant to replace the github.com/measurement-kit/cmake-utils and github.com/measurement-kit/ci-common subrepositories. Rather than having to keep the submodules up to date, we automatically generate files and scripts implementing the same functionality.
Because this tool generates standalone CMakeLists.txt and docker.sh, it
means that it can easily be replaced with better tools, or no tools. Yet, the
burden of keeping in sync the subrepos is gone and it is replaced with the
much lower burden of running mkbuild from time to time to sync.
An earlier design of this tool was such that CMakeLists.txt and
docker.sh were not committed to the repository. Yet, this is probably
not advisable since it may lead to non reproducible builds, because
the newly generated CMakeLists.txt and/or docker.sh may differ. In
any case, should we decided that not committing these files into
the repository is instead better, we just need to update the build
instructions to mention to compile and run mkbuild as the first step.