Создание библиотеки только для заголовков, которая может быть включена через add_subdirectory

#c #cmake #c 20 #header-only

#c #cmake #c 20 #только для заголовков

Вопрос:

Я создаю облегченную библиотеку только для заголовков для сопрограмм в C 20 под названием Conduit. Структура библиотеки выглядит следующим образом, и у нее нет зависимостей, отличных от стандартной библиотеки C :

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

Вопрос: Как мне написать CMakeLists.txt файл для моей библиотеки, чтобы другие проекты могли использовать Conduit, добавив его в качестве подкаталога через add_subdirectory ?

Хотя conduit предоставляет опцию установки, предполагаемый способ использования conduit — добавить его в качестве подкаталога внутри своего проекта. Внутри CMakeLists.txt папка для example_project, там была бы строка add_subdirectory(conduit) , а структура каталогов example_project выглядела бы примерно так:

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

Что у меня есть до сих пор: это то, что я в настоящее время использую в качестве CMakeLists.txt файл для канала. Он компилируется и запускается tests.cpp с множеством различных тестов, но когда я добавляю conduit в качестве подкаталога в другой проект (через подмодуль git add_subdirectory в CMakeLists.txt ), CMake не добавляет conduit/ include/ в список включенных файлов.

 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()
  

Комментарии:

1. Вам вообще не нужно include_directories , поскольку вы используете target_include_directories . Добавляются ли какие-либо включаемые каталоги при использовании conduit?

2. Когда другой проект использует conduit через add_subdirectory, он не добавляет conduit / include в список включенных каталогов этого проекта, как предполагалось. Это то, что я пытаюсь исправить.

3. Я понимаю это, поэтому я спрашиваю, будет ли добавлено что -нибудь. Когда у меня была эта проблема в прошлом, это потому, что у меня были неправильные параметры в target_include_directories .

4. Это ничего не добавляло к команде компиляции. Я обнаружил, что если я добавлю target_link_libraries в CMakeLists для проекта, включающего conduit, он будет включать conduit, но ни один из параметров компилятора, которые я настроил в conduit, не будет распространен (нужно ли мне использовать target_compile_options?)