pkgfpmake.pp 8.1 KB

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