fpcmmain.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. {
  2. $Id$
  3. Copyright (c) 2001 by Peter Vreman
  4. FPCMake - Main module
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$ifdef fpc}{$mode objfpc}{$endif}
  12. {$H+}
  13. unit fpcmmain;
  14. interface
  15. uses
  16. sysutils,classes,
  17. fpcmdic;
  18. const
  19. Version='v1.99.0';
  20. Title='fpcmake '+Version;
  21. TitleDate=Title+' ['+{$ifdef fpc}{$i %DATE}{$else}'n/a'{$endif}+']';
  22. type
  23. TTarget=(t_all,
  24. t_linux,t_go32v2,t_win32,t_os2,t_freebsd
  25. );
  26. const
  27. TargetStr : array[TTarget] of string=('all',
  28. 'linux','go32v2','win32','os2','freebsd'
  29. );
  30. TargetSuffix : array[TTarget] of string=('',
  31. '_linux','_go32v2','_win32','_os2','_freebsd'
  32. );
  33. type
  34. TKeyValueItem = class(TDictionaryItem)
  35. private
  36. FValue : string;
  37. public
  38. constructor Create(const k,v:string);
  39. property Value:string read FValue write FValue;
  40. end;
  41. TKeyValue = class(TDictionary)
  42. private
  43. function GetKey(const k:string):string;
  44. public
  45. procedure Add(const k,v:String);
  46. property Key[const s:string]:string read GetKey;default;
  47. end;
  48. TFPCMakeSection = class(TDictionaryItem)
  49. private
  50. FList : TStringList;
  51. FDictionary : TKeyValue;
  52. procedure PrintDic(p:TDictionaryItem);
  53. procedure BuildIniDic(p:TDictionaryItem);
  54. procedure BuildMakefileDic(p:TDictionaryItem);
  55. function GetKey(const k:string):string;
  56. public
  57. constructor Create(const n:string);
  58. constructor CreateKeyValue(const n:string);
  59. destructor Destroy;override;
  60. procedure AddLine(const s:string);
  61. procedure AddKey(const k,v:string);
  62. procedure ParseIni;
  63. procedure BuildIni;
  64. procedure BuildMakefile;
  65. procedure Print;
  66. property Key[const s:string]:string read GetKey;default;
  67. property List:TStringList read FList;
  68. property Dictionary:TKeyValue read FDictionary;
  69. end;
  70. TFPCMake = class
  71. private
  72. FStream : TStream;
  73. FFileName : string;
  74. FCommentChars : TSysCharSet;
  75. FEmptyLines : boolean;
  76. FSections : TDictionary;
  77. FPackageSec,
  78. FExportSec : TFPCMakeSection;
  79. FPackageName,
  80. FPackageVersion : string;
  81. FRequireList : TStringList;
  82. FVariables : TKeyValue;
  83. procedure Init;
  84. procedure ParseSec(p:TDictionaryItem);
  85. procedure PrintSec(p:TDictionaryItem);
  86. function GetSec(const AName:string):TDictionaryItem;
  87. public
  88. constructor Create(const AFileName:string);
  89. constructor CreateFromStream(s:TStream;const AFileName:string);
  90. destructor Destroy;override;
  91. procedure LoadSections;
  92. procedure LoadMakefileFPC;
  93. procedure LoadPackageSection;
  94. procedure LoadRequiredPackage(const ReqName,ReqVersion:string);
  95. procedure LoadRequires(FromFPCMake:TFPCMake);
  96. function GetTargetRequires(t:TTarget):TStringList;
  97. procedure CreateExportSection;
  98. procedure SubstVariables(var s:string);
  99. function GetVariable(const inivar:string):string;
  100. procedure Print;
  101. property Section[const s:string]:TDictionaryItem read GetSec;default;
  102. property RequireList:TStringList read FRequireList;
  103. property Variables:TKeyValue read FVariables;
  104. property PackageName:string read FPackageName;
  105. property PackageVersion:string read FPackageVersion;
  106. property PackageSec:TFPCMakeSection read FPackageSec;
  107. property ExportSec:TFPCMakeSection read FExportSec;
  108. property CommentChars:TSysCharSet read FCommentChars write FCommentChars;
  109. property EmptyLines:Boolean read FEmptyLines write FEmptyLines;
  110. end;
  111. function posidx(const substr,s : string;idx:integer):integer;
  112. implementation
  113. resourcestring
  114. s_not_list_sec='Not a list section "%s"';
  115. s_not_key_value_sec='Not a key-value section "%s"';
  116. s_err_section_start='%s:%d: Wrong section start';
  117. s_err_not_key_value='Parse error key=value excepted: "%s"';
  118. s_err_no_section='%s:%d: Entries without section';
  119. s_no_package_section='No package section found';
  120. s_no_package_name='No package name set';
  121. s_no_package_version='No package version set';
  122. s_err_require_format='Wrong require format "%s"';
  123. type
  124. tspecialdir=record
  125. dir,unitdir,packdir : string;
  126. end;
  127. const
  128. specialdirs = 4;
  129. specialdir : array[1..specialdirs] of tspecialdir=(
  130. (dir: 'rtl'; unitdir: '$(UNITSDIR)/rtl'; packdir: '$(FPCDIR)/rtl'),
  131. (dir: 'fcl'; unitdir: '$(UNITSDIR)/fcl'; packdir: '$(FPCDIR)/fcl'),
  132. (dir: 'api'; unitdir: '$(UNITSDIR)/api'; packdir: '$(FPCDIR)/api'),
  133. (dir: 'fv'; unitdir: '$(UNITSDIR)/fv'; packdir: '$(FPCDIR)/fv')
  134. );
  135. {****************************************************************************
  136. Helpers
  137. ****************************************************************************}
  138. Function PathExists ( F : String) : Boolean;
  139. Var
  140. Info : TSearchRec;
  141. begin
  142. if F[Length(f)] in ['/','\'] then
  143. Delete(f,length(f),1);
  144. PathExists:=(findfirst(F,fareadonly+faarchive+fahidden+fadirectory,info)=0) and
  145. ((info.attr and fadirectory)=fadirectory);
  146. findclose(Info);
  147. end;
  148. function posidx(const substr,s : string;idx:integer):integer;
  149. var
  150. i,j : integer;
  151. e : boolean;
  152. begin
  153. i:=idx;
  154. j:=0;
  155. e:=(length(SubStr)>0);
  156. while e and (i<=Length(s)-Length(SubStr)) do
  157. begin
  158. inc(i);
  159. if (SubStr[1]=s[i]) and (Substr=Copy(s,i,Length(SubStr))) then
  160. begin
  161. j:=i;
  162. e:=false;
  163. end;
  164. end;
  165. PosIdx:=j;
  166. end;
  167. {****************************************************************************
  168. TKeyValueItem
  169. ****************************************************************************}
  170. constructor TKeyValueItem.Create(const k,v:string);
  171. begin
  172. inherited Create(k);
  173. value:=v;
  174. end;
  175. {****************************************************************************
  176. TKeyValue
  177. ****************************************************************************}
  178. function TKeyValue.GetKey(const k:string):string;
  179. var
  180. p : TKeyValueItem;
  181. begin
  182. p:=TKeyValueItem(Search(k));
  183. if p=nil then
  184. GetKey:=''
  185. else
  186. GetKey:=p.Value;
  187. end;
  188. procedure TKeyValue.Add(const k,v:string);
  189. begin
  190. Insert(TKeyValueItem.Create(k,v));
  191. end;
  192. {****************************************************************************
  193. TFPCMakeSection
  194. ****************************************************************************}
  195. constructor TFPCMakeSection.Create(const n:string);
  196. begin
  197. inherited Create(n);
  198. FList:=TStringList.Create;
  199. FDictionary:=nil;
  200. end;
  201. constructor TFPCMakeSection.CreateKeyValue(const n:string);
  202. begin
  203. inherited Create(n);
  204. FList:=nil;
  205. FDictionary:=TKeyValue.Create;
  206. end;
  207. destructor TFPCMakeSection.Destroy;
  208. begin
  209. inherited Destroy;
  210. FList.Free;
  211. FDictionary.Free;
  212. end;
  213. procedure TFPCMakeSection.AddLine(const s:string);
  214. begin
  215. if FList=nil then
  216. raise Exception.Create(Format(s_not_list_sec,[Name]));
  217. FList.Add(s);
  218. end;
  219. procedure TFPCMakeSection.AddKey(const k,v:string);
  220. begin
  221. if FDictionary=nil then
  222. raise Exception.Create(Format(s_not_key_value_sec,[Name]));
  223. { Don't add empty values }
  224. if v<>'' then
  225. FDictionary.Add(k,v);
  226. end;
  227. procedure TFPCMakeSection.PrintDic(p:TDictionaryItem);
  228. begin
  229. with TKeyValueItem(p) do
  230. begin
  231. writeln(' ',name,' = "',value,'"');
  232. end;
  233. end;
  234. function TFPCMakeSection.GetKey(const k:string):string;
  235. begin
  236. if FDictionary=nil then
  237. raise Exception.Create(Format(s_not_key_value_sec,[Name]));
  238. GetKey:=FDictionary[k];
  239. end;
  240. procedure TFPCMakeSection.Print;
  241. var
  242. i : integer;
  243. begin
  244. writeln('[',Name,']');
  245. if assigned(FList) then
  246. begin
  247. writeln(' List:');
  248. for i:=0 to FList.Count-1 do
  249. Writeln(' "'+FList[i],'"');
  250. if assigned(FDictionary) then
  251. writeln('');
  252. end;
  253. if assigned(FDictionary) then
  254. begin
  255. writeln(' Dictionary:');
  256. FDictionary.Foreach(@PrintDic);
  257. end;
  258. end;
  259. procedure TFPCMakeSection.ParseIni;
  260. var
  261. p : TKeyValueItem;
  262. i,j,len,maxi : integer;
  263. s,newkey,value : string;
  264. begin
  265. { If already processed skip }
  266. if assigned(FDictionary) then
  267. exit;
  268. { Don't process rules section }
  269. if (Name='rules') then
  270. exit;
  271. { Parse the section }
  272. FDictionary:=TKeyValue.Create;
  273. { Parse the list }
  274. maxi:=FList.Count;
  275. i:=0;
  276. while (i<maxi) do
  277. begin
  278. s:=Trim(FList[i]);
  279. len:=Length(s);
  280. { Concat lines ending with \ }
  281. while s[len]='\' do
  282. begin
  283. Delete(s,len,1);
  284. if i+1<maxi then
  285. begin
  286. inc(i);
  287. s:=s+Trim(FList[i]);
  288. len:=Length(s);
  289. end;
  290. end;
  291. { Parse key=value line }
  292. j:=0;
  293. while (j<len) and (s[j+1] in ['A'..'Z','a'..'z','0'..'9','_']) do
  294. inc(j);
  295. NewKey:=Copy(s,1,j);
  296. While (j<len) and (s[j+1] in [' ',#9]) do
  297. inc(j);
  298. inc(j);
  299. if s[j]<>'=' then
  300. Raise Exception.Create(Format(s_err_not_key_value,[s]));
  301. While (j<len) and (s[j+1] in [' ',#9]) do
  302. inc(j);
  303. if j=len then
  304. Raise Exception.Create(Format(s_err_not_key_value,[s]));
  305. Value:=Copy(s,j+1,len-j);
  306. p:=TKeyValueItem(FDictionary[NewKey]);
  307. { Concat values if key already exists }
  308. if assigned(p) then
  309. p.Value:=p.Value+' '+Value
  310. else
  311. FDictionary.Add(NewKey,Value);
  312. inc(i);
  313. end;
  314. { List is not used anymore }
  315. FList.Free;
  316. FList:=nil;
  317. end;
  318. procedure TFPCMakeSection.BuildIniDic(p:TDictionaryItem);
  319. begin
  320. with TKeyValueItem(p) do
  321. begin
  322. FList.Add(Name+'='+Value);
  323. end;
  324. end;
  325. procedure TFPCMakeSection.BuildIni;
  326. begin
  327. if assigned(FList) then
  328. exit;
  329. FList:=TStringList.Create;
  330. FDictionary.Foreach(@BuildIniDic);
  331. FDictionary.Free;
  332. FDictionary:=nil;
  333. end;
  334. procedure TFPCMakeSection.BuildMakefileDic(p:TDictionaryItem);
  335. begin
  336. FList.Add(Uppercase(Name+'_'+TKeyValueItem(p).Name)+'='+TKeyValueItem(p).Value);
  337. end;
  338. procedure TFPCMakeSection.BuildMakefile;
  339. begin
  340. if assigned(FList) then
  341. exit;
  342. FList:=TStringList.Create;
  343. FDictionary.Foreach(@BuildMakefileDic);
  344. FDictionary.Free;
  345. FDictionary:=nil;
  346. end;
  347. {****************************************************************************
  348. TFPCMake
  349. ****************************************************************************}
  350. constructor TFPCMake.Create(const AFileName:string);
  351. begin
  352. FFileName:=AFileName;
  353. FStream:=nil;
  354. Init;
  355. end;
  356. constructor TFPCMake.CreateFromStream(s:TStream;const AFileName:string);
  357. begin
  358. FFileName:=AFileName;
  359. FStream:=s;
  360. Init;
  361. end;
  362. procedure TFPCMake.Init;
  363. begin
  364. FSections:=TDictionary.Create;
  365. FRequireList:=TStringList.Create;
  366. FVariables:=TKeyValue.Create;
  367. FCommentChars:=[';','#'];
  368. FEmptyLines:=false;
  369. FPackageName:='';
  370. FPackageVersion:='';
  371. FPackageSec:=nil;
  372. FExportSec:=nil;
  373. end;
  374. destructor TFPCMake.Destroy;
  375. begin
  376. FSections.Free;
  377. FRequireList.Free;
  378. FVariables.Free;
  379. end;
  380. procedure TFPCMake.LoadSections;
  381. var
  382. SLInput : TStringList;
  383. i,j,n : integer;
  384. s,
  385. SecName : string;
  386. CurrSec : TFPCMakeSection;
  387. begin
  388. try
  389. SLInput:=TStringList.Create;
  390. if assigned(FStream) then
  391. SLInput.LoadFromStream(FStream)
  392. else
  393. SLInput.LoadFromFile(FFileName);
  394. { Load Input into sections list }
  395. n:=SLInput.Count;
  396. i:=0;
  397. while (i<n) do
  398. begin
  399. s:=Trim(SLInput[i]);
  400. if (EmptyLines and (s='')) or
  401. ((s<>'') and not(s[1] in FCommentChars)) then
  402. begin
  403. { section start? }
  404. if (s<>'') and (s[1]='[') then
  405. begin
  406. j:=pos(']',s);
  407. if j=0 then
  408. raise Exception.Create(Format(s_err_section_start,[FFileName,i]));
  409. SecName:=Copy(s,2,j-2);
  410. CurrSec:=TFPCMakeSection(FSections[SecName]);
  411. if CurrSec=nil then
  412. CurrSec:=TFPCMakeSection(FSections.Insert(TFPCMakeSection.Create(SecName)));
  413. end
  414. else
  415. begin
  416. if CurrSec=nil then
  417. raise Exception.Create(Format(s_err_no_section,[FFileName,i]));
  418. { Insert string without spaces stripped }
  419. CurrSec.AddLine(SLInput[i]);
  420. end;
  421. end;
  422. inc(i);
  423. end;
  424. finally
  425. SLInput.Free;
  426. end;
  427. end;
  428. procedure TFPCMake.LoadMakefileFPC;
  429. begin
  430. LoadSections;
  431. { Parse all sections }
  432. FSections.Foreach(@ParseSec);
  433. end;
  434. procedure TFPCMake.LoadPackageSection;
  435. begin
  436. { Get package info from package section }
  437. FPackageSec:=TFPCMakeSection(FSections['package']);
  438. if FPackageSec=nil then
  439. begin
  440. Writeln('Note: no package section');
  441. exit;
  442. end;
  443. { Parse the section to key=value pairs }
  444. FPackageSec.ParseIni;
  445. { mandatory name }
  446. FPackageName:=FPackageSec['name'];
  447. if FPackageName='' then
  448. Raise Exception.Create(s_no_package_name);
  449. { mandatory version }
  450. FPackageVersion:=FPackageSec['version'];
  451. if FPackageVersion='' then
  452. Raise Exception.Create(s_no_package_version);
  453. { Set the ExportSec }
  454. FExportSec:=TFPCMakeSection(FSections[Lowercase(FPackageName)]);
  455. end;
  456. procedure TFPCMake.CreateExportSection;
  457. var
  458. t : TTarget;
  459. begin
  460. { Don't create a section twice }
  461. if FExportSec<>nil then
  462. exit;
  463. { Look if we've already an own section, else create a new
  464. key-value section }
  465. FExportSec:=TFPCMakeSection(FSections[LowerCase(FPackageName)]);
  466. if FExportSec=nil then
  467. FExportSec:=TFPCMakeSection(FSections.Insert(TFPCMakeSection.CreateKeyValue(LowerCase(FPackageName))));
  468. { Add default the values to the export section }
  469. FExportSec.AddKey('name',FPackageName);
  470. FExportSec.AddKey('version',FPackageVersion);
  471. { Add required packages }
  472. for t:=low(TTarget) to high(TTarget) do
  473. FExportSec.AddKey('require'+TargetSuffix[t],FPackageSec['require'+TargetSuffix[t]]);
  474. { Unit dir }
  475. {FExportSec.AddKey('unitdir','$(UNITSDIR)/'+Lowercase(PackageName));}
  476. end;
  477. procedure TFPCMake.LoadRequiredPackage(const ReqName,ReqVersion:string);
  478. function TryFile(const fn:string):boolean;
  479. var
  480. ReqFPCMake : TFPCMake;
  481. HList : TStringList;
  482. NewSec,ReqSec,Sec : TFPCMakeSection;
  483. begin
  484. TryFile:=false;
  485. if FileExists(fn) then
  486. begin
  487. writeln('Package ',ReqName,': ',fn);
  488. ReqFPCMake:=TFPCMake.Create(fn);
  489. ReqFPCMake.LoadMakefileFPC;
  490. ReqFPCMake.LoadPackageSection;
  491. { Check package name and version }
  492. if LowerCase(ReqFPCMake.PackageName)<>ReqName then
  493. raise Exception.Create('s_wrong_package_name');
  494. if (ReqVersion<>'') and (ReqFPCMake.PackageVersion<ReqVersion) then
  495. raise Exception.Create('s_wrong_package_version');
  496. { First load the requirements of this package }
  497. LoadRequires(ReqFPCMake);
  498. { Get a copy of the export section }
  499. if assigned(ReqFPCMake.ExportSec) then
  500. begin
  501. ReqFPCMake.ExportSec.BuildIni;
  502. NewSec:=TFPCMakeSection(FSections.Insert(TFPCMakeSection.Create(ReqName)));
  503. NewSec.List.AddStrings(ReqFPCMake.ExportSec.List);
  504. NewSec.ParseIni;
  505. end;
  506. { Get a copy of the require section }
  507. ReqSec:=TFPCMakeSection(ReqFPCMake['require']);
  508. if assigned(ReqSec) then
  509. begin
  510. ReqSec.BuildIni;
  511. NewSec:=TFPCMakeSection(FSections.Insert(TFPCMakeSection.Create(ReqName+'_require')));
  512. NewSec.List.AddStrings(ReqSec.List);
  513. NewSec.ParseIni;
  514. end;
  515. { Free }
  516. ReqFPCMake.Free;
  517. TryFile:=true;
  518. end;
  519. end;
  520. var
  521. s : string;
  522. i : integer;
  523. begin
  524. writeln(ReqName,' - ',ReqVersion);
  525. s:='$(PACKAGESDIR)/'+ReqName;
  526. For i:=1 to SpecialDirs do
  527. if SpecialDir[i].Dir=ReqName then
  528. begin
  529. s:=SpecialDir[i].PackDir;
  530. break;
  531. end;
  532. SubstVariables(s);
  533. if TryFile(s+'/Makefile.fpc') then
  534. exit;
  535. Raise Exception.Create('s_package_not_found');
  536. end;
  537. procedure TFPCMake.LoadRequires(FromFPCMake:TFPCMake);
  538. var
  539. s,
  540. ReqName,
  541. ReqVersion : string;
  542. i,j : integer;
  543. t : TTarget;
  544. Sec : TFPCMakeSection;
  545. begin
  546. Sec:=TFPCMakeSection(FromFPCMake['require']);
  547. if Sec=nil then
  548. exit;
  549. for t:=low(TTarget) to high(TTarget) do
  550. begin
  551. s:=Sec['packages'+TargetSuffix[t]];
  552. repeat
  553. i:=pos(' ',s);
  554. if i=0 then
  555. begin
  556. ReqName:=Trim(s);
  557. s:='';
  558. end
  559. else
  560. begin
  561. ReqName:=Trim(Copy(s,1,i));
  562. Delete(s,1,i);
  563. s:=TrimLeft(s);
  564. end;
  565. if ReqName<>'' then
  566. begin
  567. i:=Pos('(',ReqName);
  568. if i>0 then
  569. begin
  570. j:=Pos(')',ReqName);
  571. if (i=1) or (j=0) then
  572. Raise Exception.Create(Format(s_err_require_format,[ReqName]));
  573. ReqVersion:=Copy(ReqName,i+1,j-i-1);
  574. ReqName:=Copy(ReqName,1,i-1);
  575. end
  576. else
  577. ReqVersion:='';
  578. { We only use lowercase names }
  579. ReqName:=Lowercase(ReqName);
  580. { Already loaded ? }
  581. if not RequireList.Find(ReqName,i) then
  582. begin
  583. LoadRequiredPackage(ReqName,ReqVersion);
  584. RequireList.Add(ReqName);
  585. end;
  586. end;
  587. until s='';
  588. end;
  589. { Force an rtl dependency }
  590. if not RequireList.Find('rtl',i) then
  591. begin
  592. LoadRequiredPackage('rtl','');
  593. RequireList.Add('rtl');
  594. end;
  595. end;
  596. function TFPCMake.GetTargetRequires(t:TTarget):TStringList;
  597. var
  598. ReqSec : TFPCMakeSection;
  599. ReqList : TStringList;
  600. procedure AddReqSec(t:TTarget;Sec:TFPCMakeSection);
  601. var
  602. s,
  603. ReqName : string;
  604. RSec : TFPCMakeSection;
  605. i,j : integer;
  606. begin
  607. s:=Sec['packages'+TargetSuffix[t]];
  608. while s<>'' do
  609. begin
  610. i:=pos(' ',s);
  611. if i=0 then
  612. begin
  613. ReqName:=Trim(s);
  614. s:='';
  615. end
  616. else
  617. begin
  618. ReqName:=Trim(Copy(s,1,i));
  619. Delete(s,1,i);
  620. s:=TrimLeft(s);
  621. end;
  622. if ReqName<>'' then
  623. begin
  624. i:=Pos('(',ReqName);
  625. if i>0 then
  626. ReqName:=Copy(ReqName,1,i-1);
  627. { We only use lowercase names }
  628. ReqName:=Lowercase(ReqName);
  629. { Already loaded ? }
  630. if not ReqList.Find(ReqName,i) then
  631. begin
  632. RSec:=TFPCMakeSection(FSections[ReqName+'_require']);
  633. if assigned(RSec) then
  634. begin
  635. { for packages we depend on always include the
  636. target and all keys }
  637. if t<>t_all then
  638. AddReqSec(t_all,RSec);
  639. AddReqSec(t,RSec);
  640. end;
  641. ReqList.Add(ReqName);
  642. end;
  643. end;
  644. end;
  645. end;
  646. begin
  647. ReqList:=TStringList.Create;
  648. ReqSec:=TFPCMakeSection(FSections['require']);
  649. if assigned(ReqSec) then
  650. AddReqSec(t,ReqSec);
  651. GetTargetRequires:=ReqList;
  652. end;
  653. procedure TFPCMake.SubstVariables(var s:string);
  654. var
  655. i,j,k : integer;
  656. s2,s3 : string;
  657. Sec : TFPCMakeSection;
  658. begin
  659. repeat
  660. i:=Pos('$(',s);
  661. if i=0 then
  662. break;
  663. j:=PosIdx(')',s,i+2);
  664. s2:=Copy(s,i+2,j-i-2);
  665. k:=pos('.',s2);
  666. if k>0 then
  667. begin
  668. s3:=Copy(s2,k+1,Length(s2)-k);
  669. s2:=Copy(s2,1,k-1);
  670. Sec:=TFPCMakeSection(Section[s2]);
  671. if assigned(Sec) then
  672. s2:=Sec[s3]
  673. else
  674. s2:='';
  675. end
  676. else
  677. s2:=Variables[s2];
  678. Delete(s,i,j-i+1);
  679. Insert(s2,s,i);
  680. until false;
  681. end;
  682. function TFPCMake.GetVariable(const inivar:string):string;
  683. var
  684. Sec : TFPCMakeSection;
  685. Dic : TKeyValue;
  686. i : integer;
  687. begin
  688. Result:='';
  689. i:=Pos('.',inivar);
  690. if i<>0 then
  691. begin
  692. Sec:=TFPCMakeSection(FSections[Copy(Inivar,1,i-1)]);
  693. if assigned(Sec) then
  694. begin
  695. Dic:=TKeyValue(Sec.Dictionary);
  696. Result:=Dic[Copy(IniVar,i+1,Length(IniVar)-i)];
  697. end
  698. else
  699. exit;
  700. end
  701. else
  702. Result:=Variables[IniVar];
  703. end;
  704. procedure TFPCMake.ParseSec(p:TDictionaryItem);
  705. begin
  706. TFPCMakeSection(p).ParseIni;
  707. end;
  708. procedure TFPCMake.PrintSec(p:TDictionaryItem);
  709. begin
  710. TFPCMakeSection(p).Print;
  711. end;
  712. procedure TFPCMake.Print;
  713. begin
  714. FSections.Foreach(@PrintSec);
  715. end;
  716. function TFPCMake.GetSec(const AName:string):TDictionaryItem;
  717. begin
  718. GetSec:=FSections.Search(AName);
  719. end;
  720. end.
  721. {
  722. $Log$
  723. Revision 1.1 2001-01-24 21:59:36 peter
  724. * first commit of new fpcmake
  725. }