Package.pas 19 KB

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