【问题标题】:C++ build process - lib dependenciesC++ 构建过程 - lib 依赖项
【发布时间】:2018-05-30 18:35:44
【问题描述】:

我有一个包含 5 个项目的 Visual Studio 解决方案

  • 主要:应用程序
  • A、B、C、D:静态库

主要取决于 A,B。 A 取决于 C,D。

我对构建过程的理解很脆弱。

这些库单独构建得很好,尤其是 A;我不觉得我将 C 和 D 链接到 A。

为了构建 Main 应用程序,我必须将 A、B、C 和 D 作为输入库,尽管 Main 仅直接依赖于 A、B。

现在我正在尝试使用 CMake 在 Linux 上构建整个东西,但我发现自己再次接触到这些链接。这一次我不想使用蛮力,而是更愿意了解它是如何联系在一起的。

我应该将 A、B、C 和 D 构建为 .a 静态库并让 Main 包含它们吗?

如果没有 C 和 D 的符号,A 怎么可能构建?

【问题讨论】:

  • How is it possible for A to build without the symbols from C and D? - 静态未链接,因此它们不需要定义来自其他库的符号。 Should I just build A,B,C and D as .a static libraries and have the Main include them all? - 如果这行得通,你为什么需要寻找其他方法?
  • 对我来说,应用程序应该包含二级依赖关系是没有意义的。如果依赖关系更深,这将意味着我必须包含整个链。
  • 您可能想要 SHARED 库 - 它们与其依赖项相关联,并将该链接存储在其中。
  • 我从我的队友那里看到了一些代码,其中涉及到带有一些令人困惑的宏的附加标头:__declspec(dllexport/dllimport),我直到现在才理解。

标签: c++ linux windows build cmake


【解决方案1】:

静态库只是包含目标文件(即单独编译的源文件)的档案。因此,在构建静态库时,您不会“链接”它,而是“归档”它。

链接可执行文件或共享库时必须解析符号。此时链接器会尝试解析所有符号,如果无法解析,则会出现undefined reference 错误。但是,这又与链接有关。静态库不需要在其中定义所有符号。

在您的情况下,如果 ABCD 是静态库,它们将彼此独立构建。从CD 构建A 唯一需要的是编译器需要的头文件。

在构建可执行文件时,您需要指定所有静态库,即使 Main 没有“直接”引用来自 CD 的符号。

现在,即使静态库不能隐式依赖于其他库,CMake 也提供了一种在构建系统级别表达这种依赖关系的方法。您可以执行以下操作

add_library(C STATIC ${B_SOURCES})
add_library(D STATIC ${D_SOURCES})

add_library(A STATIC ${A_SOURCES})
target_link_libraries(A PUBLIC C D)

target_link_libraries 上面的命令不会导致 ACD 链接 - 正如我所写的那样,这没有静态库工作。相反,它通知 CMake 在将可执行文件与A 链接时,它也必须将其与CD 链接:

add_executable(Main ${MAIN_SOURCES})
target_link_libraries(Main PRIVATE A)

即使target_link_libraries 仅包含A,CMake 生成的Makefile 也会链接CD - 因为它们被指定为A 的依赖项。


dllexport 和 dllimport

这两个属性仅适用于共享库 (DLL)。它们控制从 DLL 导出的符号(即,可从链接到该 DLL 的可执行文件访问)。 Here's a link 描述 Linux 上的想法和等价物。

【讨论】:

  • 很好的答案!谢谢!只是为了讨论和澄清一个特定的案例。如果 A 和 B 都依赖于 C,并且我执行 target_link_libraries(...),是否意味着我在构建 Main 时添加了两次来自 C 的代码?
  • 不,C 只会链接一次。 CMake 将以正确的顺序将库传递给链接器(因为ld 需要以正确顺序的库,当它们之间存在依赖关系时),而不会不必要地复制它们。我认为只有当库之间存在循环依赖关系时,才能多次提及一个库。顺便说一句 - 如果您使用 CMake 的 Makefile 生成器,您可以通过将 CMAKE_VERBOSE_MAKEFILE 设置为 YES 来查看生成的命令。
猜你喜欢
  • 2011-09-17
  • 1970-01-01
  • 2012-10-19
  • 2021-05-14
  • 2012-01-15
  • 2017-03-31
  • 2018-08-22
  • 2013-01-30
  • 1970-01-01
相关资源
最近更新 更多