pkgfpmake.pp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. unit pkgfpmake;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,pkghandler;
  6. implementation
  7. uses
  8. fprepos,
  9. pkgoptions,
  10. pkgglobals,
  11. pkgmessages;
  12. type
  13. { TFPMakeCompiler }
  14. TFPMakeCompiler = Class(TPackagehandler)
  15. Private
  16. Procedure CompileFPMake;
  17. Public
  18. Function Execute(const Args:TActionArgs):boolean;override;
  19. end;
  20. { TFPMakeRunner }
  21. TFPMakeRunner = Class(TPackagehandler)
  22. Protected
  23. Function RunFPMake(const Command:string):Integer;
  24. end;
  25. { TFPMakeRunnerCompile }
  26. TFPMakeRunnerCompile = Class(TFPMakeRunner)
  27. Public
  28. Function Execute(const Args:TActionArgs):boolean;override;
  29. end;
  30. { TFPMakeRunnerBuild }
  31. TFPMakeRunnerBuild = Class(TFPMakeRunner)
  32. Public
  33. Function Execute(const Args:TActionArgs):boolean;override;
  34. end;
  35. { TFPMakeRunnerInstall }
  36. TFPMakeRunnerInstall = Class(TFPMakeRunner)
  37. Public
  38. Function Execute(const Args:TActionArgs):boolean;override;
  39. end;
  40. { TFPMakeRunnerManifest }
  41. TFPMakeRunnerManifest = Class(TFPMakeRunner)
  42. Public
  43. Function Execute(const Args:TActionArgs):boolean;override;
  44. end;
  45. { TFPMakeRunnerArchive }
  46. TFPMakeRunnerArchive = Class(TFPMakeRunner)
  47. Public
  48. Function Execute(const Args:TActionArgs):boolean;override;
  49. end;
  50. TMyMemoryStream=class(TMemoryStream)
  51. public
  52. constructor Create(p:pointer;mysize:integer);
  53. end;
  54. {$i fpmkunitsrc.inc}
  55. procedure CreateFPMKUnitSource(const AFileName:string);
  56. var
  57. InStream,
  58. OutStream : TStream;
  59. pend : pchar;
  60. begin
  61. try
  62. // Don't write trailing #0
  63. pend:=pchar(@fpmkunitsrc)+sizeof(fpmkunitsrc)-1;
  64. while pend^=#0 do
  65. dec(pend);
  66. InStream:=TMyMemoryStream.Create(@fpmkunitsrc,pend-pchar(@fpmkunitsrc));
  67. OutStream:=TFileStream.Create(AFileName,fmCreate);
  68. OutStream.CopyFrom(InStream,InStream.Size);
  69. finally
  70. InStream.Destroy;
  71. OutStream.Destroy;
  72. end;
  73. end;
  74. {*****************************************************************************
  75. TMyMemoryStream
  76. *****************************************************************************}
  77. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  78. begin
  79. inherited Create;
  80. SetPointer(p,mysize);
  81. end;
  82. { TFPMakeCompiler }
  83. Procedure TFPMakeCompiler.CompileFPMake;
  84. function CheckUnitDir(const AUnitName:string;Out AUnitDir:string):boolean;
  85. begin
  86. Result:=false;
  87. if FPMakeCompilerOptions.LocalUnitDir<>'' then
  88. begin
  89. AUnitDir:=IncludeTrailingPathDelimiter(FPMakeCompilerOptions.LocalUnitDir+AUnitName);
  90. if DirectoryExistsLog(AUnitDir) then
  91. begin
  92. Result:=true;
  93. exit;
  94. end;
  95. end;
  96. AUnitDir:=IncludeTrailingPathDelimiter(FPMakeCompilerOptions.GlobalUnitDir+AUnitName);
  97. if DirectoryExistsLog(AUnitDir) then
  98. begin
  99. Result:=true;
  100. exit;
  101. end;
  102. AUnitDir:='';
  103. end;
  104. const
  105. TempBuildDir = 'build-fpmake';
  106. Var
  107. i : Integer;
  108. OOptions,
  109. DepDir,
  110. FPMakeBin,
  111. FPMakeSrc : string;
  112. NeedFPMKUnitSource,
  113. HaveFpmake : boolean;
  114. begin
  115. SetCurrentDir(PackageBuildPath);
  116. // Check for fpmake source
  117. FPMakeBin:='fpmake'+ExeExt;
  118. FPMakeSrc:='fpmake.pp';
  119. HaveFpmake:=FileExists(FPMakeSrc);
  120. If Not HaveFPMake then
  121. begin
  122. HaveFPMake:=FileExists('fpmake.pas');
  123. If HaveFPMake then
  124. FPMakeSrc:='fpmake.pas';
  125. end;
  126. // Need to compile fpmake executable?
  127. if not FileExists(FPMakeBin) or
  128. (FileAge(FPMakeBin)<FileAge(FPMakeSrc)) then
  129. begin
  130. if Not HaveFPMake then
  131. Error(SErrMissingFPMake);
  132. OOptions:='-n';
  133. for i:=1 to FPMKUnitDepCount do
  134. begin
  135. if FPMKUnitDepAvailable[i] then
  136. begin
  137. if CheckUnitDir(FPMKUnitDeps[i].package,DepDir) then
  138. OOptions:=OOptions+' -Fu'+DepDir
  139. else
  140. Error(SErrMissingInstallPackage,[FPMKUnitDeps[i].package]);
  141. end
  142. else
  143. begin
  144. // If fpmkunit is not installed, we use the internal fpmkunit source
  145. if FPMKUnitDeps[i].package='fpmkunit' then
  146. begin
  147. NeedFPMKUnitSource:=true;
  148. OOptions:=OOptions+' -Fu'+TempBuildDir;
  149. end;
  150. if FPMKUnitDeps[i].undef<>'' then
  151. OOptions:=OOptions+' -d'+FPMKUnitDeps[i].undef;
  152. end;
  153. end;
  154. // Add RTL unit dir
  155. if not CheckUnitDir('rtl',DepDir) then
  156. Error(SErrMissingInstallPackage,['rtl']);
  157. OOptions:=OOptions+' -Fu'+DepDir;
  158. // Units in a directory for easy cleaning
  159. DeleteDir(TempBuildDir);
  160. ForceDirectories(TempBuildDir);
  161. OOptions:=OOptions+' -FU'+TempBuildDir;
  162. // Compile options
  163. // -- default is to optimize, smartlink and strip to reduce
  164. // the executable size (there can be 100's of fpmake's on a system)
  165. if vInfo in Verbosity then
  166. OOptions:=OOptions+' -vi';
  167. OOptions:=OOptions+' -O2 -XXs';
  168. // Create fpmkunit.pp if needed
  169. if NeedFPMKUnitSource then
  170. CreateFPMKUnitSource(TempBuildDir+PathDelim+'fpmkunit.pp');
  171. // Call compiler
  172. If ExecuteProcess(FPMakeCompilerOptions.Compiler,OOptions+' '+FPmakeSrc)<>0 then
  173. Error(SErrFailedToCompileFPCMake);
  174. // Cleanup units
  175. DeleteDir(TempBuildDir);
  176. end
  177. else
  178. Log(vCommands,SLogNotCompilingFPMake);
  179. end;
  180. function TFPMakeCompiler.Execute(const Args:TActionArgs):boolean;
  181. begin
  182. {$warning TODO Check arguments}
  183. CompileFPMake;
  184. result:=true;
  185. end;
  186. { TFPMakeRunner }
  187. Function TFPMakeRunner.RunFPMake(const Command:string) : Integer;
  188. Var
  189. FPMakeBin,
  190. OOptions : string;
  191. begin
  192. { Maybe compile fpmake executable? }
  193. ExecuteAction(CurrentPackage,'compilefpmake');
  194. { Create options }
  195. OOptions:=' --nofpccfg';
  196. if vInfo in Verbosity then
  197. OOptions:=OOptions+' --verbose';
  198. OOptions:=OOptions+' --compiler='+CompilerOptions.Compiler;
  199. OOptions:=OOptions+' --CPU='+CPUToString(CompilerOptions.CompilerCPU);
  200. OOptions:=OOptions+' --OS='+OSToString(CompilerOptions.CompilerOS);
  201. if IsSuperUser or GlobalOptions.InstallGlobal then
  202. OOptions:=OOptions+' --baseinstalldir='+CompilerOptions.GlobalInstallDir
  203. else
  204. OOptions:=OOptions+' --baseinstalldir='+CompilerOptions.LocalInstallDir;
  205. if CompilerOptions.LocalInstallDir<>'' then
  206. OOptions:=OOptions+' --localunitdir='+CompilerOptions.LocalUnitDir;
  207. OOptions:=OOptions+' --globalunitdir='+CompilerOptions.GlobalUnitDir;
  208. { Run FPMake }
  209. FPMakeBin:='fpmake'+ExeExt;
  210. SetCurrentDir(PackageBuildPath);
  211. Result:=ExecuteProcess(FPMakeBin,Command+OOptions);
  212. if Result<>0 then
  213. Error(SErrExecutionFPMake,[Command]);
  214. end;
  215. function TFPMakeRunnerCompile.Execute(const Args:TActionArgs):boolean;
  216. begin
  217. result:=(RunFPMake('compile')=0);
  218. end;
  219. function TFPMakeRunnerBuild.Execute(const Args:TActionArgs):boolean;
  220. begin
  221. result:=(RunFPMake('build')=0);
  222. end;
  223. function TFPMakeRunnerInstall.Execute(const Args:TActionArgs):boolean;
  224. begin
  225. result:=(RunFPMake('install')=0);
  226. end;
  227. function TFPMakeRunnerManifest.Execute(const Args:TActionArgs):boolean;
  228. begin
  229. result:=(RunFPMake('manifest')=0);
  230. end;
  231. function TFPMakeRunnerArchive.Execute(const Args:TActionArgs):boolean;
  232. begin
  233. result:=(RunFPMake('archive')=0);
  234. end;
  235. initialization
  236. RegisterPkgHandler('compilefpmake',TFPMakeCompiler);
  237. RegisterPkgHandler('fpmakecompile',TFPMakeRunnerCompile);
  238. RegisterPkgHandler('fpmakebuild',TFPMakeRunnerBuild);
  239. RegisterPkgHandler('fpmakeinstall',TFPMakeRunnerInstall);
  240. RegisterPkgHandler('fpmakemanifest',TFPMakeRunnerManifest);
  241. RegisterPkgHandler('fpmakearchive',TFPMakeRunnerArchive);
  242. end.