CMake和子目录取决于父目录

时间:2014-01-16 04:53:01

标签: cmake

如何在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。

1 个答案:

答案 0 :(得分:5)

我觉得您假设基于CMake的项目中的每个目录都必须包含自己的CMakeLists.txt文件并构建自己的库/可执行文件。

这个问题实际上与CMake并不完全相关。几乎任何构建系统都会遇到同样的问题。这里的问题是你的依赖树不清楚。应该不惜一切代价避免循环依赖。

与Java及其基于包的系统相反,C ++应用程序没有强制执行目录布局,即使是CMake也没有。 依赖关系只能用库和可执行程序来表达,前者主要用于不在使用相同功能的单独程序之间复制代码。

在您的具体情况下,不清楚是谁在使用helperinnerpkg库。所以让我们做几个假设。

1。你有几个程序使用这两个库

然后,拥有单独的库是完全合理的,除了将它们表达为平面目录结构要好得多,以便清楚地分离每个库和程序。

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文件,包括根目录,总共五个。
最上面的一个将包含每个子目录,而其余四个将负责构建每个二进制文件。 只有mainmain2中的CMake列表才会实际调用target_link_libraries()

2。源代码只编译一个程序,只使用两个库

那么为什么你首先需要图书馆?

由于只有一个可执行程序main,因此没有重复的代码和功能。

在这种情况下,解决方案是保留当前目录结构,其中子目录不是,而是主题
按主题,我指的是最终程序功能的一个子集,为了便于维护而明确分开,但 NOT 暗示与其他主题的依赖关系。

为什么不关心那种情况下的依赖?仅仅因为您不需要创建库。只需将每个cpp文件添加为main程序的源,这样就可以在链接时自动解决所有依赖关系。

就CMake而言,您只需要在顶部有一个CMakeLists.txt文件,它只会构建一个程序并列出每个子目录中的每个cpp文件,如下所示:

add_executable(main
    main.cpp
    helper/helper.cpp
    helper/innerpkg/a.cpp
)

3。主程序使用一个库,每个库使用另一个库

这也假设您确实需要生成一个库,它将成为项目安装部分的一部分,以供第三方应用程序使用。

在这种情况下,通过使helperinnerpkg只有一个库来解决循环依赖问题。
然后,您应该具有如下所示的目录结构:

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中的每个文件,并与帮助程序库链接。