【问题标题】:Link up src/ with CMake as library #include'd with some `libname/` prefix链接 src/ 与 CMake 作为库 #include'd 与一些 `libname/` 前缀
【发布时间】:2020-07-25 23:52:48
【问题描述】:

对于我的研究项目,我正在建立一个项目 (coom) 来对数据结构上的一组算法进行基准测试。对于单元测试,我选择了 Bandit,这让我的项目结构如下所示:

+ root
|-- CMakeLists.txt
|-+ external/
| \-- bandit/
|-+ src/
| |-- CMakeLists.txt
| |-- node.cpp
| \-- node.h 
\-+ test/
  |-- CMakeLists.txt
  |-- test.cpp
  \-- test_node.cpp

根据我使用其他语言的经验,这在我看来是一个标准的项目结构? test/ 文件夹包含对 src/ 中逻辑的单元测试,并且没有与源代码和测试代码混合的依赖项,而是在 external/ 中。

想要如下所示的测试文件(不相关的部分已删除)

// test/test.cpp
#include <bandit/bandit.h>
(...)

#include "test_node.cpp"

int main(int argc, char* argv[]) {
  (...)
}
// test/test_node.cpp
#include <coom/node.h>
(...)

但我的问题是,当我尝试使用cmake .. 和随后的Makefile 进行编译时,他们无法在src/ 中找到源代码,我得到编译器错误:

fatal error: coom/node.h: No such file or directory. 

我希望test/CMakeLists.txt 看起来应该如下所示:

# test/CMakeLists.txt
add_executable (test_unit test.cpp)
target_link_libraries(test_unit coom)

我不知道如何设置CMakeLists.txtsrc/CMakeLists.txt 以确保获得上述预期结果。目前它们看起来如下:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project (coom VERSION 0.1)

# ============================================================================ #
# Dependencies
(...)

# ============================================================================ #
# COOM project
add_subdirectory (src)
add_subdirectory (test)
# src/CMakeLists.txt
# ============================================================================ #
# Link up files for the library
set(HEADERS
  node.h
)

set(SOURCES
  node.cpp
)

add_library(coom ${HEADERS} ${SOURCES})

我可以从其他项目中看到,可以将src/ 目录与一些libname/ 前缀链接,但我无法从他们的CMakeLists.txt 文件中辨别出我做错了什么。我已经研究过编写coom.pc.in 文件并提供install-target,并尝试使用set_target_propertiesFOLDER coomPREFIX coom,但均未成功。我可以将include_directory(../src) 破解到test/CMakeLists.txt 中,以便能够通过#include &lt;node.cpp&gt; 包含该文件,但这表明我做的事情本质上是错误的。

在这一点上,我非常担心,CMake 文档对我帮助不大。

【问题讨论】:

    标签: c++ cmake linker include-path


    【解决方案1】:

    您的coom 目标没有定义包含目录。您可以定义用于此目标的包含目录(使用target_include_directories()),并且传播这些包含目录,以便使用test_unit 目标可以看到它们(使用PUBLIC):

    # src/CMakeLists.txt
    # ============================================================================ #
    # Link up files for the library
    set(HEADERS
      node.h
    )
    
    set(SOURCES
      node.cpp
    )
    
    add_library(coom ${HEADERS} ${SOURCES})
    
    target_include_directories(coom PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
    

    此外,node.h 标头的文件路径是coom/src/node.h,而不是coom/node.h。但是,由于您现在将 coom/src 作为公共包含目录,您可以使用以下内容在测试文件中包含 node.h 标头:

    #include <node.h>
    

    【讨论】:

    • 关于coom/src/node.hcoom/node.h 我看到我两次使用相同的名称使我的问题不清楚。后者是当前文件结构的意图。也许这是不可能的? target_include_directories 有效(并且比我目前尝试的所有方法都漂亮),但它是最佳实践吗?也许我在文件夹结构上做错了什么?
    • 不,我不认为 CMake 或编译器支持这种“别名”前缀(因为缺少更好的术语),除非您对目录进行符号链接。 coom/node.h 根本不是头文件的有效路径,因此编译器将不知道如何找到它。这里已经有人问过类似的问题,例如this。您可以改为使用 target_include_directories() 中的顶级 CMake 目录,然后使用 src/node.h 包含标头。也许,您可以将src 目录重命名为coom
    • @SteffanSølvsten 话虽如此,target_include_directories() 的使用是标准 CMake 实践,用于将包含目录添加到特定目标的编译中。我在回复中添加了指向文档的链接。
    • 它解释了为什么 TPIE 依赖项的 src/ 文件夹名为 tpie/。感谢您对另一个问题的参考;令人恼火的是,我对“前缀”的搜索并没有出现。感谢您的详尽回答。
    猜你喜欢
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多