pkgoptions.pp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  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, fpTemplate, pkgglobals;
  15. Const
  16. UnitConfigFileName = 'fpunits.cfg';
  17. ManifestFileName = 'manifest.xml';
  18. MirrorsFileName = 'mirrors.xml';
  19. PackagesFileName = 'packages.xml';
  20. VersionsFileName = 'versions-%s.dat';
  21. CurrentConfigVersion = 4;
  22. Type
  23. { TGlobalOptions }
  24. TGlobalOptions = Class(TPersistent)
  25. private
  26. FConfigFilename: string;
  27. FSaveInifileChanges : Boolean;
  28. FConfigVersion : Integer;
  29. FRemoteMirrorsURL,
  30. FRemoteRepository,
  31. FLocalRepository,
  32. FCompilerConfigDir,
  33. FArchivesDir,
  34. FBuildDir,
  35. FDownloader,
  36. FDefaultCompilerConfig,
  37. FFPMakeCompilerConfig : String;
  38. // Parameter options
  39. FCompilerConfig : String;
  40. FAllowBroken,
  41. FInstallGlobal,
  42. FRecoveryMode : Boolean;
  43. FOptionParser: TTemplateParser;
  44. FShowLocation: Boolean;
  45. FSkipConfigurationFiles: boolean;
  46. FSkipFixBrokenAfterInstall: boolean;
  47. FCustomFPMakeOptions : string;
  48. function GetOptString(Index: integer): String;
  49. procedure SetOptString(Index: integer; const AValue: String);
  50. procedure UpdateLocalRepositoryOption;
  51. Public
  52. Constructor Create;
  53. destructor Destroy; override;
  54. Procedure InitGlobalDefaults;
  55. Procedure LoadGlobalFromFile(const AFileName : String);
  56. Procedure SaveGlobalToFile(const AFileName : String);
  57. procedure LogValues(ALogLevel: TLogLevel);
  58. // Is set when the inifile has an old version number (which is also the case when a new file is generated)
  59. Property SaveInifileChanges : Boolean Read FSaveInifileChanges;
  60. Property ConfigVersion : Integer read FConfigVersion;
  61. function LocalPackagesFile:string;
  62. function LocalMirrorsFile:string;
  63. function LocalVersionsFile(const ACompilerConfig:String):string;
  64. Published
  65. Property RemoteMirrorsURL : String Index 0 Read GetOptString Write SetOptString;
  66. // 1 is unused
  67. Property RemoteRepository : String Index 2 Read GetOptString Write SetOptString;
  68. Property LocalRepository : String Index 3 Read GetOptString Write SetOptString;
  69. Property BuildDir : String Index 4 Read GetOptString Write SetOptString;
  70. Property ArchivesDir : String Index 5 Read GetOptString Write SetOptString;
  71. Property CompilerConfigDir : String Index 6 Read GetOptString Write SetOptString;
  72. Property DefaultCompilerConfig : String Index 8 Read GetOptString Write SetOptString;
  73. Property FPMakeCompilerConfig : String Index 9 Read GetOptString Write SetOptString;
  74. Property Downloader: String Index 10 Read GetOptString Write SetOptString;
  75. Property CustomFPMakeOptions: String Index 11 Read GetOptString Write SetOptString;
  76. // Parameters
  77. Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
  78. Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
  79. Property RecoveryMode : Boolean Read FRecoveryMode Write FRecoveryMode;
  80. Property AllowBroken : Boolean Read FAllowBroken Write FAllowBroken;
  81. Property ShowLocation : Boolean Read FShowLocation Write FShowLocation;
  82. Property SkipConfigurationFiles: boolean read FSkipConfigurationFiles write FSkipConfigurationFiles;
  83. Property SkipFixBrokenAfterInstall: boolean read FSkipFixBrokenAfterInstall write FSkipFixBrokenAfterInstall;
  84. end;
  85. { TCompilerOptions }
  86. TCompilerOptions = Class(TPersistent)
  87. private
  88. FConfigFilename: string;
  89. FSaveInifileChanges: Boolean;
  90. FConfigVersion : Integer;
  91. FCompiler,
  92. FCompilerVersion,
  93. FLocalInstallDir,
  94. FGlobalInstallDir,
  95. FLocalPrefix,
  96. FGlobalPrefix: String;
  97. FCompilerCPU: TCPU;
  98. FCompilerOS: TOS;
  99. FOptionParser: TTemplateParser;
  100. FOptions: TStrings;
  101. function GetOptions: TStrings;
  102. function GetOptString(Index: integer): String;
  103. procedure SetOptString(Index: integer; const AValue: String);
  104. procedure SetCompilerCPU(const AValue: TCPU);
  105. procedure SetCompilerOS(const AValue: TOS);
  106. Public
  107. Constructor Create;
  108. Destructor Destroy; override;
  109. Procedure InitCompilerDefaults;
  110. Procedure LoadCompilerFromFile(const AFileName : String);
  111. Procedure SaveCompilerToFile(const AFileName : String);
  112. procedure LogValues(ALogLevel: TLogLevel; const ACfgName:string);
  113. procedure UpdateLocalRepositoryOption;
  114. procedure CheckCompilerValues;
  115. Function LocalUnitDir:string;
  116. Function GlobalUnitDir:string;
  117. Function HasOptions: boolean;
  118. // Is set when the inifile has an old version number (which is also the case when a new file is generated)
  119. Property SaveInifileChanges : Boolean Read FSaveInifileChanges;
  120. Property ConfigVersion : Integer read FConfigVersion;
  121. Published
  122. Property Compiler : String Index 1 Read GetOptString Write SetOptString;
  123. Property CompilerTarget : String Index 2 Read GetOptString Write SetOptString;
  124. Property CompilerVersion : String Index 3 Read GetOptString Write SetOptString;
  125. Property GlobalInstallDir : String Index 4 Read GetOptString Write SetOptString;
  126. Property LocalInstallDir : String Index 5 Read GetOptString Write SetOptString;
  127. Property GlobalPrefix : String Index 6 Read GetOptString Write SetOptString;
  128. Property LocalPrefix : String Index 7 Read GetOptString Write SetOptString;
  129. Property Options : TStrings read GetOptions;
  130. Property CompilerOS : TOS Read FCompilerOS Write SetCompilerOS;
  131. Property CompilerCPU : TCPU Read FCompilerCPU Write SetCompilerCPU;
  132. end;
  133. var
  134. GlobalOptions : TGlobalOptions;
  135. CompilerOptions : TCompilerOptions;
  136. FPMakeCompilerOptions : TCompilerOptions;
  137. procedure LoadGlobalDefaults(CfgFile: string);
  138. procedure LoadCompilerDefaults;
  139. Implementation
  140. uses
  141. pkgmessages;
  142. Const
  143. DefaultMirrorsURL = 'http://www.freepascal.org/repository/'+MirrorsFileName;
  144. {$ifdef localrepository}
  145. DefaultRemoteRepository = 'file://'+{$I %HOME%}+'/repository/';
  146. {$else}
  147. DefaultRemoteRepository = 'auto';
  148. {$endif}
  149. // ini file keys
  150. SDefaults = 'Defaults';
  151. // All configs
  152. KeyConfigVersion = 'ConfigVersion';
  153. // Global config
  154. KeyRemoteMirrorsURL = 'RemoteMirrors';
  155. KeyRemoteRepository = 'RemoteRepository';
  156. KeyLocalRepository = 'LocalRepository';
  157. KeyArchivesDir = 'ArchivesDir';
  158. KeyBuildDir = 'BuildDir';
  159. KeyCompilerConfigDir = 'CompilerConfigDir';
  160. KeyCompilerConfig = 'CompilerConfig';
  161. KeyFPMakeCompilerConfig = 'FPMakeCompilerConfig';
  162. KeyDownloader = 'Downloader';
  163. KeyCustomFPMakeOptions = 'FPMakeOptions';
  164. // Compiler dependent config
  165. KeyGlobalPrefix = 'GlobalPrefix';
  166. KeyLocalPrefix = 'LocalPrefix';
  167. KeyGlobalInstallDir = 'GlobalInstallDir';
  168. KeyLocalInstallDir = 'LocalInstallDir';
  169. KeyCompiler = 'Compiler' ;
  170. KeyCompilerOS = 'OS';
  171. KeyCompilerCPU = 'CPU';
  172. KeyCompilerVersion = 'Version';
  173. procedure LoadGlobalDefaults(CfgFile: string);
  174. var
  175. i : integer;
  176. GeneratedConfig,
  177. UseGlobalConfig : boolean;
  178. begin
  179. GeneratedConfig:=false;
  180. UseGlobalConfig:=false;
  181. // First try specified config file
  182. if (CfgFile<>'') then
  183. begin
  184. if not FileExists(cfgfile) then
  185. Error(SErrNoSuchFile,[cfgfile]);
  186. end
  187. else
  188. begin
  189. // Now try if a local config-file exists
  190. cfgfile:=GetAppConfigFile(False,False);
  191. if not FileExists(cfgfile) then
  192. begin
  193. // If not, try to find a global configuration file
  194. cfgfile:=GetAppConfigFile(True,False);
  195. if FileExists(cfgfile) then
  196. UseGlobalConfig := true
  197. else
  198. begin
  199. // Create a new configuration file
  200. if not IsSuperUser then // Make a local, not global, configuration file
  201. cfgfile:=GetAppConfigFile(False,False);
  202. ForceDirectories(ExtractFilePath(cfgfile));
  203. GlobalOptions.SaveGlobalToFile(cfgfile);
  204. GeneratedConfig:=true;
  205. end;
  206. end;
  207. end;
  208. // Load file or create new default configuration
  209. if not GeneratedConfig then
  210. begin
  211. GlobalOptions.LoadGlobalFromFile(cfgfile);
  212. if GlobalOptions.SaveInifileChanges and (not UseGlobalConfig or IsSuperUser) then
  213. GlobalOptions.SaveGlobalToFile(cfgfile);
  214. end;
  215. GlobalOptions.CompilerConfig:=GlobalOptions.DefaultCompilerConfig;
  216. // Tracing of what we've done above, need to be done after the verbosity is set
  217. if GeneratedConfig then
  218. pkgglobals.Log(vlDebug,SLogGeneratingGlobalConfig,[cfgfile])
  219. else
  220. pkgglobals.Log(vlDebug,SLogLoadingGlobalConfig,[cfgfile]);
  221. // Log configuration
  222. GlobalOptions.LogValues(vlDebug);
  223. end;
  224. procedure LoadCompilerDefaults;
  225. var
  226. S : String;
  227. begin
  228. // Load default compiler config
  229. S:=GlobalOptions.CompilerConfigDir+GlobalOptions.CompilerConfig;
  230. CompilerOptions.UpdateLocalRepositoryOption;
  231. if FileExists(S) then
  232. begin
  233. pkgglobals.Log(vlDebug,SLogLoadingCompilerConfig,[S]);
  234. CompilerOptions.LoadCompilerFromFile(S)
  235. end
  236. else
  237. begin
  238. // Generate a default configuration if it doesn't exists
  239. if GlobalOptions.CompilerConfig='default' then
  240. begin
  241. pkgglobals.Log(vlDebug,SLogGeneratingCompilerConfig,[S]);
  242. CompilerOptions.InitCompilerDefaults;
  243. CompilerOptions.SaveCompilerToFile(S);
  244. if CompilerOptions.SaveInifileChanges then
  245. CompilerOptions.SaveCompilerToFile(S);
  246. end
  247. else
  248. Error(SErrMissingCompilerConfig,[S]);
  249. end;
  250. // Log compiler configuration
  251. CompilerOptions.LogValues(vlDebug,'');
  252. // Load FPMake compiler config, this is normally the same config as above
  253. S:=GlobalOptions.CompilerConfigDir+GlobalOptions.FPMakeCompilerConfig;
  254. FPMakeCompilerOptions.UpdateLocalRepositoryOption;
  255. if FileExists(S) then
  256. begin
  257. pkgglobals.Log(vlDebug,SLogLoadingFPMakeCompilerConfig,[S]);
  258. FPMakeCompilerOptions.LoadCompilerFromFile(S);
  259. if FPMakeCompilerOptions.SaveInifileChanges then
  260. FPMakeCompilerOptions.SaveCompilerToFile(S);
  261. end
  262. else
  263. Error(SErrMissingCompilerConfig,[S]);
  264. // Log compiler configuration
  265. FPMakeCompilerOptions.LogValues(vlDebug,'fpmake-building ');
  266. end;
  267. {*****************************************************************************
  268. TGlobalOptions
  269. *****************************************************************************}
  270. constructor TGlobalOptions.Create;
  271. begin
  272. FOptionParser := TTemplateParser.Create;
  273. FOptionParser.Values['AppConfigDir'] := GetAppConfigDir(false);
  274. FOptionParser.Values['UserDir'] := GetUserDir;
  275. InitGlobalDefaults;
  276. end;
  277. destructor TGlobalOptions.Destroy;
  278. begin
  279. FOptionParser.Free;
  280. inherited Destroy;
  281. end;
  282. function TGlobalOptions.GetOptString(Index: integer): String;
  283. begin
  284. Case Index of
  285. 0 : Result:=FRemoteMirrorsURL;
  286. 2 : Result:=FRemoteRepository;
  287. 3 : Result:=FOptionParser.ParseString(FLocalRepository);
  288. 4 : Result:=FOptionParser.ParseString(FBuildDir);
  289. 5 : Result:=FOptionParser.ParseString(FArchivesDir);
  290. 6 : Result:=FOptionParser.ParseString(FCompilerConfigDir);
  291. 8 : Result:=FDefaultCompilerConfig;
  292. 9 : Result:=FFPMakeCompilerConfig;
  293. 10 : Result:=FDownloader;
  294. 11 : Result:=FCustomFPMakeOptions;
  295. else
  296. Error('Unknown option');
  297. end;
  298. end;
  299. procedure TGlobalOptions.SetOptString(Index: integer; const AValue: String);
  300. begin
  301. If AValue=GetOptString(Index) then
  302. Exit;
  303. Case Index of
  304. 1 : FRemoteMirrorsURL:=AValue;
  305. 2 : FRemoteRepository:=AValue;
  306. 3 : begin
  307. FLocalRepository:=AValue;
  308. UpdateLocalRepositoryOption;
  309. end;
  310. 4 : FBuildDir:=FixPath(AValue);
  311. 5 : FArchivesDir:=FixPath(AValue);
  312. 6 : FCompilerConfigDir:=FixPath(AValue);
  313. 8 : FDefaultCompilerConfig:=AValue;
  314. 9 : FFPMakeCompilerConfig:=AValue;
  315. 10 : FDownloader:=AValue;
  316. 11 : FCustomFPMakeOptions:=AValue;
  317. else
  318. Error('Unknown option');
  319. end;
  320. end;
  321. procedure TGlobalOptions.UpdateLocalRepositoryOption;
  322. begin
  323. FOptionParser.Values['LocalRepository'] := LocalRepository;
  324. end;
  325. function TGlobalOptions.LocalPackagesFile:string;
  326. begin
  327. Result:=LocalRepository+PackagesFileName;
  328. end;
  329. function TGlobalOptions.LocalMirrorsFile:string;
  330. begin
  331. Result:=LocalRepository+MirrorsFileName;
  332. end;
  333. function TGlobalOptions.LocalVersionsFile(const ACompilerConfig:String):string;
  334. begin
  335. Result:=LocalRepository+Format(VersionsFileName,[ACompilerConfig]);
  336. end;
  337. Procedure TGlobalOptions.InitGlobalDefaults;
  338. var
  339. i: Integer;
  340. begin
  341. FConfigVersion:=CurrentConfigVersion;
  342. // Retrieve Local fppkg directory
  343. {$ifdef unix}
  344. if IsSuperUser then
  345. begin
  346. if DirectoryExists('/usr/local/lib/fpc') then
  347. FLocalRepository:='/usr/local/lib/fpc/fppkg/'
  348. else
  349. FLocalRepository:='/usr/lib/fpc/fppkg/';
  350. end
  351. else
  352. FLocalRepository:='{UserDir}.fppkg/';
  353. {$else}
  354. if IsSuperUser then
  355. FLocalRepository:=IncludeTrailingPathDelimiter(GetAppConfigDir(true))
  356. else
  357. FLocalRepository:='{AppConfigDir}';
  358. {$endif}
  359. UpdateLocalRepositoryOption;
  360. // Directories
  361. FBuildDir:='{LocalRepository}build'+PathDelim;
  362. FArchivesDir:='{LocalRepository}archives'+PathDelim;
  363. FCompilerConfigDir:='{LocalRepository}config'+PathDelim;
  364. // Remote
  365. FRemoteMirrorsURL:=DefaultMirrorsURL;
  366. FRemoteRepository:=DefaultRemoteRepository;
  367. // Other config
  368. FDefaultCompilerConfig:='default';
  369. FFPMakeCompilerConfig:='default';
  370. // Downloader
  371. {$if defined(unix) or defined(windows)}
  372. FDownloader:='lnet';
  373. {$else}
  374. FDownloader:='base';
  375. {$endif}
  376. // Parameter defaults
  377. FCompilerConfig:=FDefaultCompilerConfig;
  378. FInstallGlobal:=False;
  379. FRecoveryMode:=False;
  380. FAllowBroken:=False;
  381. SetLength(FPMKUnitDeps,FPMKUnitDepDefaultCount);
  382. for i := 0 to FPMKUnitDepDefaultCount-1 do
  383. FPMKUnitDeps[i]:=FPMKUnitDepsDefaults[i];
  384. end;
  385. procedure TGlobalOptions.LoadGlobalFromFile(const AFileName: String);
  386. Var
  387. Ini : TMemIniFile;
  388. begin
  389. Ini:=TMemIniFile.Create(AFileName);
  390. try
  391. FConfigFileName:=AFileName;
  392. With Ini do
  393. begin
  394. FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
  395. if (FConfigVersion<>CurrentConfigVersion) then
  396. begin
  397. log(vlDebug,SLogUpgradingConfig,[AFileName]);
  398. FSaveInifileChanges:=true;
  399. if FConfigVersion<1 then
  400. begin
  401. FRemoteRepository:='auto';
  402. end;
  403. if FConfigVersion<3 then
  404. begin
  405. // Directories
  406. FBuildDir:=FLocalRepository+'build'+PathDelim;
  407. FArchivesDir:=FLocalRepository+'archives'+PathDelim;
  408. FCompilerConfigDir:=FLocalRepository+'config'+PathDelim;
  409. end;
  410. if (FConfigVersion>CurrentConfigVersion) then
  411. Error(SErrUnsupportedConfigVersion,[AFileName]);
  412. end;
  413. FRemoteMirrorsURL:=ReadString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
  414. FRemoteRepository:=ReadString(SDefaults,KeyRemoteRepository,FRemoteRepository);
  415. FLocalRepository:=ReadString(SDefaults,KeyLocalRepository,FLocalRepository);
  416. UpdateLocalRepositoryOption;
  417. FBuildDir:=FixPath(ReadString(SDefaults,KeyBuildDir,FBuildDir));
  418. FArchivesDir:=FixPath(ReadString(SDefaults,KeyArchivesDir,FArchivesDir));
  419. FCompilerConfigDir:=FixPath(ReadString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir));
  420. FDefaultCompilerConfig:=ReadString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
  421. FFPMakeCompilerConfig:=ReadString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
  422. FDownloader:=ReadString(SDefaults,KeyDownloader,FDownloader);
  423. FCustomFPMakeOptions:=ReadString(SDefaults,KeyCustomFPMakeOptions,FCustomFPMakeOptions);
  424. end;
  425. finally
  426. Ini.Free;
  427. end;
  428. end;
  429. procedure TGlobalOptions.SaveGlobalToFile(const AFileName: String);
  430. Var
  431. Ini : TIniFile;
  432. begin
  433. if FileExists(AFileName) then
  434. BackupFile(AFileName);
  435. Ini:=TIniFile.Create(AFileName);
  436. try
  437. With Ini do
  438. begin
  439. WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
  440. WriteString(SDefaults,KeyLocalRepository,FLocalRepository);
  441. WriteString(SDefaults,KeyBuildDir,FBuildDir);
  442. WriteString(SDefaults,KeyArchivesDir,FArchivesDir);
  443. WriteString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir);
  444. WriteString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
  445. WriteString(SDefaults,KeyRemoteRepository,FRemoteRepository);
  446. WriteString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
  447. WriteString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
  448. WriteString(SDefaults,KeyDownloader,FDownloader);
  449. FSaveInifileChanges:=False;
  450. end;
  451. Ini.UpdateFile;
  452. finally
  453. Ini.Free;
  454. end;
  455. end;
  456. procedure TGlobalOptions.LogValues(ALogLevel: TLogLevel);
  457. begin
  458. log(ALogLevel,SLogGlobalCfgHeader,[FConfigFilename]);
  459. log(ALogLevel,SLogGlobalCfgRemoteMirrorsURL,[FRemoteMirrorsURL]);
  460. log(ALogLevel,SLogGlobalCfgRemoteRepository,[FRemoteRepository]);
  461. log(ALogLevel,SLogGlobalCfgLocalRepository,[FLocalRepository,LocalRepository]);
  462. log(ALogLevel,SLogGlobalCfgBuildDir,[FBuildDir,BuildDir]);
  463. log(ALogLevel,SLogGlobalCfgArchivesDir,[FArchivesDir,ArchivesDir]);
  464. log(ALogLevel,SLogGlobalCfgCompilerConfigDir,[FCompilerConfigDir,CompilerConfigDir]);
  465. log(ALogLevel,SLogGlobalCfgDefaultCompilerConfig,[FDefaultCompilerConfig]);
  466. log(ALogLevel,SLogGlobalCfgFPMakeCompilerConfig,[FPMakeCompilerConfig]);
  467. log(ALogLevel,SLogGlobalCfgDownloader,[FDownloader]);
  468. end;
  469. {*****************************************************************************
  470. TCompilerOptions
  471. *****************************************************************************}
  472. constructor TCompilerOptions.Create;
  473. begin
  474. FOptionParser := TTemplateParser.Create;
  475. FOptionParser.Values['AppConfigDir'] := GetAppConfigDir(false);
  476. FOptionParser.Values['UserDir'] := GetUserDir;
  477. {$ifdef unix}
  478. FLocalInstallDir:='{LocalPrefix}'+'lib'+PathDelim+'fpc'+PathDelim+'{CompilerVersion}'+PathDelim;
  479. FGlobalInstallDir:='{GlobalPrefix}'+'lib'+PathDelim+'fpc'+PathDelim+'{CompilerVersion}'+PathDelim;
  480. {$else unix}
  481. FLocalInstallDir:='{LocalPrefix}';
  482. FGlobalInstallDir:='{GlobalPrefix}';
  483. {$endif}
  484. end;
  485. destructor TCompilerOptions.Destroy;
  486. begin
  487. FOptionParser.Free;
  488. if assigned(FOptions) then
  489. FreeAndNil(FOptions);
  490. inherited Destroy;
  491. end;
  492. function TCompilerOptions.GetOptString(Index: integer): String;
  493. begin
  494. Case Index of
  495. 1 : Result:=FCompiler;
  496. 2 : Result:=MakeTargetString(CompilerCPU,CompilerOS);
  497. 3 : Result:=FCompilerVersion;
  498. 4 : Result:=FOptionParser.ParseString(FGlobalInstallDir);
  499. 5 : Result:=FOptionParser.ParseString(FLocalInstallDir);
  500. 6 : Result:=FixPath(FOptionParser.ParseString(FGlobalPrefix));
  501. 7 : Result:=FixPath(FOptionParser.ParseString(FLocalPrefix));
  502. else
  503. Error('Unknown option');
  504. end;
  505. end;
  506. function TCompilerOptions.GetOptions: TStrings;
  507. begin
  508. if not assigned(FOptions) then
  509. begin
  510. FOptions := TStringList.Create;
  511. FOptions.Delimiter:=' ';
  512. end;
  513. Result := FOptions;
  514. end;
  515. procedure TCompilerOptions.SetOptString(Index: integer; const AValue: String);
  516. begin
  517. If AValue=GetOptString(Index) then
  518. Exit;
  519. Case Index of
  520. 1 : FCompiler:=AValue;
  521. 2 : StringToCPUOS(AValue,FCompilerCPU,FCompilerOS);
  522. 3 : begin
  523. FCompilerVersion:=AValue;
  524. FOptionParser.Values['CompilerVersion'] := FCompilerVersion;
  525. end;
  526. 4 : FGlobalInstallDir:=FixPath(AValue);
  527. 5 : FLocalInstallDir:=FixPath(AValue);
  528. 6 : begin
  529. FGlobalPrefix:=AValue;
  530. FOptionParser.Values['GlobalPrefix'] := GlobalPrefix;
  531. end;
  532. 7 : begin
  533. FLocalPrefix:=AValue;
  534. FOptionParser.Values['LocalPrefix'] := LocalPrefix;
  535. end
  536. else
  537. Error('Unknown option');
  538. end;
  539. end;
  540. procedure TCompilerOptions.SetCompilerCPU(const AValue: TCPU);
  541. begin
  542. if FCompilerCPU=AValue then
  543. exit;
  544. FCompilerCPU:=AValue;
  545. end;
  546. procedure TCompilerOptions.UpdateLocalRepositoryOption;
  547. begin
  548. FOptionParser.Values['LocalRepository'] := GlobalOptions.LocalRepository;
  549. end;
  550. procedure TCompilerOptions.CheckCompilerValues;
  551. var
  552. AVersion : string;
  553. ACpu : TCpu;
  554. AOs : TOS;
  555. begin
  556. if Compiler='' then
  557. Exit;
  558. if (CompilerCPU=cpuNone) or
  559. (CompilerOS=osNone) or
  560. (CompilerVersion='') then
  561. begin
  562. GetCompilerInfo(Compiler,'-iVTPTO',AVersion,ACpu,AOs);
  563. if CompilerCPU=cpuNone then
  564. CompilerCPU := ACpu;
  565. if CompilerOS=osNone then
  566. CompilerOS:=AOs;
  567. if CompilerVersion='' then
  568. CompilerVersion:=AVersion;
  569. end;
  570. end;
  571. procedure TCompilerOptions.SetCompilerOS(const AValue: TOS);
  572. begin
  573. if FCompilerOS=AValue then
  574. exit;
  575. FCompilerOS:=AValue;
  576. end;
  577. function TCompilerOptions.LocalUnitDir:string;
  578. var ALocalInstallDir: string;
  579. begin
  580. ALocalInstallDir:=LocalInstallDir;
  581. if ALocalInstallDir<>'' then
  582. result:=ALocalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
  583. else
  584. result:='';
  585. end;
  586. function TCompilerOptions.GlobalUnitDir:string;
  587. var AGlobalInstallDir: string;
  588. begin
  589. AGlobalInstallDir:=GlobalInstallDir;
  590. if AGlobalInstallDir<>'' then
  591. result:=AGlobalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
  592. else
  593. result:='';
  594. end;
  595. function TCompilerOptions.HasOptions: boolean;
  596. begin
  597. result := assigned(FOptions);
  598. end;
  599. procedure TCompilerOptions.InitCompilerDefaults;
  600. var
  601. ACompilerVersion: string;
  602. fpcdir: string;
  603. begin
  604. FConfigVersion:=CurrentConfigVersion;
  605. if fcompiler = '' then
  606. FCompiler:=ExeSearch('fpc'+ExeExt,GetEnvironmentVariable('PATH'));
  607. if FCompiler='' then
  608. Raise EPackagerError.Create(SErrMissingFPC);
  609. // Detect compiler version/target from -i option
  610. GetCompilerInfo(FCompiler,'-iVTPTO',ACompilerVersion,FCompilerCPU,FCompilerOS);
  611. CompilerVersion := ACompilerVersion;
  612. // Temporary hack to workaround bug in fpc.exe that doesn't support spaces
  613. // We retrieve the real binary
  614. if FCompilerVersion='2.2.0' then
  615. FCompiler:=GetCompilerInfo(FCompiler,'-PB');
  616. log(vlDebug,SLogDetectedCompiler,[FCompiler,FCompilerVersion,MakeTargetString(FCompilerCPU,FCompilerOS)]);
  617. // Use the same algorithm as the compiler, see options.pas
  618. // Except that the prefix is extracted and GlobalInstallDir is set using
  619. // that prefix
  620. {$ifdef Unix}
  621. FGlobalPrefix:='/usr/local/';
  622. if not DirectoryExists(FGlobalPrefix+'lib/fpc/'+FCompilerVersion+'/') and
  623. DirectoryExists('/usr/lib/fpc/'+FCompilerVersion+'/') then
  624. FGlobalPrefix:='/usr/';
  625. {$else unix}
  626. FGlobalPrefix:=ExtractFilePath(FCompiler)+'..'+PathDelim;
  627. if not(DirectoryExists(FGlobalPrefix+PathDelim+'units')) and
  628. not(DirectoryExists(FGlobalPrefix+PathDelim+'rtl')) then
  629. FGlobalPrefix:=FGlobalPrefix+'..'+PathDelim;
  630. FGlobalPrefix:=ExpandFileName(FGlobalPrefix);
  631. {$endif unix}
  632. log(vlDebug,SLogDetectedPrefix,['global',FGlobalPrefix]);
  633. // User writable install directory
  634. if not IsSuperUser then
  635. begin
  636. FLocalPrefix:= '{LocalRepository}';
  637. log(vlDebug,SLogDetectedPrefix,['local',FLocalPrefix]);
  638. end;
  639. fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'));
  640. if fpcdir<>'' then
  641. begin
  642. {$ifndef Unix}
  643. fpcdir:=ExpandFileName(fpcdir);
  644. {$endif unix}
  645. log(vlDebug,SLogFPCDirEnv,[fpcdir]);
  646. FGlobalInstallDir:=fpcdir;
  647. end;
  648. end;
  649. procedure TCompilerOptions.LoadCompilerFromFile(const AFileName: String);
  650. Var
  651. Ini : TMemIniFile;
  652. begin
  653. Ini:=TMemIniFile.Create(AFileName);
  654. try
  655. FConfigFilename:=AFileName;
  656. With Ini do
  657. begin
  658. FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
  659. if (FConfigVersion<>CurrentConfigVersion) then
  660. begin
  661. log(vlDebug,SLogUpgradingConfig,[AFileName]);
  662. FSaveInifileChanges:=true;
  663. if (FConfigVersion>CurrentConfigVersion) then
  664. Error(SErrUnsupportedConfigVersion,[AFileName]);
  665. end;
  666. GlobalPrefix:=ReadString(SDefaults,KeyGlobalPrefix,FGlobalPrefix);
  667. LocalPrefix:=ReadString(SDefaults,KeyLocalPrefix,FLocalPrefix);
  668. FGlobalInstallDir:=FixPath(ReadString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir));
  669. FLocalInstallDir:=FixPath(ReadString(SDefaults,KeyLocalInstallDir,FLocalInstallDir));
  670. FCompiler:=ReadString(SDefaults,KeyCompiler,FCompiler);
  671. FCompilerOS:=StringToOS(ReadString(SDefaults,KeyCompilerOS,OSToString(CompilerOS)));
  672. FCompilerCPU:=StringToCPU(ReadString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU)));
  673. CompilerVersion:=ReadString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  674. end;
  675. finally
  676. Ini.Free;
  677. end;
  678. end;
  679. procedure TCompilerOptions.SaveCompilerToFile(const AFileName: String);
  680. Var
  681. Ini : TIniFile;
  682. begin
  683. if FileExists(AFileName) then
  684. BackupFile(AFileName);
  685. Ini:=TIniFile.Create(AFileName);
  686. try
  687. With Ini do
  688. begin
  689. WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
  690. WriteString(SDefaults,KeyGlobalPrefix,FGlobalPrefix);
  691. WriteString(SDefaults,KeyLocalPrefix,FLocalPrefix);
  692. WriteString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir);
  693. WriteString(SDefaults,KeyLocalInstallDir,FLocalInstallDir);
  694. WriteString(SDefaults,KeyCompiler,FCompiler);
  695. WriteString(SDefaults,KeyCompilerOS,OSToString(CompilerOS));
  696. WriteString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU));
  697. WriteString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  698. FSaveInifileChanges:=False;
  699. end;
  700. Ini.UpdateFile;
  701. finally
  702. Ini.Free;
  703. end;
  704. end;
  705. procedure TCompilerOptions.LogValues(ALogLevel: TLogLevel; const ACfgName:string);
  706. begin
  707. log(ALogLevel,SLogCompilerCfgHeader,[ACfgName,FConfigFilename]);
  708. log(ALogLevel,SLogCompilerCfgCompiler,[FCompiler]);
  709. log(ALogLevel,SLogCompilerCfgTarget,[MakeTargetString(CompilerCPU,CompilerOS)]);
  710. log(ALogLevel,SLogCompilerCfgVersion,[FCompilerVersion]);
  711. log(ALogLevel,SLogCompilerCfgGlobalPrefix,[FGlobalPrefix,GlobalPrefix]);
  712. log(ALogLevel,SLogCompilerCfgLocalPrefix,[FLocalPrefix,LocalPrefix]);
  713. log(ALogLevel,SLogCompilerCfgGlobalInstallDir,[FGlobalInstallDir,GlobalInstallDir]);
  714. log(ALogLevel,SLogCompilerCfgLocalInstallDir,[FLocalInstallDir,LocalInstallDir]);
  715. log(ALogLevel,SLogCompilerCfgOptions,[Options.DelimitedText]);
  716. end;
  717. initialization
  718. GlobalOptions:=TGlobalOptions.Create;
  719. CompilerOptions:=TCompilerOptions.Create;
  720. FPMakeCompilerOptions:=TCompilerOptions.Create;
  721. finalization
  722. FreeAndNil(GlobalOptions);
  723. FreeAndNil(CompilerOptions);
  724. FreeAndNil(FPMakeCompilerOptions);
  725. end.