/components/codetools/codetoolsconfig.pas

http://github.com/graemeg/lazarus · Pascal · 485 lines · 372 code · 50 blank · 63 comment · 35 complexity · 14e2dd87516f139b15f5191aceea2ca9 MD5 · raw file

  1. {
  2. ***************************************************************************
  3. * *
  4. * This source is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This code is distributed in the hope that it will be useful, but *
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  12. * General Public License for more details. *
  13. * *
  14. * A copy of the GNU General Public License is available on the World *
  15. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  16. * obtain it by writing to the Free Software Foundation, *
  17. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. * *
  19. ***************************************************************************
  20. Author: Mattias Gaertner
  21. Abstract:
  22. This unit helps to setup and configure the codetools.
  23. Example:
  24. Create an empty unit empty.pas and do
  25. Options:=TCodeToolsOptions.Create;
  26. Options.LoadFromFile('config.xml');
  27. Options.FPCPath:='/usr/bin/ppc386';
  28. Options.FPCSrcDir:='/home/username/freepascal/fpc';
  29. Options.LazarusSrcDir:='/home/username/pascal/lazarus';
  30. Options.ProjectDir:='/home/username/pascal/project1/';
  31. Options.TestPascalFile:=Options.ProjectDir+'empty.pas';
  32. CodeToolBoss.Init(Options);
  33. Options.SaveToFile('config.xml');
  34. Options.Free;
  35. .. use CodeToolBoss ..
  36. }
  37. unit CodeToolsConfig;
  38. {$mode objfpc}{$H+}
  39. {$I codetools.inc}
  40. interface
  41. uses
  42. Classes, SysUtils, Laz2_XMLCfg, Laz2_XMLRead, Laz2_XMLWrite, Laz2_DOM,
  43. FileProcs, LazFileUtils, LazFileCache, LazUTF8, CodeCache, DefineTemplates;
  44. type
  45. { TCodeBufXMLConfig }
  46. TCodeBufXMLConfig = class(TXMLConfig)
  47. private
  48. FCodeCache: TCodeCache;
  49. protected
  50. fKeepFileAttributes: boolean;
  51. procedure ReadXMLFile(out ADoc: TXMLDocument; const AFilename: String); override;
  52. procedure WriteXMLFile(ADoc: TXMLDocument; const AFileName: String); override;
  53. function GetCache: TCodeCache;
  54. public
  55. constructor CreateWithCache(AFilename: string;
  56. LoadContent: boolean = true; // init/load from disk
  57. LoadFileAttributes: boolean = true; // load lineending and encoding
  58. ASource: string = ''; // init with this source
  59. ACache: TCodeCache = nil);
  60. property CodeCache: TCodeCache read FCodeCache write FCodeCache;
  61. property KeepFileAttributes: boolean read fKeepFileAttributes write fKeepFileAttributes;
  62. end;
  63. var
  64. DefaultConfigCodeCache: TCodeCache = nil; // set by CodeToolBoss
  65. type
  66. { TCodeToolsOptions }
  67. TCodeToolsOptions = class
  68. private
  69. FConfigCaches: TFPCTargetConfigCaches;
  70. FFPCOptions: string;
  71. FFPCPath: string;
  72. FFPCSrcDir: string;
  73. FFPCUnitPath: string;
  74. FLazarusSrcDir: string;
  75. FLazarusSrcOptions: string;
  76. FLCLWidgetType: string;
  77. FModified: boolean;
  78. FPPUExt: string;
  79. FProjectDir: string;
  80. FSourceCaches: TFPCSourceCaches;
  81. FTargetOS: string;
  82. FTargetProcessor: string;
  83. FTestPascalFile: string;
  84. FUnitLinkList: string;
  85. FUnitLinkListValid: boolean;
  86. procedure SetFPCOptions(const AValue: string);
  87. procedure SetFPCPath(const AValue: string);
  88. procedure SetFPCSrcDir(const AValue: string);
  89. procedure SetFPCUnitPath(const AValue: string);
  90. procedure SetLazarusSrcDir(const AValue: string);
  91. procedure SetLCLWidgetType(const AValue: string);
  92. procedure SetLazarusSrcOptions(const AValue: string);
  93. procedure SetModified(const AValue: boolean);
  94. procedure SetPPUExt(const AValue: string);
  95. procedure SetProjectDir(const AValue: string);
  96. procedure SetTargetOS(const AValue: string);
  97. procedure SetTargetProcessor(const AValue: string);
  98. procedure SetTestPascalFile(const AValue: string);
  99. procedure SetUnitLinkList(const AValue: string);
  100. procedure SetUnitLinkListValid(const AValue: boolean);
  101. public
  102. constructor Create;
  103. destructor Destroy; override;
  104. procedure InitWithEnvironmentVariables;
  105. function FindDefaultCompilerFilename: string;
  106. procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
  107. procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
  108. procedure SaveToFile(const Filename: string);
  109. procedure LoadFromFile(const Filename: string);
  110. property Modified: boolean read FModified write SetModified;
  111. // FPC
  112. property FPCSrcDir: string read FFPCSrcDir write SetFPCSrcDir; // e.g. /usr/share/fpcsrc
  113. property FPCPath: string read FFPCPath write SetFPCPath; // e.g. /usr/bin/fpc or /usr/bin/ppc386
  114. property FPCOptions: string read FFPCOptions write SetFPCOptions; // extra options for fpc
  115. property TargetOS: string read FTargetOS write SetTargetOS;
  116. property TargetProcessor: string read FTargetProcessor write SetTargetProcessor;
  117. property TestPascalFile: string read FTestPascalFile write SetTestPascalFile; // points to an empty unit
  118. property FPCUnitPath: string read FFPCUnitPath write SetFPCUnitPath;
  119. property PPUExt: string read FPPUExt write SetPPUExt;
  120. property SourceCaches: TFPCSourceCaches read FSourceCaches;
  121. property ConfigCaches: TFPCTargetConfigCaches read FConfigCaches;
  122. property UnitLinkListValid: boolean read FUnitLinkListValid write SetUnitLinkListValid;
  123. property UnitLinkList: string read FUnitLinkList write SetUnitLinkList;
  124. // Project
  125. property ProjectDir: string read FProjectDir write SetProjectDir;
  126. // Lazarus
  127. property LazarusSrcDir: string read FLazarusSrcDir write SetLazarusSrcDir;
  128. property LCLWidgetType: string read FLCLWidgetType write SetLCLWidgetType;
  129. property LazarusSrcOptions: string read FLazarusSrcOptions write SetLazarusSrcOptions;
  130. end;
  131. implementation
  132. { TCodeToolsOptions }
  133. procedure TCodeToolsOptions.SetFPCOptions(const AValue: string);
  134. begin
  135. if FFPCOptions=AValue then exit;
  136. FFPCOptions:=AValue;
  137. Modified:=true;
  138. end;
  139. procedure TCodeToolsOptions.SetFPCPath(const AValue: string);
  140. var
  141. NewValue: String;
  142. begin
  143. NewValue:=TrimAndExpandFilename(AValue);
  144. if FFPCPath=NewValue then exit;
  145. FFPCPath:=NewValue;
  146. FUnitLinkListValid:=false;
  147. Modified:=true;
  148. end;
  149. procedure TCodeToolsOptions.SetFPCSrcDir(const AValue: string);
  150. var
  151. NewValue: String;
  152. begin
  153. NewValue:=TrimAndExpandFilename(AValue);
  154. if FFPCSrcDir=NewValue then exit;
  155. FFPCSrcDir:=NewValue;
  156. FUnitLinkListValid:=false;
  157. Modified:=true;
  158. end;
  159. procedure TCodeToolsOptions.SetFPCUnitPath(const AValue: string);
  160. begin
  161. if FFPCUnitPath=AValue then exit;
  162. FFPCUnitPath:=AValue;
  163. FUnitLinkListValid:=false;
  164. Modified:=true;
  165. end;
  166. procedure TCodeToolsOptions.SetLazarusSrcDir(const AValue: string);
  167. var
  168. NewValue: String;
  169. begin
  170. NewValue:=TrimAndExpandFilename(AValue);
  171. if FLazarusSrcDir=NewValue then exit;
  172. FLazarusSrcDir:=NewValue;
  173. Modified:=true;
  174. end;
  175. procedure TCodeToolsOptions.SetLCLWidgetType(const AValue: string);
  176. begin
  177. if FLCLWidgetType=AValue then exit;
  178. FLCLWidgetType:=AValue;
  179. Modified:=true;
  180. end;
  181. procedure TCodeToolsOptions.SetLazarusSrcOptions(const AValue: string);
  182. begin
  183. if FLazarusSrcOptions=AValue then exit;
  184. FLazarusSrcOptions:=AValue;
  185. Modified:=true;
  186. end;
  187. procedure TCodeToolsOptions.SetModified(const AValue: boolean);
  188. begin
  189. if FModified=AValue then exit;
  190. FModified:=AValue;
  191. end;
  192. procedure TCodeToolsOptions.SetPPUExt(const AValue: string);
  193. begin
  194. if FPPUExt=AValue then exit;
  195. FPPUExt:=AValue;
  196. Modified:=true;
  197. end;
  198. procedure TCodeToolsOptions.SetProjectDir(const AValue: string);
  199. begin
  200. if FProjectDir=AValue then exit;
  201. FProjectDir:=AppendPathDelim(AValue);
  202. Modified:=true;
  203. end;
  204. procedure TCodeToolsOptions.SetTargetOS(const AValue: string);
  205. begin
  206. if FTargetOS=AValue then exit;
  207. FTargetOS:=AValue;
  208. FUnitLinkListValid:=false;
  209. Modified:=true;
  210. end;
  211. procedure TCodeToolsOptions.SetTargetProcessor(const AValue: string);
  212. begin
  213. if FTargetProcessor=AValue then exit;
  214. FTargetProcessor:=AValue;
  215. FUnitLinkListValid:=false;
  216. Modified:=true;
  217. end;
  218. procedure TCodeToolsOptions.SetTestPascalFile(const AValue: string);
  219. begin
  220. if FTestPascalFile=AValue then exit;
  221. FTestPascalFile:=AValue;
  222. Modified:=true;
  223. end;
  224. procedure TCodeToolsOptions.SetUnitLinkList(const AValue: string);
  225. begin
  226. if FUnitLinkList=AValue then exit;
  227. FUnitLinkList:=AValue;
  228. Modified:=true;
  229. end;
  230. procedure TCodeToolsOptions.SetUnitLinkListValid(const AValue: boolean);
  231. begin
  232. if FUnitLinkListValid=AValue then exit;
  233. FUnitLinkListValid:=AValue;
  234. Modified:=true;
  235. end;
  236. constructor TCodeToolsOptions.Create;
  237. begin
  238. FPPUExt:='.ppu';
  239. FLCLWidgetType:='gtk2';
  240. FConfigCaches:=TFPCTargetConfigCaches.Create(nil);
  241. FSourceCaches:=TFPCSourceCaches.Create(nil);
  242. end;
  243. destructor TCodeToolsOptions.Destroy;
  244. begin
  245. FreeAndNil(FConfigCaches);
  246. FreeAndNil(FSourceCaches);
  247. inherited Destroy;
  248. end;
  249. procedure TCodeToolsOptions.InitWithEnvironmentVariables;
  250. { procedure WriteEnv;
  251. var
  252. i: Integer;
  253. begin
  254. for i:=0 to GetEnvironmentVariableCount-1 do
  255. debugln(['TCodeToolsOptions.InitWithEnvironmentVariables ',i,' ',GetEnvironmentStringUTF8(i)]);
  256. end;
  257. }
  258. begin
  259. if GetEnvironmentVariableUTF8('PP')<>'' then
  260. FPCPath:=GetEnvironmentVariableUTF8('PP')
  261. else if (FPCPath='') or not FileExistsCached(FPCPath) then
  262. FPCPath:=FindDefaultCompilerFilename;
  263. if GetEnvironmentVariableUTF8('FPCDIR')<>'' then
  264. FPCSrcDir:=GetEnvironmentVariableUTF8('FPCDIR');
  265. if GetEnvironmentVariableUTF8('LAZARUSDIR')<>'' then
  266. LazarusSrcDir:=GetEnvironmentVariableUTF8('LAZARUSDIR');
  267. if GetEnvironmentVariableUTF8('FPCTARGET')<>'' then
  268. TargetOS:=GetEnvironmentVariableUTF8('FPCTARGET');
  269. if GetEnvironmentVariableUTF8('FPCTARGETCPU')<>'' then
  270. TargetProcessor:=GetEnvironmentVariableUTF8('FPCTARGETCPU');
  271. end;
  272. function TCodeToolsOptions.FindDefaultCompilerFilename: string;
  273. begin
  274. Result:=SearchFileInPath(GetDefaultCompilerFilename,'',
  275. GetEnvironmentVariableUTF8('PATH'),PathSeparator,ctsfcDefault);
  276. end;
  277. procedure TCodeToolsOptions.SaveToXMLConfig(XMLConfig: TXMLConfig;
  278. const Path: string);
  279. begin
  280. XMLConfig.SetDeleteValue(Path+'FPC/Options/Value',FPCOptions,'');
  281. XMLConfig.SetDeleteValue(Path+'FPC/CompilerPath/Value',FPCPath,'');
  282. XMLConfig.SetDeleteValue(Path+'FPC/SrcDir/Value',FPCSrcDir,'');
  283. XMLConfig.SetDeleteValue(Path+'FPC/UnitPath/Value',FPCUnitPath,'');
  284. XMLConfig.SetDeleteValue(Path+'FPC/TargetOS/Value',TargetOS,'');
  285. XMLConfig.SetDeleteValue(Path+'FPC/TargetProcessor/Value',TargetProcessor,'');
  286. XMLConfig.SetDeleteValue(Path+'FPC/PPUExt/Value',PPUExt,'.ppu');
  287. XMLConfig.SetDeleteValue(Path+'FPC/TestPascalFile/Value',TestPascalFile,'');
  288. XMLConfig.SetDeleteValue(Path+'FPC/UnitLinkList/Value',UnitLinkList,'');
  289. XMLConfig.SetDeleteValue(Path+'FPC/UnitLinkList/Valid',UnitLinkListValid,false);
  290. XMLConfig.SetDeleteValue(Path+'Lazarus/SrcDir/Value',LazarusSrcDir,'');
  291. XMLConfig.SetDeleteValue(Path+'Lazarus/SrcDirOptions/Value',LazarusSrcOptions,'');
  292. XMLConfig.SetDeleteValue(Path+'Lazarus/LCLWidgetType/Value',LCLWidgetType,'');
  293. XMLConfig.SetDeleteValue(Path+'Project/Dir/Value',ProjectDir,'');
  294. FConfigCaches.SaveToXMLConfig(XMLConfig,Path+'FPCConfigCaches/');
  295. FSourceCaches.SaveToXMLConfig(XMLConfig,Path+'FPCSrcDirCaches/');
  296. Modified:=false;
  297. end;
  298. procedure TCodeToolsOptions.LoadFromXMLConfig(XMLConfig: TXMLConfig;
  299. const Path: string);
  300. var
  301. i: Integer;
  302. UnitPath: string;
  303. begin
  304. FPCOptions:=XMLConfig.GetValue(Path+'FPC/Options/Value','');
  305. FPCPath:=XMLConfig.GetValue(Path+'FPC/CompilerPath/Value','');
  306. FPCSrcDir:=XMLConfig.GetValue(Path+'FPC/SrcDir/Value','');
  307. UnitPath:=XMLConfig.GetValue(Path+'FPC/UnitPath/Value','');
  308. for i:=1 to length(UnitPath) do
  309. if (UnitPath[i] in [#0..#8,#10..#31]) then
  310. UnitPath[i]:=';';
  311. FPCUnitPath:=UnitPath;
  312. TargetOS:=XMLConfig.GetValue(Path+'FPC/TargetOS/Value','');
  313. TargetProcessor:=XMLConfig.GetValue(Path+'FPC/TargetProcessor/Value','');
  314. PPUExt:=XMLConfig.GetValue(Path+'FPC/PPUExt/Value','.ppu');
  315. TestPascalFile:=XMLConfig.GetValue(Path+'FPC/TestPascalFile/Value','');
  316. UnitLinkList:=XMLConfig.GetValue(Path+'FPC/UnitLinkList/Value','');
  317. // UnitLinkListValid must be set as last
  318. UnitLinkListValid:=XMLConfig.GetValue(Path+'FPC/UnitLinkList/Valid',false);
  319. FConfigCaches.LoadFromXMLConfig(XMLConfig,Path+'FPCConfigCaches/');
  320. FSourceCaches.LoadFromXMLConfig(XMLConfig,Path+'FPCSrcDirCaches/');
  321. LazarusSrcDir:=XMLConfig.GetValue(Path+'Lazarus/SrcDir/Value','');
  322. LazarusSrcOptions:=XMLConfig.GetValue(Path+'Lazarus/SrcDirOptions/Value','');
  323. LCLWidgetType:=XMLConfig.GetValue(Path+'Lazarus/LCLWidgetType/Value','');
  324. ProjectDir:=XMLConfig.GetValue(Path+'Project/Dir/Value','');
  325. Modified:=false;
  326. end;
  327. procedure TCodeToolsOptions.SaveToFile(const Filename: string);
  328. var
  329. XMLConfig: TXMLConfig;
  330. begin
  331. XMLConfig:=TXMLConfig.CreateClean(Filename);
  332. try
  333. SaveToXMLConfig(XMLConfig,'CodeToolsOptions/');
  334. XMLConfig.Flush;
  335. finally
  336. XMLConfig.Free;
  337. end;
  338. end;
  339. procedure TCodeToolsOptions.LoadFromFile(const Filename: string);
  340. var
  341. XMLConfig: TXMLConfig;
  342. begin
  343. XMLConfig:=TXMLConfig.Create(Filename);
  344. try
  345. LoadFromXMLConfig(XMLConfig,'CodeToolsOptions/');
  346. XMLConfig.Flush;
  347. finally
  348. XMLConfig.Free;
  349. end;
  350. end;
  351. { TCodeBufXMLConfig }
  352. procedure TCodeBufXMLConfig.ReadXMLFile(out ADoc: TXMLDocument;
  353. const AFilename: String);
  354. var
  355. Buf: TCodeBuffer;
  356. ms: TMemoryStream;
  357. Cache: TCodeCache;
  358. begin
  359. Cache:=GetCache;
  360. if Cache<>nil then begin
  361. Buf:=Cache.LoadFile(AFilename);
  362. if Buf<>nil then begin
  363. fKeepFileAttributes:=true;
  364. ms:=TMemoryStream.Create;
  365. try
  366. Buf.SaveToStream(ms);
  367. ms.Position:=0;
  368. Laz2_XMLRead.ReadXMLFile(ADoc, ms, ReadFlags);
  369. exit; // success
  370. finally
  371. ms.Free;
  372. end;
  373. end;
  374. end;
  375. // try default (this will create the normal exceptions)
  376. inherited ReadXMLFile(ADoc, AFilename);
  377. end;
  378. procedure TCodeBufXMLConfig.WriteXMLFile(ADoc: TXMLDocument;
  379. const AFileName: String);
  380. var
  381. Buf: TCodeBuffer;
  382. ms: TMemoryStream;
  383. Cache: TCodeCache;
  384. begin
  385. Cache:=GetCache;
  386. if Cache<>nil then begin
  387. Buf:=nil;
  388. if (not fKeepFileAttributes) or (not FileExistsCached(AFileName)) then
  389. Buf:=Cache.CreateFile(AFilename)
  390. else
  391. Buf:=Cache.LoadFile(AFilename);
  392. if Buf<>nil then begin
  393. fKeepFileAttributes:=true;
  394. ms:=TMemoryStream.Create;
  395. try
  396. Laz2_XMLWrite.WriteXMLFile(ADoc, ms, WriteFlags);
  397. ms.Position:=0;
  398. Buf.LoadFromStream(ms);
  399. if Buf.FileOnDiskIsEqual then exit;
  400. //debugln(['TCodeBufXMLConfig.WriteXMLFile writing ',AFileName,' ...']);
  401. if Buf.Save then exit; // success
  402. finally
  403. ms.Free;
  404. end;
  405. end;
  406. end;
  407. // try default (this will create the normal exceptions)
  408. inherited WriteXMLFile(ADoc, AFileName);
  409. end;
  410. function TCodeBufXMLConfig.GetCache: TCodeCache;
  411. begin
  412. Result:=CodeCache;
  413. if Result=nil then
  414. Result:=DefaultConfigCodeCache;
  415. end;
  416. constructor TCodeBufXMLConfig.CreateWithCache(AFilename: string;
  417. LoadContent: boolean; LoadFileAttributes: boolean; ASource: string;
  418. ACache: TCodeCache);
  419. begin
  420. CodeCache:=ACache;
  421. fKeepFileAttributes:=LoadFileAttributes;
  422. if (ASource<>'') then
  423. inherited CreateWithSource(AFilename,ASource)
  424. else if LoadContent then
  425. inherited Create(AFilename)
  426. else
  427. inherited CreateClean(AFilename);
  428. end;
  429. end.