【发布时间】:2011-09-01 06:02:47
【问题描述】:
我有一个以前编译过的 c++ 程序,但在使用 Jamfiles 后,程序不再编译,ld 发出了一个duplicate symbol error。在连续恢复到原始 Jamfiles、运行bjam clean、手动删除对象并在 MacOs 10.6.7 上从带有 gcc 前端的 clang 切换到 gcc 4.2.1 之后,这种情况仍然存在。
程序的简化描述是有main.cpp和四个文件a.h,cpp和b.h,cpp,它们被编译成一个静态库,链接到main.o。 main.cpp 和 b.cpp 都通过两个不同的中间文件依赖于包含违规符号 off.h 的文件,但 a.h 和 a.cpp 都不依赖于 off.h。
在你问之前,我确保所有文件都包含在多个定义保护中(#ifndef、#define、#endif),虽然我确实找到了一个缺少它们的文件,但它没有引用 @ 987654337@。更重要的是,b.h 不包含任何引用off.h 的内容,只有实现b.cpp 对off.h 进行任何引用。仅这一点就让我感到困惑。
为了增加我的困惑,我能够从b.cpp 中删除对off.h 的引用,并且正如预期的那样,它重新编译成功。但是,当我重新添加引用时,它也编译成功,并在清除目标文件后继续这样做。我仍然不知道为什么它无法编译,特别是考虑到符号不应该发生冲突,我已经防止了符号重复,并且我已经摆脱了任何先前/不完整的构建。
由于我能够成功编译我的程序,我怀疑我能否重现它来测试任何建议。但是,我很好奇这是如何发生的,如果我在未来遇到这种行为,如果有超出我所做的事情,我可以做些什么来解决它?
【问题讨论】:
-
@Neil,并非如此。注意:在我找到“解决方案”之前,我多次尝试编译都能够重现此问题。而且,由于问题不再出现,我希望答案更理论化,而不是具体化。但是,我试图更好地了解在不存在冲突时可能导致两个单独编译单元中引用的符号发生冲突的原因。以及我可以采取哪些额外步骤来诊断和缓解问题。
-
我给这 90% 的机会,你实际上并没有清理所有的目标文件(可能是 libtool 或某些东西将它们隐藏在隐藏目录中?)。然而,如果你不能重现它,就没有办法追根究底。
-
@bdonlan,有趣的想法,如果 libtool 执行这种缓存会很烦人。据推测,应该通过
bjam clean或rm *.o *.a删除所有对象和库。如果不是,那么在重新编译时,它们应该被覆盖。此外,默认情况下,当您更改编译器时,bjam 会在不同的目录中编译,因此 libtool 或其他工具的任何缓存都会使这种分离毫无意义。此外,在我看来,这种缓存会使创建可靠的构建变得困难,从而使其相当令人反感。 -
@bdonlan,关于你关于不可约化的观点,作为前测试人员,这些类型的问题对测试人员和开发人员来说都是最令人沮丧的,他们经常会因此而被拒绝。但是,我认为这些问题是有道理的:尽管采取了预防措施,我怎么会陷入这种情况?一旦在这种情况下,可以做些什么来摆脱它?虽然缺乏具体的修复,但这些问题暴露了构建过程/语言中的潜在缺陷,新手/中级程序员可能不清楚。
-
@bdonlan,bjam 似乎使用
rm -f,或操作系统的等价物,我正在为我的具有清除功能的 VCS 使用 mercurial。