Creating a header-only library that can be included via add_subdirectory

298 Views Asked by At

I'm creating a lightweight header-only library for coroutines in C++20 called Conduit. The structure of the library looks like this, and it has no dependencies other than the C++ standard library:

conduit
|
|---CMakeLists.txt
|
|---tests/tests.cpp
|
|---include/conduit/
        |---coroutine.hpp
        |---future.hpp
        |---[Other header files...]

Question: How do I write the CMakeLists.txt file for my library so that other projects can use Conduit by adding it as a subdirectory via add_subdirectory?

While conduit does provide an installation option, the intended way for someone to use conduit is to add it as a sub-directory inside their project. Inside the CMakeLists.txt folder for example_project, there'd be a line add_subdirectory(conduit), and the directory structure of example_project would look something like this:

example_project
|
|---CMakeLists.txt
|
|---src/...
|
|---include/...
|
|---conduit
    |
    |---CMakeLists.txt
    |
    |---tests/tests.cpp
    |
    |---include/conduit/
            |---coroutine.hpp
            |---future.hpp
            |---[Other header files...]

What I have so far: This is what I'm currently using as the CMakeLists.txt file for conduit. It compiles and runs tests.cpp with a variety of different tests, but when I add conduit as a sub-directory to another project (via git submodule + add_subdirectory in CMakeLists.txt), CMake doesn't add conduit/include/ to the list of include files.

cmake_minimum_required(VERSION 3.0.0)
project(conduit VERSION 0.3.0 LANGUAGES CXX)

option(CONDUIT_Install "Install CMake targets during install step." ON)

if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
    add_compile_options("/std:c++latest" "/await" "/EHsc")
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
    add_compile_options("-std=c++20")
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
    add_compile_options("-std=c++20" "-fcoroutines")
endif()

include_directories(include)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CONDUIT_TARGET_NAME ${PROJECT_NAME})
set(CONDUIT_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")

add_library(${CONDUIT_TARGET_NAME} INTERFACE)
 
target_compile_definitions(
    ${CONDUIT_TARGET_NAME}
    INTERFACE
)

target_include_directories(
    ${CONDUIT_TARGET_NAME}
    INTERFACE
    $<BUILD_INTERFACE:${CONDUIT_INCLUDE_BUILD_DIR}>
    $<INSTALL_INTERFACE:include>
)

install(
    DIRECTORY ${CONDUIT_INCLUDE_BUILD_DIR}
    DESTINATION include
)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
    include(CTest)
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
    add_executable(run_tests tests/tests.cpp)
    set(THREADS_PREFER_PTHREAD_FLAG ON)
    find_package(Threads REQUIRED)
    target_link_libraries(run_tests PRIVATE Threads::Threads)

    foreach(X IN ITEMS 
        test_coroutine
        test_destroy
        test_exception_1
        test_exception_2
        test_future
        test_generator
        test_on_suspend
        test_recursive_generator
        test_resume_on_alternate_thread
        test_source
        test_suspend_invoke
        test_task)
        add_test(NAME "${X}" COMMAND run_tests "${X}")
    endforeach()
endif()
0

There are 0 best solutions below