库标头在标头中不可见,但在cmake构建下的.cpp文件中完全可见。为什么?

时间:2018-10-24 17:14:47

标签: c++ cmake

我有一个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方面是错误的,或者整个文件层次结构都缺少某些内容。

2 个答案:

答案 0 :(得分: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将位于include路径上。

答案 1 :(得分:0)

确实是从INCLUDE_DIRECTORIES()切换为TARGET_INCLUDE_DIRECTORIES(),无需更改项目结构。