fpmakecreatefile.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. unit fpmakecreatefile;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. fpmakeParseJSon,
  7. fpTemplate,
  8. fpmkunit;
  9. procedure CreateFile(AOutputFileName: string; ATemplate: TStringList; APackages: TPackages; ASkipBackup, ACreateDir: boolean);
  10. function TemplateParser: TTemplateParser;
  11. implementation
  12. type
  13. { TfpmakeTemplateParser }
  14. TfpmakeTemplateParser = class(TTemplateParser)
  15. public
  16. constructor Create;
  17. Procedure OnGetParamProc(Sender : TObject; Const TagString : String; TagParams:TStringList; Out ReplaceText : String);
  18. end;
  19. var
  20. GTemplateParser: TTemplateParser;
  21. resourcestring
  22. SErrDelBackupFailed = 'Error: Delete of old backup file "%s" failed.';
  23. SErrCreateDirFailed = 'Error: Could not create the directory for file "%s".';
  24. SErrNoSuchDirectory = 'Error: Directory of file "%s" does not exists. User -p to force creation.';
  25. SErrBackupFailed = 'Error: Backup of file "%s" to "%s" failed.';
  26. SBackupCreated = 'Saved old "%s" to "%s"';
  27. function GetConditionalAdd(const Value: string; CPUs: TCPUS; OSes: TOSes; const AddName: string): string;
  28. begin
  29. if (CPUs <> AllCPUs) and (OSes <> AllOSes) then
  30. result := result + ' '+AddName+'('''+Value+''','+ExtCPUsToString(CPUs)+','+ExtOSesToString(OSes)+');' + LineEnding
  31. else if (CPUs <> AllCPUs) then
  32. result := result + ' '+AddName+'('''+Value+''','+ExtCPUsToString(CPUs)+');' + LineEnding
  33. else if (OSes <> AllOSes) then
  34. result := result + ' '+AddName+'('''+Value+''','+ExtOSesToString(OSes)+');' + LineEnding
  35. else
  36. result := result + ' '+AddName+'('''+Value+''');' + LineEnding;
  37. end;
  38. function GetConditionalStringsMacro(ACondStrings: TConditionalStrings; APropName: string): string;
  39. var
  40. ADependency: TConditionalString;
  41. i: Integer;
  42. begin
  43. if ACondStrings.Count=0 then
  44. Exit;
  45. if ACondStrings.Count=1 then
  46. begin
  47. ADependency := ACondStrings[0];
  48. result := result + GetConditionalAdd(ADependency.Value, ADependency.CPUs, ADependency.OSes,APropName+'.Add');
  49. end
  50. else
  51. begin
  52. result := ' with '+APropName+' do' + LineEnding +
  53. ' begin'+LineEnding;
  54. for i := 0 to ACondStrings.Count-1 do
  55. begin
  56. ADependency := ACondStrings[i];
  57. result := result + GetConditionalAdd(ADependency.Value, ADependency.CPUs, ADependency.OSes,' Add');
  58. end;
  59. result := result +
  60. ' end;' + LineEnding;
  61. end;
  62. end;
  63. function GetConditionalPackagePropertiesMacro(APackage: TPackage): string;
  64. begin
  65. result := '';
  66. if APackage.CPUs<>AllCPUs then
  67. result := result + ' P.CPUs := '+ExtCPUSToString(APackage.CPUs)+';'+LineEnding;
  68. if APackage.OSes<>AllOSes then
  69. result := result + ' P.OSes := '+ExtOSesToString(APackage.OSes)+';'+LineEnding;
  70. end;
  71. function GetTargetsMacro(aTargets: TTargets): string;
  72. var
  73. ATarget: TTarget;
  74. i: Integer;
  75. d: integer;
  76. begin
  77. if aTargets.Count=0 then
  78. Exit;
  79. result := ' with P.Targets do' + LineEnding +
  80. ' begin'+LineEnding;
  81. for i := 0 to aTargets.Count-1 do
  82. begin
  83. ATarget := aTargets.Items[i] as TTarget;
  84. result := result + GetConditionalAdd(ATarget.Name + ATarget.Extension, ATarget.CPUs, ATarget.OSes,' T := AddUnit');
  85. if atarget.ResourceStrings then
  86. result := result + ' T.Resourcestrings := True;'+LineEnding;
  87. for d := 0 to aTarget.Dependencies.Count-1 do
  88. begin
  89. if ATarget.Dependencies[d].DependencyType=depInclude then
  90. result := result + ' T.Dependencies.AddInclude('''+ATarget.Dependencies[d].Value+''');'+LineEnding
  91. else if ATarget.Dependencies[d].DependencyType=depUnit then
  92. result := result + ' T.Dependencies.AddUnit('''+ATarget.Dependencies[d].Value+''');'+LineEnding
  93. else
  94. result := result + ' T.Dependencies.Add('''+ATarget.Dependencies[d].Value+''');'+LineEnding;
  95. end;
  96. end;
  97. result := result +
  98. ' end;';
  99. end;
  100. procedure CreateFile(AOutputFileName: string; ATemplate: TStringList; APackages: TPackages; ASkipBackup, ACreateDir: boolean);
  101. Var
  102. Fout : Text;
  103. S,BFN : String;
  104. I : Integer;
  105. PackageNr: Integer;
  106. APackage: TPackage;
  107. begin
  108. If (AOutputFileName<>'')
  109. and FileExists(AOutputFileName)
  110. and not ASkipBackup then
  111. begin
  112. BFN:=ChangeFileExt(AOutputFileName,'.bak');
  113. If FileExists(BFN) and not DeleteFile(BFN) then
  114. begin
  115. Writeln(StdErr,Format(SErrDelBackupFailed,[BFN]));
  116. Halt(1);
  117. end;
  118. If not RenameFile(AOutputFileName,BFN) then
  119. begin
  120. Writeln(StdErr,Format(SErrBackupFailed,[AOutputFileName,BFN]));
  121. Halt(1);
  122. end
  123. else
  124. Writeln(Format(SBackupCreated,[ExtractFileName(AOutputFileName),ExtractFileName(BFN)]));
  125. end;
  126. if (AOutputFileName<>'') and (ExtractFilePath(AOutputFileName)<>'') and not DirectoryExists(ExtractFilePath(AOutputFileName)) then
  127. begin
  128. if ACreateDir then
  129. begin
  130. if not ForceDirectories(ExtractFilePath(AOutputFileName)) then
  131. begin
  132. Writeln(StdErr,Format(SErrCreateDirFailed,[AOutputFileName]));
  133. Halt(1);
  134. end;
  135. end
  136. else
  137. begin
  138. Writeln(StdErr,Format(SErrNoSuchDirectory,[AOutputFileName]));
  139. Halt(1);
  140. end;
  141. end;
  142. Assign(Fout,AOutputFileName);
  143. Rewrite(FOut);
  144. Try
  145. for PackageNr := 0 to APackages.Count-1 do
  146. begin
  147. APackage := APackages.Items[PackageNr] as TPackage;
  148. TemplateParser.Values['packagename'] := APackage.Name;
  149. TemplateParser.Values['directory'] := APackage.Directory;
  150. TemplateParser.Values['version'] := APackage.Version;
  151. TemplateParser.Values['author'] := APackage.Author;
  152. TemplateParser.Values['license'] := APackage.License;
  153. TemplateParser.Values['homepageurl'] := APackage.HomepageURL;
  154. TemplateParser.Values['downloadurl'] := APackage.DownloadURL;
  155. TemplateParser.Values['email'] := APackage.Email;
  156. TemplateParser.Values['description'] := APackage.Description;
  157. TemplateParser.Values['needlibc'] := BoolToStr(APackage.NeedLibC,'true','false');
  158. TemplateParser.Values['conditionalpackageproperties'] := GetConditionalPackagePropertiesMacro(APackage);
  159. TemplateParser.Values['packagedependencies'] := GetConditionalStringsMacro(APackage.Dependencies, 'P.Dependencies');
  160. TemplateParser.Values['packagesourcepaths'] := GetConditionalStringsMacro(APackage.SourcePath, 'P.SourcePath');
  161. TemplateParser.Values['targets'] := GetTargetsMacro(APackage.Targets);
  162. For I:=0 to ATemplate.Count-1 do
  163. begin
  164. S:=ATemplate[i];
  165. S := TemplateParser.ParseString(S);
  166. Writeln(FOut,S);
  167. end;
  168. end;
  169. Finally
  170. Close(Fout);
  171. end;
  172. end;
  173. function TemplateParser: TTemplateParser;
  174. begin
  175. if not assigned(GTemplateParser) then
  176. begin
  177. GTemplateParser := TfpmakeTemplateParser.Create;
  178. GTemplateParser.StartDelimiter:='%';
  179. GTemplateParser.EndDelimiter:='%';
  180. GTemplateParser.ParamStartDelimiter:='(';
  181. GTemplateParser.ParamEndDelimiter:=')';
  182. GTemplateParser.Values['PWD'] := GetCurrentDir;
  183. GTemplateParser.Values['BUILDDATE'] := DateToStr(Date);
  184. GTemplateParser.Values['BUILDTIME'] := TimeToStr(Time);
  185. end;
  186. result := GTemplateParser;
  187. end;
  188. { TfpmakeTemplateParser }
  189. constructor TfpmakeTemplateParser.Create;
  190. begin
  191. inherited create;
  192. AllowTagParams := True;
  193. OnReplaceTag := @OnGetParamProc;
  194. end;
  195. procedure TfpmakeTemplateParser.OnGetParamProc(Sender : TObject; Const TagString : String; TagParams:TStringList; Out ReplaceText : String);
  196. var
  197. i: Integer;
  198. s: string;
  199. begin
  200. if TagString = 'quotedstr' then
  201. begin
  202. i := TagParams.Count;
  203. ReplaceText:='';
  204. for i := 0 to TagParams.Count-1 do
  205. begin
  206. GetParam(TagParams[i],s);
  207. ReplaceText:=ReplaceText + quotedstr(s);
  208. end;
  209. end
  210. else
  211. GetParam(TagString,ReplaceText);
  212. end;
  213. initialization
  214. GTemplateParser := nil
  215. finalization
  216. GTemplateParser.Free;
  217. end.