本文通過構建一個包含 EXE、兩個包的 Project Group,通過修改 contains/requires、運行時包列表、觀察模塊加載情況,實證包的編譯鏈接規則與運行時自動加載邏輯。
// EXE 主程序
program ProjectEXE;
uses Forms, Windows, UnitFormMain in 'UnitFormMain.pas' {FormMain};
{$R *.res}
begin Application.Initialize; Application.CreateForm(TFormMain, FormMain); Application.Run; end.
// 包 Package1: 包含基類 FormAnother 和派生類 Form1
package Package1;
requires vcl, rtl;
contains UnitFormAnother in 'UnitFormAnother.pas' {FormAnother}, UnitForm1 in 'UnitForm1.pas' {Form1};
end.
// 包 Package2: 包含派生類 Form2,依賴 Package1
package Package2;
requires rtl, vcl; // 或 requires Package1
contains UnitForm2 in 'UnitForm2.pas' {Form2};
end.
requires)出發,遞歸獲取所有依賴包中包含的單元集合。uses/contains 出發,遞歸獲取項目直接引用的單元集合。驗證:Package1 僅 contains Form1(隱式引用 FormAnother),編譯警告「隱式引入 UnitFormAnother」。最終 Package1.bpl 確包含三個單元。EXE 勾選 Package1 後,EXE 僅含 FormMain,Form1/FormAnother 在 Package1.bpl 中。
requires Package1 時,Package2.bpl 僅含 Form2(FormAnother 來自 Package1)。requires vcl, rtl 不依賴 Package1 時,Package2.bpl 含 Form2 + FormAnother(雙份副本)。實驗:EXE uses Form1,Package2 contains Form2 requires Package1,EXE 僅勾選 Package2。運行時模塊窗口顯示:rtl、vcl、Package1 被加載,Package2 未加載!
規則:Delphi 自動加載集合 A 中與集合 B 有交集的包。Package2 雖在列表中,但其單元 Form2 未被 EXE 直接引用(EXE 引用 Form1),故 Package2 不自動加載。Package1 包含 Form1(屬於 B),故自動加載。
要實現完全手動 LoadPackage,包必須:
requires 鏈中(直接/間接)。uses/contains 鏈中。Delphi 按 .bpg 列表順序編譯。若被依賴項在下方,會報「找不到文件」。解決:用文本編輯器調整 .bpg 中項目順序,將基礎包置前。
包機制的核心是集合運算與依賴傳遞。編譯期通過「B - A」實現單元去重與動態鏈接;運行期通過「A ∩ B」決定自動加載。掌握這兩條規則,即可精準控制包的劃分、依賴與加載行為,避免「隱式引入」警告與「重複單元」錯誤。