如何在CMake中处理这种编译情况?假设我们有一个源代码目录,其子目录如
src:
helper:
innerpkg:
a.cpp
a.h
helper.cpp
helper.h
main.cpp
main.h
文件a.cpp调用文件helper.cpp中的东西,虽然helper.cpp可能不会调用a.cpp中的任何内容。因此,如果我们让helper子目录成为库,而innerpkg成为库,我们就会遇到一个问题,其中helper需要包含innerpkg,但innerpkg也需要帮助器 - 一个循环依赖。处理这个问题的正确方法是什么,仍然将一些源文件保留在帮助程序中?顺便说一下,我很擅长使用CMake。
编辑:innerpkg中的CMakeLists.txt文件可能如下所示:
include_directories(${CCMBS_SOURCE_DIR})
set(INNERPKG_SRC a.cpp)
add_library(innerpkg ${INNKERPKG_SRC})
和帮手:
include_directories(${PROJ_SOURCE_DIR})
add_subdirectory(innerpkg)
set(HELPER_SRC helper.cpp)
add_library(helper ${HELPER_SRC})
target_link_libraries(ui "-Wl,--whole-archive")
target_link_libraries(ui innerpkg)
target_link_libraries(ui "-Wl,--no-whole-archive")
如果这有帮助。如何设置这些来解决这个问题?
编辑:确切的依赖结构是这样的:innerpkg中的东西取决于helper中的内容。 innerpkg由main使用。另一种情况是帮助器也依赖于innerpkg中的东西,即循环依赖,而main则使用helper或innerpkg。
答案 0 :(得分:5)
我觉得您假设基于CMake的项目中的每个目录都必须包含自己的CMakeLists.txt文件并构建自己的库/可执行文件。
这个问题实际上与CMake并不完全相关。几乎任何构建系统都会遇到同样的问题。这里的问题是你的依赖树不清楚。应该不惜一切代价避免循环依赖。
与Java及其基于包的系统相反,C ++应用程序没有强制执行目录布局,即使是CMake也没有。 依赖关系只能用库和可执行程序来表达,前者主要用于不在使用相同功能的单独程序之间复制代码。
在您的具体情况下,不清楚是谁在使用helper
和innerpkg
库。所以让我们做几个假设。
然后,拥有单独的库是完全合理的,除了将它们表达为平面目录结构要好得多,以便清楚地分离每个库和程序。
src
├─ helper
│ ├─ helper.cpp
│ └─ helper.h
├─ innerpkg
│ ├─ a.cpp
│ └─ a.h
├─ main
│ ├─ main.cpp
│ └─ main.h
└─ main2
├─ main2.cpp
└─ main2.h
显然,既然你说helper.cpp不需要调用a.cpp中定义的东西,那么helper
库不依赖于innerpkg
,因此没有循环依赖性。
就CMake而言,每个目录中都有一个CMakeLists.txt文件,包括根目录,总共五个。
最上面的一个将包含每个子目录,而其余四个将负责构建每个二进制文件。
只有main
和main2
中的CMake列表才会实际调用target_link_libraries()
。
那么为什么你首先需要图书馆?
由于只有一个可执行程序main
,因此没有重复的代码和功能。
在这种情况下,解决方案是保留当前目录结构,其中子目录不是库,而是主题。
按主题,我指的是最终程序功能的一个子集,为了便于维护而明确分开,但 NOT 暗示与其他主题的依赖关系。
为什么不关心那种情况下的依赖?仅仅因为您不需要创建库。只需将每个cpp文件添加为main
程序的源,这样就可以在链接时自动解决所有依赖关系。
就CMake而言,您只需要在顶部有一个CMakeLists.txt文件,它只会构建一个程序并列出每个子目录中的每个cpp文件,如下所示:
add_executable(main
main.cpp
helper/helper.cpp
helper/innerpkg/a.cpp
)
这也假设您确实需要生成一个库,它将成为项目安装部分的一部分,以供第三方应用程序使用。
在这种情况下,通过使helper
和innerpkg
只有一个库来解决循环依赖问题。
然后,您应该具有如下所示的目录结构:
src
├─ helper
│ ├─ helper.cpp
│ ├─ helper.h
│ └─ innerpkg
│ ├─ a.cpp
│ └─ a.h
└─ main
├─ main.cpp
└─ main.h
与上一点类似,helper
下的目录结构没有隐含依赖关系,因为只编译一个库。
此外,即使main
使用innerpkg
中的功能,它也只是透明地作为helper
的一部分公开。
就CMake而言,您将拥有一个顶级CMakeLists.txt,包括两个子目录,一个在helper
列出helper和innerpkg中的每个cpp文件以构建一个库,一个在main
列表中main中的每个文件,并与帮助程序库链接。