如何使用更高级别的CMake订购/设计共享库

时间:2014-08-04 14:07:06

标签: c++ include cmake include-path

目前我有一个大约30个班级的共享库。我的想法是将它们分组到子目录中,意味着子目录包含或多或少等于/具有相同内容的类(ui,utils,backend等)。

但是我遇到了一个典型的问题:我有一些在项目中共享的导出定义/常量,我的第一个问题是:如何在子目录中的头中包含这个头?

我经常看到#include ../Header.h解决方案,但我的个人意见是,这非常难看。

所以我做了什么:

Application/
      main.cpp
MyLibrary/
      Header.h
      foo/
            Foo.h (#include <Header.h>
      bar/
            Bar.h (#include <Header.h> #include <foo/Foo.h>)

在我的库CMakeList中,我添加了include_directory和MyLibrary目录的根目录。

我的应用程序可执行文件CMakeLists.txt看起来像这样(伪CMake)

project(application)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)

add_executable(application main.cpp)

target_link_libraries(application mylibrary)

main.cpp我包括这样的内容:

#include <MyLibrary/Header.h>
#include <MyLibrary/bar/Bar.h>

现在的问题是,编译器不知道在哪里查找包含的&lt;&gt; INSIDE 库,例如foo.bar中的Header.h包含指向${CMAKE_CURRENT_SOURCE_DIR}/Header.h - 但是CMAKE_CURRENT_SOURCE_DIR是应用程序的路径而不是库

所以我必须添加库的目录,编译器可以找到该库的其他标题(库中的标题包含库中的另一个标题,通过&lt;&gt;而不是&#34;&#34 ;)

所以我最终得到这样的东西:

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../MyLibrary)

现在Bar.h可以找到foo / Foo.h,否则会出错。而且这更难看了

所以我的问题:在CMake中解决这个问题是否有好的/棘手的方法?或者有人可以给我一些更好的项目结构吗?解决方案必须在MSVC,GCC和clang下运行。

2 个答案:

答案 0 :(得分:2)

如果您考虑安装后库的外观,您可能会得到一些关于结构的提示。例如:

<install-prefix>/Foo/foo.hpp -> has `#include <Boo/boo.hpp>`
<install-prefix>/Boo/boo.hpp -> has `#include <Bar/bar.hpp>`
<install-prefix>/Bar/bar.hpp -> has `#include <Bar/details/utils.hpp>`
<install-prefix>/Bar/details/utils.hpp

在安装完成之前,这是可能的布局:

<source-dir>/Sources/Foo/foo.hpp
<source-dir>/Sources/Boo/boo.hpp
<source-dir>/3rdParty/Bar/bar.hpp
<source-dir>/3rdParty/Bar/details/utils.hpp

因此CMakeLists.txt必须包含(或更好target_include_directories):

include_directories(<source-dir>/Sources)
include_directories(<source-dir>/3rdParty)

所以对于你的情况,恕我直言,它必须是这样的:

Application/
    main.cpp
MyLibrary/
    Header.h
    foo/
        Foo.h (#include <MyLibrary/Header.h>
    bar/
        Bar.h (#include <MyLibrary/Header.h> #include <MyLibrary/foo/Foo.h>)

答案 1 :(得分:0)

我为解决这个问题所做的是有一个顶级的CMakeLists.txt,它设置指向项目目录顶部的变量。在您的情况下,这将是包含应用程序 MyLibrary 的目录。

ProjectRoot
CMakeLists.txt // top
   Application/
      CMakeLists.txt
      main.cpp
   MyLibrary/
      CMakeLists.txt
      Header.h
      foo/
            Foo.h (#include <Header.h>
      bar/
            Bar.h (#include <Header.h> #include <foo/Foo.h>)

# Top level cmakelists
project (myproject)
set (my_app_src_top "${CMAKE_CURRENT_SOURCE_DIR}" )
set (my_app_build_top "${CMAKE_CURRENT_BINARY_DIR}" )
add_subdirectory( MyLibrary )
add_subdirectory( Application ) 

然后在您的子目录CmakeLists中,您可以添加如下所示的包含路径:

include_directories( ${my_app_src_top}/MyLibrary )

我也只是在顶级CMakeLists.txt中定义一个项目。在这种情况下,您可以引用$ {PROJECT_SOURCE_DIR},但如果您在子目录中定义项目,那么我认为这将根据您构建的最后一个子目录重置。

我认为通过这种结构你应该能够

#include <foo/Foo.h>
#include <bar/Bar.h>

另外,您可能希望将./添加到每个子目录的include_directories。