pkgoptions.pp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  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. // pkgglobals must be AFTER fpmkunit
  15. uses Classes, Sysutils, Inifiles, fpTemplate, fpmkunit, pkgglobals, fgl;
  16. Const
  17. UnitConfigFileName = 'fpunits.cfg';
  18. ManifestFileName = 'manifest.xml';
  19. MirrorsFileName = 'mirrors.xml';
  20. PackagesFileName = 'packages.xml';
  21. MinSupportedConfigVersion = 4;
  22. CurrentConfigVersion = 5;
  23. Type
  24. TFPRepositoryType = (fprtUnknown, fprtInstalled, fprtAvailable);
  25. { TFppkgOptionSection }
  26. TCompilerOptions = class;
  27. TFppkgOptions = class;
  28. TFppkgOptionSection = class(TPersistent)
  29. private
  30. FOptionParser: TTemplateParser;
  31. FName: string;
  32. protected
  33. class function GetKey: string; virtual;
  34. procedure AddKeyValueToStrings(AStrings: TStrings; AKey, AValue: string); overload;
  35. procedure AddKeyValueToStrings(AStrings: TStrings; AKey: string; AValue: Integer); overload;
  36. property OptionParser: TTemplateParser read FOptionParser;
  37. public
  38. constructor Create(AnOptionParser: TTemplateParser); virtual;
  39. procedure AddKeyValue(const AKey, AValue: string); virtual;
  40. procedure SaveToStrings(AStrings: TStrings); virtual;
  41. procedure LogValues(ALogLevel: TLogLevel); virtual;
  42. function AllowDuplicate: Boolean; virtual;
  43. property Name: string read FName write FName;
  44. end;
  45. TFppkgOptionSectionList = specialize TFPGObjectList<TFppkgOptionSection>;
  46. { TFppkgGLobalOptionSection }
  47. TFppkgGlobalOptionSection = class(TFppkgOptionSection)
  48. private
  49. FCustomFPMakeOptions: string;
  50. FBuildDir: string;
  51. FCompilerConfigDir: string;
  52. FConfigVersion: integer;
  53. FCompilerConfig: string;
  54. FInstallRepository: string;
  55. FDownloader: string;
  56. FFPMakeCompilerConfig: string;
  57. FLocalRepository: string;
  58. FRemoteMirrorsURL: string;
  59. FRemoteRepository: string;
  60. FArchivesDir: string;
  61. function GetArchivesDir: string;
  62. function GetBuildDir: string;
  63. function GetCompilerConfigDir: string;
  64. function GetLocalRepository: string;
  65. procedure SetArchivesDir(AValue: string);
  66. procedure SetBuildDir(AValue: string);
  67. procedure SetCompilerConfigDir(AValue: string);
  68. procedure SetConfigVersion(AValue: integer);
  69. procedure SetCompilerConfig(AValue: string);
  70. procedure SetCustomFPMakeOptions(AValue: string);
  71. procedure SetDownloader(AValue: string);
  72. procedure SetFPMakeCompilerConfig(AValue: string);
  73. procedure SetLocalRepository(AValue: string);
  74. procedure SetRemoteMirrorsURL(AValue: string);
  75. procedure SetRemoteRepository(AValue: string);
  76. public
  77. constructor Create(AnOptionParser: TTemplateParser); override;
  78. destructor Destroy; override;
  79. procedure AddKeyValue(const AKey, AValue: string); override;
  80. procedure SaveToStrings(AStrings: TStrings); override;
  81. procedure LogValues(ALogLevel: TLogLevel); override;
  82. function LocalMirrorsFile:string;
  83. function LocalPackagesFile:string;
  84. property ConfigVersion: integer read FConfigVersion write SetConfigVersion;
  85. property LocalRepository: string read GetLocalRepository write SetLocalRepository;
  86. property BuildDir: string read GetBuildDir write SetBuildDir;
  87. property CompilerConfigDir: string read GetCompilerConfigDir write SetCompilerConfigDir;
  88. property ArchivesDir: string read GetArchivesDir write SetArchivesDir;
  89. property Downloader: string read FDownloader write SetDownloader;
  90. property CompilerConfig: string read FCompilerConfig write SetCompilerConfig;
  91. property FPMakeCompilerConfig: string read FFPMakeCompilerConfig write SetFPMakeCompilerConfig;
  92. property InstallRepository: string read FInstallRepository write FInstallRepository;
  93. property RemoteRepository: string read FRemoteRepository write SetRemoteRepository;
  94. property RemoteMirrorsURL: string read FRemoteMirrorsURL write SetRemoteMirrorsURL;
  95. Property CustomFPMakeOptions: string read FCustomFPMakeOptions Write SetCustomFPMakeOptions;
  96. end;
  97. { TFppkgCustomOptionSection }
  98. TFppkgCustomOptionSection = class(TFppkgOptionSection);
  99. { TFppkgRepositoryOptionSection }
  100. TFppkgRepositoryOptionSection = class(TFppkgOptionSection)
  101. private
  102. FDescription: string;
  103. FInstallRepositoryName: string;
  104. FPath: string;
  105. FPrefix: string;
  106. FRepositoryName: string;
  107. function GetPath: string;
  108. function GetPrefix: string;
  109. procedure SetDescription(AValue: string);
  110. procedure SetPrefix(AValue: string);
  111. procedure SetRepositoryName(AValue: string);
  112. procedure SetPath(AValue: string);
  113. protected
  114. procedure SaveToStrings(AStrings: TStrings); override;
  115. class function GetKey: string; override;
  116. public
  117. procedure AddKeyValue(const AKey, AValue: string); override;
  118. procedure LogValues(ALogLevel: TLogLevel); override;
  119. function AllowDuplicate: Boolean; override;
  120. function GetRepositoryType: TFPRepositoryType; virtual;
  121. property RepositoryName: string read FRepositoryName write SetRepositoryName;
  122. property Description: string read FDescription write SetDescription;
  123. property Path: string read GetPath write SetPath;
  124. property Prefix: string read GetPrefix write SetPrefix;
  125. property InstallRepositoryName: string read FInstallRepositoryName write FInstallRepositoryName;
  126. end;
  127. TFppkgRepositoryOptionSectionClass = class of TFppkgRepositoryOptionSection;
  128. { TFppkgIncludeFilesOptionSection }
  129. TFppkgIncludeFilesOptionSection = class(TFppkgOptionSection)
  130. private
  131. FOptions: TFppkgOptions;
  132. // Only used for logging
  133. FOptionCache: TStringList;
  134. FCurrentDir: String;
  135. procedure IncludeFile(AFileName: string);
  136. procedure IncludeFileMask(AFileNameMask: string);
  137. protected
  138. class function GetKey: string; override;
  139. public
  140. constructor Create(AnOptionParser: TTemplateParser; AnOptions: TFppkgOptions; ACurrentDir: string);
  141. destructor Destroy; override;
  142. procedure SaveToStrings(AStrings: TStrings); override;
  143. procedure AddKeyValue(const AKey, AValue: string); override;
  144. procedure LogValues(ALogLevel: TLogLevel); override;
  145. function AllowDuplicate: Boolean; override;
  146. end;
  147. { TFppkgCommandLineOptionSection }
  148. TFppkgCommandLineOptionSection = class(TFppkgOptionSection)
  149. private
  150. FAllowBroken: Boolean;
  151. FCompilerConfig: string;
  152. FInstallRepository: string;
  153. FRecoveryMode: Boolean;
  154. FShowLocation: Boolean;
  155. FSkipConfigurationFiles: Boolean;
  156. FSkipFixBrokenAfterInstall: Boolean;
  157. public
  158. constructor Create(AnOptionParser: TTemplateParser); override;
  159. property RecoveryMode: Boolean read FRecoveryMode write FRecoveryMode;
  160. property ShowLocation: Boolean read FShowLocation write FShowLocation;
  161. property CompilerConfig : string read FCompilerConfig write FCompilerConfig;
  162. property InstallRepository: string read FInstallRepository write FInstallRepository;
  163. property SkipConfigurationFiles: Boolean read FSkipConfigurationFiles write FSkipConfigurationFiles;
  164. property AllowBroken : Boolean read FAllowBroken write FAllowBroken;
  165. property SkipFixBrokenAfterInstall: Boolean read FSkipFixBrokenAfterInstall write FSkipFixBrokenAfterInstall;
  166. end;
  167. { TFppkgOptions }
  168. TFppkgOptions = class(TPersistent)
  169. private
  170. FOptionParser: TTemplateParser;
  171. FSectionList: TFppkgOptionSectionList;
  172. function GetCommandLineSection: TFppkgCommandLineOptionSection;
  173. function GetGlobalSection: TFppkgGLobalOptionSection;
  174. function GetSectionList: TFppkgOptionSectionList;
  175. public
  176. constructor Create();
  177. destructor Destroy; override;
  178. procedure LoadFromFile(const AFileName: string);
  179. procedure SaveToFile(const AFileName: string);
  180. function GetSectionByName(const SectionName: string): TFppkgOptionSection;
  181. procedure LogValues(ALogLevel: TLogLevel);
  182. procedure BindToCompilerOptions(ACompilerOptions: TCompilerOptions);
  183. procedure AddRepositoriesForCompilerSettings(ACompilerOptions: TCompilerOptions);
  184. function AddRepositoryOptionSection(ASectionClass: TFppkgRepositoryOptionSectionClass): TFppkgRepositoryOptionSection;
  185. function AddIncludeFilesOptionSection(AFileMask: string): TFppkgIncludeFilesOptionSection;
  186. property SectionList: TFppkgOptionSectionList read GetSectionList;
  187. property GlobalSection: TFppkgGLobalOptionSection read GetGlobalSection;
  188. property CommandLineSection: TFppkgCommandLineOptionSection read GetCommandLineSection;
  189. end;
  190. { TCompilerOptions }
  191. TCompilerOptions = Class(TPersistent)
  192. private
  193. FConfigFilename: string;
  194. FSaveInifileChanges: Boolean;
  195. FConfigVersion : Integer;
  196. FCompiler,
  197. FCompilerVersion,
  198. FLocalInstallDir,
  199. FGlobalInstallDir,
  200. FLocalPrefix,
  201. FGlobalPrefix: String;
  202. FCompilerCPU: TCPU;
  203. FCompilerOS: TOS;
  204. FOptionParser: TTemplateParser;
  205. FOptions: TStrings;
  206. function GetOptions: TStrings;
  207. function GetOptString(Index: integer): String;
  208. procedure SetOptString(Index: integer; const AValue: String);
  209. procedure SetCompilerCPU(const AValue: TCPU);
  210. procedure SetCompilerOS(const AValue: TOS);
  211. Public
  212. Constructor Create;
  213. Destructor Destroy; override;
  214. Procedure InitCompilerDefaults;
  215. Procedure LoadCompilerFromFile(const AFileName : String);
  216. function SaveCompilerToFile(const AFileName : String): Boolean;
  217. procedure LogValues(ALogLevel: TLogLevel; const ACfgName:string);
  218. procedure UpdateLocalRepositoryOption(FppkgOptions: TFppkgOptions);
  219. procedure CheckCompilerValues;
  220. Function HasOptions: boolean;
  221. // Is set when the inifile has an old version number (which is also the case when a new file is generated)
  222. Property SaveInifileChanges : Boolean Read FSaveInifileChanges;
  223. Property ConfigVersion : Integer read FConfigVersion;
  224. Published
  225. Property Compiler : String Index 1 Read GetOptString Write SetOptString;
  226. Property CompilerTarget : String Index 2 Read GetOptString Write SetOptString;
  227. Property CompilerVersion : String Index 3 Read GetOptString Write SetOptString;
  228. Property GlobalInstallDir : String Index 4 Read GetOptString Write SetOptString; deprecated;
  229. Property LocalInstallDir : String Index 5 Read GetOptString Write SetOptString; deprecated;
  230. Property GlobalPrefix : String Index 6 Read GetOptString Write SetOptString;
  231. Property LocalPrefix : String Index 7 Read GetOptString Write SetOptString;
  232. Property Options : TStrings read GetOptions;
  233. Property CompilerOS : TOS Read FCompilerOS Write SetCompilerOS;
  234. Property CompilerCPU : TCPU Read FCompilerCPU Write SetCompilerCPU;
  235. end;
  236. Implementation
  237. uses
  238. pkgUninstalledSrcsRepo,
  239. pkgPackagesStructure,
  240. pkgmessages;
  241. Const
  242. DefaultMirrorsURL = 'https://www.freepascal.org/repository/'+MirrorsFileName;
  243. {$ifdef localrepository}
  244. DefaultRemoteRepository = 'file://'+{$I %HOME%}+'/repository/';
  245. {$else}
  246. DefaultRemoteRepository = 'auto';
  247. {$endif}
  248. // ini file keys
  249. SDefaults = 'Defaults';
  250. // All configs
  251. KeyConfigVersion = 'ConfigVersion';
  252. // Global config
  253. KeyDeprGlobalSection = 'Defaults';
  254. KeyGlobalSection = 'Global';
  255. KeyRepositorySection = 'Repository';
  256. KeyIncludeFilesSection = 'IncludeFiles';
  257. KeyRemoteMirrorsURL = 'RemoteMirrors';
  258. KeyRemoteRepository = 'RemoteRepository';
  259. KeyLocalRepository = 'LocalRepository';
  260. KeyArchivesDir = 'ArchivesDir';
  261. KeyBuildDir = 'BuildDir';
  262. KeyCompilerConfigDir = 'CompilerConfigDir';
  263. KeyCompilerConfig = 'CompilerConfig';
  264. KeyFPMakeCompilerConfig = 'FPMakeCompilerConfig';
  265. KeyDownloader = 'Downloader';
  266. KeyCustomFPMakeOptions = 'FPMakeOptions';
  267. KeyInstallRepository = 'InstallRepository';
  268. KeyRepositoryName = 'Name';
  269. KeyRepositoryDescription = 'Description';
  270. KeyRepositoryPath = 'Path';
  271. KeyRepositoryPrefix = 'Prefix';
  272. KeyInstallRepositoryName = 'InstallRepository';
  273. KeyIncludeFile = 'File';
  274. KeyIncludeFileMask = 'FileMask';
  275. // Compiler dependent config
  276. KeyGlobalPrefix = 'GlobalPrefix';
  277. KeyLocalPrefix = 'LocalPrefix';
  278. KeyGlobalInstallDir = 'GlobalInstallDir';
  279. KeyLocalInstallDir = 'LocalInstallDir';
  280. KeyCompiler = 'Compiler' ;
  281. KeyCompilerOS = 'OS';
  282. KeyCompilerCPU = 'CPU';
  283. KeyCompilerVersion = 'Version';
  284. { TFppkgIncludeFilesOptionSection }
  285. procedure TFppkgIncludeFilesOptionSection.IncludeFile(AFileName: string);
  286. begin
  287. AFileName := FOptionParser.ParseString(AFileName);
  288. if FileExists(AFileName) then
  289. begin
  290. FOptions.LoadFromFile(AFileName);
  291. end
  292. else
  293. log(llWarning, SLogIncludeFileDoesNotExist, [AFileName]);
  294. end;
  295. procedure TFppkgIncludeFilesOptionSection.IncludeFileMask(AFileNameMask: string);
  296. var
  297. FileDir: string;
  298. SR: TSearchRec;
  299. begin
  300. AFileNameMask := FOptionParser.ParseString(AFileNameMask);
  301. FileDir := IncludeTrailingPathDelimiter(ExtractFileDir(AFileNameMask));
  302. if IsRelativePath(AFileNameMask) then
  303. FileDir := ConcatPaths([FCurrentDir, FileDir]);
  304. if DirectoryExists(FileDir) then
  305. begin
  306. if IsRelativePath(AFileNameMask) then
  307. AFileNameMask := ConcatPaths([FCurrentDir, AFileNameMask]);
  308. if FindFirst(AFileNameMask, faAnyFile-faDirectory, SR)=0 then
  309. begin
  310. repeat
  311. IncludeFile(FileDir+SR.Name);
  312. until FindNext(SR)<>0;
  313. end;
  314. FindClose(SR);
  315. end
  316. else
  317. log(llWarning, SLogIncludeFileMaskDoesNotExist, [FileDir, AFileNameMask]);
  318. end;
  319. class function TFppkgIncludeFilesOptionSection.GetKey: string;
  320. begin
  321. Result := KeyIncludeFilesSection;
  322. end;
  323. procedure TFppkgIncludeFilesOptionSection.SaveToStrings(AStrings: TStrings);
  324. begin
  325. AStrings.Add('['+KeyIncludeFilesSection+']');
  326. AddKeyValueToStrings(AStrings, KeyIncludeFileMask, FCurrentDir);
  327. end;
  328. constructor TFppkgIncludeFilesOptionSection.Create(AnOptionParser: TTemplateParser;
  329. AnOptions: TFppkgOptions; ACurrentDir: string);
  330. begin
  331. inherited Create(AnOptionParser);
  332. FOptions := AnOptions;
  333. FCurrentDir := ACurrentDir;
  334. FOptionCache := TStringList.Create;
  335. end;
  336. destructor TFppkgIncludeFilesOptionSection.Destroy;
  337. begin
  338. FOptionCache.Free;
  339. inherited Destroy;
  340. end;
  341. procedure TFppkgIncludeFilesOptionSection.AddKeyValue(const AKey, AValue: string);
  342. begin
  343. if SameText(AKey,KeyIncludeFile) then
  344. begin
  345. FOptionCache.Append(SLogIncludeFile + '=' + AValue);
  346. IncludeFile(AValue);
  347. end
  348. else if SameText(AKey,KeyIncludeFileMask) then
  349. begin
  350. FOptionCache.Append(SLogIncludeFileMask + '=' + AValue);
  351. IncludeFileMask(AValue);
  352. end;
  353. end;
  354. procedure TFppkgIncludeFilesOptionSection.LogValues(ALogLevel: TLogLevel);
  355. var
  356. i: Integer;
  357. begin
  358. inherited LogValues(ALogLevel);
  359. for i := 0 to FOptionCache.Count -1 do
  360. begin
  361. log(ALogLevel, FOptionCache.Names[i], [FOptionCache.ValueFromIndex[i], FOptionParser.ParseString(FOptionCache.ValueFromIndex[i])]);
  362. end;
  363. end;
  364. function TFppkgIncludeFilesOptionSection.AllowDuplicate: Boolean;
  365. begin
  366. Result := inherited AllowDuplicate;
  367. end;
  368. { TFppkgRepositoryOptionSection }
  369. procedure TFppkgRepositoryOptionSection.SetDescription(AValue: string);
  370. begin
  371. if FDescription = AValue then Exit;
  372. FDescription := AValue;
  373. end;
  374. procedure TFppkgRepositoryOptionSection.SetPrefix(AValue: string);
  375. begin
  376. if FPrefix = AValue then Exit;
  377. FPrefix := AValue;
  378. end;
  379. function TFppkgRepositoryOptionSection.GetPath: string;
  380. begin
  381. Result := OptionParser.ParseString(FPath);
  382. end;
  383. function TFppkgRepositoryOptionSection.GetPrefix: string;
  384. begin
  385. Result := OptionParser.ParseString(FPrefix);
  386. end;
  387. procedure TFppkgRepositoryOptionSection.SetRepositoryName(AValue: string);
  388. begin
  389. if FRepositoryName = AValue then Exit;
  390. FRepositoryName := AValue;
  391. end;
  392. procedure TFppkgRepositoryOptionSection.SetPath(AValue: string);
  393. begin
  394. if FPath = AValue then Exit;
  395. FPath := fpmkunit.FixPath(AValue, True);
  396. end;
  397. procedure TFppkgRepositoryOptionSection.SaveToStrings(AStrings: TStrings);
  398. begin
  399. inherited SaveToStrings(AStrings);
  400. AddKeyValueToStrings(AStrings, KeyRepositoryName, RepositoryName);
  401. AddKeyValueToStrings(AStrings, KeyRepositoryDescription, Description);
  402. AddKeyValueToStrings(AStrings, KeyRepositoryPath, FPath);
  403. AddKeyValueToStrings(AStrings, KeyRepositoryPrefix, FPrefix);
  404. AddKeyValueToStrings(AStrings, KeyInstallRepositoryName, InstallRepositoryName);
  405. end;
  406. class function TFppkgRepositoryOptionSection.GetKey: string;
  407. begin
  408. Result := KeyRepositorySection;
  409. end;
  410. procedure TFppkgRepositoryOptionSection.AddKeyValue(const AKey, AValue: string);
  411. begin
  412. if SameText(AKey,KeyRepositoryName) then
  413. RepositoryName := AValue
  414. else if SameText(AKey,KeyRepositoryDescription) then
  415. Description := AValue
  416. else if SameText(AKey,KeyRepositoryPath) then
  417. Path := AValue
  418. else if SameText(AKey,KeyRepositoryPrefix) then
  419. Prefix := AValue
  420. else if SameText(AKey,KeyInstallRepositoryName) then
  421. InstallRepositoryName := AValue
  422. end;
  423. procedure TFppkgRepositoryOptionSection.LogValues(ALogLevel: TLogLevel);
  424. begin
  425. inherited LogValues(ALogLevel);
  426. log(ALogLevel,SLogRepositoryName,[FRepositoryName]);
  427. log(ALogLevel,SLogRepositoryDescription,[FDescription]);
  428. log(ALogLevel,SLogRepositoryPath,[FPath,Path]);
  429. log(ALogLevel,SLogRepositoryPrefix,[FPrefix,Prefix]);
  430. log(ALogLevel,SLogInstallRepository,[FInstallRepositoryName]);
  431. end;
  432. function TFppkgRepositoryOptionSection.AllowDuplicate: Boolean;
  433. begin
  434. Result := True;
  435. end;
  436. function TFppkgRepositoryOptionSection.GetRepositoryType: TFPRepositoryType;
  437. begin
  438. result := fprtInstalled;
  439. end;
  440. { TFppkgCommandLineOptionSection }
  441. constructor TFppkgCommandLineOptionSection.Create(AnOptionParser: TTemplateParser);
  442. begin
  443. inherited Create(AnOptionParser);
  444. // Parameter defaults
  445. FRecoveryMode:=False;
  446. FAllowBroken:=False;
  447. end;
  448. { TFppkgOptionSection }
  449. class function TFppkgOptionSection.GetKey: string;
  450. begin
  451. Result := '';
  452. end;
  453. procedure TFppkgOptionSection.AddKeyValueToStrings(AStrings: TStrings; AKey, AValue: string);
  454. begin
  455. if AValue<>'' then
  456. AStrings.Add(AKey+'='+AValue);
  457. end;
  458. procedure TFppkgOptionSection.AddKeyValueToStrings(AStrings: TStrings; AKey: string; AValue: Integer);
  459. begin
  460. if AValue<>-1 then
  461. AStrings.Add(AKey+'='+IntToStr(AValue));
  462. end;
  463. constructor TFppkgOptionSection.Create(AnOptionParser: TTemplateParser);
  464. begin
  465. FOptionParser:=AnOptionParser;
  466. end;
  467. procedure TFppkgOptionSection.AddKeyValue(const AKey, AValue: string);
  468. begin
  469. // Do nothing
  470. end;
  471. procedure TFppkgOptionSection.SaveToStrings(AStrings: TStrings);
  472. begin
  473. AStrings.Add('['+GetKey+']');
  474. end;
  475. procedure TFppkgOptionSection.LogValues(ALogLevel: TLogLevel);
  476. begin
  477. log(ALogLevel,SLogCfgSectionHeader, [Trim(Name)]);
  478. end;
  479. function TFppkgOptionSection.AllowDuplicate: Boolean;
  480. begin
  481. Result:=False;
  482. end;
  483. {*****************************************************************************
  484. TFppkgGlobalOptionSection
  485. *****************************************************************************}
  486. procedure TFppkgGlobalOptionSection.SetBuildDir(AValue: string);
  487. begin
  488. if FBuildDir = AValue then Exit;
  489. FBuildDir := fpmkunit.FixPath(AValue, True);
  490. end;
  491. function TFppkgGlobalOptionSection.GetCompilerConfigDir: string;
  492. begin
  493. Result := FOptionParser.ParseString(FCompilerConfigDir);
  494. end;
  495. function TFppkgGlobalOptionSection.GetLocalRepository: string;
  496. begin
  497. Result := FOptionParser.ParseString(FLocalRepository);
  498. end;
  499. procedure TFppkgGlobalOptionSection.SetArchivesDir(AValue: string);
  500. begin
  501. if FArchivesDir = AValue then Exit;
  502. FArchivesDir := fpmkunit.FixPath(AValue, True);
  503. end;
  504. function TFppkgGlobalOptionSection.GetBuildDir: string;
  505. begin
  506. Result := FOptionParser.ParseString(FBuildDir);
  507. end;
  508. function TFppkgGlobalOptionSection.GetArchivesDir: string;
  509. begin
  510. Result := FOptionParser.ParseString(FArchivesDir);
  511. end;
  512. procedure TFppkgGlobalOptionSection.SetCompilerConfigDir(AValue: string);
  513. begin
  514. if FCompilerConfigDir = AValue then Exit;
  515. FCompilerConfigDir := fpmkunit.FixPath(AValue, True);
  516. end;
  517. procedure TFppkgGlobalOptionSection.SetConfigVersion(AValue: integer);
  518. begin
  519. if FConfigVersion = AValue then Exit;
  520. FConfigVersion := AValue;
  521. end;
  522. procedure TFppkgGlobalOptionSection.SetCompilerConfig(AValue: string);
  523. begin
  524. if FCompilerConfig = AValue then Exit;
  525. FCompilerConfig := AValue;
  526. end;
  527. procedure TFppkgGlobalOptionSection.SetCustomFPMakeOptions(AValue: string);
  528. begin
  529. if FCustomFPMakeOptions = AValue then Exit;
  530. FCustomFPMakeOptions := AValue;
  531. end;
  532. procedure TFppkgGlobalOptionSection.SetDownloader(AValue: string);
  533. begin
  534. if FDownloader = AValue then Exit;
  535. FDownloader := AValue;
  536. end;
  537. procedure TFppkgGlobalOptionSection.SetFPMakeCompilerConfig(AValue: string);
  538. begin
  539. if FFPMakeCompilerConfig = AValue then Exit;
  540. FFPMakeCompilerConfig := AValue;
  541. end;
  542. procedure TFppkgGlobalOptionSection.SetLocalRepository(AValue: string);
  543. begin
  544. if FLocalRepository = AValue then Exit;
  545. FLocalRepository := AValue;
  546. FOptionParser.Values['LocalRepository'] := LocalRepository;
  547. end;
  548. procedure TFppkgGlobalOptionSection.SetRemoteMirrorsURL(AValue: string);
  549. begin
  550. if FRemoteMirrorsURL = AValue then Exit;
  551. FRemoteMirrorsURL := AValue;
  552. end;
  553. procedure TFppkgGlobalOptionSection.SetRemoteRepository(AValue: string);
  554. begin
  555. if FRemoteRepository = AValue then Exit;
  556. FRemoteRepository := AValue;
  557. end;
  558. constructor TFppkgGlobalOptionSection.Create(AnOptionParser: TTemplateParser);
  559. begin
  560. Inherited Create(AnOptionParser);
  561. // Retrieve Local fppkg directory
  562. {$ifdef unix}
  563. if IsSuperUser then
  564. begin
  565. if DirectoryExists('/usr/local/lib/fpc') then
  566. LocalRepository:='/usr/local/lib/fpc/fppkg/'
  567. else
  568. LocalRepository:='/usr/lib/fpc/fppkg/';
  569. end
  570. else
  571. LocalRepository:='{UserDir}.fppkg/';
  572. {$else}
  573. if IsSuperUser then
  574. LocalRepository:=IncludeTrailingPathDelimiter(GetFppkgConfigDir(true))
  575. else
  576. LocalRepository:='{AppConfigDir}';
  577. {$endif}
  578. ConfigVersion := CurrentConfigVersion;
  579. CompilerConfig := 'default';
  580. FPMakeCompilerConfig := 'default';
  581. RemoteRepository := DefaultRemoteRepository;
  582. FRemoteMirrorsURL:=DefaultMirrorsURL;
  583. // Directories
  584. BuildDir:='{LocalRepository}build'+PathDelim;
  585. ArchivesDir:='{LocalRepository}archives'+PathDelim;
  586. CompilerConfigDir:='{LocalRepository}config'+PathDelim;
  587. {$if (defined(unix) and not defined(android)) or defined(windows)}
  588. Downloader:='FPC';
  589. {$else}
  590. Downloader:='base';
  591. {$endif}
  592. end;
  593. destructor TFppkgGlobalOptionSection.Destroy;
  594. begin
  595. inherited Destroy;
  596. end;
  597. procedure TFppkgGlobalOptionSection.AddKeyValue(const AKey, AValue: string);
  598. begin
  599. if SameText(AKey,KeyBuildDir) then
  600. BuildDir := AValue
  601. else if SameText(AKey,KeyDownloader) then
  602. Downloader := AValue
  603. else if SameText(AKey,KeyConfigVersion) then
  604. begin
  605. ConfigVersion := StrToIntDef(AValue,-1);
  606. if (FConfigVersion<>CurrentConfigVersion) then
  607. begin
  608. if (FConfigVersion<MinSupportedConfigVersion) or (FConfigVersion>CurrentConfigVersion) then
  609. Error(SErrUnsupportedConfigVersion);
  610. log(llWarning,SLogOldConfigFileFormat);
  611. end;
  612. end
  613. else if SameText(AKey,KeyCompilerConfig) then
  614. CompilerConfig := AValue
  615. else if SameText(AKey,KeyFPMakeCompilerConfig) then
  616. FPMakeCompilerConfig := AValue
  617. else if SameText(AKey,KeyCompilerConfigDir) then
  618. CompilerConfigDir := AValue
  619. else if SameText(AKey,KeyRemoteMirrorsURL) then
  620. RemoteMirrorsURL := AValue
  621. else if SameText(AKey,KeyRemoteRepository) then
  622. RemoteRepository := AValue
  623. else if SameText(AKey,KeyLocalRepository) then
  624. LocalRepository := AValue
  625. else if SameText(AKey,KeyArchivesDir) then
  626. ArchivesDir := AValue
  627. else if SameText(AKey,KeyInstallRepository) then
  628. InstallRepository := AValue
  629. else if SameText(AKey,KeyCustomFPMakeOptions) then
  630. CustomFPMakeOptions := AValue
  631. end;
  632. procedure TFppkgGlobalOptionSection.SaveToStrings(AStrings: TStrings);
  633. begin
  634. AStrings.Add('['+KeyGlobalSection+']');
  635. AddKeyValueToStrings(AStrings, KeyConfigVersion, CurrentConfigVersion);
  636. AddKeyValueToStrings(AStrings, KeyBuildDir, BuildDir);
  637. AddKeyValueToStrings(AStrings, KeyDownloader, Downloader);
  638. AddKeyValueToStrings(AStrings, KeyCompilerConfig, CompilerConfig);
  639. AddKeyValueToStrings(AStrings, KeyFPMakeCompilerConfig, FPMakeCompilerConfig);
  640. AddKeyValueToStrings(AStrings, KeyCompilerConfigDir, CompilerConfigDir);
  641. AddKeyValueToStrings(AStrings, KeyRemoteMirrorsURL, RemoteMirrorsURL);
  642. AddKeyValueToStrings(AStrings, KeyRemoteRepository, RemoteRepository);
  643. AddKeyValueToStrings(AStrings, KeyLocalRepository, LocalRepository);
  644. AddKeyValueToStrings(AStrings, KeyArchivesDir, ArchivesDir);
  645. AddKeyValueToStrings(AStrings, KeyCustomFPMakeOptions, CustomFPMakeOptions);
  646. end;
  647. procedure TFppkgGlobalOptionSection.LogValues(ALogLevel: TLogLevel);
  648. begin
  649. inherited LogValues(ALogLevel);
  650. log(ALogLevel,SLogGlobalCfgRemoteMirrorsURL,[FRemoteMirrorsURL]);
  651. log(ALogLevel,SLogGlobalCfgRemoteRepository,[FRemoteRepository]);
  652. log(ALogLevel,SLogGlobalCfgLocalRepository,[FLocalRepository,LocalRepository]);
  653. log(ALogLevel,SLogGlobalCfgBuildDir,[FBuildDir,BuildDir]);
  654. log(ALogLevel,SLogGlobalCfgArchivesDir,[FArchivesDir,ArchivesDir]);
  655. log(ALogLevel,SLogGlobalCfgCompilerConfigDir,[FCompilerConfigDir,CompilerConfigDir]);
  656. log(ALogLevel,SLogGlobalCfgDefaultCompilerConfig,[FCompilerConfig]);
  657. log(ALogLevel,SLogGlobalCfgFPMakeCompilerConfig,[FPMakeCompilerConfig]);
  658. log(ALogLevel,SLogGlobalCfgDownloader,[FDownloader]);
  659. end;
  660. function TFppkgGlobalOptionSection.LocalMirrorsFile: string;
  661. begin
  662. Result:=LocalRepository+MirrorsFileName;
  663. end;
  664. function TFppkgGlobalOptionSection.LocalPackagesFile: string;
  665. begin
  666. Result:=LocalRepository+PackagesFileName;
  667. end;
  668. {*****************************************************************************
  669. TFppkgOptions
  670. *****************************************************************************}
  671. function TFppkgOptions.GetSectionList: TFppkgOptionSectionList;
  672. begin
  673. Result := FSectionList;
  674. end;
  675. function TFppkgOptions.GetGlobalSection: TFppkgGLobalOptionSection;
  676. begin
  677. Result := GetSectionByName(KeyGlobalSection) as TFppkgGlobalOptionSection;
  678. // Below version 5 the global-section was called 'Defaults'
  679. if not Assigned(Result) then
  680. Result := GetSectionByName(KeyDeprGlobalSection) as TFppkgGlobalOptionSection;
  681. if not Assigned(Result) then
  682. begin
  683. Result := TFppkgGlobalOptionSection.Create(FOptionParser);
  684. Result.Name := KeyGlobalSection;
  685. FSectionList.Add(Result);
  686. end;
  687. end;
  688. function TFppkgOptions.GetCommandLineSection: TFppkgCommandLineOptionSection;
  689. begin
  690. Result := GetSectionByName(' Commandline ') as TFppkgCommandLineOptionSection;
  691. if not Assigned(Result) then
  692. begin
  693. Result := TFppkgCommandLineOptionSection.Create(FOptionParser);
  694. Result.Name := ' Commandline ';
  695. FSectionList.Add(Result);
  696. end;
  697. end;
  698. constructor TFppkgOptions.Create;
  699. begin
  700. FOptionParser := TTemplateParser.Create;
  701. FOptionParser.Values['AppConfigDir'] := GetFppkgConfigDir(false);
  702. FOptionParser.Values['UserDir'] := GetUserDir;
  703. FSectionList := TFppkgOptionSectionList.Create;
  704. end;
  705. destructor TFppkgOptions.Destroy;
  706. begin
  707. FSectionList.Free;
  708. FOptionParser.Free;
  709. inherited Destroy;
  710. end;
  711. procedure TFppkgOptions.LoadFromFile(const AFileName: string);
  712. var
  713. IniFile: TStringList;
  714. CurrentSection: TFppkgOptionSection;
  715. s: String;
  716. i: Integer;
  717. j: SizeInt;
  718. begin
  719. log(llInfo, SLogStartLoadingConfFile, [AFileName]);
  720. IniFile:=TStringList.Create;
  721. try
  722. Inifile.LoadFromFile(AFileName);
  723. for i := 0 to Inifile.Count-1 do
  724. begin
  725. s := Trim(IniFile[i]);
  726. if s = '' then
  727. Continue;
  728. if (Copy(s, 1, 1) = '[') and (Copy(s, length(s), 1) = ']') then
  729. begin
  730. s := Trim(Copy(s, 2, Length(s) - 2));
  731. CurrentSection := GetSectionByName(s);
  732. if not Assigned(CurrentSection) or CurrentSection.AllowDuplicate then
  733. begin
  734. if SameText(s, KeyGlobalSection) or SameText(s, KeyDeprGlobalSection) then
  735. CurrentSection := GetGlobalSection
  736. else
  737. begin
  738. if SameText(s, TFppkgRepositoryOptionSection.GetKey) then
  739. CurrentSection := TFppkgRepositoryOptionSection.Create(FOptionParser)
  740. else if SameText(s, TFppkgUninstalledSourceRepositoryOptionSection.GetKey) then
  741. CurrentSection := TFppkgUninstalledSourceRepositoryOptionSection.Create(FOptionParser)
  742. else if SameText(s, TFppkgIncludeFilesOptionSection.GetKey) then
  743. CurrentSection := TFppkgIncludeFilesOptionSection.Create(FOptionParser, Self, ExtractFileDir(AFileName))
  744. else if SameText(s, TFppkgUninstalledRepositoryOptionSection.GetKey) then
  745. CurrentSection := TFppkgUninstalledRepositoryOptionSection.Create(FOptionParser)
  746. else
  747. CurrentSection := TFppkgCustomOptionSection.Create(FOptionParser);
  748. FSectionList.Add(CurrentSection);
  749. CurrentSection.Name := s;
  750. end;
  751. end
  752. end
  753. else if copy(s,1,1)<>';' then // comment
  754. begin
  755. // regular key
  756. j:=Pos('=', s);
  757. if j>0 then
  758. CurrentSection.AddKeyValue(Trim(Copy(s, 1, j - 1)), Trim(Copy(s, j + 1, Length(s) - j)));
  759. end;
  760. end;
  761. finally
  762. Inifile.Free;
  763. end;
  764. end;
  765. procedure TFppkgOptions.SaveToFile(const AFileName: string);
  766. var
  767. IniFile: TStringList;
  768. CurrentSection: TFppkgOptionSection;
  769. GSection: TFppkgGlobalOptionSection;
  770. i: Integer;
  771. begin
  772. IniFile:=TStringList.Create;
  773. try
  774. GSection := GlobalSection;
  775. GSection.SaveToStrings(IniFile);
  776. for i := 0 to SectionList.Count-1 do
  777. begin
  778. CurrentSection := SectionList[i];
  779. if CurrentSection<>GSection then
  780. begin
  781. IniFile.Add('');
  782. CurrentSection.SaveToStrings(IniFile);
  783. end;
  784. end;
  785. Inifile.SaveToFile(AFileName);
  786. finally
  787. Inifile.Free;
  788. end;
  789. end;
  790. function TFppkgOptions.GetSectionByName(const SectionName: string): TFppkgOptionSection;
  791. var
  792. i: Integer;
  793. begin
  794. Result := nil;
  795. for i := 0 to SectionList.Count-1 do
  796. begin
  797. if SectionList[i].Name=SectionName then
  798. begin
  799. Result:=SectionList[i];
  800. Break;
  801. end;
  802. end;
  803. end;
  804. procedure TFppkgOptions.LogValues(ALogLevel: TLogLevel);
  805. var
  806. i: Integer;
  807. begin
  808. log(ALogLevel,SLogCfgHeader);
  809. for i := 0 to SectionList.Count-1 do
  810. begin
  811. SectionList[i].LogValues(ALogLevel);
  812. end;
  813. end;
  814. procedure TFppkgOptions.BindToCompilerOptions(ACompilerOptions: TCompilerOptions);
  815. begin
  816. FOptionParser.Values['CompilerVersion'] := ACompilerOptions.CompilerVersion;
  817. end;
  818. procedure TFppkgOptions.AddRepositoriesForCompilerSettings(
  819. ACompilerOptions: TCompilerOptions);
  820. var
  821. CurrentSection: TFppkgRepositoryOptionSection;
  822. begin
  823. CurrentSection := TFppkgRepositoryOptionSection.Create(FOptionParser);
  824. CurrentSection.RepositoryName:='global';
  825. CurrentSection.Description:='global';
  826. CurrentSection.Path:=ACompilerOptions.GlobalInstallDir;
  827. CurrentSection.Prefix:=ACompilerOptions.GlobalPrefix;
  828. FSectionList.Add(CurrentSection);
  829. CurrentSection := TFppkgRepositoryOptionSection.Create(FOptionParser);
  830. CurrentSection.RepositoryName:='local';
  831. CurrentSection.Description:='local';
  832. CurrentSection.Path:=ACompilerOptions.LocalInstallDir;
  833. CurrentSection.Prefix:=ACompilerOptions.LocalPrefix;
  834. FSectionList.Add(CurrentSection);
  835. if CommandLineSection.InstallRepository='' then
  836. begin
  837. if IsSuperUser then
  838. CommandLineSection.InstallRepository:='global'
  839. else
  840. CommandLineSection.InstallRepository:='local';
  841. end;
  842. end;
  843. function TFppkgOptions.AddRepositoryOptionSection(ASectionClass: TFppkgRepositoryOptionSectionClass): TFppkgRepositoryOptionSection;
  844. begin
  845. Result := ASectionClass.Create(FOptionParser);
  846. FSectionList.Add(Result);
  847. end;
  848. function TFppkgOptions.AddIncludeFilesOptionSection(AFileMask: string): TFppkgIncludeFilesOptionSection;
  849. begin
  850. Result := TFppkgIncludeFilesOptionSection.Create(FOptionParser, Self, AFileMask);
  851. FSectionList.Add(Result);
  852. end;
  853. {*****************************************************************************
  854. TCompilerOptions
  855. *****************************************************************************}
  856. constructor TCompilerOptions.Create;
  857. begin
  858. FOptionParser := TTemplateParser.Create;
  859. FOptionParser.Values['AppConfigDir'] := GetFppkgConfigDir(false);
  860. FOptionParser.Values['UserDir'] := GetUserDir;
  861. FSaveInifileChanges := True;
  862. {$ifdef unix}
  863. FLocalInstallDir:='{LocalPrefix}'+'lib'+PathDelim+'fpc'+PathDelim+'{CompilerVersion}'+PathDelim;
  864. FGlobalInstallDir:='{GlobalPrefix}'+'lib'+PathDelim+'fpc'+PathDelim+'{CompilerVersion}'+PathDelim;
  865. {$else unix}
  866. FLocalInstallDir:='{LocalPrefix}';
  867. FGlobalInstallDir:='{GlobalPrefix}';
  868. {$endif}
  869. end;
  870. destructor TCompilerOptions.Destroy;
  871. begin
  872. FOptionParser.Free;
  873. if assigned(FOptions) then
  874. FreeAndNil(FOptions);
  875. inherited Destroy;
  876. end;
  877. function TCompilerOptions.GetOptString(Index: integer): String;
  878. begin
  879. Case Index of
  880. 1 : Result:=FCompiler;
  881. 2 : Result:=MakeTargetString(CompilerCPU,CompilerOS);
  882. 3 : Result:=FCompilerVersion;
  883. 4 : Result:=FOptionParser.ParseString(FGlobalInstallDir);
  884. 5 : Result:=FOptionParser.ParseString(FLocalInstallDir);
  885. 6 : Result:=fpmkunit.FixPath(FOptionParser.ParseString(FGlobalPrefix), True);
  886. 7 : Result:=fpmkunit.FixPath(FOptionParser.ParseString(FLocalPrefix), True);
  887. else
  888. Error('Unknown option');
  889. end;
  890. end;
  891. function TCompilerOptions.GetOptions: TStrings;
  892. begin
  893. if not assigned(FOptions) then
  894. begin
  895. FOptions := TStringList.Create;
  896. FOptions.Delimiter:=' ';
  897. end;
  898. Result := FOptions;
  899. end;
  900. procedure TCompilerOptions.SetOptString(Index: integer; const AValue: String);
  901. begin
  902. If AValue=GetOptString(Index) then
  903. Exit;
  904. Case Index of
  905. 1 : FCompiler:=AValue;
  906. 2 : StringToCPUOS(AValue,FCompilerCPU,FCompilerOS);
  907. 3 : begin
  908. FCompilerVersion:=AValue;
  909. FOptionParser.Values['CompilerVersion'] := FCompilerVersion;
  910. end;
  911. 4 : FGlobalInstallDir:=fpmkunit.FixPath(AValue, True);
  912. 5 : FLocalInstallDir:=fpmkunit.FixPath(AValue, True);
  913. 6 : begin
  914. FGlobalPrefix:=AValue;
  915. FOptionParser.Values['GlobalPrefix'] := GlobalPrefix;
  916. end;
  917. 7 : begin
  918. FLocalPrefix:=AValue;
  919. FOptionParser.Values['LocalPrefix'] := LocalPrefix;
  920. end
  921. else
  922. Error('Unknown option');
  923. end;
  924. end;
  925. procedure TCompilerOptions.SetCompilerCPU(const AValue: TCPU);
  926. begin
  927. if FCompilerCPU=AValue then
  928. exit;
  929. FCompilerCPU:=AValue;
  930. end;
  931. procedure TCompilerOptions.UpdateLocalRepositoryOption(FppkgOptions: TFppkgOptions);
  932. begin
  933. FOptionParser.Values['LocalRepository'] := FppkgOptions.GlobalSection.LocalRepository;
  934. end;
  935. procedure TCompilerOptions.CheckCompilerValues;
  936. var
  937. AVersion : string;
  938. ACpu : TCpu;
  939. AOs : TOS;
  940. begin
  941. if Compiler='' then
  942. Exit;
  943. // This is not the place to complain when the compiler does
  944. // not exist at all.
  945. if not FileExists(Compiler) then
  946. Exit;
  947. if (CompilerCPU=cpuNone) or
  948. (CompilerOS=osNone) or
  949. (CompilerVersion='') then
  950. begin
  951. GetCompilerInfo(Compiler,'-iVTPTO',AVersion,ACpu,AOs);
  952. if CompilerCPU=cpuNone then
  953. CompilerCPU := ACpu;
  954. if CompilerOS=osNone then
  955. CompilerOS:=AOs;
  956. if CompilerVersion='' then
  957. CompilerVersion:=AVersion;
  958. end;
  959. end;
  960. procedure TCompilerOptions.SetCompilerOS(const AValue: TOS);
  961. begin
  962. if FCompilerOS=AValue then
  963. exit;
  964. FCompilerOS:=AValue;
  965. end;
  966. function TCompilerOptions.HasOptions: boolean;
  967. begin
  968. result := assigned(FOptions);
  969. end;
  970. procedure TCompilerOptions.InitCompilerDefaults;
  971. var
  972. ACompilerVersion: string;
  973. fpcdir: string;
  974. begin
  975. FConfigVersion:=CurrentConfigVersion;
  976. if fcompiler = '' then
  977. FCompiler:=ExeSearch('fpc'+ExeExt,GetEnvironmentVariable('PATH'));
  978. if FCompiler='' then
  979. Raise EPackagerError.Create(SErrMissingFPC);
  980. // Detect compiler version/target from -i option
  981. GetCompilerInfo(FCompiler,'-iVTPTO',ACompilerVersion,FCompilerCPU,FCompilerOS);
  982. CompilerVersion := ACompilerVersion;
  983. // Temporary hack to workaround bug in fpc.exe that doesn't support spaces
  984. // We retrieve the real binary
  985. if FCompilerVersion='2.2.0' then
  986. FCompiler:=GetCompilerInfo(FCompiler,'-PB');
  987. log(llDebug,SLogDetectedCompiler,[FCompiler,FCompilerVersion,MakeTargetString(FCompilerCPU,FCompilerOS)]);
  988. // Use the same algorithm as the compiler, see options.pas
  989. // Except that the prefix is extracted and GlobalInstallDir is set using
  990. // that prefix
  991. {$ifdef Unix}
  992. FGlobalPrefix:='/usr/local/';
  993. if not DirectoryExists(FGlobalPrefix+'lib/fpc/'+FCompilerVersion+'/') and
  994. DirectoryExists('/usr/lib/fpc/'+FCompilerVersion+'/') then
  995. FGlobalPrefix:='/usr/';
  996. {$else unix}
  997. FGlobalPrefix:=ExtractFilePath(FCompiler)+'..'+PathDelim;
  998. if not(DirectoryExists(FGlobalPrefix+PathDelim+'units')) and
  999. not(DirectoryExists(FGlobalPrefix+PathDelim+'rtl')) then
  1000. FGlobalPrefix:=FGlobalPrefix+'..'+PathDelim;
  1001. FGlobalPrefix:=ExpandFileName(FGlobalPrefix);
  1002. {$endif unix}
  1003. log(llDebug,SLogDetectedPrefix,['global',FGlobalPrefix]);
  1004. // User writable install directory
  1005. if not IsSuperUser then
  1006. begin
  1007. FLocalPrefix:= '{LocalRepository}';
  1008. log(llDebug,SLogDetectedPrefix,['local',FLocalPrefix]);
  1009. end;
  1010. fpcdir:=fpmkunit.FixPath(GetEnvironmentVariable('FPCDIR'), True);
  1011. if fpcdir<>'' then
  1012. begin
  1013. {$ifndef Unix}
  1014. fpcdir:=ExpandFileName(fpcdir);
  1015. {$endif unix}
  1016. log(llDebug,SLogFPCDirEnv,[fpcdir]);
  1017. FGlobalInstallDir:=fpcdir;
  1018. end;
  1019. end;
  1020. procedure TCompilerOptions.LoadCompilerFromFile(const AFileName: String);
  1021. Var
  1022. Ini : TMemIniFile;
  1023. begin
  1024. Ini:=TMemIniFile.Create(AFileName);
  1025. try
  1026. FConfigFilename:=AFileName;
  1027. With Ini do
  1028. begin
  1029. FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
  1030. if (FConfigVersion<>CurrentConfigVersion) then
  1031. begin
  1032. log(llDebug,SLogUpgradingConfig,[AFileName]);
  1033. FSaveInifileChanges:=true;
  1034. if (FConfigVersion>CurrentConfigVersion) then
  1035. Error(SErrUnsupportedConfigVersion,[AFileName]);
  1036. end
  1037. else
  1038. begin
  1039. FSaveInifileChanges:=False;
  1040. end;
  1041. GlobalPrefix:=ReadString(SDefaults,KeyGlobalPrefix,FGlobalPrefix);
  1042. LocalPrefix:=ReadString(SDefaults,KeyLocalPrefix,FLocalPrefix);
  1043. FGlobalInstallDir:=fpmkunit.FixPath(ReadString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir), True);
  1044. FLocalInstallDir:=fpmkunit.FixPath(ReadString(SDefaults,KeyLocalInstallDir,FLocalInstallDir), True);
  1045. FCompiler:=ReadString(SDefaults,KeyCompiler,FCompiler);
  1046. FCompilerOS:=StringToOS(ReadString(SDefaults,KeyCompilerOS,OSToString(CompilerOS)));
  1047. FCompilerCPU:=StringToCPU(ReadString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU)));
  1048. CompilerVersion:=ReadString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  1049. end;
  1050. finally
  1051. Ini.Free;
  1052. end;
  1053. end;
  1054. function TCompilerOptions.SaveCompilerToFile(const AFileName: String): Boolean;
  1055. Var
  1056. Ini : TIniFile;
  1057. begin
  1058. Result := False;
  1059. try
  1060. if FileExists(AFileName) then
  1061. BackupFile(AFileName);
  1062. Ini:=TIniFile.Create(AFileName);
  1063. try
  1064. With Ini do
  1065. begin
  1066. WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
  1067. WriteString(SDefaults,KeyGlobalPrefix,FGlobalPrefix);
  1068. WriteString(SDefaults,KeyLocalPrefix,FLocalPrefix);
  1069. WriteString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir);
  1070. WriteString(SDefaults,KeyLocalInstallDir,FLocalInstallDir);
  1071. WriteString(SDefaults,KeyCompiler,FCompiler);
  1072. WriteString(SDefaults,KeyCompilerOS,OSToString(CompilerOS));
  1073. WriteString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU));
  1074. WriteString(SDefaults,KeyCompilerVersion,FCompilerVersion);
  1075. FSaveInifileChanges:=False;
  1076. end;
  1077. Ini.UpdateFile;
  1078. finally
  1079. Ini.Free;
  1080. end;
  1081. Result := True;
  1082. except
  1083. on E: Exception do
  1084. log(llWarning, SWarnFailedToWriteCompConf, [AFileName, E.Message]);
  1085. end;
  1086. end;
  1087. procedure TCompilerOptions.LogValues(ALogLevel: TLogLevel; const ACfgName:string);
  1088. begin
  1089. log(ALogLevel,SLogCompilerCfgHeader,[ACfgName,FConfigFilename]);
  1090. log(ALogLevel,SLogCompilerCfgCompiler,[FCompiler]);
  1091. log(ALogLevel,SLogCompilerCfgTarget,[MakeTargetString(CompilerCPU,CompilerOS)]);
  1092. log(ALogLevel,SLogCompilerCfgVersion,[FCompilerVersion]);
  1093. log(ALogLevel,SLogCompilerCfgGlobalPrefix,[FGlobalPrefix,GlobalPrefix]);
  1094. log(ALogLevel,SLogCompilerCfgLocalPrefix,[FLocalPrefix,LocalPrefix]);
  1095. log(ALogLevel,SLogCompilerCfgGlobalInstallDir,[FGlobalInstallDir,GlobalInstallDir]);
  1096. log(ALogLevel,SLogCompilerCfgLocalInstallDir,[FLocalInstallDir,LocalInstallDir]);
  1097. log(ALogLevel,SLogCompilerCfgOptions,[Options.DelimitedText]);
  1098. end;
  1099. end.