【问题标题】:How to make a header-only library with cmake?如何用 cmake 制作一个只有头文件的库?
【发布时间】:2020-06-21 13:27:58
【问题描述】:

如何在cmake中制作一个项目,将所有c++文件收集到一个头文件中?

我有这个项目结构。

/
  project/
     folder1/
         file.cpp
         file.hpp
     folder2/
         ...etc
     CMakeLists.txt
  tests/
     test.cpp
     CMakeLists.txt
CMakeList.txt

根 cmakelists.txt

cmake_minimum_required (VERSION 3.8)

project ("CMakeProject"
    LANGUAGES C CXX)

set(CMAKE_EXECUTABLE_SUFFIX ".exe")

include(GNUInstallDirs)

add_subdirectory ("project")


option(ENABLE_TESTING OFF)

if (ENABLE_TESTING)
    enable_testing()
    add_subdirectory("tests")
endif()

项目中的CMakeLists.txt

cmake_minimum_required (VERSION 3.8)

file(GLOB projectSRC
    "*/*.cpp"
    "*/*.hpp"
    "*.cpp"
    "*.hpp"
)

add_library(project INTERFACE)

message(STATUS "CMake inatall directory: " ${CMAKE_INSTALL_INCLUDEDIR})
target_include_directories(project 
    INTERFACE 
        $<BUILD_INTERFACE:${PROJECT_INCLUDE_DIR}>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

并测试 cmakelist.txt

cmake_minimum_required (VERSION 3.8)

# install Catch2 testing library
# (https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#installing-catch2-from-git-repository or use packet manager)
find_package(Catch2 REQUIRED)

file(GLOB testSRC
    "*.cpp"
)

add_executable(tests ${testSRC})

target_link_libraries(tests
    Catch2::Catch2
    project)

include(CTest)
include(Catch)
catch_discover_tests(tests)

如何生成一个标头并使用它(在测试或其他项目中)或使该库能够具有模板?第一个更好。

【问题讨论】:

  • 如果你想把所有东西都放在头文件里,你为什么要把东西放在 .cpp 文件中??
  • 这可能是不可能的。您可以定义单个 cpp 文件的本地变量,如果您已经这样做了,那么如果多个 cpp 文件定义相同的变量,您可能会重新定义某些东西。
  • 如果很重要,我可以将所有内容移到标题中,但不能移到一个中。
  • 我从未亲自尝试过这样做。但是,您可以在 github 上查看执行此操作的开源项目。你可能会从他们的项目中得到很好的指导。我知道 2,有 pybind11 和 catch2 是仅标头库。
  • 可以在这里找到逐行解释的良好参考:dominikberner.ch/cmake-interface-lib

标签: c++ cmake shared-libraries


【解决方案1】:

如何用 cmake 制作一个只有头文件的库?

像这样:

add_library(project INTERFACE)
target_include_directories(project INTERFACE .)

然后在使用该库的目标中:

target_link_libraries(dependee
    PUBLIC/INTERFACE/PRIVATE # pick one
    project)

并像这样包含标题:

#include <project/folder1/file.hpp>

【讨论】:

  • 我在target_link_libraries中发现如果header only library是INTERFACE那么在构建项目时cmake不会检测到该库的头文件。
  • 严格来说,不应该是'.'的范围在 target_include_directories 中是 PUBLIC 还是 INTERFACE?从技术上讲,该目录中的文件包括该目录中的其他文件。我知道,实际上,这没有什么区别,因为你永远不会真正构建这个项目。我想如果您添加一个实现文件并将库更改为 PUBLIC(非仅标头),它将允许您少做一点更改。
  • @ToddR 如果库是“INTERFACE”,则该关键字只能是“INTERFACE”。
  • 值得注意的是:由于 CMake 3.19 接口库可以使用源文件创建,即add_library(project INTERFACE file1.hpp file2.hpp)。如果您正在使用 Visual Studio,这些标题现在将显示在生成的项目下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
  • 2015-06-04
  • 1970-01-01
  • 2020-04-15
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多