fpcmwr.pp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  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 FInput.GetVariable(IniVar+TargetSuffix[t],false)<>'' then
  285. begin
  286. result:=true;
  287. exit;
  288. end;
  289. end;
  290. function TMakefileWriter.CheckVariable(const inivar:string):boolean;
  291. begin
  292. Result:=(FInput.GetVariable(IniVar,false)<>'');
  293. end;
  294. procedure TMakefileWriter.AddTargetVariable(const inivar:string);
  295. var
  296. s : string;
  297. T : TTarget;
  298. begin
  299. s:=FInput.GetVariable(IniVar,false);
  300. if s<>'' then
  301. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  302. for t:=low(TTarget) to high(TTarget) do
  303. begin
  304. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  305. if s<>'' then
  306. begin
  307. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  308. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  309. FOutput.Add('endif');
  310. end;
  311. end;
  312. end;
  313. procedure TMakefileWriter.AddVariable(const inivar:string);
  314. var
  315. s : string;
  316. begin
  317. s:=FInput.GetVariable(IniVar,false);
  318. if s<>'' then
  319. FOutput.Add('override '+FixVariable(IniVar)+'='+s)
  320. end;
  321. function TMakefileWriter.AddTargetDefines(const inivar,prefix:string):string;
  322. var
  323. s : string;
  324. T : TTarget;
  325. name : string;
  326. k1,k2 : integer;
  327. begin
  328. result:='';
  329. s:=FInput.GetVariable(IniVar,false);
  330. repeat
  331. name:=GetToken(s);
  332. if Name='' then
  333. break;
  334. { Remove (..) }
  335. k1:=pos('(',name);
  336. if k1>0 then
  337. begin
  338. k2:=PosIdx(')',name,k1);
  339. if k2=0 then
  340. k2:=length(name)+1;
  341. Delete(Name,k1,k2);
  342. end;
  343. FOutput.Add(prefix+VarName(name)+'=1');
  344. { add to the list of dirs without duplicates }
  345. AddStrNoDup(result,name);
  346. until false;
  347. for t:=low(TTarget) to high(TTarget) do
  348. begin
  349. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  350. if s<>'' then
  351. begin
  352. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  353. repeat
  354. Name:=GetToken(s);
  355. if Name='' then
  356. break;
  357. { Remove (..) }
  358. k1:=pos('(',name);
  359. if k1>0 then
  360. begin
  361. k2:=PosIdx(')',name,k1);
  362. if k2=0 then
  363. k2:=length(name)+1;
  364. Delete(Name,k1,k2);
  365. end;
  366. FOutput.Add(prefix+VarName(name)+'=1');
  367. { add to the list of dirs without duplicates }
  368. AddStrNoDup(result,name);
  369. until false;
  370. FOutput.Add('endif');
  371. end;
  372. end;
  373. end;
  374. procedure TMakefileWriter.AddTool(const varname,exename,altexename:string);
  375. begin
  376. with FOutput do
  377. begin
  378. Add('ifndef '+varname);
  379. Add(varname+':=$(strip $(wildcard $(addsuffix /'+exename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  380. if altexename<>'' then
  381. begin
  382. Add('ifeq ($('+varname+'),)');
  383. Add(varname+':=$(strip $(wildcard $(addsuffix /'+altexename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  384. end;
  385. Add('ifeq ($('+varname+'),)');
  386. Add(varname+'=');
  387. Add('else');
  388. Add(varname+':=$(firstword $('+varname+'))');
  389. Add('endif');
  390. if altexename<>'' then
  391. begin
  392. Add('else');
  393. Add(varname+':=$(firstword $('+varname+'))');
  394. Add('endif');
  395. end;
  396. Add('endif');
  397. Add('export '+varname);
  398. end;
  399. end;
  400. procedure TMakefileWriter.AddTools(const inivar:string);
  401. var
  402. hs,tool : string;
  403. begin
  404. hs:=FInput.GetVariable(inivar,false);
  405. repeat
  406. Tool:=GetToken(hs);
  407. if Tool='' then
  408. break;
  409. AddTool(FixVariable(Tool),Tool,'');
  410. until false;
  411. end;
  412. procedure TMakefileWriter.AddRules;
  413. procedure AddRule(rule:trules);
  414. var
  415. i : integer;
  416. hs : string;
  417. Sec : TFPCMakeSection;
  418. Rules : TStringList;
  419. begin
  420. Sec:=TFPCMakeSection(FInput['rules']);
  421. if assigned(Sec) then
  422. begin
  423. Rules:=Sec.List;
  424. for i:=0 to Rules.Count-1 do
  425. begin
  426. if (length(rules[i])>length(rule2str[rule])) and
  427. (rules[i][1]=rule2str[rule][1]) and
  428. ((rules[i][length(rule2str[rule])+1]=':') or
  429. ((length(rules[i])>length(rule2str[rule])+1) and
  430. (rules[i][length(rule2str[rule])+2]=':'))) and
  431. (Copy(rules[i],1,length(rule2str[rule]))=rule2str[rule]) then
  432. exit;
  433. end;
  434. end;
  435. hs:='';
  436. if FHasSection[Rule2Sec[rule]] then
  437. hs:=hs+' fpc_'+rule2str[rule];
  438. { include target dirs, but not for info and targets that
  439. call other targets with a only extra settings, if the
  440. section was not included, then still process the targets }
  441. if CheckTargetVariable('target_dirs') and
  442. (not(rule in [r_info,r_shared,r_smart,r_debug,r_distinstall]) or
  443. not FHasSection[Rule2Sec[rule]]) then
  444. begin
  445. if CheckVariable('default_dir') then
  446. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(DEFAULT_DIR))'
  447. else
  448. if not(rule in [r_sourceinstall,r_zipinstall,r_zipsourceinstall]) or
  449. not(CheckVariable('package_name')) then
  450. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_DIRS))';
  451. end;
  452. { include cleaning of example dirs }
  453. if (rule=r_clean) and
  454. CheckTargetVariable('target_exampledirs') then
  455. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_EXAMPLEDIRS))';
  456. { Add the rule }
  457. AddPhony(Rule2Str[Rule]);
  458. FOutput.Add(rule2str[rule]+':'+hs);
  459. end;
  460. var
  461. rule : trules;
  462. begin
  463. for rule:=low(trules) to high(trules) do
  464. AddRule(rule);
  465. WritePhony;
  466. end;
  467. procedure TMakefileWriter.AddPhony(const s:string);
  468. begin
  469. FPhony:=FPhony+' '+s;
  470. end;
  471. procedure TMakefileWriter.WritePhony;
  472. begin
  473. if FPhony<>'' then
  474. begin
  475. FOutput.Add('.PHONY:'+FPhony);
  476. FPhony:='';
  477. end;
  478. end;
  479. procedure TMakefileWriter.AddTargetDirs(const inivar:string);
  480. procedure AddTargetDir(const s,defpref:string);
  481. var
  482. j : trules;
  483. begin
  484. FOutput.Add('ifdef '+defpref+VarName(s));
  485. for j:=low(trules) to high(trules) do
  486. begin
  487. FOutput.Add(s+'_'+rule2str[j]+':');
  488. FOutput.Add(#9+'$(MAKE) -C '+s+' '+rule2str[j]);
  489. AddPhony(s+'_'+rule2str[j]);
  490. end;
  491. FOutput.Add(s+':');
  492. FOutput.Add(#9+'$(MAKE) -C '+s+' all');
  493. AddPhony(s);
  494. WritePhony;
  495. FOutput.Add('endif');
  496. end;
  497. var
  498. hs,dir : string;
  499. prefix : string;
  500. begin
  501. prefix:=FixVariable(inivar)+'_';
  502. hs:=AddTargetDefines(inivar,prefix);
  503. repeat
  504. Dir:=GetToken(hs);
  505. if Dir='' then
  506. break;
  507. AddTargetDir(Dir,prefix);
  508. until false;
  509. end;
  510. procedure TMakefileWriter.AddRequiredPackages;
  511. procedure AddPackage(const pack,prefix:string);
  512. var
  513. packdirvar,unitdirvar : string;
  514. begin
  515. FOutput.Add('ifdef '+Prefix+VarName(pack));
  516. { create needed variables }
  517. packdirvar:='PACKAGEDIR_'+VarName(pack);
  518. unitdirvar:='UNITDIR_'+VarName(pack);
  519. { Search packagedir by looking for Makefile.fpc }
  520. FOutput.Add(packdirvar+':=$(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR)))))');
  521. FOutput.Add('ifneq ($('+packdirvar+'),)');
  522. FOutput.Add(packdirvar+':=$(firstword $('+packdirvar+'))');
  523. { If Packagedir found look for FPCMade }
  524. FOutput.Add('ifeq ($(wildcard $('+packdirvar+')/$(FPCMADE)),)');
  525. FOutput.Add('override COMPILEPACKAGES+=package_'+pack);
  526. AddPhony('package_'+pack);
  527. FOutput.Add('package_'+pack+':');
  528. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+') all');
  529. FOutput.Add('endif');
  530. { Create unit dir, check if os dependent dir exists }
  531. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/$(OS_TARGET)),)');
  532. FOutput.Add(unitdirvar+'=$('+packdirvar+')/$(OS_TARGET)');
  533. FOutput.Add('else');
  534. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  535. FOutput.Add('endif');
  536. { Package dir doesn't exists, check unit dir }
  537. FOutput.Add('else');
  538. FOutput.Add(packdirvar+'=');
  539. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  540. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  541. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  542. FOutput.Add('else');
  543. FOutput.Add(unitdirvar+'=');
  544. FOutput.Add('endif');
  545. FOutput.Add('endif');
  546. { Add Unit dir to the command line -Fu }
  547. FOutput.Add('ifdef '+unitdirvar);
  548. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  549. FOutput.Add('endif');
  550. { endif for package }
  551. FOutput.Add('endif');
  552. end;
  553. var
  554. i : integer;
  555. reqs,req,prefix : string;
  556. t : Ttarget;
  557. sl : TStringList;
  558. begin
  559. prefix:='REQUIRE_PACKAGES_';
  560. reqs:='';
  561. { Add target defines }
  562. for t:=low(ttarget) to high(ttarget) do
  563. begin
  564. sl:=FInput.GetTargetRequires(t);
  565. if sl.count>0 then
  566. begin
  567. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  568. for i:=0 to sl.count-1 do
  569. begin
  570. FOutput.Add(prefix+VarName(sl[i])+'=1');
  571. AddStrNoDup(reqs,sl[i]);
  572. end;
  573. FOutput.Add('endif');
  574. end;
  575. sl.Free;
  576. end;
  577. { Add all require packages }
  578. repeat
  579. req:=GetToken(reqs);
  580. if Req='' then
  581. break;
  582. AddPackage(req,prefix);
  583. until false;
  584. WritePhony;
  585. end;
  586. procedure TMakefileWriter.AddDefaultTools;
  587. begin
  588. AddTool('ECHO','gecho','echo');
  589. AddTool('DATE','gdate','date');
  590. AddTool('GINSTALL','ginstall','install');
  591. AddTool('CPPROG','cp','');
  592. AddTool('RMPROG','rm','');
  593. AddTool('MVPROG','mv','');
  594. AddIniSection('shelltools');
  595. AddTool('PPUMOVE','ppumove','');
  596. AddTool('FPCMAKE','fpcmake','');
  597. AddTool('ZIPPROG','zip','');
  598. AddTool('TARPROG','tar','');
  599. AddIniSection('defaulttools');
  600. end;
  601. procedure TMakefileWriter.OptimizeSections;
  602. var
  603. SkippedSecs :integer;
  604. begin
  605. { Turn some sections off, depending if files are
  606. provided }
  607. if not FInput.IsPackage then
  608. begin
  609. FHasSection[sec_zipinstall]:=false;
  610. FHasSection[sec_distinstall]:=false;
  611. end;
  612. FHasSection[sec_libs]:=CheckVariable('lib_name');
  613. { Remove unused sections for targets }
  614. SkippedSecs:=0;
  615. if (not CheckTargetVariable('target_units')) then
  616. begin
  617. inc(SkippedSecs);
  618. FHasSection[sec_units]:=false;
  619. end;
  620. if (not CheckTargetVariable('target_programs')) then
  621. begin
  622. inc(SkippedSecs);
  623. FHasSection[sec_exes]:=false;
  624. end;
  625. if (not CheckTargetVariable('target_examples')) then
  626. begin
  627. inc(SkippedSecs);
  628. { example dirs also requires the fpc_examples target, because
  629. it also depends on the all target }
  630. if (not CheckTargetVariable('target_exampledirs')) then
  631. FHasSection[sec_examples]:=false;
  632. end;
  633. if (not CheckTargetVariable('target_loaders')) then
  634. begin
  635. inc(SkippedSecs);
  636. FHasSection[sec_loaders]:=false;
  637. end;
  638. { if all 4 sections are not available we can skip also the
  639. generic compile rules }
  640. if SkippedSecs=4 then
  641. begin
  642. FHasSection[sec_compile]:=false;
  643. if (not CheckTargetVariable('install_units')) and
  644. (not CheckTargetVariable('install_files')) and
  645. (not CheckTargetVariable('install_createpackagefpc')) then
  646. FHasSection[sec_install]:=false;
  647. if (not CheckTargetVariable('clean_units')) and
  648. (not CheckTargetVariable('clean_files')) then
  649. FHasSection[sec_clean]:=false;
  650. end;
  651. end;
  652. procedure TMakefileWriter.WriteGenericMakefile;
  653. begin
  654. { Remove unused sections }
  655. OptimizeSections;
  656. { Generate Output }
  657. with FOutput do
  658. begin
  659. { Header }
  660. Add('#');
  661. Add('# Don''t edit, this file is generated by '+TitleDate);
  662. Add('#');
  663. if CheckVariable('default_rule') then
  664. Add('default: '+FInput.GetVariable('default_rule',false))
  665. else
  666. Add('default: all');
  667. { Add automatic detect sections }
  668. AddIniSection('osdetect');
  669. { Forced target }
  670. if CheckVariable('default_target') then
  671. Add('override OS_TARGET='+FInput.GetVariable('default_target',false));
  672. if CheckVariable('default_cpu') then
  673. Add('override CPU_TARGET='+FInput.GetVariable('default_cpu',false));
  674. { FPC Detection }
  675. AddIniSection('fpcdetect');
  676. AddIniSection('fpcdircheckenv');
  677. if CheckVariable('default_fpcdir') then
  678. begin
  679. Add('ifeq ($(FPCDIR),wrong)');
  680. Add('override FPCDIR='+FInput.GetVariable('default_fpcdir',false));
  681. Add('ifeq ($(wildcard $(FPCDIR)/rtl),)');
  682. Add('ifeq ($(wildcard $(FPCDIR)/units),)');
  683. Add('override FPCDIR=wrong');
  684. Add('endif');
  685. Add('endif');
  686. Add('endif');
  687. end;
  688. AddIniSection('fpcdirdetect');
  689. { Package }
  690. AddVariable('package_name');
  691. AddVariable('package_version');
  692. { First add the required packages sections }
  693. // for i:=0 to FInput.RequireList.Count-1 do
  694. // AddCustomSection(FInput.Requirelist[i]);
  695. { prerules section }
  696. if assigned(FInput['prerules']) then
  697. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  698. { Default }
  699. AddVariable('default_dir');
  700. { Targets }
  701. AddTargetVariable('target_dirs');
  702. AddTargetVariable('target_programs');
  703. AddTargetVariable('target_units');
  704. AddTargetVariable('target_loaders');
  705. AddTargetVariable('target_rsts');
  706. AddTargetVariable('target_examples');
  707. AddTargetVariable('target_exampledirs');
  708. { Clean }
  709. AddTargetVariable('clean_units');
  710. AddTargetVariable('clean_files');
  711. { Install }
  712. AddTargetVariable('install_units');
  713. AddTargetVariable('install_files');
  714. AddVariable('install_prefixdir');
  715. AddVariable('install_basedir');
  716. AddVariable('install_datadir');
  717. AddVariable('install_fpcpackage');
  718. AddVariable('install_createpackagefpc');
  719. { Dist }
  720. AddVariable('dist_zipname');
  721. AddVariable('dist_ziptarget');
  722. { Compiler }
  723. AddTargetVariable('compiler_options');
  724. AddTargetVariable('compiler_version');
  725. AddTargetVariable('compiler_includedir');
  726. AddTargetVariable('compiler_unitdir');
  727. AddTargetVariable('compiler_sourcedir');
  728. AddTargetVariable('compiler_objectdir');
  729. AddTargetVariable('compiler_librarydir');
  730. AddTargetVariable('compiler_targetdir');
  731. AddTargetVariable('compiler_unittargetdir');
  732. { Add default tools }
  733. AddDefaultTools;
  734. { default dirs/tools/extensions }
  735. AddIniSection('extensions');
  736. AddIniSection('defaultdirs');
  737. if FInput.CheckLibcRequire then
  738. AddIniSection('dirlibc');
  739. { Required packages }
  740. AddRequiredPackages;
  741. { commandline }
  742. AddIniSection('command_begin');
  743. if FInput.CheckLibcRequire then
  744. AddIniSection('command_libc');
  745. AddIniSection('command_end');
  746. { compile }
  747. if FHasSection[sec_loaders] then
  748. AddIniSection('loaderrules');
  749. if FHasSection[sec_units] then
  750. AddIniSection('unitrules');
  751. if FHasSection[sec_exes] then
  752. AddIniSection('exerules');
  753. if FHasSection[sec_rsts] then
  754. AddIniSection('rstrules');
  755. if FHasSection[sec_examples] then
  756. AddIniSection('examplerules');
  757. if FHasSection[sec_compile] then
  758. AddIniSection('compilerules');
  759. if FHasSection[sec_libs] then
  760. AddIniSection('libraryrules');
  761. { install }
  762. if FHasSection[sec_install] then
  763. AddIniSection('installrules');
  764. if FHasSection[sec_distinstall] then
  765. AddIniSection('distinstallrules');
  766. if FHasSection[sec_zipinstall] then
  767. AddIniSection('zipinstallrules');
  768. { clean }
  769. AddIniSection('cleanrules');
  770. { info }
  771. AddIniSection('inforules');
  772. { Subdirs }
  773. AddTargetDirs('target_dirs');
  774. AddTargetDirs('target_exampledirs');
  775. { Tools }
  776. AddTools('require_tools');
  777. { Rules }
  778. AddRules;
  779. { Users own rules }
  780. AddIniSection('localmakefile');
  781. AddIniSection('userrules');
  782. if assigned(FInput['rules']) then
  783. AddStrings(TFPCMakeSection(FInput['rules']).List);
  784. end;
  785. { write to disk }
  786. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  787. Fixtab(FOutput);
  788. FOutput.SaveToFile(FFileName);
  789. end;
  790. end.
  791. {
  792. $Log$
  793. Revision 1.14 2001-07-31 22:02:32 peter
  794. * install Package.fpc
  795. Revision 1.13 2001/07/13 21:01:59 peter
  796. * cygdrive support
  797. * fixed cygwin detection
  798. * fixed some duplicate and extraeous spaces
  799. Revision 1.12 2001/06/07 21:21:38 peter
  800. * remove ppufiles
  801. * fix staticlib prefix that is now libp instead of lib
  802. Revision 1.11 2001/06/06 21:58:25 peter
  803. * Win32 fixes for Makefile so it doesn't require sh.exe
  804. Revision 1.10 2001/06/04 22:18:16 peter
  805. * Still process subdirs if a target has no section defined
  806. Revision 1.9 2001/06/04 21:42:57 peter
  807. * Arguments added
  808. * Start of Package.fpc creation
  809. Revision 1.8 2001/05/30 21:39:17 peter
  810. * gecho, gdate fixes
  811. * distinstall target rewrite to not install things twice
  812. Revision 1.7 2001/05/03 21:35:10 peter
  813. * Makefile fixes
  814. Revision 1.6 2001/02/24 10:44:33 peter
  815. * another fix for internal variable checking
  816. Revision 1.5 2001/02/22 21:11:24 peter
  817. * fpcdir detection added
  818. * fixed loading of variables in fpcmake itself
  819. Revision 1.4 2001/02/20 21:49:31 peter
  820. * fixed change variable accessing using _ instead of .
  821. Revision 1.3 2001/02/01 22:00:10 peter
  822. * default.fpcdir is back
  823. * subdir requirement checking works, but not very optimal yet as
  824. it can load the same Makefile.fpc multiple times
  825. Revision 1.2 2001/01/29 21:49:10 peter
  826. * lot of updates
  827. Revision 1.1 2001/01/24 21:59:36 peter
  828. * first commit of new fpcmake
  829. }