【问题标题】:Library headers not visible in headers but perfectly visible inside .cpp file under cmake build. Why?库标头在标头中不可见,但在 cmake 构建下的 .cpp 文件中完全可见。为什么?
【发布时间】:2018-10-25 05:43:41
【问题描述】:

我有一个包含多个模块的 C++ 项目,其中一些构建为库,具有这样的结构:

/MyProject
 +---/build 
     /ModuleA 
      +---CMakeLists.txt        <- module level CMakeLists
      +---/src
      |     +--CMakeLists.txt   <- src level CMakeLists
      |     +--FileA1.cpp
      |     +--FileA2.cpp
      +---/include
      |     +--FileA1.h
      |     +--FileA2.h
      |     +--FileA3.h
      /ModuleB
      +---CMakeLists.txt
      +---/src
      |     +--CMakeLists.txt
      |     +--FileB1.cpp
      |     +--FileB2.cpp
      +---/include
      |     +--FileB1.h
      |     +--FileB2.h
      |     +--FileB3.h
      main.cpp
      CMakeLists.txt            <- project level CMakeLists

CMakeLists.txt 文件如下:

项目级别:

cmake_minimum_required(VERSION 3.05)
project(MyProject)
subdirs(ModuleA ModuleB)   
set(CMAKE_CXX_STANDARD 11) 
add_executable(MyProject main.cpp)
target_link_libraries(MyProject ModuleA ModuleB)

模块级别:

subdirs(src)

src 级别:

FIND_PACKAGE(SomePackage REQUIRED) 
INCLUDE_DIRECTORIES(
        ${SomePackage_INCLUDE_DIR}
        ${MyProject_SOURCE_DIR}/ModuleA/include
)       
SET(SOURCE_FILES <all files from ModuleA/src goes here>)
ADD_LIBRARY(ModuleA STATIC ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(ModuleA
        ${SomePackage_LIBRARIES}
)

问题是:当我在我的 ModuleA 头文件中包含来自“SomePackage”的头文件(即 FileA1.h 中的 SomePackageFile.hpp)时,我在使用 make 运行构建时遇到错误:

致命错误:SomePackageFile.hpp:没有这样的文件或目录

当我将它们包含在 cpp 文件中时,它们是可见的并且项目可以正确编译。我认为 src 级别的 CMakeLists 有问题,或者整个文件层次结构丢失了一些东西。

【问题讨论】:

  • when I include header files from 'SomePackage' in my ModuleA header files - ModuleA 头文件未编译独立。它们被编译为某个源文件的一部分,该文件属于库或可执行文件。我猜您将FileA1.h 包含在项目的main.cpp 中。请注意,您的项目的可执行文件看不到为您的模块添加的包含目录。 (命令include_directories() 不影响父目录。)

标签: c++ cmake


【解决方案1】:

我有一个 github 项目可以用作其他项目的骨架:

https://github.com/gnyiri/cmake-sandbox

如果您遵循此布局,则无需将 ${SomePackage_INCLUDE_DIR} 添加到 INCLUDE_DIRECTORIES,否则这不是将目录添加到包含路径的最佳方式。

简而言之,您应该像这样定义一个新库:

project(module_a)

set(sources
  src/source_a_1.cc
)

add_library(library_a
  ${sources}
)

target_include_directories(library_a
  PUBLIC
    $<INSTALL_INTERFACE:include>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

那么,如果你定义另一个库(library_b),你只需要在target_link_libraries中添加library_a:

project(module_b)

# set list of sources, needs to be extended when new source arrives
set(sources
  src/source_b_1.cc
)

# define a library (static by default -> liblibrary_b.a or library_a.lib will be generated)
add_library(library_b
  ${sources}
)

# include directories
target_include_directories(library_b
  PUBLIC
    $<INSTALL_INTERFACE:include>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

# link library_b
target_link_libraries(library_b
  library_a
)

注意,在这个源码树中,所有的头文件都位于

<module>/include/<module>

这样你将包含一个像这样的头文件:

#include "<module>/<module_header.h>"

这仅仅是因为 /include 将位于包含路径上。

【讨论】:

  • 使用target_include_directories(),就是这样,谢谢提示。
【解决方案2】:

从 INCLUDE_DIRECTORIES() 切换到 TARGET_INCLUDE_DIRECTORIES() 就是这种情况,不需要更改项目的结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2020-01-18
    相关资源
    最近更新 更多