pkgfpmake.pp 9.1 KB

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