pkgmkconv.pp 14 KB

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