2
0

fppkg.pp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. program fppkg;
  2. {$mode objfpc}{$H+}
  3. uses
  4. // General
  5. {$ifdef unix}
  6. baseunix,
  7. {$endif}
  8. Classes, SysUtils, TypInfo, custapp,
  9. // Repository handler objects
  10. fprepos, fpxmlrep,
  11. pkgmessages, pkgglobals, pkgoptions, pkgrepos,
  12. // Package Handler components
  13. pkghandler,pkgmkconv, pkgdownload,
  14. pkgfpmake, pkgcommands
  15. // Downloaders
  16. {$if defined(unix) or defined(windows)}
  17. ,pkgwget
  18. {$endif}
  19. ;
  20. Type
  21. { TMakeTool }
  22. TMakeTool = Class(TCustomApplication)
  23. Private
  24. ActionStack : TActionStack;
  25. ParaAction : string;
  26. ParaPackages : TStringList;
  27. procedure MaybeCreateLocalDirs;
  28. procedure ShowUsage;
  29. Public
  30. Constructor Create;
  31. Destructor Destroy;override;
  32. Function GetConfigFileName : String;
  33. Procedure LoadGlobalDefaults;
  34. Procedure LoadCompilerDefaults;
  35. Procedure ProcessCommandLine;
  36. Procedure DoRun; Override;
  37. end;
  38. EMakeToolError = Class(Exception);
  39. { TMakeTool }
  40. function TMakeTool.GetConfigFileName: String;
  41. var
  42. G : Boolean;
  43. begin
  44. if HasOption('C','config-file') then
  45. Result:=GetOptionValue('C','config-file')
  46. else
  47. begin
  48. {$ifdef unix}
  49. g:=(fpgetuid=0);
  50. {$else}
  51. g:=true;
  52. {$endif}
  53. Result:=GetAppConfigFile(G,False);
  54. end
  55. end;
  56. procedure TMakeTool.LoadGlobalDefaults;
  57. var
  58. SL : TStringList;
  59. i : integer;
  60. cfgfile : String;
  61. GeneratedConfig : boolean;
  62. begin
  63. cfgfile:=GetConfigFileName;
  64. GeneratedConfig:=false;
  65. // Load file or create new default configuration
  66. if FileExists(cfgfile) then
  67. GlobalOptions.LoadGlobalFromFile(cfgfile)
  68. else
  69. begin
  70. ForceDirectories(ExtractFilePath(cfgfile));
  71. GlobalOptions.SaveGlobalToFile(cfgfile);
  72. GeneratedConfig:=true;
  73. end;
  74. // Load default verbosity from config
  75. SL:=TStringList.Create;
  76. SL.CommaText:=GlobalOptions.DefaultVerbosity;
  77. for i:=0 to SL.Count-1 do
  78. Include(Verbosity,StringToVerbosity(SL[i]));
  79. SL.Free;
  80. GlobalOptions.CompilerConfig:=GlobalOptions.DefaultCompilerConfig;
  81. // Tracing of what we've done above, need to be done after the verbosity is set
  82. if GeneratedConfig then
  83. Log(vDebug,SLogGeneratingGlobalConfig,[cfgfile])
  84. else
  85. Log(vDebug,SLogLoadingGlobalConfig,[cfgfile])
  86. end;
  87. procedure TMakeTool.MaybeCreateLocalDirs;
  88. begin
  89. ForceDirectories(GlobalOptions.BuildDir);
  90. ForceDirectories(GlobalOptions.PackagesDir);
  91. ForceDirectories(GlobalOptions.CompilerConfigDir);
  92. end;
  93. procedure TMakeTool.LoadCompilerDefaults;
  94. var
  95. S : String;
  96. begin
  97. // Load default compiler config
  98. S:=GlobalOptions.CompilerConfigDir+GlobalOptions.CompilerConfig;
  99. if FileExists(S) then
  100. begin
  101. Log(vDebug,SLogLoadingCompilerConfig,[S]);
  102. CompilerOptions.LoadCompilerFromFile(S)
  103. end
  104. else
  105. begin
  106. // Generate a default configuration if it doesn't exists
  107. if GlobalOptions.CompilerConfig='default' then
  108. begin
  109. Log(vDebug,SLogGeneratingCompilerConfig,[S]);
  110. CompilerOptions.InitCompilerDefaults;
  111. CompilerOptions.SaveCompilerToFile(S);
  112. end
  113. else
  114. Error(SErrMissingCompilerConfig,[S]);
  115. end;
  116. // Load FPMake compiler config, this is normally the same config as above
  117. S:=GlobalOptions.CompilerConfigDir+GlobalOptions.FPMakeCompilerConfig;
  118. if FileExists(S) then
  119. begin
  120. Log(vDebug,SLogLoadingFPMakeCompilerConfig,[S]);
  121. FPMakeCompilerOptions.LoadCompilerFromFile(S)
  122. end
  123. else
  124. Error(SErrMissingCompilerConfig,[S]);
  125. end;
  126. procedure TMakeTool.ShowUsage;
  127. begin
  128. Writeln('Usage: ',Paramstr(0),' [options] <action> <package>');
  129. Writeln('Options:');
  130. Writeln(' -c --config Set compiler configuration to use');
  131. Writeln(' -h --help This help');
  132. Writeln(' -v --verbose Set verbosity');
  133. Writeln(' -g --global Force installation to global (system-wide) directory');
  134. Writeln(' -f --force Force installation also if the package is already installed');
  135. Writeln('Actions:');
  136. Writeln(' update Update packages list');
  137. Writeln(' avail List available packages');
  138. Writeln(' build Build package');
  139. Writeln(' compile Compile package');
  140. Writeln(' install Install package');
  141. Writeln(' archive Create archive of package');
  142. Writeln(' download Download package');
  143. Writeln(' convertmk Convert Makefile.fpc to fpmake.pp');
  144. // Writeln(' addconfig Add a compiler configuration for the supplied compiler');
  145. Halt(0);
  146. end;
  147. Constructor TMakeTool.Create;
  148. begin
  149. inherited Create(nil);
  150. ParaPackages:=TStringList.Create;
  151. ActionStack:=TActionStack.Create;
  152. end;
  153. Destructor TMakeTool.Destroy;
  154. begin
  155. FreeAndNil(ActionStack);
  156. FreeAndNil(ParaPackages);
  157. inherited Destroy;
  158. end;
  159. procedure TMakeTool.ProcessCommandLine;
  160. Function CheckOption(Index : Integer;Short,Long : String): Boolean;
  161. var
  162. O : String;
  163. begin
  164. O:=Paramstr(Index);
  165. Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
  166. end;
  167. Function OptionArg(Var Index : Integer) : String;
  168. Var
  169. P : Integer;
  170. begin
  171. if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
  172. begin
  173. If Index<ParamCount then
  174. begin
  175. Inc(Index);
  176. Result:=Paramstr(Index);
  177. end
  178. else
  179. Error(SErrNeedArgument,[Index,ParamStr(Index)]);
  180. end
  181. else If length(ParamStr(Index))>2 then
  182. begin
  183. P:=Pos('=',Paramstr(Index));
  184. If (P=0) then
  185. Error(SErrNeedArgument,[Index,ParamStr(Index)])
  186. else
  187. begin
  188. Result:=Paramstr(Index);
  189. Delete(Result,1,P);
  190. end;
  191. end;
  192. end;
  193. Var
  194. I : Integer;
  195. HasAction : Boolean;
  196. begin
  197. I:=0;
  198. HasAction:=false;
  199. // We can't use the TCustomApplication option handling,
  200. // because they cannot handle [general opts] [command] [cmd-opts] [args]
  201. While (I<ParamCount) do
  202. begin
  203. Inc(I);
  204. // Check options.
  205. if CheckOption(I,'c','config') then
  206. GlobalOptions.CompilerConfig:=OptionArg(I)
  207. else if CheckOption(I,'v','verbose') then
  208. Include(Verbosity,StringToVerbosity(OptionArg(I)))
  209. else if CheckOption(I,'g','global') then
  210. GlobalOptions.InstallGlobal:=true
  211. else if CheckOption(I,'h','help') then
  212. begin
  213. ShowUsage;
  214. halt(0);
  215. end
  216. else if (Length(Paramstr(i))>0) and (Paramstr(I)[1]='-') then
  217. Raise EMakeToolError.CreateFmt(SErrInvalidArgument,[I,ParamStr(i)])
  218. else
  219. // It's a command or target.
  220. begin
  221. if HasAction then
  222. ParaPackages.Add(Paramstr(i))
  223. else
  224. begin
  225. ParaAction:=Paramstr(i);
  226. HasAction:=true;
  227. end;
  228. end;
  229. end;
  230. if not HasAction then
  231. ShowUsage;
  232. end;
  233. procedure TMakeTool.DoRun;
  234. var
  235. ActionPackage : TFPPackage;
  236. OldCurrDir : String;
  237. Res : Boolean;
  238. i : Integer;
  239. begin
  240. OldCurrDir:=GetCurrentDir;
  241. Try
  242. LoadGlobalDefaults;
  243. ProcessCommandLine;
  244. MaybeCreateLocalDirs;
  245. LoadCompilerDefaults;
  246. // Load local repository, update first if this is a new installation
  247. if not FileExists(GlobalOptions.LocalPackagesFile) then
  248. pkghandler.ExecuteAction(nil,'update');
  249. LoadLocalRepository;
  250. LoadLocalStatus;
  251. if ParaPackages.Count=0 then
  252. begin
  253. Log(vDebug,SLogCommandLineAction,['[<currentdir>]',ParaAction]);
  254. res:=pkghandler.ExecuteAction(nil,ParaAction);
  255. end
  256. else
  257. begin
  258. // Process packages
  259. for i:=0 to ParaPackages.Count-1 do
  260. begin
  261. ActionPackage:=CurrentRepository.PackageByName(ParaPackages[i]);
  262. Log(vDebug,SLogCommandLineAction,['['+ActionPackage.Name+']',ParaAction]);
  263. res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
  264. if not res then
  265. break;
  266. end;
  267. end;
  268. Terminate;
  269. except
  270. On E : Exception do
  271. begin
  272. Writeln(StdErr,SErrRunning);
  273. Writeln(StdErr,E.Message);
  274. Halt(1);
  275. end;
  276. end;
  277. SetCurrentDir(OldCurrDir);
  278. end;
  279. begin
  280. With TMakeTool.Create do
  281. try
  282. run;
  283. finally
  284. Free;
  285. end;
  286. end.