Package.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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. ctUnversioned,
  59. ctDelphi4,
  60. ctDelphi5,
  61. ctDelphi6,
  62. ctDelphi7,
  63. ctDelphi8, ctDelphi8Net,
  64. ctDelphi2005, ctDelphi2005Net,
  65. ctDelphi2006, ctDelphi2006Net,
  66. ctDelphi2007, ctDelphi2007Net,
  67. ctDelphi2009, ctDelphi2009Net,
  68. ctDelphiPre2010NR, ctDelphiPre2010NRNet, // was not released, skipped to v14 (D2010)
  69. ctDelphi2010,
  70. ctDelphiXE,
  71. ctDelphiXE2,
  72. ctDelphiXE3,
  73. ctDelphiXE4,
  74. ctDelphiXE5,
  75. ctDelphiXE6,
  76. ctDelphiXE7,
  77. ctDelphiXE8,
  78. ctDelphiSeattle,
  79. ctDelphiBerlin,
  80. ctDelphiTokyo,
  81. ctDelphiRio,
  82. ctDelphiSydney,
  83. ctDelphiAlexandria,
  84. ctDelphiAthens,
  85. ctDelphiFlorence,
  86. ctDotNet, // Visual Studio
  87. ctKylix3);
  88. TCompilers = Set of TCompiler;
  89. TGenerateFlag = (gfRunTime, gfDesignTime, gfTemplate, gfDebug);
  90. TGenerateFlags = Set of TGenerateFlag;
  91. const
  92. Delphi_DotNet = [ctDelphi8Net, ctDelphi2005Net, ctDelphi2006Net, ctDelphi2007Net, ctDelphi2009Net, ctDelphiPre2010NRNet];
  93. Delphi_DotNet_1_1 = [ctDelphi8Net, ctDelphi2005Net, ctDelphi2006Net];
  94. Delphi_DotNet_2_Or_Later = [ctDelphi2007Net, ctDelphi2009Net, ctDelphiPre2010NRNet];
  95. Delphi_Native_Lowest = ctDelphi4;
  96. Delphi_Native_Highest = ctDelphiFlorence;
  97. Delphi_Native = [Delphi_Native_Lowest..Delphi_Native_Highest] - Delphi_DotNet;
  98. Delphi_Native_Ifdef_Rtl = Delphi_Native - [Delphi_Native_Lowest..ctDelphiXE];
  99. Delphi_Native_Ifdef_Rtl_CheckIOS = Delphi_Native_Ifdef_Rtl - [ctDelphiXE2..ctDelphiXE3];
  100. Delphi_NoVCLPosix = [Delphi_Native_Lowest..ctDelphiXE, ctKylix3] + Delphi_DotNet;
  101. type
  102. TPackage = class
  103. protected
  104. FCode: TStringList;
  105. FCompiler: TCompiler;
  106. FContainsClause: string;
  107. FDesc: string;
  108. FDirs: TStringList;
  109. FExt: string;
  110. FName: string;
  111. FUnits: TStringList;
  112. FVersion: string;
  113. FDesignTime: Boolean;
  114. FDebug: Boolean;
  115. FTemplate: Boolean;
  116. FOutputSubDir: string;
  117. //
  118. procedure Code(const ACode: string);
  119. procedure GenHeader; virtual;
  120. procedure GenOptions; virtual;
  121. procedure GenPreRequiresClause; virtual;
  122. procedure GenRequires; virtual;
  123. procedure GenContains; overload; virtual;
  124. procedure GenContains(const aPrefix: string; const aWritePath: Boolean); overload; virtual;
  125. procedure GenFooter; virtual;
  126. procedure GenPreContainsClause; virtual;
  127. procedure GenPreContains; virtual;
  128. procedure GenPreContainsFile(const AUnit: string); virtual;
  129. procedure GenPostContainsFile(const AUnit: string; const AIsLastFile: Boolean); virtual;
  130. procedure GenResourceScript; virtual;
  131. function IgnoreContainsFile(const AUnit: string): Boolean; virtual;
  132. procedure WriteFile;
  133. public
  134. procedure Clear;
  135. procedure AddUnit(const AName: string; const ADir: string = '');
  136. constructor Create; virtual;
  137. destructor Destroy; override;
  138. procedure Generate(ACompiler: TCompiler); overload;
  139. procedure Generate(ACompiler: TCompiler; const AFlags: TGenerateFlags); overload; virtual;
  140. procedure Generate(ACompilers: TCompilers); overload;
  141. procedure Generate(ACompilers: TCompilers; const AFlags: TGenerateFlags); overload; virtual;
  142. procedure GenerateRC(ACompiler: TCompiler); overload;
  143. procedure GenerateRC(ACompiler: TCompiler; const AFlags: TGenerateFlags); overload; virtual;
  144. procedure GenerateRC(ACompilers: TCompilers); overload;
  145. procedure GenerateRC(ACompilers: TCompilers; const AFlags: TGenerateFlags); overload; virtual;
  146. procedure Load(const ACriteria: string; const AUsePath: Boolean = False);
  147. end;
  148. const
  149. GPackageVer: array[TCompiler] of string = (
  150. '', // Unversioned
  151. '40', // 4.0
  152. '50', // 5.0
  153. '60', // 6.0
  154. '70', // 7.0
  155. '80', '80Net', // 8.0
  156. '90', '90Net', // 2005
  157. '100', '100Net', // 2006
  158. '110', '110Net', // 2007
  159. '120', '120Net', // 2009
  160. '130', '130Net', // was not released, skipped to v14 (D2010)
  161. '140', // 2010
  162. '150', // XE
  163. '160', // XE2
  164. '170', // XE3
  165. '180', // XE4
  166. '190', // XE5
  167. '200', // XE6
  168. '210', // XE7
  169. '220', // XE8
  170. '230', // 10.0 Seattle
  171. '240', // 10.1 Berlin
  172. '250', // 10.2 Tokyo
  173. '260', // 10.3 Rio
  174. '270', // 10.4 Sydney
  175. '280', // 11.0 Alexandria
  176. '290', // 12.0 Athens
  177. '370', // 13.0 Florence (package version synced with compiler version!)
  178. '', // .NET
  179. 'K3'); // Kylix
  180. GCompilerVer: array[TCompiler] of string = (
  181. '', // Unversioned
  182. '120', // 4.0
  183. '130', // 5.0
  184. '140', // 6.0
  185. '150', // 7.0
  186. '160', '160', // 8.0
  187. '170', '170', // 2005
  188. '180', '180', // 2006
  189. '185', '190', // 2007
  190. '200', '200', // 2009
  191. '', '', // was not released, skipped to v14 (D2010)
  192. '210', // 2010
  193. '220', // XE
  194. '230', // XE2
  195. '240', // XE3
  196. '250', // XE4
  197. '260', // XE5
  198. '270', // XE6
  199. '280', // XE7
  200. '290', // XE8
  201. '300', // 10.0 Seattle
  202. '310', // 10.1 Berlin
  203. '320', // 10.2 Tokyo
  204. '330', // 10.3 Rio
  205. '340', // 10.4 Sydney
  206. '350', // 11.0 Alexandria
  207. '360', // 12.0 Athens
  208. '370', // 13.0 Florence
  209. '', // .NET
  210. ''); // Kylix
  211. function iif(ATest: Boolean; const ATrue: Integer; const AFalse: Integer): Integer; overload;
  212. function iif(ATest: Boolean; const ATrue: string; const AFalse: string): string; overload;
  213. function iif(ATest: Boolean; const ATrue: Boolean; const AFalse: Boolean): Boolean; overload;
  214. var
  215. IndyVersion_Major_Str: string = '';
  216. IndyVersion_Minor_Str: string = '';
  217. IndyVersion_Release_Str: string = '';
  218. IndyVersion_Build_Str: string = '';
  219. IndyVersion_Build_Template: string = '';
  220. IndyVersion_ProductVersion_Str: string = '';
  221. IndyVersion_FileVersion_Str: string = '';
  222. IndyVersion_FileVersion_Template: string = '';
  223. IndyVersion_VersionInfo_ProductVersion_Str: string = '';
  224. IndyVersion_VersionInfo_FileVersion_Str: string = '';
  225. IndyVersion_VersionInfo_FileVersion_Template: string = '';
  226. procedure InitVersionNumbers;
  227. implementation
  228. uses
  229. SysUtils, DateUtils, DModule;
  230. function iif(ATest: Boolean; const ATrue: Integer; const AFalse: Integer): Integer;
  231. {$IFDEF USEINLINE}inline;{$ENDIF}
  232. begin
  233. if ATest then begin
  234. Result := ATrue;
  235. end else begin
  236. Result := AFalse;
  237. end;
  238. end;
  239. function iif(ATest: Boolean; const ATrue: string; const AFalse: string): string;
  240. {$IFDEF USEINLINE}inline;{$ENDIF}
  241. begin
  242. if ATest then begin
  243. Result := ATrue;
  244. end else begin
  245. Result := AFalse;
  246. end;
  247. end;
  248. function iif(ATest: Boolean; const ATrue: Boolean; const AFalse: Boolean): Boolean;
  249. {$IFDEF USEINLINE}inline;{$ENDIF}
  250. begin
  251. if ATest then begin
  252. Result := ATrue;
  253. end else begin
  254. Result := AFalse;
  255. end;
  256. end;
  257. { TPackage }
  258. procedure TPackage.AddUnit(const AName: string; const ADir: string);
  259. begin
  260. FUnits.Add(AName);
  261. FDirs.Add(ADir);
  262. end;
  263. procedure TPackage.Clear;
  264. begin
  265. FCode.Clear;
  266. FDirs.Clear;
  267. FUnits.Clear;
  268. end;
  269. procedure TPackage.Code(const ACode: string);
  270. begin
  271. FCode.Add(ACode);
  272. end;
  273. constructor TPackage.Create;
  274. begin
  275. FContainsClause := 'contains';
  276. FExt := '.dpk';
  277. FVersion := IndyVersion_Major_Str;
  278. FCode := TStringList.Create;
  279. FDirs := TStringList.Create;
  280. FUnits := TStringList.Create;
  281. end;
  282. destructor TPackage.Destroy;
  283. begin
  284. FreeAndNil(FUnits);
  285. FreeAndNil(FDirs);
  286. FreeAndNil(FCode);
  287. inherited;
  288. end;
  289. procedure TPackage.GenContains;
  290. begin
  291. GenContains('', True);
  292. end;
  293. procedure TPackage.GenContains(const aPrefix: string; const aWritePath: Boolean);
  294. var
  295. i: Integer;
  296. xPath, lastUnit, lastPath: string;
  297. begin
  298. Code('');
  299. GenPreContainsClause;
  300. Code(FContainsClause);
  301. GenPreContains;
  302. lastUnit := '';
  303. lastPath := '';
  304. for i := 0 to FUnits.Count - 1 do begin
  305. if APrefix <> '' then begin
  306. FUnits[i] := StringReplace(FUnits[i], 'Id', APrefix, []);
  307. end;
  308. if not IgnoreContainsFile(FUnits[i]) then begin
  309. xPath := '';
  310. if aWritePath and (FDirs[i] <> '') then begin
  311. xPath := IncludeTrailingPathDelimiter(FDirs[i]);
  312. end;
  313. xPath := xPath + FUnits[i] + '.pas';
  314. if (lastUnit <> '') or (lastPath <> '') then begin
  315. GenPreContainsFile(lastUnit);
  316. Code(' ' + lastUnit + ' in ''' + lastPath + '''');
  317. GenPostContainsFile(lastUnit, False);
  318. end;
  319. lastUnit := FUnits[i];
  320. lastPath := xPath;
  321. end;
  322. end;
  323. if (lastUnit <> '') or (lastPath <> '') then begin
  324. GenPreContainsFile(lastUnit);
  325. Code(' ' + lastUnit + ' in ''' + lastPath + '''');
  326. GenPostContainsFile(lastUnit, True);
  327. end;
  328. end;
  329. procedure TPackage.GenPreContainsFile(const AUnit: string);
  330. begin
  331. end;
  332. procedure TPackage.GenPostContainsFile(const AUnit: string; const AIsLastFile: Boolean);
  333. begin
  334. if FCode.Count > 0 then begin
  335. FCode[FCode.Count-1] := FCode[FCode.Count-1] + iif(AIsLastFile, ';', ',');
  336. end;
  337. end;
  338. function TPackage.IgnoreContainsFile(const AUnit: string): Boolean;
  339. begin
  340. Result := False;
  341. end;
  342. procedure TPackage.GenPreRequiresClause;
  343. begin
  344. end;
  345. procedure TPackage.GenRequires;
  346. begin
  347. end;
  348. procedure TPackage.GenFooter;
  349. begin
  350. Code('');
  351. Code('end.');
  352. end;
  353. procedure TPackage.Generate(ACompiler: TCompiler);
  354. begin
  355. Generate(ACompiler, [gfRunTime]);
  356. end;
  357. procedure TPackage.Generate(ACompiler: TCompiler; const AFlags: TGenerateFlags);
  358. begin
  359. FCompiler := ACompiler;
  360. FCode.Clear;
  361. FDesignTime := gfDesignTime in AFlags;
  362. FDebug := gfDebug in AFlags;
  363. GenHeader;
  364. GenOptions;
  365. GenPreRequiresClause;
  366. GenRequires;
  367. GenContains;
  368. GenFooter;
  369. end;
  370. procedure TPackage.Generate(ACompilers: TCompilers);
  371. begin
  372. Generate(ACompilers, [gfRunTime]);
  373. end;
  374. procedure TPackage.Generate(ACompilers: TCompilers; const AFlags: TGenerateFlags);
  375. var
  376. LCompiler: TCompiler;
  377. begin
  378. for LCompiler := Low(TCompiler) to High(TCompiler) do begin
  379. if LCompiler in ACompilers then begin
  380. Generate(LCompiler, AFlags);
  381. end;
  382. end;
  383. end;
  384. procedure TPackage.GenerateRC(ACompiler: TCompiler);
  385. begin
  386. GenerateRC(ACompiler, [gfRunTime]);
  387. end;
  388. procedure TPackage.GenerateRC(ACompiler: TCompiler; const AFlags: TGenerateFlags);
  389. begin
  390. FCompiler := ACompiler;
  391. FTemplate := gfTemplate in AFlags;
  392. FDebug := gfDebug in AFlags;
  393. if gfRunTime in AFlags then begin
  394. FCode.Clear;
  395. FDesignTime := False;
  396. GenResourceScript;
  397. end;
  398. if gfDesignTime in AFlags then begin
  399. FCode.Clear;
  400. FDesignTime := True;
  401. GenResourceScript;
  402. end;
  403. end;
  404. procedure TPackage.GenerateRC(ACompilers: TCompilers);
  405. begin
  406. GenerateRC(ACompilers, [gfRunTime]);
  407. end;
  408. procedure TPackage.GenerateRC(ACompilers: TCompilers; const AFlags: TGenerateFlags);
  409. var
  410. LCompiler: TCompiler;
  411. begin
  412. for LCompiler := Low(TCompiler) to High(TCompiler) do begin
  413. if LCompiler in ACompilers then begin
  414. GenerateRC(LCompiler, AFlags);
  415. end;
  416. end;
  417. end;
  418. procedure TPackage.GenHeader;
  419. begin
  420. Code('package ' + FName + ';');
  421. end;
  422. // TODO: make the options configurable...
  423. procedure TPackage.GenOptions;
  424. const
  425. DelphiNative_Align8 = Delphi_Native - [Delphi_Native_Lowest..ctDelphiPre2010NR] + [ctDelphi2005];
  426. begin
  427. Code('');
  428. if FCompiler in Delphi_DotNet then begin
  429. Code('{$ALIGN 0}');
  430. end else begin
  431. Code('{$R *.res}');
  432. if FCompiler in DelphiNative_Align8 then begin
  433. Code('{$ALIGN 8}');
  434. end;
  435. end;
  436. // Code('{$ASSERTIONS ON}');
  437. Code('{$BOOLEVAL OFF}');
  438. // Code('{$DEBUGINFO ON}');
  439. Code('{$EXTENDEDSYNTAX ON}');
  440. Code('{$IMPORTEDDATA ON}');
  441. // Code('{$IOCHECKS ON}');
  442. Code('{$LOCALSYMBOLS ON}');
  443. Code('{$LONGSTRINGS ON}');
  444. Code('{$OPENSTRINGS ON}');
  445. Code('{$OPTIMIZATION ON}');
  446. // Code('{$OVERFLOWCHECKS ON}');
  447. // Code('{$RANGECHECKS ON}');
  448. Code('{$REFERENCEINFO ON}');
  449. Code('{$SAFEDIVIDE OFF}');
  450. Code('{$STACKFRAMES OFF}');
  451. Code('{$TYPEDADDRESS OFF}');
  452. Code('{$VARSTRINGCHECKS ON}');
  453. Code('{$WRITEABLECONST OFF}');
  454. Code('{$MINENUMSIZE 1}');
  455. Code('{$IMAGEBASE $400000}');
  456. Code('{$DESCRIPTION ''Indy ' + FVersion + TrimRight(' ' + FDesc) + '''}');
  457. Code(iif(FDesignTime, '{$DESIGNONLY}', '{$RUNONLY}'));
  458. Code('{$IMPLICITBUILD OFF}');
  459. end;
  460. procedure TPackage.Load(const ACriteria: string; const AUsePath: Boolean = False);
  461. var
  462. LFiles: TStringList;
  463. LDir: string;
  464. I: Integer;
  465. begin
  466. Clear;
  467. LFiles := TStringList.Create;
  468. try
  469. DM.GetFileList(ACriteria, LFiles);
  470. for I := 0 to LFiles.Count - 1 do
  471. begin
  472. if AUsePath then begin
  473. LDir := DM.Ini.ReadString(LFiles[I], 'Pkg', '');
  474. end else begin
  475. LDir := '';
  476. end;
  477. AddUnit(LFiles[I], LDir);
  478. end;
  479. finally
  480. LFiles.Free;
  481. end;
  482. end;
  483. procedure TPackage.WriteFile;
  484. var
  485. LCodeOld: string;
  486. LPathname: string;
  487. LSubDir: string;
  488. begin
  489. LPathname := SysUtils.IncludeTrailingPathDelimiter(DM.OutputPath);
  490. if FOutputSubDir <> '' then begin
  491. LSubDir := SysUtils.IncludeTrailingPathDelimiter(FOutputSubDir);
  492. LPathname := LPathname + LSubDir;
  493. end;
  494. LPathname := LPathname + FName + FExt;
  495. LCodeOld := '';
  496. if FileExists(LPathname) then begin
  497. with TStringList.Create do try
  498. LoadFromFile(LPathname);
  499. LCodeOld := Text;
  500. finally Free; end;
  501. end;
  502. // Only write out the code if its different. This prevents unnecessary checkins as well
  503. // as not requiring user to lock all packages
  504. if (LCodeOld = '') or (LCodeOld <> FCode.Text) then begin
  505. FCode.SaveToFile(LPathname);
  506. WriteLn('Generated ' + LSubDir + FName + FExt);
  507. end;
  508. end;
  509. procedure TPackage.GenPreContainsClause;
  510. begin
  511. end;
  512. procedure TPackage.GenPreContains;
  513. begin
  514. end;
  515. procedure TPackage.GenResourceScript;
  516. var
  517. FileVersion : string;
  518. begin
  519. //We don't call many of the inherited Protected methods because
  520. //those are for Packages while I'm making a unit.
  521. FileVersion := iif(FTemplate,
  522. IndyVersion_VersionInfo_FileVersion_Template,
  523. IndyVersion_VersionInfo_FileVersion_Str);
  524. Code('1 VERSIONINFO ');
  525. Code('FILEVERSION ' + FileVersion);
  526. Code('PRODUCTVERSION ' + FileVersion);
  527. Code('FILEFLAGSMASK 0x3FL');
  528. Code('FILEFLAGS 0x00L');
  529. Code('FILEOS 0x40004L');
  530. Code('FILETYPE 0x1L');
  531. FileVersion := iif(FTemplate,
  532. IndyVersion_FileVersion_Template,
  533. IndyVersion_FileVersion_Str);
  534. Code('FILESUBTYPE 0x0L');
  535. Code('{');
  536. Code(' BLOCK "StringFileInfo"');
  537. Code(' {');
  538. Code(' BLOCK "000104E4"');
  539. Code(' {');
  540. Code(' VALUE "CompanyName", "Chad Z. Hower a.k.a Kudzu and the Indy Pit Crew\0"');
  541. Code(' VALUE "FileDescription", "Internet Direct (Indy) ' + IndyVersion_ProductVersion_Str + ' - ' + FDesc + ' Package\0"');
  542. Code(' VALUE "FileVersion", "' + FileVersion + '\0"');
  543. Code(' VALUE "InternalName", "' + FName + '\0"');
  544. Code(' VALUE "LegalCopyright", "Copyright © 1993 - ' + IntToStr(DateUtils.YearOf(Date)) + ' Chad Z. Hower a.k.a Kudzu and the Indy Pit Crew\0"');
  545. Code(' VALUE "OriginalFilename", "' + FName + '.bpl\0"');
  546. Code(' VALUE "ProductName", "Indy\0"');
  547. Code(' VALUE "ProductVersion", "' + IndyVersion_ProductVersion_Str + '\0"');
  548. Code(' }');
  549. Code('');
  550. Code(' }');
  551. Code('');
  552. Code(' BLOCK "VarFileInfo"');
  553. Code(' {');
  554. Code(' VALUE "Translation", 0x0001, 1252');
  555. Code(' }');
  556. Code('');
  557. Code('}');
  558. end;
  559. procedure InitVersionNumbers;
  560. var
  561. LMajor, LMinor, LRelease, LBuild, LPos: Integer;
  562. LVerNum, LTemp: string;
  563. begin
  564. if FindCmdLineSwitch('version', LVerNum) then
  565. LVerNum := Trim(LVerNum);
  566. if LVerNum = '' then begin
  567. with TMemIniFile.Create(DM.DataPath + 'PkgGen.ini') do try
  568. LVerNum := Trim(ReadString('Settings', 'LastVersion', ''));
  569. finally
  570. Free;
  571. end;
  572. WriteLn;
  573. if LVerNum <> '' then begin
  574. WriteLn('Please enter a version number in #.#.#.# format');
  575. Write ('or leave blank to reuse last version (',LVerNum,'): ');
  576. end else
  577. begin
  578. Write('Please enter a version number in #.#.#.# format: ');
  579. end;
  580. ReadLn(LTemp);
  581. LTemp := Trim(LTemp);
  582. if LTemp <> '' then begin
  583. LVerNum := LTemp;
  584. end
  585. else if LVerNum = '' then begin
  586. raise Exception.Create('Version number is missing');
  587. end;
  588. end;
  589. try
  590. LTemp := LVerNum;
  591. LPos := Pos('.', LTemp);
  592. LMajor := StrToInt(Copy(LTemp, 1, LPos-1));
  593. Delete(LTemp, 1, LPos);
  594. LPos := Pos('.', LTemp);
  595. LMinor := StrToInt(Copy(LTemp, 1, LPos-1));
  596. Delete(LTemp, 1, LPos);
  597. LPos := Pos('.', LTemp);
  598. LRelease := StrToInt(Copy(LTemp, 1, LPos-1));
  599. Delete(LTemp, 1, LPos);
  600. LBuild := StrToInt(LTemp);
  601. except
  602. Exception.RaiseOuterException(Exception.Create('Version number is invalid'));
  603. Exit;
  604. end;
  605. IndyVersion_Major_Str := IntToStr(LMajor);
  606. IndyVersion_Minor_Str := IntToStr(LMinor);
  607. IndyVersion_Release_Str := IntToStr(LRelease);
  608. IndyVersion_Build_Str := IntToStr(LBuild);
  609. IndyVersion_Build_Template := '$WCREV$';
  610. IndyVersion_ProductVersion_Str := Format('%d.%d.%d', [LMajor, LMinor, LRelease]);
  611. IndyVersion_FileVersion_Str := Format('%d.%d.%d.%d', [LMajor, LMinor, LRelease, LBuild]);
  612. IndyVersion_FileVersion_Template := Format('%d.%d.%d.%s', [LMajor, LMinor, LRelease, IndyVersion_Build_Template]);
  613. IndyVersion_VersionInfo_ProductVersion_Str := Format('%d,%d,%d', [LMajor, LMinor, LRelease]);
  614. IndyVersion_VersionInfo_FileVersion_Str := Format('%d,%d,%d,%d', [LMajor, LMinor, LRelease, LBuild]);
  615. IndyVersion_VersionInfo_FileVersion_Template := Format('%d,%d,%d,%s', [LMajor, LMinor, LRelease, IndyVersion_Build_Template]);
  616. with TMemIniFile.Create(DM.DataPath + 'PkgGen.ini') do
  617. try
  618. WriteString('Settings', 'LastVersion', LVerNum);
  619. UpdateFile;
  620. finally
  621. Free;
  622. end;
  623. WriteLn;
  624. WriteLn('Version Number set to ',LMajor,'.',LMinor,'.',LRelease,'.',LBuild);
  625. end;
  626. end.