使用Delphi包的迁移-最佳实践?

8
我正在尝试在编译应用程序之前将自己的库作为包提供,从而使我的代码模块化。多年来,我“有点”理解包的概念,当我加载组件包并单击“安装”时,我松了一口气。我知道安装组件(或组件)的过程是通过创建 BPL 并在 IDE 中注册来完成的。
但是,我开始不明白如何使文件可用,以便我可以使用包或预编译的 DCU(就像第三方供应商一样)进行编译,而无需始终将项目指向源代码。我可以使用以下设置创建包: enter image description here 我指定所有输出都将进入“c:\scratch\wow”。构建后,我发现 TEST.BPL、TEST.DCP 和许多 DUC 文件。现在,当我将另一个项目指向此文件夹以使用 DCU 时,我会遇到缺少 DFM 的错误(其中一个单元是表单)。我是否应该手动将所需的 DFM 复制到此输出文件夹中?DPK 知道这个表单,那么为什么我没有得到复制的 DFM?我想,使用 TEST.BPL,该文件包含了一切,但我希望能在两种模式下工作。当然,我可以通过将源文件夹包含在我的项目搜索路径中来解决这个问题,以找到 DFM,但是第三方库似乎已经将 DFM 放在其输出文件夹中。他们是使用安装程序在那里安装的吗?
谢谢。

1
你为什么更喜欢使用包而不是静态链接?这听起来会给你带来很多问题,却没有任何好处。 - David Heffernan
4个回答

10

像其他人所说的一样,您可以使用post-build事件将DFM文件复制到指定位置。其他人使用一次性的外部批处理文件将DFMs复制到DCU文件夹。

个人认为,对于那些不作为可重用组件开发的事物来说,制作包的好处非常少。当您不需要合理地多次使用相同的子段或包时,将现有应用程序划分为包也几乎没有好处。

我会把以下内容放入包中:

  1. Delphi可视和非可视组件。

  2. 必须在运行时插入或留下的内容。例如,假设我销售MetaWare Light和MetaWare Pro,并且我希望出于某种原因不使用编译器IFDEFs来构建不同的二进制文件,则可以选择不与系统一起发布ADVANCEDFEATURE.BPL。

创建包时需要注意的事项:

  1. 当将泛型与包结合使用时,我遇到了许多编译器错误。我还在Delphi 2009、2010、XE和XE2中遇到了IDE崩溃和锁定问题。(我认为XE3更好)

  2. 在移向BPL领域之前,您应该了解一些关于BorlandMM.dll和共享内存管理的微妙之处。

  3. 包限制了链接器决定什么要删除的能力。事实上,它几乎摧毁了它。包含所有链接到其中的内容,且无法公开访问任何可移除的内容。

  • 一旦您创建了一个二进制包并将其发送给至少一位客户,您就会拥有一个非常难以修改的合约(此BPL包含特定的签名或应用程序二进制接口),您必须小心未来永远不要更改它们或混合使用它们。即使是在您自己的客户中也要注意DLL地狱,并准备对您的包使用版本控制。正如Delphi包具有版本后缀一样,我建议您从一开始就在自己的包中使用版本后缀,并在二进制兼容性已更改时递增它们。

  • Delphi处理包之间的构建依赖关系的能力与单个整体应用程序相比要好得多。对于那些大量使用包的应用程序,我发现包含互相依赖的一堆包的项目组非常难以管理和快速构建。事实上,我经历过编译和构建都比一个750K行的超级项目慢且更加令人沮丧。

  • 我真的很怀疑您是否真的对Delphi的包区域(每当Delphi组件实际上可以无问题地构建和安装时,您是否松了一口气?)非常感兴趣,如果您真的想完全进入包的世界,我建议您先学习更多。毫无疑问,您应该进行一些实验。但我不会把全部赌注都押在此上。


    1
    非常好的解释,谢谢。我意识到这些问题(DLL地狱),这就是为什么我一直拖延不前的原因,但我正在努力赶上所有这些东西,包括寻找进一步自动化我们使用的没有安装程序的组件的安装方式 - 所有这些都需要我理解包。我怀着美好的希望,希望通过XE可以更多地利用BPL的优点而减少缺点(我的应用程序大约有750k行)。 - Brian Frost
    有趣的是,现在使用Delphi 10 Seattle,对于一个750K行的项目,你应该能够无需使用包,比在Delphi XE时代更轻松地工作。 - Warren P
    你似乎在说包的麻烦大于它们的价值(根据我的经验,我也倾向于同意),但是如果你有多个应用程序共享大量代码部分(例如许多设备对象),并且您还想强制执行边界以减少依赖性和维护架构。使用标准DLL,您将需要维护大量的平面函数调用,并且直接访问对象接口会很好?这仍然是一个坏主意吗? - SoftDeveloper
    这并不是说它们不值得。请注意,在IDE中使用设计时包(这是Delphi体验的核心元素)与选择是否在构建目标应用程序时使用BPL完全不同,这才是真正的问题所在。您没有考虑到明智的替代方案(DLL与BPL之间的区别)。问题是“使用DLL还是不使用”。由于(听好了)BPLS就是DLLS,因此所有上述与BPLS相关的问题都适用于DLLS。采用静态方式。避免制作自己的dlls。 - Warren P

    5

    是的,如果您只想在搜索路径中使用一个目录,那么应将.dfm复制到已编译单元(.dcus)的目录中。BPL当然包含.dfms,您需要一个.dcp才能将BPL与您的应用程序链接。

    第三方工具必须使用其安装程序将.dfms和.dcus放在同一目录中。


    2

    您可以使用后期构建事件(项目/选项/构建事件)来代替手动复制*.DFM文件,例如:

    copy “$(PROJECTDIR)\Unit1.DFM” “c:\Scratch\wow\Unit1.DFM”
    

    好主意。我已经在使用同样的方法,使用madExcept来修补二进制文件。 - Brian Frost
    @Brian:如果你在IDE中安装了madExcept,你就不需要使用后置构建事件来修补exe文件。一旦安装了madExcept(如果选项已打开,请参见Project|madExcept选项),它会自动完成这个任务。 - Marjan Venema
    @Serg:构建事件的性能如何?我曾经尝试过,每次构建都需要额外花费近30秒钟来将exe文件复制到另一个位置...但我放弃了,也许太早了? - Marjan Venema
    @Marjan - 这很奇怪。我从未遇到过与 postbuild 事件相关的问题,尽管我只在构建包时使用它们来复制 *.res 和 *.dfm 文件。 - kludg
    @Marjan Venema:这在防病毒软件中非常普遍——因为它们试图监视一切,所以它们可能会引起奇怪的缓慢(因为它们正在分析一个大型可执行文件被复制)...... 这是一段时间之前在 ServerFault.com 上的一个问题。 - Fabricio Araujo
    显示剩余2条评论

    0

    我找到了一种方法,可以在不将 .dfm 文件移动到 .dcu 文件目录的情况下实现这一点,因此您可以为 .dcu 文件、.dcp 文件和 .bpl 文件分别设置目录。

    您需要做的就是像我一样,在您的良好结构中创建另一个目录。该目录名为 RES,其中应放置所有资源文件(.res 文件,而不是 .dcr 文件),这些资源文件由使用您的包(组件)编译的应用程序使用。在 Delphi 库路径中,除了 DCU 目录(您应该已经有了)之外,还必须包括名为 RES 的目录。

    在您的组件(设计时)中,您可以随意对表单进行操作(设计它,放置其他组件等)。在该单元的源代码中,您将 {$R *.dfm} 替换为 {$R UnitName.dfm}。这样做后,保存所有更改并关闭 DPK。现在将 .dfm 文件移动到 RES 文件夹中(不要复制,移动!),因为 .dfm 文件是 Delphi 的资源文件({$R} 指令是证明!),然后再次打开 DPK 以了解发生了什么变化。

    首先请注意,您可能无法从其单元中打开表单(F12),尽管 Delphi 没有发出“DFM 缺失”的错误。

    现在,在您的包上进行构建,然后安装它。又意识到了吗?没有显示错误!这是因为您已经在Delphi库搜索路径(RES目录)中指定了.dfm文件的位置。

    完成!您可以使用您的组件,并且当您的组件被包含在应用程序中时,dfm将被找到。

    你们中的许多人现在可能会说,这样我将无法在组件设计时间内进行可视化表单编辑。是的,这是真的,但是如果您考虑一下,为什么我要经常将一个表单更改为组件,而实际上只应该使用和轻微编辑组件呢?得出自己的结论吧 ;)


    猜测一下:硬链接 DFM 文件是否可行? - Uli Gerhardt
    @Ulrich Gerhardt - 你说的“硬链接”是什么意思?把.dfm文件的内容放进一个真正的.res文件里吗?我相信这样可以,但我不知道怎么做 ;) - Carlos B. Feitoza Filho
    请参阅http://en.wikipedia.org/wiki/Hard_link。这是一种文件系统功能,允许您在多个目录中使用不同的名称链接到**一个**文件。 - Uli Gerhardt
    @Ulrich Gerhardt - 你好!我认为这不会起作用,因为Delphi需要真实的文件,但是由于这种技术似乎比制作普通链接更复杂,你可能想尝试一下。如果你愿意,由于大多数人都知道这个主题,可以尝试并在此处发布结果。 - Carlos B. Feitoza Filho
    哎呀,快速测试表明 Delphi 在保存 DFM 时会破坏硬链接。 :-( - Uli Gerhardt

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接