Conan and Waf Quickstart Guide

In this quickstart guide, I'll show you how you can start using Conan recipes in your Waf projects. If you want some more in-depth explanations, you can checkout my longer article here.

Setup

Conan doesn't currently have built-in support for Waf, but you can use the plugin that I created for that.

1
2
pip install conan #install Conan
conan config install https://github.com/AlexRamallo/waf-conan-generator #install my Waf plugin

That command will essentially just do a git clone of the repo into your conan config folder (minus some unneeded files).

Sample Project

Create a new folder for this project and download the latest waf script into it.

1
2
3
4
mkdir MyProject
cd MyProject
curl https://waf.io/waf-2.0.26 --output waf
chmod +x waf #add execute permission to waf

For this demo, I'll be using the spdlog library that's available on Conan Center. This is a handy logging library which depends on the popular fmt library.

Here's the full source code for that app:

1
2
3
4
5
6
7
//main.cpp
#include <spdlog/spdlog.h>

int main(int argc, char *argv[]){
    spdlog::info("Hello, waf! {}", argv[0]);
    return 0;
}

Create conanfile.txt

The conanfile.txt file is what tells Conan what our dependencies are, and what build system we're using.

1
2
3
4
5
6
#conanfile.txt
[requires]
spdlog/1.12.0

[generators]
Waf

It's pretty straightforward.

Create wscript

The wscript for our project will be pretty standard, with the only special thing being that we need to load the dependency data provided to us by Conan.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#wscript
def options(opt):
    opt.load("compiler_cxx")

def configure(conf):
    conf.load("conan_deps", tooldir="build") #tooldir should point to Conan output folder
    conf.load("compiler_cxx")

def build(bld):
    bld(
        features = "cxx cxxprogram conan", # needed for linking with conan packages
        source = "main.cpp",
        target = "app",
        use = "spdlog" # name of conan package we want to link with
    )

And that's it! The three main things to notice are:

  1. At line 6 we load the info that Conan will generate for us, which is used to pass the correct compiler/link flags for all dependencies
  2. At line 11 we add a "conan" feature string, which is needed when we want to link with conan dependencies
  3. At line 14 we pass "spdlog" to the use attribute, ensuring we compile/link with that library

Compiling it

Before we can compile, we need to run conan install in order to generate the dependency data that Waf needs:

1
2
3
conan install . -of=build
./waf configure
./waf build

The -of=build flag will tell Conan to generate the dependency data into a folder called build, which is the same folder we loaded from in our wscript's configure method. I used "build" in this example since that's also the name of Waf's default output folder, so you can clean it all with a simple waf distclean. However, you could change that folder to whatever you want.

Running it

Running it is easy:

1
./build/app

The spdlog package and its dependencies will use static linking by default. So we don't have to worry about missing .DLLs or setting LD_LIBRARY_PATH for this example.

However, if you do decide to use dynamic linking, then you can let Conan handle that stuff for you by executing the conanrun.sh script that was generated in the build folder when you called conan install:

1
2
3
source build/conanrun.sh #activate run env (with correct lib search paths)
./build/app
source build/deactivate_conanrun.sh #restore original environment

Next Steps

Now that you know how to use Waf and Conan together, try playing around with some of the 1600+ packages on Conan Center. There are some interesting ones on there, like boost, SDL, Cairo, libcurl, openssl, and much more.

You don't have to worry about following arcane build instructions, installing multiple different build systems, or adding dozens of flags to your build scripts. As a Conan user, all you have to do is add a new line to the [requires] section of your conanfile.txt, and you're ready to go!