年后相对闲一点,安装了 Delphi XE2,试着把她的 rtl (Run Time Library) 重新编译一下,把 .dpk 存此备忘,注意其中使用了 NameSpace。
包含 rtl160.bpl 和 vcl160.bpl。注意其中的 system.pas 是不需要的,它会被每次自动链接到 .bpl 或 .exe 中,且这个单元是不允许修改的,其它的好像都可以修改。;)
package Company.Librarys;
{$R *.res}
{$R *.otares}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$RUNONLY}
{$IMPLICITBUILD OFF}
contains
System.Odbc,
Winapi.Windows,
System.UITypes,
System.Types,
Winapi.StructuredQueryCondition,
Winapi.ActiveX,
Winapi.Messages,
Winapi.StructuredQuery,
Winapi.ObjectArray,
System.RegularExpressions,
System.RegularExpressionsConsts,
System.RegularExpressionsAPI,
System.Character,
System.SysUtils,
System.Internal.ExcUtils,
System.SysConst,
System.RTLConsts,
Winapi.PsAPI,
Winapi.SHFolder,
Winapi.ImageHlp,
System.Win.Crtl,
System.Variants,
System.VarUtils,
System.Classes,
System.TypInfo,
System.RegularExpressionsCore,
Winapi.PropKey,
Winapi.PropSys,
Winapi.KnownFolders,
Winapi.Wincodec,
Winapi.D3DX10,
Winapi.DxgiFormat,
Winapi.D3D10_1,
Winapi.D3D10,
Winapi.DxgiType,
Winapi.DXGI,
Winapi.DXTypes,
Winapi.MultiMon,
Winapi.D2D1,
System.IOUtils,
System.Math,
System.Masks,
System.DateUtils,
System.Generics.Defaults,
System.Generics.Collections,
System.SyncObjs,
System.Diagnostics,
System.TimeSpan,
System.AnsiStrings,
System.StrUtils,
Winapi.Manipulations,
Winapi.MsInkAut15,
Winapi.MsInkAut,
Winapi.TpcShrd,
Winapi.RtsCom,
System.Rtti,
System.ObjAuto,
System.DebugUtils,
System.Zip,
System.ZLib,
System.ZLibConst,
Winapi.IpHlpApi,
Winapi.IpExport,
Winapi.IpRtrMib,
Winapi.IpTypes,
Winapi.WinSock,
Winapi.WMF9,
Winapi.DirectShow9,
System.Win.ComObj,
System.Win.ComConst,
Winapi.MMSystem,
Winapi.Direct3D9,
Winapi.DirectSound,
Winapi.DirectDraw,
Winapi.GDIPUTIL,
Winapi.GDIPOBJ,
Winapi.GDIPAPI,
Winapi.DirectMusic,
Winapi.DirectPlay8,
Winapi.DirectInput,
Winapi.DX7toDX8,
Winapi.Direct3D8,
Winapi.Direct3D,
Winapi.D3DX9,
Winapi.D3DX8,
Winapi.DXFile,
Winapi.DxDiag,
Winapi.Cor,
Winapi.CorHdr,
Winapi.CorError,
Winapi.WinSvc,
Winapi.WinSpool,
Winapi.Winsock2,
Winapi.Qos,
Winapi.Winsafer,
Winapi.WinInet,
System.WideStrUtils,
System.WideStrings,
System.Internal.VarHlpr,
Winapi.UxTheme,
Winapi.CommCtrl,
Winapi.UrlMon,
Winapi.TlHelp32,
System.Internal.StrHlpr,
Winapi.ShLwApi,
Winapi.ShlObj,
Winapi.msxml,
Winapi.RegStr,
Winapi.ShellAPI,
Winapi.RichEdit,
Winapi.PenWin,
Winapi.oleacc,
Winapi.OpenGL,
Winapi.OleDlg,
Winapi.OleDB,
System.Win.ObjComAuto,
Winapi.Nb30,
Winapi.Mtx,
Winapi.Mapi,
Winapi.LZExpand,
Winapi.Isapi2,
Winapi.Isapi,
Winapi.Imm,
Winapi.FlatSB,
Winapi.Dwmapi,
Winapi.Dlgs,
Winapi.DDEml,
Winapi.Cpl,
Winapi.CommDlg,
Winapi.COMAdmin,
Winapi.AspTlb,
Winapi.ADOInt,
Winapi.ComSvcs,
Winapi.AclAPI,
Winapi.AccCtrl,
System.Win.ScktComp,
System.HelpIntfs,
System.Contnrs,
System.MaskUtils,
System.VarCmplx,
System.VarConv,
System.ConvUtils,
System.Win.StdVCL,
System.StdConvs,
System.Win.Registry,
System.IniFiles,
System.Win.ComObjWrapper,
System.Win.VCLCom,
System.UIConsts,
Vcl.Styles,
Vcl.Consts,
Vcl.ExtCtrls,
Vcl.Dialogs,
Vcl.Themes,
Vcl.Forms,
Vcl.ImgList,
Vcl.Graphics,
Vcl.StdCtrls,
Vcl.ActnList,
Vcl.Controls,
Vcl.GraphUtil,
Vcl.Menus,
Vcl.StdActns,
Vcl.ComCtrls,
Vcl.ComStrs,
Vcl.Printers,
Vcl.ListActns,
Vcl.ToolWin,
Vcl.Clipbrd,
Vcl.ButtonGroup,
Vcl.CategoryButtons,
Vcl.Grids,
Vcl.Mask,
Vcl.Direct2D,
Vcl.ShellAnimations,
Vcl.IMouse,
Vcl.DockTabSet,
Vcl.CaptionedDockTree,
Vcl.Tabs,
Vcl.XPMan,
Vcl.Buttons,
Vcl.CmAdmCtl,
Vcl.OleCtrls,
Vcl.OleConst,
Vcl.AxCtrls,
Vcl.OleServer,
Vcl.HtmlHelpViewer,
Vcl.WinHelpViewer,
Vcl.ExtActns,
Vcl.ExtDlgs,
Vcl.AppEvnts,
Vcl.SvcMgr,
Vcl.OleCtnrs,
Vcl.ValEdit;
end.
这是阿亮第一次写文章,有不正确的地方,欢迎讨论指正。
首先要更正一个错误的结论:只要程序用到Borland的包,就必须要带上VCLxx.bpl。
非也!
想必用Dll来实现功能模块分割的伙计们都有痛苦经历:无法导出类;无法共享主进程的全局变量;调用Dll时可能要传递一大堆参数;令人心烦的PChar;等等等等...
Borland通过包Borland Package Library来解决了这些痛苦,在这里我们只讨论运行时包。
阿亮在2003年就因为工作原因研究了一下Delphi 5的包,并成功的将一个大的系统按功能模块分拆到单个运行时包文件中,当时就想把VCL50.bpl重新编译一下,没有成功,很不甘心!头段时间安装了Delphi 7,想重新试一下,结果居然成功了,也就是说,你可以写一个个头很小的exe文件(这对于有些程序员来说非常有吸引力,他们希望自己的的程序越小越好,甚至到了痴迷的程度,阿亮也算其中一员),可以多小呢?譬如20KB的exe,这个主程序只是一个框架,它可能仅包含一个主窗休、初始化一些应用需要的全局结构或变量、实现动态装入和卸载包的代码,后面至少带一个被重新编译的VCL包,当然,这个VCL包可能包含所有的Delphi提供的标准单元,也可以仅包含你的应用需要的单元。
你可能发布的应用程序结构可能是以下结构:
App.exe (* 主程序 *)
Borland.bpl (* 被重新编译过的Borland VCL单元运行时包 *)
Common.bpl (* 应用程序公用包, 所有的全局结构和单元定义和实现在此包中,主程序和模块包共同uses此包的的共用单元,以实现全局共享 *)
Module1.bpl (* 模块一 *)
Module2.bpl (* 模块二 *)
...
其中Borland.bpl和Common.bpl是静态装入的,也就是说App.exe被Windows装入时这两个文件必须在App.exe能够找到的路径中,典型的是在App.exe相同的文件夹或Windows System 文件夹中。
而Module1.bpl、Moudle2.bpl...是需要动态装入的,这一点对于一个应用系统的扩展性非常非常重要!对于应用系统的的可定制性、控制应用的功能结构来说都是具有决定性的意义,理论上说只要你把主框架搭好了以后,模块是可以无限制添加的,你可以用以此框架为基础搭建一个进销存系统,同时它还可以是一个图形系统,或者是一个复杂的ERP系统,这一切都决定于你发布的模块包。
说了这么多,现在我们开始重新编译rtl70.bpl,这个包是所有VCL包的祖先(至少Delphi 7是这样),它包括一些重要的基础单元,如Windows、SysUtils、Classes等,且这个包是唯一一个不依赖其它运行时包的运行时包。
打开Delphi 7
1、 关掉Delphi 创建的默认工程(如果有的话);
2、 File->New->Other,选择Package;
3、 New 一个Form,编译一次;
4、 再切换窗口回到Package – Pacakge1.dpk;
5、 双击Requires节点下的rtl.dcp,将得到rtl.dpk;
6、 按F12切换到rtl.dpk源代码,将其另存如d:/delphi.dpk;
7、 Close All;
8、 Open d:/delphi.dpk,将Options中的Output Diretory及DCP Output Directory文件夹都改在.;
9、 编译它,出错时将VarHlpr、StrHlpr删除掉,阿亮目前还不知道此两单无是干嘛用的,删掉再说;
10、 编译成功,将在D:/生成Delphi.bpl和Delphi.dcp两个文件,其它的如VCL、VCLX、VCLDB等等运行时包的单元名也可以此法得到,添加到Delphi.dpk后面重新编译即可。
这样,发布应用时就不用带着VCL70.bpl、RTL70.bpl、VCLX.bpl等文件了,就一个Delphi.bpl就成了。
当然,凡事有利有弊:
1、 如果共用包(Common.bpl)被重新编译,则主程序和所有的模块包可能都需要重新编译,所以前期共用包和主程序框架的结构要尽可能考虑完整一些;
2、 如果你用到第三方控件,请选择那些有源码的控件,因为它们的运行时包也必须要重新编译,去掉RTL、VCL等需要的包,换成Delphi.bcp,这应该也容易,阿亮就将Dxexpress的所有文件重新编译得到Express.bpl。我们很幸运!不是吗?在我们这个时代这些东东很容易找到,并且它们都写得很棒,为什么不用呢!
3、 你可能需要专门写个工具来维护包给你带来的模块版本问题;
4、 如果你有多应用个以动态包的形式发布,解决方法:其一,将Delphi.bpl安装到Windows System文件夹,让你的应用共享这个包;其二,为每个应用发布一个Delphi到应用的安装目录!?而这样将有背于M$的思想,这需要你选择。
liyl[AT]founder[DOT]com
2005-04-12 12:34

