pkgfpmake.pp 8.7 KB

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