How to package header-only libraries

Without unit tests

Packaging a header only library, without requiring to build and run unit tests for it within conan, can be done with a very simple recipe. Assuming you have the recipe in the source repo root folder, and the headers in a subfolder called include, you could do:

from conans import ConanFile

class HelloConan(ConanFile):
    name = "Hello"
    version = "0.1"
    # No settings/options are necessary, this is header only
    exports_sources = "include/*"

    def package(self):
        self.copy("*.h")

If you want to package an external repository, you can use the source() method to do a clone or download instead of the exports_sources fields.

  • There is no need for settings, as changing them will not affect the final package artifacts
  • There is no need for build() method, as header-only are not built
  • There is no need for a custom package_info() method. The default one already adds “include” subfolder to the include path
  • Note that this recipe has no other dependencies, settings or options. If it had any of those, it would be very convenient to add the package_id() method, to ensure that only one package with always the same ID is create irrespective of the configurations and dependencies:
def package_id(self):
    self.info.header_only()

Package is created with:

$ conan create user/channel

With unit tests

If you want to run the library unit test while packaging, you would need this recipe:

from conans import ConanFile, CMake

class HelloConan(ConanFile):
    name = "Hello"
    version = "0.1"
    settings = "os", "compiler", "arch", "build_type"
    exports_sources = "include/*", "CMakeLists.txt", "example.cpp"

    def build(self): # this is not building a library, just tests
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
        cmake.test()

    def package(self):
        self.copy("*.h")

    def package_id(self):
        self.info.header_only()

Which will use a CMakeLists.txt file in the root folder:

project(Package CXX)
cmake_minimum_required(VERSION 2.8.12)

include_directories("include")
add_executable(example example.cpp)

enable_testing()
add_test(NAME example
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
        COMMAND example)

and some example.cpp file, which will be our “unit test” of the library:

#include <iostream>
#include "hello.h"

int main() {
    hello();
}
  • This will use different compilers and versions, as configured by conan settings (in command line or profiles), but will always generate just 1 output package, always with the same ID.
  • The necessary files for the unit tests, must be exports_sources too (or retrieved from source() method)
  • If the package had dependencies, via requires, it would be necessary to add the generators = "cmake" to the package recipe and adding the conanbuildinfo.cmake file to the testing CMakeLists.txt:
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

add_executable(example example.cpp)
target_link_libraries(example ${CONAN_LIBS}) # not necessary if dependencies are also header-only

Package is created with:

$ conan create user/channel

Note

This with/without tests is referring to running full unitary tests over the library, which is different to the test_package functionality that checks the integrityg of the package. The above examples are describing the approaches for unit-testing the library within the recipe. In either case, it is recommended to have a test_package folder, so the conan create command checks the package once it is created. Check the packaging getting started guide