简体   繁体   English

如何创建依赖于外部头文件的cmake header-only库?

[英]How to create a cmake header-only library that depends on external header files?

I have a project with the following file structure: 我有一个具有以下文件结构的项目:

project
 |
 |-------> lib1
 |           |----> lib1.h
 |
 |-------> lib2
 |           |----> lib2.h
 |
 |-------> main.cc

The two libs lib1 and lib2 only contain header files while lib2.h includes lib1.h , and main.cc includes lib2.h . 两个libs lib1lib2只包含头文件,而lib2.h包含lib1.hmain.cc包含lib2.h

How do I write the cmake file for this project now? 我现在如何为这个项目编写cmake文件? I tried to create an interface library for lib2 , but the compiler can't find lib1.h . 我试图为lib2创建一个接口库 ,但编译器找不到lib1.h Here are the contents of my cmake files: 以下是我的cmake文件的内容:

CMakeLists.txt for lib2: lib2的CMakeLists.txt:

add_library(lib2 INTERFACE)
target_sources(lib2 INTERFACE lib2.h)
target_include_directories(lib2 INTERFACE ../lib1/lib1.h)

CMakeLists.txt for the whole project: 整个项目的CMakeLists.txt:

add_executable(project main.cc)
target_link_libraries(project lib2)

What's the problem in the cmake files? cmake文件中有什么问题?

As stated in the comments, target_include_directories should be given a path to a directory, not to a file. 如评论中所述,应为target_include_directories提供目录的路径,而不是文件的路径。

Moreover, if you want to create a dependency for lib2 on lib1 , you should do it through target_link_libraries : a dependency is not only about include directories, but also about compile options, definitions, target properties... 此外,如果你想创建一个依赖lib2lib1 ,你应该这样做,通过target_link_libraries :依赖不仅是包含目录,但也对编译选项,定义,目标属性...

target_sources doesn't work with interface libraries. target_sources不适用于接口库。 From this answer , You can use a custom target without commands to associate the sources to a target without impacting the build process (for msvc, QtCreator and other GUI-based tools, this makes the sources accessible through the IDE; AFAIK it's useless for other build tools). 这个答案中 ,您可以使用没有命令的自定义目标将源关联到目标而不影响构建过程(对于msvc,QtCreator和其他基于GUI的工具,这使得可以通过IDE访问源; AFAIK对其他无用)构建工具)。

Your cmake may look like this: 您的cmake可能如下所示:

add_library(lib1 INTERFACE)
target_sources(lib1 INTERFACE lib1.h)

target_include_directories(lib1 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib1"
)

add_library(lib2 INTERFACE)
if(MSVC)
    add_custom_target(lib2.headers SOURCES lib2.h)
endif()

target_include_directories(lib2 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib2"
)

target_link_libraries(lib2 INTERFACE lib1)

add_executable(project main.cc)
target_link_libraries(project lib2)

Advanced tip: you can specify a different directory in target_include_directories for the build tree and the install tree (see documentation ): 高级提示:您可以在target_include_directories为构建树和安装树指定其他目录(请参阅文档 ):

target_include_directories(lib1 INTERFACE
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib1>
    $<INSTALL_INTERFACE:${YOUR_INSTALL_DIR}/lib1>
)

I've used an empty _only_for_compiling_the_lib.cpp file as the simplest and fastest workaround, but clearly the above solution is strongly advised. 我使用了一个空的_only_for_compiling_the_lib.cpp文件作为最简单和最快速的解决方法,但显然强烈建议使用上述解决方案。

I simply wasn't aware of INTERFACE keyword. 我根本不知道INTERFACE关键字。

This problem was due to full path issue of INTERFACE library files, which got fixed in cmake version 3.13. 此问题是由INTERFACE库文件的完整路径问题引起的,该问题已在cmake 3.13版中得到修复。

For more info: https://gitlab.kitware.com/cmake/cmake/issues/17556 欲了解更多信息: https//gitlab.kitware.com/cmake/cmake/issues/17556

This page also contains an example for better understanding. 此页面还包含一个更好理解的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM