Search code examples
c++linuxcmakebuildheader-only

Facing problems in my first time handling CMake, Third party(header only) libraries


I want to use the following library https://github.com/gmeuli/caterpillar

It's documentation says that it's a header-only library, and that I should "directly integrate it into my source files with #include <caterpillar/caterpillar.h>." It also depends on a few other libraries, one of which I need to use directly as well.

So far I have done the following:

  1. create cmake project to make an 'executable' (with the vscode extension)
  2. created a 'lib' folder, inside which I did
git clone https://github.com/gmeuli/caterpillar
  1. Then, I did include_directories(lib) in my cmake file.
  2. But #include <caterpillar/caterpillar.h> doesn't quite work in my singular main.cpp file.

I played around with various CMake functions, and it either gave the error "No such file or directory" regarding caterpillar/caterpillar.h itself, or it gave "cannot open source file... dependent of caterpillar/caterpillar.h" depending on how I messed with the cmake file.

For reference:

cat ~/project/main.cpp

#include <caterpillar/caterpillar.hpp>
#include <lorina/lorina.hpp> //how do I include this ? it's in the lib folder of caterpillar itself, or do I need to have a copy of it in my lib folder too

int main()
{
    // stuff in lorina:: namespace
    // stuff in caterpillar:: namespace
    return 0;
}

cat ~/project/CMakeLists.txt

include_directories(lib)
//... rest is stuff like CXX standard, etc etc

tree ~/project

main.cpp
lib/
    caterpillar/
build/
    cmake generated stuff
CMakeLists.txt

Solution

  • Firstly, modern cmake recommends target_include_directories() instead of old include_directories() for better scope management.

    Actually <caterpillar/caterpillar.hpp> is not in $PROJECT_SOURCE_DIR/lib directory. That's why your code not works.

    CMakeLists example:

    cmake_minimum_required(VERSION 3.22)
    project(myproject)
    
    set(CMAKE_CXX_STANDARD 17)
    
    add_executable(my_project main.cpp)
    
    target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/include)
    
    # project_src_dir/lib/catepillar/include/ is the directory where you find the headers like <catepillar/catepillar.hpp>
    
    target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/lib/lorina)
    

    caterpillar's document describes how to include their headers in a traditional style, assuming the readers could understand this and decide where to put the headers themselves. (which means you don't need the whole git repo but only the "include" dir.)


    For this specific problem, the library has provided a detailed CMakeLists.txt for users to include:

    cmake_minimum_required(VERSION 3.22)
    project(my_project)
    
    set(CMAKE_CXX_STANDARD 17)
    
    add_subdirectory(lib/caterpillar)
    # this works because "project_src_dir/lib/catepillar/CMakeLists.txt" exists.
    
    add_executable(my_project main.cpp)
    target_link_libraries(my_project PRIVATE caterpillar)
    # you need to tell cmake to add all catepillar settings into your project