【问题标题】:How to require a header-only library without binary in cmake?如何在 cmake 中要求没有二进制文件的仅标头库?
【发布时间】:2018-11-16 09:44:33
【问题描述】:

我创建了一个只有头文件的库,它是使用 cmake 安装的

add_library(mylib INTERFACE)

和导出的目标。 这很好用,当我在另一个库 (mylib2) 的 cmake 文件中使用 find_package(mylib REQUIRED)target_link_library 时,其中包括标题。

但是当我使用导出的目标和target_link_library 链接mylib2 时,生成的VS 文件在链接库中包含mylib.lib

当我在所有三个项目的生成文件中查找字符串 mylib.lib 时,只有 Visual Studio 文件包含此字符串,PackageConfigPackageTargets 文件均不包含文件名。

标头库在其 CMakeLists.txt 中使用导出的目标

add_library(mylib INTERFACE)
target_compile_definitions(mylib INTERFACE -D_USE_MATH_DEFINES)
target_link_libraries(mylib INTERFACE somelibraries)
target_include_directories(mylib INTERFACE
        $<INSTALL_INTERFACE:include>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
configure_package_config_file(mylibConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX})
install(TARGETS mylib EXPORT mylib-targets)
install(EXPORT mylib-targets FILE mylibTargets.cmake DESTINATION ${CMAKE_INSTALL_PREFIX})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake DESTINATION ${CMAKE_INSTALL_PREFIX})
install(DIRECTORY ./ DESTINATION include FILES_MATCHING PATTERN "*.h")

第二个库刚刚使用

find_package(mylib REQUIRED)
add_library(mylib2 source.cpp)
target_link_libraries(mylib2 mylib)
# some stuff to export targets, similar to the first lib

最终项目使用

add_binary(myproject source.cpp)
set(LINK_LIBRARIES mylib2)
target_link_libraries(myproject ${LINK_LIBRARIES}) # mylib2.lib is added to the project.

add_binary(myproject2 source.cpp)
target_link_libraries(myproject mylib2) # only the include paths are added.

仅当库是从变量设置时才会出现问题。

cmake 在流程的哪个阶段将库文件名添加到链接库?不应该继承INTERFACE属性吗?

【问题讨论】:

  • 你没有在第一个代码sn-p中安装mylib2目标,所以你不能从第二个代码中使用它。也就是说,您可以使用mylib2,但它表示库名称(转换为mylib2.lib),而不是目标
  • 对不起,我在简化代码时犯了一个错误,把它贴在这里。头库是mylib,只定义了自己的目标(并导出mylib目标)。第二个库 (mylib2) 针对mylib 导出的目标“链接”并从中获取正确的包含路径。程序项目链接到mylib2,但没有明确针对mylib,而是将mylib.lib 添加到库列表中。我重新排列了问题中的代码 sn-ps 并修复了对 mylib2 的错误引用。

标签: c++ cmake


【解决方案1】:

要包含库,您通常必须包含头文件并链接一些目标文件。

话虽如此,如果所述库是仅标题的,您只需执行include_directories(&lt;library-include-folder&gt;) 即可。由于通常不应将您的库编译为 .lib 文件。

在您的情况下,您可能必须这样做:(假设 mylib 仅是标头)

find_package(mylib REQUIRED)
# Provides MYLIB_INCLUDE_DIR to include
# The line above also provides a MYLIB_LIBRARIES, which for header-only libraries should be empty

include_directories(${MYLIB_INCLUDE_DIR})
add_executable(main main.cpp)
target_link_libraries(main ${MYLIB_LIBRARIES}) # This can be onmitted since there is nothing to link

【讨论】:

  • 我使用exported targets打包它,当您将库添加到target_link_libraries时,它会正确设置目标包含、编译定义等。将target_link_libraries 用于仅标头库似乎有点奇怪,但在链接mylib2 时效果很好。
猜你喜欢
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-05-11
  • 2015-01-18
  • 2012-11-24
  • 2017-02-14
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多