首页 > 解决方案 > 创建可以通过 add_subdirectory 包含的仅标头库

问题描述

我正在为 C++20 中的协程创建一个轻量级的仅包含标头的库,称为 Conduit。库的结构是这样的,除了 C++ 标准库之外没有其他依赖:

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

问题:如何为我的库编写 CMakeLists.txt 文件,以便其他项目可以通过将其添加为子目录来使用 Conduit add_subdirectory

虽然导管确实提供了安装选项,但人们使用导管的预期方式是将其作为子目录添加到他们的项目中。在 example_project 的 CMakeLists.txt 文件夹内,会有一行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,但是当我将管道作为子目录添加到另一个项目时(通过add_subdirectoryCMakeLists.txt 中的 git submodule +),CMake 不会将管道/包含/添加到列表中的包含文件。

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

标签: c++cmakec++20header-only

解决方案


推荐阅读