2009-05-24 79 views
8

我们的团队多年来一直使用Delphi 6,然后在2006年前切换到Delphi 2006。在这两个版本中,我们遇到以下问题:通常编译器会抱怨一个被推测为递归使用的单元。这个单位是一个40k LOC单位,是一个项目的核心,拥有近100万LOC(包括第三方)。不正确的循环参考错误

错误消息是不正确的:该项目的完整版本始终工作。不幸的是,这个错误信息并不能告诉我们所在的循环引用的位置,只是该单元的名称。有时甚至会发生有效的错误消息被列出2-4次,直到该循环引用问题被“找到”。很明显,编译器在这里以一个圆圈运行。由于该项目的大小,很难手动找到问题。因此,我制作了一个工具,其中证明确实没有循环引用(该工具会创建单元的定向依赖关系图并确定该图中的相关性组件 - 除了我故意放置某些内容外,没有其他功能)。

这不仅影响F9编译,而且代码完成/洞察力在大多数时间不工作。有时它工作时,我再次按Ctrl空间...

任何想法我们如何可以隔离甚至解决问题?请注意,将40k LOC单元拆分为较小的单元将非常困难,因为它包含大约15个大类,这些大类在接口部分相互依赖(我知道这很糟糕,但应该可以工作)。

更新
我们不断地重构,但是这是一个艰难的单位重构,因为一切都依赖于一切,几乎。一直试图通过接口绕过它,但我们正在谈论一些具有100多种方法和属性的类。它会更慢。

升级到D2009可能是一个可行的选择,但现在我们坚持使用D2006(unicode和价格标签是这里的两个瓶塞)。无论如何,如果问题有帮助的话,问题至少从D6开始就存在。

关于修剪使用条款,我们经常用Icarus来做这件事。但目前为止这并没有帮助。现在我们在接口部分下降到90个自定义单位。但是,对于真实的循环引用,问题可能出现在任何单元中。还尝试将所有单位添加到dpr。

该项目与其他项目共享很多代码,并且有一些IFDEF。但是,定义不是在项目选项中设置的,而是通过常用的包含文件。因此所有模块应该看到相同的定义。而且,在完全重建之后不久,问题又重新出现,而不切换到另一个项目。

回答

0

您是否有任何其他使用相同代码库的项目?如果在不同的编译器设置或IFDEF下编译其中的一个,它可能会改变某些DCU中的某些事情,从而导致循环依赖。完整构建重建所有DCU,然后问题消失。

0

尝试Icarus(免费)来自Peganza。如果没有告诉你问题是什么,请尝试使用他们的Pascal分析仪。

2

看起来很清楚,这是由于背景编译器和实物之间的细微差别。您可以查看(QualityCentral)该主题的已知内容。另外,由于您没有明确说明这一点,因此如果可能的话,您应该删除不必要的单元并将使用语句移到实现中。也许你的工具可以帮助这个。

而只是为了确保您应该检查单位别名和路径设置。

4

我可能会因此而低估。在D2005中,我有一个10k的loc单元(datamodule),它停止了编译。必须将一些数据集/代码分离到另一个数据模块。这10万个单位是,并且是一团糟。你真的应该考虑重构一些代码给其他单位。我的模块自D2005 /分离后变得更糟,但它仍然编译在D2007中。所以我的答案是a)重构和b)升级到D2009。

2

您认为完整构建总是成功,但在增量构建失败后不久出现此错误。假设您在IDE中遇到过这种情况,是否尝试过使用命令行编译器dcc32来执行增量构建?

如果你不给它提供“-Q”开关(这可能是大多数Makefiles或脚本的命令行版本),它会输出很多信息按什么顺序编译它的文件。您可以尝试在IDE出现错误后尝试执行增量构建,也可以在IDE旁边打开命令行并使用Alt + Tab进行编译,从而完全跳过IDE中的编译。

我简单地假设你有一种方法来构建使用dcc32,这种或那种方式 - 与我无法想象的项目大小。

+0

对,我们在所有项目(和更多)的完整构建脚本中使用dcc32。我并不期望将其用作IDE编译的替代品;它不会帮助您了解代码洞察力,以及谁知道当时需要多长时间。 但也许这是一种诊断问题的方法?理想情况下,dcc32增量会遇到同样的问题,它的输出会触发一些想法... – 2009-05-25 18:53:01

+0

是的,这正是我想要建议的,也许我没有成功通过明确说明:-(抱歉,使用dcc32应该看看哪些文件被编译了几次,并且在哪个文件之后它全部停止了。除非IDE编译器和dcc32真的不一样,但是这个我不会假设。 – mghie 2009-05-25 20:21:13

2

我们经常遇到类似的问题,并且我们从未处理过(或困扰了很长时间)以找到确切的原因。在按Ctrl-F9时,Delphi选择编译单元的顺序似乎有问题,这与单元的实际依赖性顺序不兼容。

  • 您是否尝试在按Ctrl-F9之前删除“MyBigFatUnit.dcu”?
  • 您是否尝试在您的dpr/dpk文件中重新排列单位声明,以便单位显示正确的编译顺序? (即:如果单元B依赖于单元A,则单元A应该首先出现在dpr/dpk中)
0

我们也有这个问题,还有一个相当大的代码库。

我们目前正在使用D2009,但在Delphi的所有以前版本中都遇到了这个问题。

它经常发生在从源代码控制更新后立即发生,所以我怀疑在Delphi构建过程中有一些时间戳问题。

在我们的情况下,如果按Ctrl-F9失败,并报告了循环引用,第二按Ctrl-F9将一般工作

0

我已被告知,处理,这是在项目中打开另一个任意文件的一种方式,更改该文件并保存,然后再次尝试运行增量编译。令人惊讶的是,这通常起作用。

我们有一个4 MLOC项目,这不时出现,这个“解决方案”适合我。

0

我已经打过这个了,以我的经验,这个错误是准合法的。这已经有一段时间了(这个错误与版本无关),但是我对这种情况的记忆是它涉及一个循环,其中的一部分循环在实现中。

单元A在实现中使用B.单元B在界面中使用A.如果先编译B,则它会调用A,但由于B的调用在实现中会成功。如果你先编译A,它会调用B,B会转向并在接口中调用A,boom。如果两个交叉引用都在实现中,这样的循环只是安全的。

解决方案是设计一些东西,以便在界面中使用最少的东西,并确保在这些单元中没有任何类似的循环。只要你将你的类型定义与代码单元分开,这很容易做到。

根据你正在做的事情而出现的错误是这个问题的标志,因为它涉及到你如何进入循环。当你做一个完整的版本时,订单是一致的,你可以得到它100%或0%,它不是随机的。