pkgmkconv.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. unit pkgmkconv;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,pkghandler;
  6. { TMakeFileConverter }
  7. Type
  8. TSectionType = (stNone,stPackage,stTarget,stclean,stinstall,stCompiler,
  9. stDefault,stRequire,stRules,stPrerules);
  10. TMakeFileConverter = Class(TPackagehandler)
  11. Private
  12. FSection : TSectionType;
  13. FPackageName,
  14. FpackageDir,
  15. FPackageOptions,
  16. FPackageDeps,
  17. FBuilDUnit,
  18. FSubName,
  19. FPackageVersion : String;
  20. // Reading;
  21. procedure DoPackageLine(Const S : String);
  22. Procedure DoTargetLine(Line : String; Var T,R,D : TStrings);
  23. Procedure DoInstallLine(Line : String; Var IFL : TStrings);
  24. procedure DoCleanLine(Line : String; Var CFL : TStrings);
  25. procedure DoRequireLine(Line : String);
  26. procedure DoCompilerLine(Line : String;Var SD : TStrings);
  27. // Writing;
  28. procedure WriteOSCPUCheck(Src: TStrings;OS,CPU : String);
  29. procedure StartPackage(Src : TStrings; Dir,OS : String);
  30. procedure EndPackage(Src : TStrings; Dir,OS : String);
  31. procedure DoTargets(Src,T,R,SD : TStrings; Dir,Prefix : String);
  32. procedure DoCleans(Src,CFL : TStrings);
  33. procedure DoInstalls(Src,IFL : TStrings);
  34. Procedure StartInstaller(Src : TStrings);
  35. Procedure EndInstaller(Src : TStrings);
  36. Function GetLine (L : TStrings; Var I : Integer) : String;
  37. procedure ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
  38. Procedure ConvertFile(Const Source,Dest: String);
  39. Public
  40. Function Execute(const Args:TActionArgs):boolean;override;
  41. end;
  42. implementation
  43. uses typinfo,pkgmessages;
  44. Function GetWord(var S : String; Sep : Char) : String;
  45. Var
  46. L : Integer;
  47. begin
  48. L:=Pos(Sep,S);
  49. If (L=0) then
  50. L:=Length(S)+1;
  51. Result:=Copy(S,1,L-1);
  52. Delete(S,1,L);
  53. S:=Trim(S);
  54. end;
  55. Function GetWord(var S : String) : String;
  56. begin
  57. Result:=GetWord(S,' ');
  58. end;
  59. Function IsCPU (S: String) : Boolean;
  60. begin
  61. Result:=Pos(lowercase(S)+',','i386,powerpc,arm,alpha,sparc,')<>0
  62. end;
  63. Function GetOSCPU(L : String; var OS,CPU : String) : String;
  64. Procedure Add(Var A : String; ad : String);
  65. begin
  66. If (A<>'') then
  67. A:=A+',';
  68. A:=A+ad;
  69. end;
  70. Var
  71. S : String;
  72. begin
  73. OS:='';
  74. CPU:='';
  75. S:=GetWord(L,',');
  76. While (S<>'') do
  77. begin
  78. If (S<>'all') then
  79. If IsCPU(S) then
  80. Add(CPU,S)
  81. else
  82. Add(OS,S);
  83. S:=GetWord(L,',');
  84. end;
  85. end;
  86. { TMakeFileConverter }
  87. procedure TMakeFileConverter.StartInstaller(Src: TStrings);
  88. begin
  89. With Src do
  90. begin
  91. Add('{$mode objfpc}{$H+}');
  92. Add('program fpmake;');
  93. Add('');
  94. Add(' { Generated automatically by '+ExtractFileName(Paramstr(0))+' on '+DateToStr(Sysutils.Date)+' }');
  95. Add('');
  96. Add('uses fpmktype,fpmkunit;');
  97. Add('');
  98. Add('Var');
  99. Add(' T : TTarget;');
  100. Add('');
  101. Add('begin');
  102. Add(' With Installer do ');
  103. Add(' begin');
  104. end;
  105. end;
  106. procedure TMakeFileConverter.EndInstaller(Src: TStrings);
  107. begin
  108. With Src do
  109. begin
  110. Add(' Run;');
  111. Add(' end;');
  112. Add('end.');
  113. Add('');
  114. end;
  115. end;
  116. Function TMakeFileConverter.GetLine (L : TStrings; Var I : Integer) : String;
  117. Var
  118. P : Integer;
  119. OK : Boolean;
  120. begin
  121. OK:=False;
  122. Result:='';
  123. Repeat
  124. Result:=Result+L[i];
  125. P:=Pos('#',Result);
  126. If (P>0) then
  127. Result:=Copy(Result,1,P-1);
  128. Result:=Trim(Result);
  129. P:=Length(Result);
  130. If (P>0) and (Result[P]='\') then
  131. Result:=Copy(Result,1,P-1)
  132. else
  133. OK:=(Result<>'');
  134. if Not OK then
  135. Inc(I);
  136. Until OK or (I>L.Count-1);
  137. end;
  138. Function SplitNamevalue(Const S : String; Var AName,AValue : String) : boolean;
  139. var
  140. L : Integer;
  141. begin
  142. L:=Pos('=',S);
  143. Result:=(L<>0);
  144. If Result then
  145. begin
  146. AName:=LowerCase(trim(Copy(S,1,L-1)));
  147. AValue:=S;
  148. Delete(AValue,1,L);
  149. AValue:=Trim(Avalue);
  150. end
  151. else
  152. begin
  153. AName:='';
  154. AValue:='';
  155. end;
  156. end;
  157. procedure TMakeFileConverter.StartPackage(Src : TStrings; Dir,OS : String);
  158. Var
  159. S : String;
  160. begin
  161. With Src do
  162. begin
  163. Add(' { ');
  164. Add(' '+FPackageName);
  165. Add(' } ');
  166. Add(' StartPackage('''+FPackageName+''');');
  167. If (Dir<>'') then
  168. Add(' Directory:='''+ExcludeTrailingPathDelimiter(Dir)+''';');
  169. If (OS<>'') and (OS<>'all') then
  170. Add(' OS:=['+OS+'];');
  171. If (FPackageVersion<>'') then
  172. Add(' Version:='''+FPackageVersion+''';');
  173. If (FPackageOptions<>'') then
  174. Add(' Options:='''+FPackageOptions+''';');
  175. If (FPackageDeps<>'') then
  176. begin
  177. S:=GetWord(FPackageDeps);
  178. While S<>'' do
  179. begin
  180. Add(' Dependencies.Add('''+S+''');');
  181. S:=GetWord(FPackageDeps);
  182. end;
  183. end;
  184. end;
  185. end;
  186. procedure TMakeFileConverter.EndPackage(Src : TStrings; Dir,OS : String);
  187. begin
  188. Src.add(' EndPackage;');
  189. FPackageName:='';
  190. FPackageVersion:='';
  191. FPackageOptions:='';
  192. FBuilDUnit:='';
  193. FPackageDeps:='';
  194. end;
  195. procedure TMakeFileConverter.DoPackageLine(Const S : String);
  196. Var V,N : String;
  197. begin
  198. SplitNameValue(S,N,V);
  199. If (N='name') then
  200. FPackageName:=V
  201. else If (N='version') then
  202. FPackageVersion:=V
  203. else If (N='main') then
  204. begin
  205. FPackageName:='sub';
  206. FSubName:=V;
  207. end
  208. else
  209. Writeln(StdErr,'Unknown name/value pair in package section :',N);
  210. end;
  211. {
  212. Convert various entries of type
  213. XXYY_OSN=words
  214. to entries of type
  215. prefix_word=OS1,OS2,OS3
  216. OS is never empty, 'all' is default.
  217. }
  218. Procedure AddStrings(Var L : TStrings; Values,Prefix,OS : String) ;
  219. Var
  220. S,O : String;
  221. i : integer;
  222. begin
  223. If (L=Nil) then
  224. L:=TstringList.Create;
  225. If prefix<>'' then
  226. prefix:=prefix+'_';
  227. S:=GetWord(Values);
  228. While (S<>'') do
  229. begin
  230. S:=Prefix+S;
  231. I:=L.IndexOfName(S);
  232. If (I<>-1) then
  233. begin
  234. O:=L.Values[S];
  235. If (O='all') then
  236. O:='';
  237. If (O<>'') then
  238. O:=O+',';
  239. O:=O+OS;
  240. L.Values[S]:=O;
  241. end
  242. else
  243. L.Add(S+'='+OS);
  244. S:=GetWord(Values);
  245. end;
  246. end;
  247. procedure TMakeFileConverter.DoTargetLine(Line : String; Var T,R,D : TStrings);
  248. Var
  249. V,N,OS : String;
  250. P : Integer;
  251. begin
  252. SplitNameValue(Line,N,V);
  253. P:=Pos('_',N);
  254. If (P=0) then
  255. OS:='all'
  256. else
  257. begin
  258. OS:=N;
  259. Delete(OS,1,P);
  260. N:=Copy(N,1,P-1);
  261. end;
  262. If (N='dirs') then
  263. AddStrings(D,V,'',OS)
  264. else If (N='units') then
  265. AddStrings(T,V,'unit',OS)
  266. else If (N='implicitunits') then
  267. AddStrings(T,V,'unit',OS)
  268. else If (N='programs') then
  269. AddStrings(T,V,'program',OS)
  270. else If (N='examples') then
  271. AddStrings(T,V,'exampleunit',OS)
  272. else If (N='rsts') then
  273. AddStrings(R,V,'',OS)
  274. else
  275. Writeln(StdErr,'Unknown name/value pair in target section : ',Line);
  276. end;
  277. procedure TMakeFileConverter.DoInstallLine(Line : String; Var IFL : TStrings);
  278. Var
  279. S,V,N,OS : String;
  280. P : Integer;
  281. begin
  282. SplitNameValue(Line,N,V);
  283. P:=Pos('_',N);
  284. If (P=0) then
  285. OS:='all'
  286. else
  287. begin
  288. OS:=N;
  289. Delete(OS,1,P);
  290. N:=Copy(N,1,P-1);
  291. end;
  292. If (N='fpcpackage') then
  293. P:=0 // temporary, needs fixing.
  294. else If (N='buildunit') then
  295. FBuildUnit:=V // temporary, needs fixing.
  296. else If (N='units') then
  297. begin
  298. S:=GetWord(V);
  299. While (S<>'') do
  300. begin
  301. AddStrings(IFL,S+'.o','',OS);
  302. AddStrings(IFL,S+'.ppu','',OS);
  303. S:=GetWord(V);
  304. end;
  305. end
  306. else
  307. Writeln(StdErr,'Unknown name/value pair in install section : ',N);
  308. end;
  309. procedure TMakeFileConverter.DoCleanLine(Line : String; Var CFL : TStrings);
  310. Var
  311. V,N,S,OS : String;
  312. P : Integer;
  313. begin
  314. SplitNameValue(Line,N,V);
  315. P:=Pos('_',N);
  316. If (P=0) then
  317. OS:='all'
  318. else
  319. begin
  320. OS:=N;
  321. Delete(OS,1,P);
  322. N:=Copy(N,1,P-1);
  323. end;
  324. If (N='fpcpackage') then
  325. P:=0 // temporary, needs fixing.
  326. else If (N='units') then
  327. begin
  328. S:=GetWord(V);
  329. While (S<>'') do
  330. begin
  331. AddStrings(CFL,S+'.o','',OS);
  332. AddStrings(CFL,S+'.ppu','',OS);
  333. S:=GetWord(V);
  334. end;
  335. end
  336. else
  337. Writeln(StdErr,'Unknown name/value pair in clean section : ',N);
  338. end;
  339. procedure TMakeFileConverter.DoRequireLine(Line : String);
  340. Var
  341. V,N,OS : String;
  342. P : Integer;
  343. begin
  344. SplitNameValue(Line,N,V);
  345. P:=Pos('_',N);
  346. If (P=0) then
  347. OS:='all'
  348. else
  349. begin
  350. OS:=N;
  351. Delete(OS,1,P);
  352. N:=Copy(N,1,P-1);
  353. end;
  354. if (N='packages') then
  355. FPackageDeps:=V
  356. else If (N='libc') and (Upcase(V)='Y') then
  357. P:=0 // Set options ?
  358. else
  359. Writeln(StdErr,'Unknown name/value pair in require section : ',N);
  360. end;
  361. procedure TMakeFileConverter.DoCompilerLine(Line : String;Var SD : TStrings);
  362. Var
  363. V,N,OS : String;
  364. P : Integer;
  365. begin
  366. SplitNameValue(Line,N,V);
  367. P:=Pos('_',N);
  368. If (P=0) then
  369. OS:='all'
  370. else
  371. begin
  372. OS:=N;
  373. Delete(OS,1,P);
  374. N:=Copy(N,1,P-1);
  375. end;
  376. If (N='includedir') then
  377. FPackageOptions:=Trim(FPackageOptions+' -Fi'+V)
  378. else If (N='options') then
  379. FPackageOptions:=Trim(FPackageOptions+' '+V)
  380. else If (N='targetdir') then
  381. P:=0 // Ignore
  382. else if (N='sourcedir') or (N='unitdir') then
  383. begin
  384. If (SD=Nil) then
  385. SD:=TStringList.Create;
  386. SD.Add(OS+'='+V);
  387. end
  388. else
  389. Writeln(StdErr,'Unknown name/value pair in compiler section : ',N);
  390. end;
  391. Function SearchInDirs(Prefix,AName, Dirs : String) : string;
  392. Var
  393. D,S : String;
  394. begin
  395. S:=GetWord(Dirs);
  396. Result:='';
  397. While (Result='') and (S<>'') do
  398. begin
  399. D:=Prefix+S+PathDelim;
  400. If FileExists(D+AName+'.pp') or FileExists(D+AName+'.pas') then
  401. Result:=S;
  402. S:=GetWord(Dirs);
  403. end;
  404. end;
  405. procedure TMakeFileConverter.DoTargets(Src,T,R,SD : TStrings; Dir,Prefix : String);
  406. Var
  407. I,J,P : Integer;
  408. Pre,N,V,D,DOS,OS,CPU : String;
  409. Res : Boolean;
  410. begin
  411. If (Dir<>'') then
  412. Dir:=IncludeTrailingPathDelimiter(Dir);
  413. If (Prefix<>'') then
  414. Prefix:=IncludeTrailingPathDelimiter(Prefix);
  415. Dir:=Prefix+Dir;
  416. Res:=False;
  417. If Assigned(T) then
  418. For I:=0 to T.Count-1 do
  419. begin
  420. T.GetNamevalue(I,N,V);
  421. P:=Pos('_',N);
  422. If (P<>0) then
  423. begin
  424. Pre:=Copy(N,1,P-1);
  425. Delete(N,1,P);
  426. end;
  427. If Assigned(R) then
  428. Res:=R.IndexOfName(N)<>-1;
  429. GetOSCPU(V,OS,CPU);
  430. Pre[1]:=Upcase(Pre[1]);
  431. Src.Add(' T:=Targets.Add'+Pre+'('''+Prefix+N+''');');
  432. If (CPU<>'') then
  433. Src.Add(' T.CPU:=['+CPU+'];');
  434. If (OS<>'') then
  435. Src.Add(' T.OS:=['+OS+'];');
  436. If res then
  437. Src.add(' T.ResourceStrings:=True;');
  438. If (CompareText(FBuildUnit,N)=0) then
  439. Src.add(' T.Install:=False;');
  440. if Assigned(SD) then
  441. for J:=0 to SD.Count-1 do
  442. begin
  443. SD.GetNameValue(J,DOS,D);
  444. If (DOS<>'all') then
  445. Src.Add(' if (Defaults.OS='+DOS+') then');
  446. Src.add(' T.Directory:='''+SearchInDirs(Dir,N,D)+''';');
  447. end;
  448. end;
  449. end;
  450. procedure TMakeFileConverter.WriteOSCPUCheck(Src: TStrings;OS,CPU : String);
  451. Var
  452. S : String;
  453. begin
  454. If (CPU<>'') then
  455. S:='(Defaults.CPU='+CPU+')';
  456. If (OS<>'') then
  457. begin
  458. IF (S<>'') then
  459. S:=S+' OR ';
  460. S:=S+'(Defaults.OS='+CPU+')';
  461. end;
  462. If (S<>'') then
  463. Src.Add(' If '+S+' then');
  464. end;
  465. procedure TMakeFileConverter.DoInstalls(Src,IFL : TStrings);
  466. Var
  467. I,J,P : Integer;
  468. Pre,N,V,D,DOS,OS,CPU : String;
  469. begin
  470. If Assigned(IFL) then
  471. For I:=0 to IFL.Count-1 do
  472. begin
  473. IFL.GetNamevalue(I,N,V);
  474. GetOSCPU(V,OS,CPU);
  475. WriteOSCPUCheck(Src,OS,CPU);
  476. Src.add(' InstallFiles.Add('''+N+''');');
  477. end;
  478. end;
  479. procedure TMakeFileConverter.DoCleans(Src,CFL : TStrings);
  480. Var
  481. I,J,P : Integer;
  482. N,V,DOS,OS,CPU : String;
  483. begin
  484. If Assigned(CFL) then
  485. For I:=0 to CFL.Count-1 do
  486. begin
  487. CFL.GetNamevalue(I,N,V);
  488. GetOSCPU(V,OS,CPU);
  489. WriteOSCPUCheck(Src,OS,CPU);
  490. Src.add(' CleanFiles.Add('''+N+''');');
  491. end;
  492. end;
  493. procedure TMakeFileConverter.ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
  494. Function IsSection(var S : String) : Boolean;
  495. Var
  496. L : Integer;
  497. begin
  498. L:=Length(S);
  499. Result:=(L>0) and (S[1]='[') and (S[L]=']');
  500. If Result then
  501. S:=trim(Copy(S,2,L-2));
  502. end;
  503. Var
  504. R,L,T,D,S,SD,IFL,CFL : TStrings;
  505. I,J : Integer;
  506. Prefix,Line,DN : String;
  507. B : Boolean;
  508. begin
  509. Log(vDebug,'Converting '+AFileName);
  510. T:=Nil;
  511. D:=Nil;
  512. S:=Nil;
  513. SD:=Nil;
  514. R:=Nil;
  515. IFL:=Nil;
  516. CFL:=Nil;
  517. FPackageOptions:='';
  518. FPackageDir:='';
  519. L:=TStringList.Create;
  520. try
  521. L.LoadFromFile(AFileName);
  522. I:=0;
  523. While (I<L.Count) do
  524. begin
  525. Line:=GetLine(L,I);
  526. If IsSection(Line) then
  527. begin
  528. J:=GetEnumValue(TypeInfo(TSectionType),'st'+Line);
  529. If (J=-1) then
  530. begin
  531. FSection:=stNone;
  532. Error('Unsupported section: '+Line);
  533. end
  534. else
  535. FSection:=TSectiontype(J);
  536. end
  537. else
  538. case FSection of
  539. stPackage : DoPackageLine(Line);
  540. stTarget : DoTargetLine(Line,T,R,D);
  541. stInstall : DoInstallLine(Line,IFL);
  542. stClean : DoCleanLine(Line,CFL);
  543. stCompiler : DoCompilerLine(Line,SD);
  544. strequire : DoRequireLine(Line);
  545. end;
  546. inc(I);
  547. end;
  548. // If there are only 'dir' entries, then there is no package name.
  549. B:=False;
  550. if (FPackageName<>'') then
  551. begin
  552. Prefix:='';
  553. B:=FPackageName<>'sub';
  554. If B then
  555. StartPackage(Src,Dir,OS)
  556. else
  557. Prefix:=Dir;
  558. DoTargets(Src,T,R,SD,Dir,Prefix);
  559. DoInstalls(Src,IFL);
  560. DoCleans(Src,CFL);
  561. end;
  562. If Assigned(D) then
  563. begin
  564. If (Dir<>'') then
  565. Dir:=IncludeTrailingPathDelimiter(Dir);
  566. For I:=0 to D.Count-1 do
  567. begin
  568. D.GetNameValue(I,DN,Line);
  569. If (Line<>'all') and (Line<>'') then
  570. OS:=Line;
  571. DN:=Dir+DN+PathDelim;
  572. If FileExists(DN+'Makefile.fpc') then
  573. ConvertFile(DN+'Makefile.fpc',Src,DN,OS);
  574. end;
  575. end;
  576. If B then
  577. EndPackage(Src,Dir,OS);
  578. Finally
  579. S.Free;
  580. IFL.Free;
  581. CFL.Free;
  582. D.Free;
  583. SD.Free;
  584. T.Free;
  585. L.Free;
  586. end;
  587. end;
  588. procedure TMakeFileConverter.ConvertFile(const Source, Dest: String);
  589. Var
  590. L : TStrings;
  591. begin
  592. Log(vInfo,SLogGeneratingFPMake);
  593. L:=TStringList.Create;
  594. Try
  595. StartInstaller(L);
  596. ConvertFile(Source,L,'','');
  597. EndInstaller(L);
  598. L.SaveToFile(Dest);
  599. Finally
  600. L.Free;
  601. end;
  602. end;
  603. function TMakeFileConverter.Execute(const Args:TActionArgs):boolean;
  604. begin
  605. ConvertFile('Makefile.fpc','fpmake.pp');
  606. result:=true;
  607. end;
  608. begin
  609. RegisterPkgHandler('convertmk',TMakeFileConverter);
  610. end.