pkgoptions.pp 17 KB

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