如何使用CMake命令/设计一个共享库,使用更高的包括

How to order/design a shared library with CMake that use higher includes

本文关键字:共享 包括 一个 命令 CMake 何使用      更新时间:2023-10-16

目前我有一个大约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>

现在的问题是,编译器不知道在库中查找包含的<> ,例如在foo中的Header.h包含。bar指向${CMAKE_CURRENT_SOURCE_DIR}/Header.h,但CMAKE_CURRENT_SOURCE_DIR是应用程序的路径,而不是库

的路径。

所以我必须添加库的目录,编译器可以找到库的其他头文件(库中的头文件通过<>而不是"在库中包含另一个头文件)

所以我以这样的方式结束:

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

现在Bar.h可以找到foo/foo .h,否则就会出错。这个更难看

所以我的问题:是否有一个好的/棘手的方法来解决这个问题在CMake ?或者谁能给我一些关于更好的项目结构的建议?解决方案必须在MSVC、GCC和clang下运行。

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

<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>)

我所做的是解决这个问题是有一个顶级的CMakeLists.txt设置变量,将指向项目目录的顶部。在您的示例中,这将是包含ApplicationMyLibrary的目录。

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 ) 

然后在你的子目录cmakelist中,你可以像这样添加include路径:

include_directories( ${my_app_src_top}/MyLibrary )

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

我认为有了这个结构,你应该能够

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

另外,您可能希望在每个子目录的include_directories中添加。/。