我决定找一个把共享代码放到库中的方法.我考虑过DLL和BPL.在这种情况下,BPL似乎更加程序员友好,更不麻烦,特别是代码仅在我们的软件中使用,只在Delphi中使用.
我把所有的exe模块所有的代码都分成了BPL,一切似乎都很好,但是有一些我不明白的东西,如果你向我解释了,那将是不胜感激的.
>我将代码划分为BPL后所期望的是,使用我创建的BPL来部署exe文件就足够了.但事实证明,他们还需要一个rtl100.bpl和vcl100.bpl.为什么会这样?我只想部署exe和我的BPL.我不想为最终用户提供Borland和第三方公司提供的一大堆图书:).我希望他们在以前被编译的exes中被编译.有可能吗?
>我到目前为止做的是:
>我将所有共享的pas单位放到BPL中.每个BPL包含属于同一类别的单元,因此对于程序员而言,在给定的BPL中可以期待什么代码.
>每个BPL是一个“运行时和设计时间”库.
>每个BPL都是“明确重建”的.
后者是BPL的默认项目设置.
>如果涉及到exe项目:
>我删除了我以前提交给BPL的所有单位.
>我在BDS 2006中的Tools-> Install软件包菜单中安装了我的BPL.
>在我的exe项目设置中,我检查了选项“使用运行时包构建”,并在下面的编辑框中列出了所有的BPL包(只有我的包,因为我清除了所有其他出现的那些).
这就是我所做的一切. exe项目正确编译,但是我没有访问BPL的源代码(我不能从我的exe项目导入代码),即使所有的BPL与源代码文件一起存储.为什么?对我来说似乎很奇怪
我总是倾向于写冗长的描述 – 对不起:) :).我会感谢你的帮助.我只需要几点解释,我提到的几点:仅使用我的BPL部署exe,我做的整体的正确性,以及无法导航到BPL源代码.提前非常感谢!
感谢大家的讨论.有人说我选择的方法不是一个好主意.我们的软件由100多个模块组成(其中大部分是不同设备的驱动程序).他们大多数共享相同的代码 – 在大多数情况下,类.问题是这些类并不总是放在单独的独立的pas单元中.我的意思是,共享代码通常放在包含模块特定代码的单元中.这意味着当您修复共享类中的错误时,将其定义的pas单元复制到所有软件模块中并重新编译是不够的.不幸的是,您必须将固定的代码片段复制并粘贴到每个模块中,逐个进入正确的单元和类.这需要很多时间,这是我想要消除的,选择正确的方法 – 请帮助我.
我认为使用BPL将是一个很好的解决方案,但它有一些缺点,正如你们中提到的一样.最糟糕的问题是,如果每个EXE需要几个BPL,我们的技术支持人员将必须知道哪个EXE需要哪些BPL,然后为最终用户提供正确的文件.只要我们没有软件更新程序,这对我们的技术人员和最终用户来说都是很大的.他们肯定会迷路而生气: – /.
还可能会发生兼容性问题 – 如果一个BPL由许多EXE共享,则一个BPL的修改对于一个EXE而言可能是不错的,而对于其他一个BPL来说是不利的 – @Warren P.
那么我应该怎么做,使错误修复更快地在许多项目中做?我想到以下方法之一.如果你有更好的想法,请让我知道.
>将共享代码放入单独的独立的pas单元中,所以当在其中一个中存在错误修复时,将其复制到所有项目(覆盖旧文件)并重新编译它们就足够了.
这个解决方案似乎是可以的,只要后面修改的代码是精简的.但是,我们也拥有一般使用功能和程序的pas单元,通常不会修改 – 我们在必要时添加新功能,但在单个项目中.所以想象一下,你在100个模块之一中编写一个新功能,并将其放入其通用单元中.一两个月后,您修改了不同的模块,您认为您需要与2个月前所写的相同的功能.你必须找到这个模块(如果你不记得这个模块是很困难的),并将这个函数复制到你的代码中.显然,每个模块中的一般用途单元变得完全不同,只要它们分别存储在每个项目中即可.然后,如果有一个错误修复做…整个故事重复.
>为所有共享代码创建BPL,但将其链接到EXE,以使EXE是独立的.
对我来说似乎是最好的解决方案,但有一些缺点.如果我在BPL中进行错误修复,那么每个程序员都必须更新计算机上的BPL.如果他们忘记了怎么办?但是,我认为这是一个小问题.如果我们照顾通知对方的变化,一切都应该是好的.
> @CodeInChaos:我不知道我是否正确理解你.你的意思是在项目之间共享pas文件?怎么做?我们在SVN中存储源代码.这意味着我们必须将共享代码存储在一个单独的文件夹中,并使所有项目在那里搜索该代码,对吧?并从SVN下载一个项目和所有文件夹依赖于…
请帮我选择一个很好的解决方案.我只是不想让公司因为愚蠢的软件开发方法而花费更多的时间和金钱,而不仅仅是错误修复.
非常感谢你.
解决方法
标题询问如何将项目划分为bpls,但真正的问题似乎是:
“在项目之间共享代码的最佳方式是什么?
有几种方法可以做到这一点:
>共享单位
> Dlls
> BPLs
无论您走哪一个方向,您都可能需要重组项目.从您的描述来看,每个项目都是相对孤立开发的.代码使用复制/粘贴进行共享,快速失去同步,并导致大量重复的工作.所以我们来看看分享代码的各种技巧.
共享单位
这是最直接的方法.您可以在项目中创建一个共享位置和地址代码,以便在此位置中重用.这些单元静态链接到您的项目中,因此您不必担心与主要可执行文件一起部署额外的依赖关系.到目前为止,静态链接单元是最简单的故障排除和调试.
编译器需要能够找到您的共享单元.有四种方式告诉编译器在哪里看.
>将它们添加到项目中 – SHIFT F11 – 将单位的引用添加到项目文件(dpr,dproj)中.如果该单元位于与项目文件相同的目录树下,则IDE将通常使用相对路径,否则将使用绝对路径,如果开发人员机器未配置相同,则可能会有问题.
>项目的搜索路径 – CTRL SHIFT F11 Delphi编译器>搜索路径 – 添加一个目录,编译器将看到那里查找项目中任何单元的uses子句中提到的单元.如果可以,最好使用相对路径.您还可以使用环境变量:$(MyPath)
>全球搜索路径 – 工具>选项>环境选项> Delphi选项>图书馆 – Win32>库路径 – 此处列出的任何路径都可用于机器上的所有项目.这是机器依赖的
>命令行 – 如果从脚本或构建自动化工具构建,可以使用dcc32的-U开关或msbuild的/ property:UnitSearchPath = switch设置搜索路径.
选项1和2将是最有用的.
就SVN存储库而言,您可以选择组织项目和共享单元的几个选项.最简单的方法是将所有项目与共享单元一起放在单个树干下:
Projects trunk ProjectA ProjectB ProjectC Library (shared units)
如果由于某种原因上述结构是不可能的,你可以尝试这种替代方法:
ProjectA trunk Library (branch of main library) ProjectB trunk Library (branch of main library) ProjectC trunk Library (branch of main library) Library trunk (main library)
在此配置中,对每个项目的库文件夹所做的更改将不会立即提供给其他项目.每个项目都需要定期将更改与主库项目进行同步.这样做的一个副作用是破坏其他项目的更改将被延迟,直到其他项目同步.无论你认为这是好还是坏.一方面,在涉及的代码在开发人员的头脑中仍然是新鲜的时候,错误更容易和更便宜.另一方面,如果您不执行单元测试(我强烈建议您执行)或代码非常脆弱,或者您只是让开发人员容易做出鲁莽的更改,您可能需要控制这些更改被推入其他项目的频率.
的Dll
Dll允许您通过在运行时链接到代码来共享代码.它们暴露了可以从主可执行文件或另一个DLL中调用的函数.
虽然dll在运行时总是链接,但您可以决定是否在应用程序启动时加载,或者仅在需要时加载.启动时加载被称为静态加载,并且在Delphi中使用外部指令来实现.系统api调用的绝大多数rtl / vcl类使用静态加载.动态加载允许延迟dll的加载,直到需要.这使用WinAPI函数LoadLibrary和GetProcAddress.对FreeLibrary的相应调用将卸载一个dll.
不幸的是,标准的dll限制了可以传递什么样的数据类型.如果您需要从非Delphi项目访问dll,您将需要限制使用c风格的数据类型.如果您只使用Delphi项目的dll,您可以安全地使用Delphi字符串和动态数组,如果您在dll中使用SharedMem单元以及使用它的任何项目.
您可以安全地使用dll内的对象,但是如果要在dll和应用程序之间传递对象,则需要提取对象的数据并将其作为原始类型传递,并将其重新组合到另一端的对象中.这被称为(de)序列化或编组,并且比滚动自己的方法有更简单的方法来做到这一点.
COM(组件对象模型)在Delphi中得到很好的支持,但它有一点学习曲线.使用COM对象非常简单,但如果您不熟悉COM,则设计一个COM对象将需要时间. COM具有语言中立的优势,并且在大多数针对Windows平台的语言(包括针对.NET框架的语言)中得到支持.
Bpls
Bpls(也称为简单的“包”)是专门格式化的dll,使得使用对象更容易.像标准的dll一样,它们在运行时链接,可以静态或动态加载.它们比COM dll更容易学习和使用,并且比COM提供更多的seamles集成到项目中.软件包由两部分组成:bpl和dcp. dcp就像编译一个普通单元文件时生成的dcu文件,除了它包含一大堆单元.使用在bpl中编译的类与将dcp添加到项目的包列表一样简单,然后将单元添加到项目单位之一的uses子句中.
部署应用程序时,您还需要安装bpl.正如其他人所说,你必须将rtl包放在最低限度,最有可能的是vcl包,如果你使用任何表单.有一种方法可以在您的项目中部署Borland提供的bpls.您可以创建一个仅包含项目所需单元的“迷你”rtl包.确定要包括哪些单位是困难的.
概要
从您给出的创建共享单元文件库到静态链接的描述可能是最方便的路线.我还建议尝试一个名为Simian的程序.它将帮助您跟踪代码库中的重复代码以包含在共享库中.它不直接支持pascal,但它使用纯文本解析器对其配置进行了一些调整.
我也不能强调单元测试的价值.特别是如果你正在转向共享库.一组精心编写的单元测试经常运行,当开发人员更改课程并打破不相关的项目时,可以立即反馈.