pkgoptions.pp 17 KB

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