fpcmwr.pp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. {
  2. $Id$
  3. Copyright (c) 2001 by Peter Vreman
  4. FPCMake - Makefile writer
  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 fpcmwr;
  14. interface
  15. uses
  16. sysutils,classes,
  17. fpcmmain;
  18. type
  19. tsections=(sec_none,
  20. sec_units,sec_exes,sec_loaders,sec_examples,sec_rsts,
  21. sec_compile,sec_install,
  22. sec_distinstall,sec_zipinstall,sec_clean,sec_libs,
  23. sec_command,sec_exts,sec_dirs,sec_tools,sec_info
  24. );
  25. trules=(
  26. r_all,r_debug,r_smart,
  27. r_examples,
  28. r_shared,
  29. r_install,r_sourceinstall,r_exampleinstall,r_distinstall,
  30. r_zipinstall,r_zipsourceinstall,r_zipexampleinstall,r_zipdistinstall,
  31. r_clean,r_distclean,r_cleanall,
  32. r_info
  33. );
  34. const
  35. rule2str : array[trules] of string=(
  36. 'all','debug','smart',
  37. 'examples',
  38. 'shared',
  39. 'install','sourceinstall','exampleinstall','distinstall',
  40. 'zipinstall','zipsourceinstall','zipexampleinstall','zipdistinstall',
  41. 'clean','distclean','cleanall',
  42. 'info'
  43. );
  44. rule2sec : array[trules] of tsections=(
  45. sec_compile,sec_compile,sec_compile,
  46. sec_examples,
  47. sec_libs,
  48. sec_install,sec_install,sec_install,sec_distinstall,
  49. sec_zipinstall,sec_zipinstall,sec_zipinstall,sec_zipinstall,
  50. sec_clean,sec_clean,sec_clean,
  51. sec_info
  52. );
  53. type
  54. TMakefileWriter=class
  55. private
  56. FFileName : string;
  57. FIni : TFPCMake;
  58. FInput : TFPCMake;
  59. FOutput : TStringList;
  60. FPhony : string;
  61. FHasSection : array[tsections] of boolean;
  62. procedure LoadFPCMakeIni;
  63. procedure AddIniSection(const s:string);
  64. procedure AddCustomSection(const s:string);
  65. procedure AddTargetVariable(const inivar:string);
  66. procedure AddVariable(const inivar:string);
  67. function AddTargetDefines(const inivar,prefix:string):string;
  68. procedure AddRequiredPackages;
  69. procedure AddTool(const varname,exename,altexename:string);
  70. procedure AddTools(const inivar:string);
  71. procedure AddRules;
  72. procedure AddPhony(const s:string);
  73. procedure WritePhony;
  74. procedure AddTargetDirs(const inivar:string);
  75. function CheckTargetVariable(const inivar:string):boolean;
  76. function CheckVariable(const inivar:string):boolean;
  77. procedure AddDefaultTools;
  78. procedure OptimizeSections;
  79. public
  80. constructor Create(AFPCMake:TFPCMake;const AFileName:string);
  81. destructor Destroy;override;
  82. procedure WriteGenericMakefile;
  83. end;
  84. implementation
  85. {$i fpcmake.inc}
  86. type
  87. TMyMemoryStream=class(TMemoryStream)
  88. public
  89. constructor Create(p:pointer;mysize:integer);
  90. end;
  91. {*****************************************************************************
  92. Helpers
  93. *****************************************************************************}
  94. function FixVariable(s:string):string;
  95. var
  96. i : integer;
  97. begin
  98. Result:=UpperCase(s);
  99. i:=pos('.',Result);
  100. if i>0 then
  101. Result[i]:='_';
  102. end;
  103. function VarName(const s:string):string;
  104. var
  105. i,j : longint;
  106. begin
  107. i:=0;
  108. result:=s;
  109. while i<length(result) do
  110. begin
  111. inc(i);
  112. case result[i] of
  113. '{' :
  114. begin
  115. { this are pkgs which are hold the dirs between the accolades }
  116. j:=PosIdx('}',result,i);
  117. if j>0 then
  118. Delete(result,i,j-i+1)
  119. else
  120. Delete(result,i,1);
  121. dec(i);
  122. end;
  123. '$','(',')' :
  124. begin
  125. Delete(result,i,1);
  126. dec(i);
  127. end;
  128. 'a'..'z' :
  129. result[i]:=chr(ord(result[i])-32);
  130. end;
  131. end;
  132. end;
  133. procedure AddStrNoDup(var s:string;const s2:string);
  134. var
  135. i,idx : longint;
  136. again,add : boolean;
  137. begin
  138. add:=false;
  139. idx:=0;
  140. repeat
  141. again:=false;
  142. i:=posidx(s2,s,idx);
  143. if (i=0) then
  144. add:=true
  145. else
  146. if (i=1) then
  147. begin
  148. if (length(s)>length(s2)) and
  149. (s[length(s2)+1]<>' ') then
  150. add:=true;
  151. end
  152. else
  153. if (i>1) and
  154. ((s[i-1]<>' ') or
  155. ((length(s)>=i+length(s2)) and (s[i+length(s2)]<>' '))) then
  156. begin
  157. idx:=i+length(s2);
  158. again:=true;
  159. end;
  160. until not again;
  161. if add then
  162. begin
  163. if s='' then
  164. s:=s2
  165. else
  166. s:=s+' '+s2;
  167. end;
  168. end;
  169. procedure FixTab(sl:TStringList);
  170. var
  171. i,j,k : integer;
  172. s,s2 : string;
  173. begin
  174. i:=0;
  175. while (i<sl.Count) do
  176. begin
  177. if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
  178. begin
  179. s:=sl[i];
  180. k:=0;
  181. j:=0;
  182. repeat
  183. inc(j);
  184. case s[j] of
  185. ' ' :
  186. inc(k);
  187. #9 :
  188. k:=(k+7) and not(7);
  189. else
  190. break;
  191. end;
  192. until (j=length(s));
  193. if k>7 then
  194. begin
  195. s2:='';
  196. Delete(s,1,j-1);
  197. while (k>7) do
  198. begin
  199. s2:=s2+#9;
  200. dec(k,8);
  201. end;
  202. while (k>0) do
  203. begin
  204. s2:=s2+' ';
  205. dec(k);
  206. end;
  207. sl[i]:=s2+s;
  208. end;
  209. end;
  210. inc(i);
  211. end;
  212. end;
  213. {*****************************************************************************
  214. TMyMemoryStream
  215. *****************************************************************************}
  216. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  217. begin
  218. inherited Create;
  219. SetPointer(p,mysize);
  220. end;
  221. {*****************************************************************************
  222. TMakefileWriter
  223. *****************************************************************************}
  224. constructor TMakefileWriter.Create(AFPCMake:TFPCMake;const AFileName:string);
  225. begin
  226. FInput:=AFPCMake;
  227. FFileName:=AFileName;
  228. FOutput:=TStringList.Create;
  229. FPhony:='';
  230. FillChar(FHasSection,sizeof(FHasSection),1);
  231. LoadFPCMakeIni;
  232. end;
  233. destructor TMakefileWriter.Destroy;
  234. begin
  235. FOutput.Free;
  236. FIni.Free;
  237. end;
  238. procedure TMakefileWriter.LoadFPCMakeIni;
  239. var
  240. IniStream : TStream;
  241. begin
  242. try
  243. IniStream:=TMyMemoryStream.Create(@fpcmakeini,sizeof(fpcmakeini));
  244. FIni:=TFPCMake.CreateFromStream(IniStream,'fpcmake.ini');
  245. { Leave the '#' comments in the output }
  246. // FIni.CommentChars:=[';'];
  247. FIni.LoadSections;
  248. finally
  249. IniStream.Destroy;
  250. end;
  251. end;
  252. procedure TMakefileWriter.AddIniSection(const s:string);
  253. var
  254. Sec : TFPCMakeSection;
  255. begin
  256. Sec:=TFPCMakeSection(FIni[s]);
  257. if assigned(Sec) then
  258. FOutput.AddStrings(Sec.List)
  259. else
  260. Raise Exception.Create(Format('Section "%s" doesn''t exists in fpcmake.ini',[s]));
  261. end;
  262. procedure TMakefileWriter.AddCustomSection(const s:string);
  263. var
  264. Sec : TFPCMakeSection;
  265. begin
  266. Sec:=TFPCMakeSection(FInput[s]);
  267. if assigned(Sec) then
  268. begin
  269. Sec.BuildMakefile;
  270. FOutput.AddStrings(Sec.List);
  271. end;
  272. end;
  273. function TMakefileWriter.CheckTargetVariable(const inivar:string):boolean;
  274. var
  275. t : TTarget;
  276. begin
  277. result:=false;
  278. if FInput.GetVariable(IniVar,false)<>'' then
  279. begin
  280. result:=true;
  281. exit;
  282. end;
  283. for t:=low(TTarget) to high(TTarget) do
  284. if (t in FInput.IncludeTargets) and
  285. (FInput.GetVariable(IniVar+TargetSuffix[t],false)<>'') then
  286. begin
  287. result:=true;
  288. exit;
  289. end;
  290. end;
  291. function TMakefileWriter.CheckVariable(const inivar:string):boolean;
  292. begin
  293. Result:=(FInput.GetVariable(IniVar,false)<>'');
  294. end;
  295. procedure TMakefileWriter.AddTargetVariable(const inivar:string);
  296. var
  297. s : string;
  298. T : TTarget;
  299. begin
  300. s:=FInput.GetVariable(IniVar,false);
  301. if s<>'' then
  302. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  303. for t:=low(TTarget) to high(TTarget) do
  304. if t in FInput.IncludeTargets then
  305. begin
  306. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  307. if s<>'' then
  308. begin
  309. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  310. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  311. FOutput.Add('endif');
  312. end;
  313. end;
  314. end;
  315. procedure TMakefileWriter.AddVariable(const inivar:string);
  316. var
  317. s : string;
  318. begin
  319. s:=FInput.GetVariable(IniVar,false);
  320. if s<>'' then
  321. FOutput.Add('override '+FixVariable(IniVar)+'='+s)
  322. end;
  323. function TMakefileWriter.AddTargetDefines(const inivar,prefix:string):string;
  324. var
  325. s : string;
  326. T : TTarget;
  327. name : string;
  328. k1,k2 : integer;
  329. begin
  330. result:='';
  331. s:=FInput.GetVariable(IniVar,false);
  332. repeat
  333. name:=GetToken(s,' ');
  334. if Name='' then
  335. break;
  336. { Remove (..) }
  337. k1:=pos('(',name);
  338. if k1>0 then
  339. begin
  340. k2:=PosIdx(')',name,k1);
  341. if k2=0 then
  342. k2:=length(name)+1;
  343. Delete(Name,k1,k2);
  344. end;
  345. FOutput.Add(prefix+VarName(name)+'=1');
  346. { add to the list of dirs without duplicates }
  347. AddStrNoDup(result,name);
  348. until false;
  349. for t:=low(TTarget) to high(TTarget) do
  350. if t in FInput.IncludeTargets then
  351. begin
  352. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  353. if s<>'' then
  354. begin
  355. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  356. repeat
  357. Name:=GetToken(s,' ');
  358. if Name='' then
  359. break;
  360. { Remove (..) }
  361. k1:=pos('(',name);
  362. if k1>0 then
  363. begin
  364. k2:=PosIdx(')',name,k1);
  365. if k2=0 then
  366. k2:=length(name)+1;
  367. Delete(Name,k1,k2);
  368. end;
  369. FOutput.Add(prefix+VarName(name)+'=1');
  370. { add to the list of dirs without duplicates }
  371. AddStrNoDup(result,name);
  372. until false;
  373. FOutput.Add('endif');
  374. end;
  375. end;
  376. end;
  377. procedure TMakefileWriter.AddTool(const varname,exename,altexename:string);
  378. begin
  379. with FOutput do
  380. begin
  381. Add('ifndef '+varname);
  382. Add(varname+':=$(strip $(wildcard $(addsuffix /'+exename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  383. if altexename<>'' then
  384. begin
  385. Add('ifeq ($('+varname+'),)');
  386. Add(varname+':=$(strip $(wildcard $(addsuffix /'+altexename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  387. end;
  388. Add('ifeq ($('+varname+'),)');
  389. Add(varname+'=');
  390. Add('else');
  391. Add(varname+':=$(firstword $('+varname+'))');
  392. Add('endif');
  393. if altexename<>'' then
  394. begin
  395. Add('else');
  396. Add(varname+':=$(firstword $('+varname+'))');
  397. Add('endif');
  398. end;
  399. Add('endif');
  400. Add('export '+varname);
  401. end;
  402. end;
  403. procedure TMakefileWriter.AddTools(const inivar:string);
  404. var
  405. hs,tool : string;
  406. begin
  407. hs:=FInput.GetVariable(inivar,false);
  408. repeat
  409. Tool:=GetToken(hs,' ');
  410. if Tool='' then
  411. break;
  412. AddTool(FixVariable(Tool),Tool,'');
  413. until false;
  414. end;
  415. procedure TMakefileWriter.AddRules;
  416. procedure AddRule(rule:trules);
  417. var
  418. i : integer;
  419. hs : string;
  420. Sec : TFPCMakeSection;
  421. Rules : TStringList;
  422. begin
  423. Sec:=TFPCMakeSection(FInput['rules']);
  424. if assigned(Sec) then
  425. begin
  426. Rules:=Sec.List;
  427. for i:=0 to Rules.Count-1 do
  428. begin
  429. if (length(rules[i])>length(rule2str[rule])) and
  430. (rules[i][1]=rule2str[rule][1]) and
  431. ((rules[i][length(rule2str[rule])+1]=':') or
  432. ((length(rules[i])>length(rule2str[rule])+1) and
  433. (rules[i][length(rule2str[rule])+2]=':'))) and
  434. (Copy(rules[i],1,length(rule2str[rule]))=rule2str[rule]) then
  435. exit;
  436. end;
  437. end;
  438. hs:='';
  439. if FHasSection[Rule2Sec[rule]] then
  440. hs:=hs+' fpc_'+rule2str[rule];
  441. { include target dirs, but not for info and targets that
  442. call other targets with a only extra settings, if the
  443. section was not included, then still process the targets }
  444. if CheckTargetVariable('target_dirs') and
  445. (not(rule in [r_info,r_shared,r_smart,r_debug,r_distinstall]) or
  446. not FHasSection[Rule2Sec[rule]]) then
  447. begin
  448. if CheckVariable('default_dir') then
  449. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(DEFAULT_DIR))'
  450. else
  451. if not(rule in [r_sourceinstall,r_zipinstall,r_zipsourceinstall]) or
  452. not(CheckVariable('package_name')) then
  453. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_DIRS))';
  454. end;
  455. { include cleaning of example dirs }
  456. if (rule=r_clean) and
  457. CheckTargetVariable('target_exampledirs') then
  458. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_EXAMPLEDIRS))';
  459. { Add the rule }
  460. AddPhony(Rule2Str[Rule]);
  461. FOutput.Add(rule2str[rule]+':'+hs);
  462. end;
  463. var
  464. rule : trules;
  465. begin
  466. for rule:=low(trules) to high(trules) do
  467. AddRule(rule);
  468. WritePhony;
  469. end;
  470. procedure TMakefileWriter.AddPhony(const s:string);
  471. begin
  472. FPhony:=FPhony+' '+s;
  473. end;
  474. procedure TMakefileWriter.WritePhony;
  475. begin
  476. if FPhony<>'' then
  477. begin
  478. FOutput.Add('.PHONY:'+FPhony);
  479. FPhony:='';
  480. end;
  481. end;
  482. procedure TMakefileWriter.AddTargetDirs(const inivar:string);
  483. procedure AddTargetDir(const s,defpref:string);
  484. var
  485. j : trules;
  486. begin
  487. FOutput.Add('ifdef '+defpref+VarName(s));
  488. for j:=low(trules) to high(trules) do
  489. begin
  490. FOutput.Add(s+'_'+rule2str[j]+':');
  491. FOutput.Add(#9+'$(MAKE) -C '+s+' '+rule2str[j]);
  492. AddPhony(s+'_'+rule2str[j]);
  493. end;
  494. FOutput.Add(s+':');
  495. FOutput.Add(#9+'$(MAKE) -C '+s+' all');
  496. AddPhony(s);
  497. WritePhony;
  498. FOutput.Add('endif');
  499. end;
  500. var
  501. hs,dir : string;
  502. prefix : string;
  503. begin
  504. prefix:=FixVariable(inivar)+'_';
  505. hs:=AddTargetDefines(inivar,prefix);
  506. repeat
  507. Dir:=GetToken(hs,' ');
  508. if Dir='' then
  509. break;
  510. AddTargetDir(Dir,prefix);
  511. until false;
  512. end;
  513. procedure TMakefileWriter.AddRequiredPackages;
  514. procedure AddPackage(const pack,prefix:string);
  515. var
  516. packdirvar,unitdirvar : string;
  517. begin
  518. FOutput.Add('ifdef '+Prefix+VarName(pack));
  519. { create needed variables }
  520. packdirvar:='PACKAGEDIR_'+VarName(pack);
  521. unitdirvar:='UNITDIR_'+VarName(pack);
  522. { Search packagedir by looking for Makefile.fpc }
  523. FOutput.Add(packdirvar+':=$(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR)))))');
  524. FOutput.Add('ifneq ($('+packdirvar+'),)');
  525. FOutput.Add(packdirvar+':=$(firstword $('+packdirvar+'))');
  526. { If Packagedir found look for FPCMade }
  527. FOutput.Add('ifeq ($(wildcard $('+packdirvar+')/$(FPCMADE)),)');
  528. FOutput.Add('override COMPILEPACKAGES+=package_'+pack);
  529. AddPhony('package_'+pack);
  530. FOutput.Add('package_'+pack+':');
  531. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+') all');
  532. FOutput.Add('endif');
  533. { Create unit dir, check if os dependent dir exists }
  534. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/$(OS_TARGET)),)');
  535. FOutput.Add(unitdirvar+'=$('+packdirvar+')/$(OS_TARGET)');
  536. FOutput.Add('else');
  537. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  538. FOutput.Add('endif');
  539. { Package dir doesn't exists, check unit dir }
  540. FOutput.Add('else');
  541. FOutput.Add(packdirvar+'=');
  542. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  543. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  544. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  545. FOutput.Add('else');
  546. FOutput.Add(unitdirvar+'=');
  547. FOutput.Add('endif');
  548. FOutput.Add('endif');
  549. { Add Unit dir to the command line -Fu }
  550. FOutput.Add('ifdef '+unitdirvar);
  551. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  552. FOutput.Add('endif');
  553. { endif for package }
  554. FOutput.Add('endif');
  555. end;
  556. var
  557. i : integer;
  558. reqs,req,prefix : string;
  559. t : Ttarget;
  560. sl : TStringList;
  561. begin
  562. prefix:='REQUIRE_PACKAGES_';
  563. reqs:='';
  564. { Add target defines }
  565. for t:=low(ttarget) to high(ttarget) do
  566. if t in FInput.IncludeTargets then
  567. begin
  568. sl:=FInput.GetTargetRequires(t);
  569. { show info }
  570. FInput.Verbose(FPCMakeInfo,TargetStr[t]+' requires: '+sl.CommaText);
  571. if sl.count>0 then
  572. begin
  573. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  574. for i:=0 to sl.count-1 do
  575. begin
  576. FOutput.Add(prefix+VarName(sl[i])+'=1');
  577. AddStrNoDup(reqs,sl[i]);
  578. end;
  579. FOutput.Add('endif');
  580. end;
  581. sl.Free;
  582. end;
  583. { Add all require packages }
  584. repeat
  585. req:=GetToken(reqs,' ');
  586. if Req='' then
  587. break;
  588. AddPackage(req,prefix);
  589. until false;
  590. WritePhony;
  591. end;
  592. procedure TMakefileWriter.AddDefaultTools;
  593. begin
  594. AddTool('ECHO','gecho','echo');
  595. AddTool('DATE','gdate','date');
  596. AddTool('GINSTALL','ginstall','install');
  597. AddTool('CPPROG','cp','');
  598. AddTool('RMPROG','rm','');
  599. AddTool('MVPROG','mv','');
  600. AddIniSection('shelltools');
  601. AddTool('PPUMOVE','ppumove','');
  602. AddTool('FPCMAKE','fpcmake','');
  603. AddTool('ZIPPROG','zip','');
  604. AddTool('TARPROG','tar','');
  605. AddIniSection('defaulttools');
  606. end;
  607. procedure TMakefileWriter.OptimizeSections;
  608. var
  609. SkippedSecs :integer;
  610. begin
  611. { Turn some sections off, depending if files are
  612. provided }
  613. if not FInput.IsPackage then
  614. begin
  615. FHasSection[sec_zipinstall]:=false;
  616. FHasSection[sec_distinstall]:=false;
  617. end;
  618. FHasSection[sec_libs]:=CheckVariable('lib_name');
  619. { Remove unused sections for targets }
  620. SkippedSecs:=0;
  621. if (not CheckTargetVariable('target_units')) then
  622. begin
  623. inc(SkippedSecs);
  624. FHasSection[sec_units]:=false;
  625. end;
  626. if (not CheckTargetVariable('target_programs')) then
  627. begin
  628. inc(SkippedSecs);
  629. FHasSection[sec_exes]:=false;
  630. end;
  631. if (not CheckTargetVariable('target_examples')) then
  632. begin
  633. inc(SkippedSecs);
  634. { example dirs also requires the fpc_examples target, because
  635. it also depends on the all target }
  636. if (not CheckTargetVariable('target_exampledirs')) then
  637. FHasSection[sec_examples]:=false;
  638. end;
  639. if (not CheckTargetVariable('target_loaders')) then
  640. begin
  641. inc(SkippedSecs);
  642. FHasSection[sec_loaders]:=false;
  643. end;
  644. { if all 4 sections are not available we can skip also the
  645. generic compile rules }
  646. if SkippedSecs=4 then
  647. begin
  648. FHasSection[sec_compile]:=false;
  649. if (not CheckTargetVariable('install_units')) and
  650. (not CheckTargetVariable('install_files')) and
  651. (not CheckTargetVariable('install_createpackagefpc')) then
  652. FHasSection[sec_install]:=false;
  653. { Package.fpc also needs to be cleaned }
  654. if (not CheckTargetVariable('clean_units')) and
  655. (not CheckTargetVariable('clean_files')) and
  656. (not CheckTargetVariable('install_createpackagefpc')) then
  657. FHasSection[sec_clean]:=false;
  658. end;
  659. end;
  660. procedure TMakefileWriter.WriteGenericMakefile;
  661. begin
  662. { Remove unused sections }
  663. OptimizeSections;
  664. { Generate Output }
  665. with FOutput do
  666. begin
  667. { Header }
  668. Add('#');
  669. Add('# Don''t edit, this file is generated by '+TitleDate);
  670. Add('#');
  671. if CheckVariable('default_rule') then
  672. Add('default: '+FInput.GetVariable('default_rule',false))
  673. else
  674. Add('default: all');
  675. { Add automatic detect sections }
  676. AddIniSection('osdetect');
  677. { Forced target }
  678. if CheckVariable('require_target') then
  679. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  680. else if CheckVariable('default_target') then
  681. Add('OS_TARGET='+FInput.GetVariable('default_target',false));
  682. if CheckVariable('require_cpu') then
  683. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  684. else if CheckVariable('default_cpu') then
  685. Add('CPU_TARGET='+FInput.GetVariable('default_cpu',false));
  686. { FPC Detection }
  687. AddIniSection('fpcdetect');
  688. AddIniSection('fpcdircheckenv');
  689. if CheckVariable('default_fpcdir') then
  690. begin
  691. Add('ifeq ($(FPCDIR),wrong)');
  692. Add('override FPCDIR='+FInput.GetVariable('default_fpcdir',false));
  693. Add('ifeq ($(wildcard $(FPCDIR)/rtl),)');
  694. Add('ifeq ($(wildcard $(FPCDIR)/units),)');
  695. Add('override FPCDIR=wrong');
  696. Add('endif');
  697. Add('endif');
  698. Add('endif');
  699. end;
  700. AddIniSection('fpcdirdetect');
  701. { Package }
  702. AddVariable('package_name');
  703. AddVariable('package_version');
  704. AddVariable('package_targets');
  705. { First add the required packages sections }
  706. // for i:=0 to FInput.RequireList.Count-1 do
  707. // AddCustomSection(FInput.Requirelist[i]);
  708. { prerules section }
  709. if assigned(FInput['prerules']) then
  710. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  711. { Default }
  712. AddVariable('default_dir');
  713. { Targets }
  714. AddTargetVariable('target_dirs');
  715. AddTargetVariable('target_programs');
  716. AddTargetVariable('target_units');
  717. AddTargetVariable('target_loaders');
  718. AddTargetVariable('target_rsts');
  719. AddTargetVariable('target_examples');
  720. AddTargetVariable('target_exampledirs');
  721. { Clean }
  722. AddTargetVariable('clean_units');
  723. AddTargetVariable('clean_files');
  724. { Install }
  725. AddTargetVariable('install_units');
  726. AddTargetVariable('install_files');
  727. AddVariable('install_prefix');
  728. AddVariable('install_basedir');
  729. AddVariable('install_datadir');
  730. AddVariable('install_fpcpackage');
  731. AddVariable('install_createpackagefpc');
  732. { Dist }
  733. AddVariable('dist_destdir');
  734. AddVariable('dist_zipname');
  735. AddVariable('dist_ziptarget');
  736. { Compiler }
  737. AddTargetVariable('compiler_options');
  738. AddTargetVariable('compiler_version');
  739. AddTargetVariable('compiler_includedir');
  740. AddTargetVariable('compiler_unitdir');
  741. AddTargetVariable('compiler_sourcedir');
  742. AddTargetVariable('compiler_objectdir');
  743. AddTargetVariable('compiler_librarydir');
  744. AddTargetVariable('compiler_targetdir');
  745. AddTargetVariable('compiler_unittargetdir');
  746. { default Dirs and extensions }
  747. AddIniSection('defaultdirs');
  748. if FInput.CheckLibcRequire then
  749. AddIniSection('dirlibc');
  750. AddIniSection('extensions');
  751. { Add default tools }
  752. AddDefaultTools;
  753. { Required packages }
  754. AddRequiredPackages;
  755. { commandline }
  756. AddIniSection('command_begin');
  757. if FInput.CheckLibcRequire then
  758. AddIniSection('command_libc');
  759. AddIniSection('command_end');
  760. { compile }
  761. if FHasSection[sec_loaders] then
  762. AddIniSection('loaderrules');
  763. if FHasSection[sec_units] then
  764. AddIniSection('unitrules');
  765. if FHasSection[sec_exes] then
  766. AddIniSection('exerules');
  767. if FHasSection[sec_rsts] then
  768. AddIniSection('rstrules');
  769. if FHasSection[sec_examples] then
  770. AddIniSection('examplerules');
  771. if FHasSection[sec_compile] then
  772. AddIniSection('compilerules');
  773. if FHasSection[sec_libs] then
  774. AddIniSection('libraryrules');
  775. { install }
  776. if FHasSection[sec_install] then
  777. AddIniSection('installrules');
  778. if FHasSection[sec_distinstall] then
  779. AddIniSection('distinstallrules');
  780. if FHasSection[sec_zipinstall] then
  781. AddIniSection('zipinstallrules');
  782. { clean }
  783. AddIniSection('cleanrules');
  784. { info }
  785. AddIniSection('inforules');
  786. { Subdirs }
  787. AddTargetDirs('target_dirs');
  788. AddTargetDirs('target_exampledirs');
  789. { Tools }
  790. AddTools('require_tools');
  791. { Rules }
  792. AddRules;
  793. { Users own rules }
  794. AddIniSection('localmakefile');
  795. AddIniSection('userrules');
  796. if assigned(FInput['rules']) then
  797. AddStrings(TFPCMakeSection(FInput['rules']).List);
  798. end;
  799. { write to disk }
  800. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  801. Fixtab(FOutput);
  802. FOutput.SaveToFile(FFileName);
  803. end;
  804. end.
  805. {
  806. $Log$
  807. Revision 1.18 2001-10-14 21:38:33 peter
  808. * cross compiling support
  809. Revision 1.17 2001/09/11 11:04:51 pierre
  810. * handle default cpu and target without override, use require section for override
  811. Revision 1.16 2001/08/22 20:45:19 peter
  812. * firstword added
  813. * pathexist fix to include sysfile
  814. Revision 1.15 2001/08/02 20:50:29 peter
  815. * -T<target> support
  816. * better error reporting for not found dirs
  817. * some cleanups and nicer strings
  818. Revision 1.14 2001/07/31 22:02:32 peter
  819. * install Package.fpc
  820. Revision 1.13 2001/07/13 21:01:59 peter
  821. * cygdrive support
  822. * fixed cygwin detection
  823. * fixed some duplicate and extraeous spaces
  824. Revision 1.12 2001/06/07 21:21:38 peter
  825. * remove ppufiles
  826. * fix staticlib prefix that is now libp instead of lib
  827. Revision 1.11 2001/06/06 21:58:25 peter
  828. * Win32 fixes for Makefile so it doesn't require sh.exe
  829. Revision 1.10 2001/06/04 22:18:16 peter
  830. * Still process subdirs if a target has no section defined
  831. Revision 1.9 2001/06/04 21:42:57 peter
  832. * Arguments added
  833. * Start of Package.fpc creation
  834. Revision 1.8 2001/05/30 21:39:17 peter
  835. * gecho, gdate fixes
  836. * distinstall target rewrite to not install things twice
  837. Revision 1.7 2001/05/03 21:35:10 peter
  838. * Makefile fixes
  839. Revision 1.6 2001/02/24 10:44:33 peter
  840. * another fix for internal variable checking
  841. Revision 1.5 2001/02/22 21:11:24 peter
  842. * fpcdir detection added
  843. * fixed loading of variables in fpcmake itself
  844. Revision 1.4 2001/02/20 21:49:31 peter
  845. * fixed change variable accessing using _ instead of .
  846. Revision 1.3 2001/02/01 22:00:10 peter
  847. * default.fpcdir is back
  848. * subdir requirement checking works, but not very optimal yet as
  849. it can load the same Makefile.fpc multiple times
  850. Revision 1.2 2001/01/29 21:49:10 peter
  851. * lot of updates
  852. Revision 1.1 2001/01/24 21:59:36 peter
  853. * first commit of new fpcmake
  854. }