自定义组件的依赖问题

11

我正在尝试为我创建的自定义组件制作一个包。它基于几个库,包括Graphics32、GraphicEx和CCR.Exif。

我创建了一个“Package”项目,编写了包含其注册过程的单元,将一些额外的引用(包括dbrtl.dcp、inet.dcp、soaprtl.dcp、vclimg.dcp、xmlrtl.dcp和dclGraphicEx140.dcp)添加到了“requires”部分,并添加了许多单元到“contains”部分,以避免有关它隐式发生的警告。该项目可以在我的机器上编译并安装使用,没有任何问题。然而,当我想要在另一台机器上安装它时,问题就开始了。最终,我不得不从我使用的所有第三方组件中复制所有DCU,以及GraphicEx的DCP和BPL,甚至必须安装GraphicEx。

提供大量文件是令人烦恼的,但可以克服,但安装其他包是行不通的。我可以通过将更多的单元放入“contains”部分来摆脱那个DCP和BPL,但这导致在我实际安装了GraphicEx的机器上出现错误信息。这让我感到困惑,因为使用Graphics32不会出现这样的情况...

无论如何,我如何使我的分发最小化并避免这种情况?我希望我的团队中的其他开发人员能够使用该包,而不必担心我用来构建它的内容。首先,难道所有第三方单元都不能编译成自己的DCU吗?


7
组件安装是 Delphi 的一大痛点,而 Embarcadero 近年来一直忽视这个问题。 - kludg
@afrazier 为其他开发人员(团队成员)提供控件的包。 - Thijs van Dien
6
我同意 @Serg 的观点。每当我需要部署有依赖关系的组件时,我总是感到非常烦躁,甚至想自杀。我从来不费心创建软件包,而是在运行时加载大部分组件,以避免这场噩梦... - kobik
1
那么第三方组件开发者如何做到这一点呢?他们总是只使用VCL吗?我无法想象最好的解决方案是手动将所有使用的单元复制到我的代码中,然后从uses中删除它们... - Thijs van Dien
2
@tvdien,我见过的大多数第三方VCL都只依赖于“本地”的VCL / RTL,除非它们使用众所周知的其他第三方组件作为选项,例如“TNT”(通常是编译器指令选项)或需要添加PNG支持(因此它们使用PngImage作为选项),或基于VST等等...当然,这一切都取决于Delphi版本,因为大多数众所周知的第三方组件(非商业化)现在已经集成在较新版本的Delphi中(即XE/2)。 - kobik
显示剩余2条评论
4个回答

2
您所经历的对于编写组件的人来说是一件平常事。分发通常都是这样的。包不会携带其他包,而是引用它们。这是它们的本质。
为了克服这种情况,我总是以同样的方式处理我的组件,就像它们是要销售的产品一样:我建立一个安装向导,分发和注册包需要的所有内容。
在我的情况下,InnoSetup非常好用(http://www.jrsoftware.org/isinfo.php)。

你如何检查一个软件包是否已经安装(因为你不能重复安装)?没有一个固定的位置来期望它。 - Thijs van Dien
@ThijsvanDien:所有在IDE中注册的包都列在Windows注册表下的HKEY_CURRENT_USER\Software\Embarcadero\BDS\7.0\Known Packages。BDS版本取决于Delphi版本。如果我没记错,7.0表示Delphi 2010。查看该键下的项目以确定某个包是否已经存在于IDE中。 - AlexSC

0

摘要

已经有一段时间没有使用Delphi了,但是我开发了自己的自定义可视化控件(我最后一次使用的版本是Delphi 6)。

在处理包依赖关系时有两个问题。一个是在Delphi环境中安装,使控件出现在组件面板上,以及组件编辑器和属性编辑器。

另一个问题是将编译后的包分发到客户机器上。

这也取决于您正在运行哪个版本的Delphi。

设计时

在开发自定义包时,有一个选项卡用于指示目标文件夹。

手册通常告诉开发人员将这些文本框留空。有时候可以工作,有时候不行。我会在相应的文本框中显式地编写每个文件夹路径。

有一个文本框路径用于“.dcp”文件,另一个用于“.dcu”等等。

如果您有可视化控件以及像属性编辑器或组件编辑器之类的东西,则最好将代码拆分为2个包(“运行时”和“设计时”)。

我通常将Delphi(包)项目放在Delphi安装文件夹外面。

运行时

通常,快速的方法是将“*.bpl”、“*.dcp”文件放置在Windows(32)/系统文件夹或类似的“DLL” Windows文件夹中。

建议包文件夹结构源代码

管理包可能会很困难。我不知道Embarcadero和Delphi的新版本安装过程有多大变化。以下图表是如何组织源代码的示例。希望能对您有所帮助。

[-]--+--c:
.....|
.....+--[-]--+--software
.............|
.............+--[+]-----java
.............|
.............+--[+]-----php
.............|
.............+--[-]--+--delphi (not the delphi folder in program files)
.....................|
.....................+--[+]-----apps (source code for delphi programs)
.....................|
.....................+--[+]-----other
.....................|
.....................+--[-]--+--packages (all delphi packages source code here)
.............................|
.............................+--[+]-----lib (a single package for non visual controls, libraries)
.............................|
.............................+--[+]-----tools (package pair for non visual tcomponent descendants)
.............................|
.............................+--[+]-----json (example)
.............................|
.............................+--[+]-----xml (example)
.............................|
.............................+--[-]--+--mycontrols (folder custom visual controls)
.............................|.......|
.............................|.......+--[-]--+--delphi40 (folder for delphi40 version of "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------dsgvclctrls40.dpk (design-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------runvclctrls40.dpk (run-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--demos (individual example for each "mycontrol")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--design ("*.pas" component editors  destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--sources ("*.pas" source code destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--bin ("*.dcu" destination folder)
.............................|.......|........
.............................|.......+--[+]--+--delphi50 (folder for delphi50 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi60 (folder for delphi60 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi70 (folder for delphi70 version of "mycontrols")
.............................|................
.............................+--[-]-----etc...

祝福。


3
抱歉,我不明白这如何回答您关于如何编写和/或分发组件的问题,以便用户(开发人员)无需采取特殊措施(下载/安装依赖项,以特定方式组织项目)即可使用它。 - Thijs van Dien
“设计时”是你的目标之前的一步。而“运行时”则更加注重于分发。 - umlcat

0

我认为AlexSC的答案是最好的,但如果您绝对必须拥有一个没有依赖项的自定义组件,那么可能会有另一种选择。

不久前,我遇到了Delphi依赖关系的挫败,试图为我们的开发人员创建一个内部组件。我的建议:

  1. 卸载组件使用的所有依赖项

  2. 在您的组件包中,从您的包的要求部分中删除上述dcp。

  3. 将依赖项的源文件复制到您的组件中

当您分发组件时,您将不得不将所需依赖项的代码与其一起分发

如果您想单独使用依赖项,则会遇到问题,因为Delphi不允许在已安装的包中具有重复的单元名称。

此外,您不想使用DCU的原因是DCU针对特定平台和编译器进行编译。因此,除非您确定所有开发人员都在同一平台上并且使用相同版本的Delphi,否则需要重新编译依赖项代码。

再次强调,AlexSC的答案是最好的,而InnoStudio是一个很棒的小工具。


0
Thijs,你不能只用一个包来实现这个。目标开发人员几乎需要你添加到包中的所有内容。但是还有一种实现你想要的方式:使用你自己组件中正在使用的所有组件/库构建DLL,并将所有这些外部组件/库包装到一些将从DLL导出的代码中。然后,在不直接使用外部组件的情况下构建您的组件,而是使用您构建的DLL。您不能在组件中“使用”其他外部组件/库的任何单元。您必须构建一个新单元,其中包含从DLL导出的所有数据类型和所需声明。所有这些都完美地工作,但对于大量外部组件或库而言,它很快就会变得非常复杂。

我能否使用BPL代替DLL来使用对象?并且,将BPL编译到exe中不是也可以吗? - Thijs van Dien

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