目前我有一个大约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设置变量,将指向项目目录的顶部。在您的示例中,这将是包含Application和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 )
然后在你的子目录cmakelist中,你可以像这样添加include路径:
include_directories( ${my_app_src_top}/MyLibrary )
我也只是在顶层定义了一个项目CMakeLists.txt。在这种情况下,您可能能够引用${PROJECT_SOURCE_DIR},但如果您在子目录中定义项目,那么我认为这将根据您构建的最后一个子目录进行重置。
我认为有了这个结构,你应该能够
#include <foo/Foo.h>
#include <bar/Bar.h>
另外,您可能希望在每个子目录的include_directories中添加。/。