pkgoptions.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. {
  2. This file is part of the Free Pascal Utilities
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$mode objfpc}
  11. {$h+}
  12. unit pkgoptions;
  13. interface
  14. uses Classes, Sysutils, Inifiles, fprepos;
  15. Const
  16. ManifestFileName = 'manifest.xml';
  17. MirrorsFileName = 'mirrors.xml';
  18. PackagesFileName = 'packages.xml';
  19. VersionsFileName = 'versions-%s.dat';
  20. CurrentConfigVersion = 3;
  21. Type
  22. { TGlobalOptions }
  23. TGlobalOptions = Class(TPersistent)
  24. private
  25. FDirty : Boolean;
  26. FConfigVersion : Integer;
  27. FRemoteMirrorsURL,
  28. FRemoteRepository,
  29. FLocalRepository,
  30. FCompilerConfigDir,
  31. FArchivesDir,
  32. FBuildDir,
  33. FDownloader,
  34. FDefaultCompilerConfig,
  35. FFPMakeCompilerConfig : String;
  36. // Parameter options
  37. FCompilerConfig : String;
  38. FInstallGlobal : Boolean;
  39. function GetOptString(Index: integer): String;
  40. procedure SetOptString(Index: integer; const AValue: String);
  41. Public
  42. Constructor Create;
  43. Procedure InitGlobalDefaults;
  44. Procedure LoadGlobalFromFile(const AFileName : String);
  45. Procedure SaveGlobalToFile(const AFileName : String);
  46. Property Dirty : Boolean Read FDirty;
  47. Property ConfigVersion : Integer read FConfigVersion;
  48. function LocalPackagesFile:string;
  49. function LocalMirrorsFile:string;
  50. function LocalVersionsFile(const ACompilerConfig:String):string;
  51. Published
  52. Property RemoteMirrorsURL : String Index 0 Read GetOptString Write SetOptString;
  53. // 1 is unused
  54. Property RemoteRepository : String Index 2 Read GetOptString Write SetOptString;
  55. Property LocalRepository : String Index 3 Read GetOptString Write SetOptString;
  56. Property BuildDir : String Index 4 Read GetOptString Write SetOptString;
  57. Property ArchivesDir : String Index 5 Read GetOptString Write SetOptString;
  58. Property CompilerConfigDir : String Index 6 Read GetOptString Write SetOptString;
  59. Property DefaultCompilerConfig : String Index 8 Read GetOptString Write SetOptString;
  60. Property FPMakeCompilerConfig : String Index 9 Read GetOptString Write SetOptString;
  61. Property Downloader: String Index 10 Read GetOptString Write SetOptString;
  62. // Parameters
  63. Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
  64. Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
  65. end;
  66. { TCompilerOptions }
  67. TCompilerOptions = Class(TPersistent)
  68. private
  69. FDirty: Boolean;
  70. FConfigVersion : Integer;
  71. FCompiler,
  72. FCompilerVersion,
  73. FLocalInstallDir,
  74. FGlobalInstallDir : String;
  75. FCompilerCPU: TCPU;
  76. FCompilerOS: TOS;
  77. function GetOptString(Index: integer): String;
  78. procedure SetOptString(Index: integer; const AValue: String);
  79. procedure SetCompilerCPU(const AValue: TCPU);
  80. procedure SetCompilerOS(const AValue: TOS);
  81. Public
  82. Constructor Create;
  83. Procedure InitCompilerDefaults;
  84. Procedure LoadCompilerFromFile(const AFileName : String);
  85. Procedure SaveCompilerToFile(const AFileName : String);
  86. Property Dirty : Boolean Read FDirty;
  87. Property ConfigVersion : Integer read FConfigVersion;
  88. Function LocalUnitDir:string;
  89. Function GlobalUnitDir:string;
  90. Published
  91. Property Compiler : String Index 1 Read GetOptString Write SetOptString;
  92. Property CompilerTarget : String Index 2 Read GetOptString Write SetOptString;
  93. Property CompilerVersion : String Index 3 Read GetOptString Write SetOptString;
  94. Property GlobalInstallDir : String Index 4 Read GetOptString Write SetOptString;
  95. Property LocalInstallDir : String Index 5 Read GetOptString Write SetOptString;
  96. Property CompilerOS : TOS Read FCompilerOS Write SetCompilerOS;
  97. Property CompilerCPU : TCPU Read FCompilerCPU Write SetCompilerCPU;
  98. end;
  99. var
  100. GlobalOptions : TGlobalOptions;
  101. CompilerOptions : TCompilerOptions;
  102. FPMakeCompilerOptions : TCompilerOptions;
  103. Implementation
  104. uses
  105. pkgglobals,
  106. pkgmessages;
  107. Const
  108. DefaultMirrorsURL = 'http://www.freepascal.org/repository/'+MirrorsFileName;
  109. {$ifdef localrepository}
  110. DefaultRemoteRepository = 'file://'+{$I %HOME%}+'/repository/';
  111. {$else}
  112. DefaultRemoteRepository = 'auto';
  113. {$endif}
  114. // ini file keys
  115. SDefaults = 'Defaults';
  116. // All configs
  117. KeyConfigVersion = 'ConfigVersion';
  118. // Global config
  119. KeyRemoteMirrorsURL = 'RemoteMirrors';
  120. KeyRemoteRepository = 'RemoteRepository';
  121. KeyLocalRepository = 'LocalRepository';
  122. KeyArchivesDir = 'ArchivesDir';
  123. KeyBuildDir = 'BuildDir';
  124. KeyCompilerConfigDir = 'CompilerConfigDir';
  125. KeyCompilerConfig = 'CompilerConfig';
  126. KeyFPMakeCompilerConfig = 'FPMakeCompilerConfig';
  127. KeyDownloader = 'Downloader';
  128. // Compiler dependent config
  129. KeyGlobalInstallDir = 'GlobalInstallDir';
  130. KeyLocalInstallDir = 'LocalInstallDir';
  131. KeyCompiler = 'Compiler' ;
  132. KeyCompilerOS = 'OS';
  133. KeyCompilerCPU = 'CPU';
  134. KeyCompilerVersion = 'Version';
  135. {*****************************************************************************
  136. TGlobalOptions
  137. *****************************************************************************}
  138. constructor TGlobalOptions.Create;
  139. begin
  140. InitGlobalDefaults;
  141. end;
  142. function TGlobalOptions.GetOptString(Index: integer): String;
  143. begin
  144. Case Index of
  145. 0 : Result:=FRemoteMirrorsURL;
  146. 2 : Result:=FRemoteRepository;
  147. 3 : Result:=FLocalRepository;
  148. 4 : Result:=FBuildDir;
  149. 5 : Result:=FArchivesDir;
  150. 6 : Result:=FCompilerConfigDir;
  151. 8 : Result:=FDefaultCompilerConfig;
  152. 9 : Result:=FFPMakeCompilerConfig;
  153. 10 : Result:=FDownloader;
  154. else
  155. Error('Unknown option');
  156. end;
  157. end;
  158. procedure TGlobalOptions.SetOptString(Index: integer; const AValue: String);
  159. begin
  160. If AValue=GetOptString(Index) then
  161. Exit;
  162. Case Index of
  163. 1 : FRemoteMirrorsURL:=AValue;
  164. 2 : FRemoteRepository:=AValue;
  165. 3 : FLocalRepository:=AValue;
  166. 4 : FBuildDir:=FixPath(AValue);
  167. 5 : FArchivesDir:=FixPath(AValue);
  168. 6 : FCompilerConfigDir:=FixPath(AValue);
  169. 8 : FDefaultCompilerConfig:=AValue;
  170. 9 : FFPMakeCompilerConfig:=AValue;
  171. 10 : FDownloader:=AValue;
  172. else
  173. Error('Unknown option');
  174. end;
  175. FDirty:=True;
  176. end;
  177. function TGlobalOptions.LocalPackagesFile:string;
  178. begin
  179. Result:=FLocalRepository+PackagesFileName;
  180. end;
  181. function TGlobalOptions.LocalMirrorsFile:string;
  182. begin
  183. Result:=FLocalRepository+MirrorsFileName;
  184. end;
  185. function TGlobalOptions.LocalVersionsFile(const ACompilerConfig:String):string;
  186. begin
  187. Result:=FLocalRepository+Format(VersionsFileName,[ACompilerConfig]);
  188. end;
  189. Procedure TGlobalOptions.InitGlobalDefaults;
  190. begin
  191. FConfigVersion:=CurrentConfigVersion;
  192. // Retrieve Local fppkg directory
  193. {$ifdef unix}
  194. if IsSuperUser then
  195. begin
  196. if DirectoryExists('/usr/local/lib/fpc') then
  197. FLocalRepository:='/usr/local/lib/fpc/fppkg/'
  198. else
  199. FLocalRepository:='/usr/lib/fpc/fppkg/';
  200. end
  201. else
  202. FLocalRepository:=IncludeTrailingPathDelimiter(GetEnvironmentVariable('HOME'))+'.fppkg/';
  203. {$else}
  204. FLocalRepository:=IncludeTrailingPathDelimiter(GetAppConfigDir(IsSuperUser));
  205. {$endif}
  206. // Directories
  207. FBuildDir:=FLocalRepository+'build'+PathDelim;
  208. FArchivesDir:=FLocalRepository+'archives'+PathDelim;
  209. FCompilerConfigDir:=FLocalRepository+'config'+PathDelim;
  210. // Remote
  211. FRemoteMirrorsURL:=DefaultMirrorsURL;
  212. FRemoteRepository:=DefaultRemoteRepository;
  213. // Other config
  214. FDefaultCompilerConfig:='default';
  215. FFPMakeCompilerConfig:='default';
  216. // Downloader
  217. {$if defined(unix) or defined(windows)}
  218. FDownloader:='lnet';
  219. {$else}
  220. FDownloader:='base';
  221. {$endif}
  222. // Parameter defaults
  223. FCompilerConfig:=FDefaultCompilerConfig;
  224. FInstallGlobal:=False;
  225. end;
  226. procedure TGlobalOptions.LoadGlobalFromFile(const AFileName: String);
  227. Var
  228. Ini : TMemIniFile;
  229. begin
  230. try
  231. Ini:=TMemIniFile.Create(AFileName);
  232. With Ini do
  233. begin
  234. FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
  235. if (FConfigVersion<>CurrentConfigVersion) then
  236. begin
  237. Log(vlDebug,SLogUpgradingConfig,[AFileName]);
  238. FDirty:=true;
  239. if FConfigVersion<1 then
  240. begin
  241. FRemoteRepository:='auto';
  242. end;
  243. if FConfigVersion<3 then
  244. begin
  245. // Directories
  246. FBuildDir:=FLocalRepository+'build'+PathDelim;
  247. FArchivesDir:=FLocalRepository+'archives'+PathDelim;
  248. FCompilerConfigDir:=FLocalRepository+'config'+PathDelim;
  249. end;
  250. if (FConfigVersion>CurrentConfigVersion) then
  251. Error(SErrUnsupportedConfigVersion,[AFileName]);
  252. end;
  253. FRemoteMirrorsURL:=ReadString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
  254. {$warning Temporary Config check, can be removed in March-2008}
  255. if FConfigVersion>=1 then
  256. FRemoteRepository:=ReadString(SDefaults,KeyRemoteRepository,FRemoteRepository);
  257. FLocalRepository:=ReadString(SDefaults,KeyLocalRepository,FLocalRepository);
  258. FBuildDir:=FixPath(ReadString(SDefaults,KeyBuildDir,FBuildDir));
  259. FArchivesDir:=FixPath(ReadString(SDefaults,KeyArchivesDir,FArchivesDir));
  260. FCompilerConfigDir:=FixPath(ReadString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir));
  261. FDefaultCompilerConfig:=ReadString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
  262. FFPMakeCompilerConfig:=ReadString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
  263. FDownloader:=ReadString(SDefaults,KeyDownloader,FDownloader);
  264. end;
  265. finally
  266. Ini.Free;
  267. end;
  268. end;
  269. procedure TGlobalOptions.SaveGlobalToFile(const AFileName: String);
  270. Var
  271. Ini : TIniFile;
  272. begin
  273. if FileExists(AFileName) then
  274. BackupFile(AFileName);
  275. try
  276. Ini:=TIniFile.Create(AFileName);
  277. With Ini do
  278. begin
  279. WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
  280. WriteString(SDefaults,KeyBuildDir,FBuildDir);
  281. WriteString(SDefaults,KeyArchivesDir,FArchivesDir);
  282. WriteString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir);
  283. WriteString(SDefaults,KeyLocalRepository,FLocalRepository);
  284. WriteString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
  285. WriteString(SDefaults,KeyRemoteRepository,FRemoteRepository);
  286. WriteString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
  287. WriteString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
  288. WriteString(SDefaults,KeyDownloader,FDownloader);
  289. FDirty:=False;
  290. end;
  291. Ini.UpdateFile;
  292. finally
  293. Ini.Free;
  294. end;
  295. end;
  296. {*****************************************************************************
  297. TCompilerOptions
  298. *****************************************************************************}
  299. constructor TCompilerOptions.Create;
  300. begin
  301. end;
  302. function TCompilerOptions.GetOptString(Index: integer): String;
  303. begin
  304. Case Index of
  305. 1 : Result:=FCompiler;
  306. 2 : Result:=MakeTargetString(CompilerCPU,CompilerOS);
  307. 3 : Result:=FCompilerVersion;
  308. 4 : Result:=FGlobalInstallDir;
  309. 5 : Result:=FLocalInstallDir;
  310. else
  311. Error('Unknown option');
  312. end;
  313. end;
  314. procedure TCompilerOptions.SetOptString(Index: integer; const AValue: String);
  315. begin
  316. If AValue=GetOptString(Index) then
  317. Exit;
  318. Case Index of
  319. 1 : FCompiler:=AValue;
  320. 2 : StringToCPUOS(AValue,FCompilerCPU,FCompilerOS);
  321. 3 : FCompilerVersion:=AValue;
  322. 4 : FGlobalInstallDir:=FixPath(AValue);
  323. 5 : FLocalInstallDir:=FixPath(AValue);
  324. else
  325. Error('Unknown option');
  326. end;
  327. FDirty:=True;
  328. end;
  329. procedure TCompilerOptions.SetCompilerCPU(const AValue: TCPU);
  330. begin
  331. if FCompilerCPU=AValue then
  332. exit;
  333. FCompilerCPU:=AValue;
  334. FDirty:=True;
  335. end;
  336. procedure TCompilerOptions.SetCompilerOS(const AValue: TOS);
  337. begin
  338. if FCompilerOS=AValue then
  339. exit;
  340. FCompilerOS:=AValue;
  341. FDirty:=True;
  342. end;
  343. function TCompilerOptions.LocalUnitDir:string;
  344. begin
  345. if FLocalInstallDir<>'' then
  346. result:=FLocalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
  347. else
  348. result:='';
  349. end;
  350. function TCompilerOptions.GlobalUnitDir:string;
  351. begin
  352. if FGlobalInstallDir<>'' then
  353. result:=FGlobalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
  354. else
  355. result:='';
  356. end;
  357. procedure TCompilerOptions.InitCompilerDefaults;
  358. var
  359. infoSL : TStringList;
  360. begin
  361. FConfigVersion:=CurrentConfigVersion;
  362. FCompiler:=FileSearch('fpc'+ExeExt,GetEnvironmentVariable('PATH'));
  363. if FCompiler='' then
  364. Raise EPackagerError.Create(SErrMissingFPC);
  365. // Detect compiler version/target from -i option
  366. infosl:=TStringList.Create;
  367. infosl.Delimiter:=' ';
  368. infosl.DelimitedText:=GetCompilerInfo(FCompiler,'-iVTPTO');
  369. if infosl.Count<>3 then
  370. Raise EPackagerError.Create(SErrInvalidFPCInfo);
  371. FCompilerVersion:=infosl[0];
  372. FCompilerCPU:=StringToCPU(infosl[1]);
  373. FCompilerOS:=StringToOS(infosl[2]);
  374. // Temporary hack to workaround bug in fpc.exe that doesn't support spaces
  375. // We retrieve the real binary
  376. if FCompilerVersion='2.2.0' then
  377. FCompiler:=GetCompilerInfo(FCompiler,'-PB');
  378. Log(vlDebug,SLogDetectedCompiler,[FCompiler,FCompilerVersion,MakeTargetString(FCompilerCPU,FCompilerOS)]);
  379. // Use the same algorithm as the compiler, see options.pas
  380. {$ifdef Unix}
  381. FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
  382. if FGlobalInstallDir='' then
  383. begin
  384. FGlobalInstallDir:='/usr/local/lib/fpc/'+FCompilerVersion+'/';
  385. if not DirectoryExists(FGlobalInstallDir) and
  386. DirectoryExists('/usr/lib/fpc/'+FCompilerVersion) then
  387. FGlobalInstallDir:='/usr/lib/fpc/'+FCompilerVersion+'/';
  388. end;
  389. {$else unix}
  390. FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
  391. if FGlobalInstallDir='' then
  392. begin
  393. FGlobalInstallDir:=ExtractFilePath(FCompiler)+'../';
  394. if not(DirectoryExists(FGlobalInstallDir+'/units')) and
  395. not(DirectoryExists(FGlobalInstallDir+'/rtl')) then
  396. FGlobalInstallDir:=FGlobalInstallDir+'../';
  397. end;
  398. FGlobalInstallDir:=ExpandFileName(FGlobalInstallDir);
  399. {$endif unix}
  400. Log(vlDebug,SLogDetectedFPCDIR,['global',FGlobalInstallDir]);
  401. // User writable install directory
  402. if not IsSuperUser then
  403. begin
  404. FLocalInstallDir:=GlobalOptions.LocalRepository+'lib'+PathDelim+FCompilerVersion+PathDelim;
  405. Log(vlDebug,SLogDetectedFPCDIR,['local',FLocalInstallDir]);
  406. end;
  407. end;
  408. procedure TCompilerOptions.LoadCompilerFromFile(const AFileName: String);
  409. Var
  410. Ini : TMemIniFile;
  411. begin
  412. try
  413. Ini:=TMemIniFile.Create(AFileName);
  414. With Ini do
  415. begin
  416. FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
  417. if (FConfigVersion<>CurrentConfigVersion) then
  418. begin
  419. Log(vlDebug,SLogUpgradingConfig,[AFileName]);
  420. FDirty:=true;
  421. if (FConfigVersion>CurrentConfigVersion) then
  422. Error(SErrUnsupportedConfigVersion,[AFileName]);
  423. end;
  424. FGlobalInstallDir:=FixPath(ReadString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir));
  425. FLocalInstallDir:=FixPath(ReadString(SDefaults,KeyLocalInstallDir,FLocalInstallDir));
  426. FCompiler:=ReadString(SDefaults,KeyCompiler,FCompiler);
  427. FCompilerOS:=StringToOS(ReadString(SDefaults,KeyCompilerOS,OSToString(CompilerOS)));
  428. FCompilerCPU:=StringToCPU(ReadString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU)));
  429. FCompilerVersion:=ReadString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  430. end;
  431. finally
  432. Ini.Free;
  433. end;
  434. end;
  435. procedure TCompilerOptions.SaveCompilerToFile(const AFileName: String);
  436. Var
  437. Ini : TIniFile;
  438. begin
  439. if FileExists(AFileName) then
  440. BackupFile(AFileName);
  441. try
  442. Ini:=TIniFile.Create(AFileName);
  443. With Ini do
  444. begin
  445. WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
  446. WriteString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir);
  447. WriteString(SDefaults,KeyLocalInstallDir,FLocalInstallDir);
  448. WriteString(SDefaults,KeyCompiler,FCompiler);
  449. WriteString(SDefaults,KeyCompilerOS,OSToString(CompilerOS));
  450. WriteString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU));
  451. WriteString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  452. FDirty:=False;
  453. end;
  454. Ini.UpdateFile;
  455. finally
  456. Ini.Free;
  457. end;
  458. end;
  459. initialization
  460. GlobalOptions:=TGlobalOptions.Create;
  461. CompilerOptions:=TCompilerOptions.Create;
  462. FPMakeCompilerOptions:=TCompilerOptions.Create;
  463. finalization
  464. FreeAndNil(GlobalOptions);
  465. FreeAndNil(CompilerOptions);
  466. FreeAndNil(FPMakeCompilerOptions);
  467. end.