C++ 相互依赖的静态库
假设我有两个静态构建的库。libFoo.a和libBar.a a使用libBar.a和libBar.a中的函数,而libFoo.a恰好也使用libFoo.a中的函数 现在,让我们创建一个使用libFoo和libBar的程序baz.cpp。通常,您会键入:C++ 相互依赖的静态库,c++,c,linker,C++,C,Linker,假设我有两个静态构建的库。libFoo.a和libBar.a a使用libBar.a和libBar.a中的函数,而libFoo.a恰好也使用libFoo.a中的函数 现在,让我们创建一个使用libFoo和libBar的程序baz.cpp。通常,您会键入: g++ baz.cpp -lfoo -lbar 但是,由于这两个静态库相互使用……对于如何让编译时链接器接受这种情况并将它们链接在一起,我没有明显的解决方案 这是否是C++标准的明智和允许的事情?如果是的话,有没有一种非黑客的方式来处理这个问
g++ baz.cpp -lfoo -lbar
但是,由于这两个静态库相互使用……对于如何让编译时链接器接受这种情况并将它们链接在一起,我没有明显的解决方案
<>这是否是C++标准的明智和允许的事情?如果是的话,有没有一种非黑客的方式来处理这个问题
或者首选的方法是将libBar和libFoo中的所有对象文件一起编译到一个静态库中吗?有两种替代解决方案:
- 重复库名称:
-lfoo-lbar-lfoo
- 使用链接器组:
-Wl,--start-group-lfoo-lbar-Wl,--end-group
链接器组的效果是,它有效地改变了链接器算法:它首先将组中的所有对象文件和库抛出到一个错误篮中,然后尝试解决所有问题(无论链接器组中的顺序如何),然后继续下一个组。有两种替代解决方案:
- 重复库名称:
-lfoo-lbar-lfoo
- 使用链接器组:
-Wl,--start-group-lfoo-lbar-Wl,--end-group
链接器组的效果是它有效地改变了链接器算法:它首先将组中的所有对象文件和库抛出到一个bug篮子中,然后尝试解决所有问题(无论链接器组中的顺序如何),然后继续下一个组。C++标准对库没有任何规定。通常的处理方法是两次提到其中一个库
-lfoo-lbar-lfoo
,我认为至少在某些系统上,您可以对这两个库.a文件进行ranlib。当然,请注意,这对您的代码组织来说是一件非常奇怪的事情。我认为如果您有循环依赖,那么您的库设计就是有缺陷的。要么将两个库合并为一个库,要么重构第三个库。@Jonathon:我有过几次循环依赖,即使是在完全正交的设计中。考虑一个需要时间信息的日志库,时间函数也希望能够记录错误。注意,调用图中不一定存在循环依赖性,并且仍然存在链接器问题。C++标准对库没有什么要说的。通常的处理方法是两次提到其中一个库-lfoo-lbar-lfoo
,我认为至少在某些系统上,您可以对这两个库.a文件进行ranlib。当然,请注意,这对您的代码组织来说是一件非常奇怪的事情。我认为如果您有循环依赖,那么您的库设计就是有缺陷的。要么将两个库合并为一个库,要么重构第三个库。@Jonathon:我有过几次循环依赖,即使是在完全正交的设计中。考虑一个需要时间信息的日志库,时间函数也希望能够记录错误。请注意,调用图中不一定存在循环依赖关系,您仍然存在链接器问题。第三种选择:解决两个库中明显的糟糕设计,要么将公共代码提取到两个库都依赖的第三个库中,要么将这两个库合并到一个库中。循环依赖关系通常是一个更大的内聚问题的标志。一个选项是从每个库中提取所有对象文件,然后创建一个包含所有对象文件的libfoobar.a
库。唯一容易出现的问题是,如果有两个同名的对象文件,每个库一个。明智的重命名可以解决这个问题。链接器组对我来说真是太好了。谢谢Johannes。第三种选择:解决两个库中明显的糟糕设计,要么将公共代码拉到它们都依赖的第三个库中,要么将这两个库合并到一个库中。循环依赖关系通常是一个更大的内聚问题的标志。一个选项是从每个库中提取所有对象文件,然后创建一个包含所有对象文件的libfoobar.a
库。唯一容易出现的问题是,如果有两个同名的对象文件,每个库一个。明智的重命名可以解决这个问题。链接器组对我来说真是太好了。谢谢你,约翰。