pkgoptions.pp 41 KB

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