简体   繁体   English

我可以重新编译Delphi IDE使用的.PAS文件吗?

[英]Can I recompile the .PAS files used by the Delphi IDE?

I am familiar with Jeff Atwood's article about how errors are always the programmer's fault , but I believe I have really and truly found a bug in a Delphi .pas file. 我熟悉Jeff Atwood关于错误总是程序员错误的文章 ,但我相信我确实在Delphi .pas文件中发现了一个错误。

Specifically, I'm using Delphi 2007, and the error is on line 955 of the DBCommon.pas file, which on my machine is located here: 具体来说,我使用的是Delphi 2007,错误发生在DBCommon.pas文件的第955行,该文件位于我的机器上:

C:\\program files\\codegear\\rad studio\\5.0\\source\\Win32\\db\\DBCommon.pas C:\\ program files \\ codegear \\ rad studio \\ 5.0 \\ source \\ Win32 \\ db \\ DBCommon.pas

And the code is this: 代码是这样的:

...
  FieldIndex := StrToInt(Token);
  if DataSet.FieldCount >= FieldIndex then
    LastField := DataSet.Fields[FieldIndex-1].FieldName else
...

If "Token" has a value of zero, then we try to access index -1 of DataSet.Fields, resulting in a list index out of bounds error. 如果“Token”的值为零,那么我们尝试访问DataSet.Fields的索引-1,从而导致列表索引超出边界错误。

This error is not raised to the user, because it is handled before it gets that high up, but it is enormously irritating to have the debugger break in every time this happens. 这个错误不会引发给用户,因为它在它达到高位之前就被处理了,但是每次发生这种情况时调试器就会中断是非常恼人的。

I could "Ignore this exception type" but Index out of bounds errors are common enough that I don't want to universally ignore them. 我可以“忽略这个异常类型”,但索引越界错误很常见,我不想普遍忽略它们。

The situation that causes FieldIndex to be zero is when you have a SELECT statement whose ORDER BY contains a function, as in: 导致FieldIndex为零的情况是当您有一个SELECT语句,其ORDER BY包含一个函数时,如:

ORDER BY
  CASE WHEN FIELD1 = FIELD3 THEN 1 ELSE 2 END
 ,CASE WHEN FIELD2 = FIELD4 THEN 1 ELSE 2 END

I can fix the bug in DBCommon.pas, but Delphi will not recompile itself, and my change does not take effect. 我可以修复DBCommon.pas中的错误,但Delphi不会重新编译,我的更改不会生效。 If I rename the .DCU file, then it just complains that "DBCommon.dcu" cannot be found. 如果我重命名.DCU文件,那么它只是抱怨无法找到“DBCommon.dcu”。

So (finally) my question is: Can I recompile DBCommon.pas with my fix, and if so, how? 所以(最后)我的问题是:我可以用我的修复程序重新编译DBCommon.pas,如果是的话,怎么样?

You can probably put dbcommon.pas in youre project directory. 您可以将dbcommon.pas放在项目目录中。 It will then be compiled along with the rest of the project. 然后将与项目的其余部分一起编译。

See previous answers for how to create the situation where you can recompile modified VCL source. 有关如何创建可以重新编译已修改的VCL源的情况,请参阅前面的答案。 I would however add that you seriously consider managing your changes in your change control system, using the "Vendor Branch" SCM pattern. 然而,我想补充一点,你认真考虑使用“供应商分支”SCM模式管理变更控制系统中的变更。

In simple terms (using SVN as a reference): 简单来说(使用SVN作为参考):

  • Create a "vendor source" copy of the original vendor supplied files. 创建原始供应商提供的文件的“供应商源”副本。 This is your "pristine" reference copy. 这是您的“原始”参考副本。

  • Create a branch representing that pristine copy (eg "2009" for the Delphi 2009 version of the VCL) 创建表示该原始副本的分支(例如,对于VCL的Delphi 2009版本,为“2009”)

  • create a further branch into a separate "vendor library" folder. 在另一个“供应商库”文件夹中创建另一个分支。 THIS is the copy of the library that you should reference in your projects 这是您应该在项目中引用的库的副本

  • any modifications to the vendor source are made in the "vendor library" branch. 对供应商源的任何修改都在“供应商库”分支中进行。

  • when the vendor provides a new version of the library you check the new version in to the "vendor source" project and create a new branch for the new version. 当供应商提供库的新版本时,您将新版本检入“供应商源”项目并为新版本创建新分支。

you can then easily diff the vendor revisions. 然后,您可以轻松区分供应商修订。 But more importantly (with SubVersion, and possibly othe SCM systems) you should also be able to simply merge (ie automatically) the new vendor source with your "vendor library" branch to easily incorporate vendor changes with your own modifications. 但更重要的是(使用SubVersion,可能还有其他SCM系统),您还应该能够简单地(即自动)将新供应商源与您的“供应商库”分支合并(以便轻松地将供应商更改与您自己的修改相结合)。

This is all described far better than I just did in the excellent O'Reilly book: "Version Control with SubVersion" 这一切都比我在优秀的O'Reilly书中所描述的要好得多:“SubVersion版本控制”

NOTE however that the "loaddirs" utility mentioned in that book is no longer supported due to copyright issues, so updating "vendor drops" is currently a manual exercise, but this occurs only infrequently and is not a major burden. 但请注意,由于版权问题,不再支持该书中提到的“loaddirs”实用程序,因此更新“供应商丢弃”目前是一种手动练习,但这种情况很少发生,并且不是主要负担。

We are using this pattern ourselves, although in the case of the VCL we do not maintain a complete copy of the entire VCL source tree in our "vendor source" or "vendor library", but instead only track changed and dependent units. 我们自己使用这种模式,但在VCL的情况下,我们不在我们的“供应商源”或“供应商库”中维护整个VCL源代码树的完整副本,而是仅跟踪已更改的和相关的单元。 For other libraries managed under a vendor branch we typically do maintain complete copies but decided this wasn't necessary for the VCL. 对于在供应商分支下管理的其他库,我们通常会保留完整副本,但认为这对于VCL来说不是必需的。

We've only just implemented this pattern however, so we may yet decide that we need to take a more comprehensive approach with the VCL too. 我们只是刚刚实现了这种模式,所以我们可能还决定我们需要对VCL采取更全面的方法。

ymmv 因人而异

You can, but often you don't have to. 你可以,但通常你不必。 Recompiling a VCL unit sometime means recompiling all the rest of the VCL units either because you've changed the interface of a unit or because the compiler gets confused and thinks you've changed the interface. 有时重新编译VCL单元意味着重新编译所有其余的VCL单元,因为你已经改变了单元的接口,或者因为编译器感到困惑并且认为你已经改变了接口。 Recompiling a VCL unit also rules out the possibility of using most run-time packages because you can't recompile Delphi's run-time packages. 重新编译VCL单元还排除了使用大多数运行时软件包的可能性,因为您无法重新编译Delphi的运行时软件包。

Instead of recompiling, you can use run-time patching. 您可以使用运行时修补,而不是重新编译。 I've used the method in the TNT Unicode controls , but Madshi also provides a way to replace a function with your own implementation. 我已经在TNT Unicode控件中使用了该方法,但Madshi还提供了一种用自己的实现替换函数的方法。 If you copy the implementation of DBCommon.GetIndexForOrderBy into your own unit and make your fixes, you can use this command to patch the VCL version with your own: 如果将DBCommon.GetIndexForOrderBy的实现复制到您自己的单元并进行修复,则可以使用此命令使用您自己的修补VCL版本:

var
  Old_GetIndexForOrderBy: Pointer;

HookCode(@DBCommon.GetIndexForOrderBy,
         @Fixed_GetIndexForOrderBy,
         Old_GetIndexForOrderBy,
         0);

With the Tnt Unicode library, find the OverwriteProcedure routine in the TntSystem unit. 使用Tnt Unicode库,在TntSystem单元中找到OverwriteProcedure例程。 It's not public, so you'll need to either declare it in the unit interface or copy it into your own unit. 它不是公开的,因此您需要在单元界面中声明它或将其复制到您自己的单元中。 Then you can call it much like the Madshi code above: 然后你可以像上面的Madshi代码那样调用它:

var
  Old_GetIndexForOrderBy_Data: TOverwrittenData;

OverwriteProcedure(@DBCommon.GetIndexForOrderBy,
                   @Fixed_GetIndexForOrderBy,
                   @Old_GetIndexForOrderBy_Data);

We have a folder under our project source tree called VCL, into which we place copies of the VCL source that we wish to modify slightly. 我们在项目源代码树下有一个名为VCL的文件夹,我们在其中放置了我们希望稍微修改的VCL源代码的副本。 Your example is a good candidate for doing the same thing. 你的例子是做同样事情的好人选。 You will need to modify the search path for your project so that "your" VCL folder is earlier on your path than the "Source" folders under your Delphi installation. 您需要修改项目的搜索路径,以便“你的”VCL文件夹在路径上比Delphi安装下的“Source”文件夹更早。 You may also find that if you copy one VCL source unit out and modify it, you will have to also copy other VCL source units out into "your" folder which may be dependencies. 您可能还会发现,如果您复制一个VCL源单元并对其进行修改,则还必须将其他VCL源单元复制到“您的”文件夹中,该文件夹可能是依赖项。

Our reason for doing this is that we want our builds to have zero compiler hints and warnings. 我们这样做的原因是我们希望我们的构建没有编译器提示和警告。 There are some parts of the VCL source that are not hint/warning free. VCL源的某些部分没有提示/警告。

"I am familiar with Jeff Atwood's article about how errors are always the programmer's fault, but I believe I have really and truly found a bug in a Delphi .pas file" “我熟悉Jeff Atwood关于错误总是程序员错误的文章,但我相信我确实在Delphi .pas文件中发现了一个错误”

Are you joking me? 你在开玩笑吗? With Delphi you always blame Borland first :) Something is weird, go Google it and see if it is a Delphi bug. 使用Delphi,你总是首先责怪Borland :)有点奇怪,去Google吧,看看它是否是Delphi的bug。 Only if cannot find any similar reports you site down and check your code line by line. 只有在找不到任何类似报告的情况下,您才能下线并逐行检查您的代码。

After I reinstall Delphi I have to patch the original PAS files in 6 (six) places. 重新安装Delphi后,我必须在6(六)个地方修补原始的PAS文件。 There are tons of bugs that appear on a fresh Delphi installation and can be easily reproduced. 新的Delphi安装中出现了大量的错误,可以轻松复制。 Delphi (the one that we all love) is full of bugs. Delphi(我们都喜欢的那个)充满了bug。 There is an entire history created around this. 围绕着这个创造了整个历史。 There are so many people releasing external patches (such as http://andy.jgknet.de/blog/?page_id=288 ) and Borland/Imprise/GoGear/Embarcadero keep ignoring them. 有很多人发布外部补丁(例如http://andy.jgknet.de/blog/?page_id=288 )和Borland / Imprise / GoGear / Embarcadero一直忽略它们。 It is a true wonder they included FastMM in their release. 这是一个真正的奇迹,他们在发布时包含了FastMM。

Anyway, I have recompiled those PAS files and now I replace the original DCUs with the patched ones. 无论如何,我已经重新编译了那些PAS文件,现在我用修补后的DCU替换原来的DCU。

Simply - Yes. 简单 - 是的。 Using one of the above answers [By Tom or Connor]. 使用上述答案之一[汤姆或康纳]。 Copy DBCommon.pas to your project folder rather than edit the original. 将DBCommon.pas复制到项目文件夹而不是编辑原始文件夹。 This leaves other projects and compilations unaffected because it won't be on the path. 这使得其他项目和编辑不受影响,因为它不会在路径上。

您可以设置: DataSetProvider.Option.poRetainServerOrder = True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM