Package.pas 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. { Rev 1.8 25/11/2004 8:10:20 AM czhower
  18. { Removed D4, D8, D10, D11
  19. }
  20. {
  21. { Rev 1.7 2004.11.14 10:35:34 AM czhower
  22. { Update
  23. }
  24. {
  25. { Rev 1.6 12/10/2004 17:51:36 HHariri
  26. { Fixes for VS
  27. }
  28. {
  29. { Rev 1.5 2004.08.30 11:27:56 czhower
  30. { Updates
  31. }
  32. {
  33. { Rev 1.4 2004.06.13 8:06:10 PM czhower
  34. { Update for D8
  35. }
  36. {
  37. { Rev 1.3 09/06/2004 12:06:40 CCostelloe
  38. { Added Kylix 3
  39. }
  40. {
  41. { Rev 1.2 02/06/2004 17:00:44 HHariri
  42. { design-time added
  43. }
  44. {
  45. { Rev 1.1 2004.05.19 10:01:48 AM czhower
  46. { Updates
  47. }
  48. {
  49. { Rev 1.0 2004.01.22 8:18:32 PM czhower
  50. { Initial checkin
  51. }
  52. unit Package;
  53. interface
  54. uses
  55. Classes, IniFiles;
  56. type
  57. TCompiler =(
  58. ctUnknown,
  59. ctDelphi5,
  60. ctDelphi6,
  61. ctDelphi7,
  62. ctDelphi8, ctDelphi8Net,
  63. ctDelphi2005, ctDelphi2005Net,
  64. ctDelphi2006, ctDelphi2006Net,
  65. ctDelphi2007, ctDelphi2007Net,
  66. ctDelphi2009, ctDelphi2009Net,
  67. ctDelphi13, ctDelphi13Net, // was not released, skipped to v14 (D2010)
  68. ctDelphi2010,
  69. ctDelphiXE,
  70. ctDelphiXE2,
  71. ctDotNet, // Visual Studio
  72. ctKylix3);
  73. TCompilers = Set of TCompiler;
  74. const
  75. DelphiNet = [ctDelphi8Net, ctDelphi2005Net, ctDelphi2006Net, ctDelphi2007Net, ctDelphi2009Net, ctDelphi13Net];
  76. DelphiNet1_1 = [ctDelphi8Net, ctDelphi2005Net, ctDelphi2006Net];
  77. DelphiNet2OrLater = [ctDelphi2007Net, ctDelphi2009Net, ctDelphi13Net];
  78. DelphiNative = [ctDelphi5..ctDelphiXE2] - DelphiNet;
  79. DelphiNativeAlign8 = DelphiNative - [ctDelphi5..ctDelphi13] + [ctDelphi2005];
  80. type
  81. TPackage = class
  82. protected
  83. FCode: TStringList;
  84. FCompiler: TCompiler;
  85. FContainsClause: string;
  86. FDesc: string;
  87. FDirs: TStringList;
  88. FExt: string;
  89. FName: string;
  90. FUnits: TStringList;
  91. FVersion: string;
  92. //
  93. procedure Code(const ACode: string);
  94. procedure GenHeader; virtual;
  95. procedure GenOptions(ADesignTime: Boolean = False); virtual;
  96. procedure GenContains(const aPrefix: string = ''; const aWritePath: Boolean = True);
  97. procedure WriteFile(const APath: string);
  98. procedure WritePreContains; virtual;
  99. public
  100. procedure Clear;
  101. procedure AddUnit(const AName: string; const ADir: string = '');
  102. constructor Create; virtual;
  103. destructor Destroy; override;
  104. procedure Generate(ACompiler: TCompiler); overload; virtual;
  105. procedure Generate(ACompilers: TCompilers); overload; virtual;
  106. procedure GenerateDT(ACompiler: TCompiler); overload; virtual;
  107. procedure GenerateDT(ACompilers: TCompilers); overload; virtual;
  108. procedure Load(const ACriteria: string; const AUsePath: Boolean = False);
  109. //
  110. property Compiler: TCompiler read FCompiler;
  111. end;
  112. const
  113. GCompilerID: array[TCompiler] of string = (
  114. '',
  115. '50',
  116. '60',
  117. '70',
  118. '80', '80Net',
  119. '90', '90Net', // 2005
  120. '100', '100Net', // 2006
  121. '110', '110Net', // 2007
  122. '120', '120Net', // 2009
  123. '130', '130Net', // was not released, skipped to v14 (D2010)
  124. '140', // 2010
  125. '150', // XE
  126. '160', // XE2
  127. '',
  128. 'K3');
  129. //Fetch Defaults
  130. IdFetchDelimDefault = ' '; {Do not Localize}
  131. IdFetchDeleteDefault = True;
  132. IdFetchCaseSensitiveDefault = True;
  133. function iif(ATest: Boolean; const ATrue: Integer; const AFalse: Integer): Integer; overload;
  134. function iif(ATest: Boolean; const ATrue: string; const AFalse: string): string; overload;
  135. function iif(ATest: Boolean; const ATrue: Boolean; const AFalse: Boolean): Boolean; overload;
  136. implementation
  137. uses
  138. SysUtils, DModule;
  139. function iif(ATest: Boolean; const ATrue: Integer; const AFalse: Integer): Integer;
  140. {$IFDEF USEINLINE}inline;{$ENDIF}
  141. begin
  142. if ATest then begin
  143. Result := ATrue;
  144. end else begin
  145. Result := AFalse;
  146. end;
  147. end;
  148. function iif(ATest: Boolean; const ATrue: string; const AFalse: string): string;
  149. {$IFDEF USEINLINE}inline;{$ENDIF}
  150. begin
  151. if ATest then begin
  152. Result := ATrue;
  153. end else begin
  154. Result := AFalse;
  155. end;
  156. end;
  157. function iif(ATest: Boolean; const ATrue: Boolean; const AFalse: Boolean): Boolean;
  158. {$IFDEF USEINLINE}inline;{$ENDIF}
  159. begin
  160. if ATest then begin
  161. Result := ATrue;
  162. end else begin
  163. Result := AFalse;
  164. end;
  165. end;
  166. { TPackage }
  167. procedure TPackage.AddUnit(const AName: string; const ADir: string);
  168. begin
  169. FUnits.Add(AName);
  170. FDirs.Add(ADir);
  171. end;
  172. procedure TPackage.Clear;
  173. begin
  174. FCode := TStringList.Create;
  175. FDirs := TStringList.Create;
  176. FUnits := TStringList.Create;
  177. end;
  178. procedure TPackage.Code(const ACode: string);
  179. begin
  180. FCode.Add(ACode);
  181. end;
  182. constructor TPackage.Create;
  183. begin
  184. FContainsClause := 'contains';
  185. FExt := '.dpk';
  186. FVersion := '10';
  187. FCode := TStringList.Create;
  188. FDirs := TStringList.Create;
  189. FUnits := TStringList.Create;
  190. end;
  191. destructor TPackage.Destroy;
  192. begin
  193. FreeAndNil(FUnits);
  194. FreeAndNil(FDirs);
  195. FreeAndNil(FCode);
  196. inherited;
  197. end;
  198. procedure TPackage.GenContains;
  199. var
  200. i: Integer;
  201. xPath: string;
  202. begin
  203. Code('');
  204. Code(FContainsClause);
  205. WritePreContains;
  206. for i := 0 to FUnits.Count - 1 do begin
  207. if APrefix <> '' then begin
  208. FUnits[i] := StringReplace(FUnits[i], 'Id', APrefix, []);
  209. end;
  210. xPath := '';
  211. if aWritePath and (FDirs[i] <> '') then begin
  212. xPath := FDirs[i] + '\';
  213. end;
  214. Code(' ' + FUnits[i] + ' in ''' + xPath + FUnits[i] + '.pas'''
  215. + iif(i < FUnits.Count - 1, ',', ';'));
  216. end;
  217. end;
  218. procedure TPackage.Generate(ACompiler: TCompiler);
  219. begin
  220. FCompiler := ACompiler;
  221. FCode.Clear;
  222. end;
  223. procedure TPackage.Generate(ACompilers: TCompilers);
  224. var
  225. LCompiler: TCompiler;
  226. begin
  227. for LCompiler := Low(TCompiler) to High(TCompiler) do begin
  228. if LCompiler in ACompilers then begin
  229. Generate(LCompiler);
  230. end;
  231. end;
  232. end;
  233. procedure TPackage.GenerateDT(ACompiler: TCompiler);
  234. begin
  235. FCompiler := ACompiler;
  236. FCode.Clear;
  237. end;
  238. procedure TPackage.GenerateDT(ACompilers: TCompilers);
  239. var
  240. LCompiler: TCompiler;
  241. begin
  242. for LCompiler := Low(TCompiler) to High(TCompiler) do begin
  243. if LCompiler in ACompilers then begin
  244. GenerateDT(LCompiler);
  245. end;
  246. end;
  247. end;
  248. procedure TPackage.GenHeader;
  249. begin
  250. Code('package ' + FName + ';');
  251. end;
  252. procedure TPackage.GenOptions(ADesignTime: Boolean = False);
  253. begin
  254. Code('');
  255. if FCompiler in DelphiNet then begin
  256. Code('{$ALIGN 0}');
  257. end else begin
  258. Code('{$R *.res}');
  259. if FCompiler in DelphiNativeAlign8 then begin
  260. Code('{$ALIGN 8}');
  261. end;
  262. end;
  263. // Code('{$ASSERTIONS ON}');
  264. Code('{$BOOLEVAL OFF}');
  265. // Code('{$DEBUGINFO ON}');
  266. Code('{$EXTENDEDSYNTAX ON}');
  267. Code('{$IMPORTEDDATA ON}');
  268. // Code('{$IOCHECKS ON}');
  269. Code('{$LOCALSYMBOLS ON}');
  270. Code('{$LONGSTRINGS ON}');
  271. Code('{$OPENSTRINGS ON}');
  272. Code('{$OPTIMIZATION ON}');
  273. // Code('{$OVERFLOWCHECKS ON}');
  274. // Code('{$RANGECHECKS ON}');
  275. Code('{$REFERENCEINFO ON}');
  276. Code('{$SAFEDIVIDE OFF}');
  277. Code('{$STACKFRAMES OFF}');
  278. Code('{$TYPEDADDRESS OFF}');
  279. Code('{$VARSTRINGCHECKS ON}');
  280. Code('{$WRITEABLECONST OFF}');
  281. Code('{$MINENUMSIZE 1}');
  282. Code('{$IMAGEBASE $400000}');
  283. Code('{$DESCRIPTION ''Indy ' + FVersion + TrimRight(' ' + FDesc) + '''}');
  284. Code(iif(ADesignTime, '{$DESIGNONLY}', '{$RUNONLY}'));
  285. Code('{$IMPLICITBUILD ON}');
  286. end;
  287. procedure TPackage.Load(const ACriteria: string; const AUsePath: Boolean = False);
  288. var
  289. LFiles: TStringList;
  290. I: Integer;
  291. begin
  292. Clear;
  293. LFiles := TStringList.Create;
  294. try
  295. DM.GetFileList(ACriteria, LFiles);
  296. for I := 0 to LFiles.Count - 1 do
  297. begin
  298. if AUsePath then begin
  299. AddUnit(LFiles[I], DM.Ini.ReadString(LFiles[I], 'Pkg', ''));
  300. end else begin
  301. AddUnit(LFiles[I]);
  302. end;
  303. end;
  304. finally
  305. LFiles.Free;
  306. end;
  307. end;
  308. procedure TPackage.WriteFile(const APath: string);
  309. var
  310. LCodeOld: string;
  311. LPathname: string;
  312. begin
  313. Code('');
  314. Code('end.');
  315. LPathname := APath + FName + FExt;
  316. LCodeOld := '';
  317. if FileExists(LPathname) then begin
  318. with TStringList.Create do try
  319. LoadFromFile(LPathname);
  320. LCodeOld := Text;
  321. finally Free; end;
  322. end;
  323. // Only write out the code if its different. This prevents unnecessary checkins as well
  324. // as not requiring user to lock all packages
  325. if (LCodeOld = '') or (LCodeOld <> FCode.Text) then begin
  326. FCode.SaveToFile(LPathname);
  327. WriteLn('Generated ' + FName + FExt);
  328. end;
  329. end;
  330. procedure TPackage.WritePreContains;
  331. begin
  332. end;
  333. end.