fpcmwr.pp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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')) then
  645. FHasSection[sec_install]:=false;
  646. if (not CheckTargetVariable('clean_units')) and
  647. (not CheckTargetVariable('clean_files')) then
  648. FHasSection[sec_clean]:=false;
  649. end;
  650. end;
  651. procedure TMakefileWriter.WriteGenericMakefile;
  652. begin
  653. { Remove unused sections }
  654. OptimizeSections;
  655. { Generate Output }
  656. with FOutput do
  657. begin
  658. { Header }
  659. Add('#');
  660. Add('# Don''t edit, this file is generated by '+TitleDate);
  661. Add('#');
  662. if CheckVariable('default_rule') then
  663. Add('default: '+FInput.GetVariable('default_rule',false))
  664. else
  665. Add('default: all');
  666. { Add automatic detect sections }
  667. AddIniSection('osdetect');
  668. { Forced target }
  669. if CheckVariable('default_target') then
  670. Add('override OS_TARGET='+FInput.GetVariable('default_target',false));
  671. if CheckVariable('default_cpu') then
  672. Add('override CPU_TARGET='+FInput.GetVariable('default_cpu',false));
  673. { FPC Detection }
  674. AddIniSection('fpcdetect');
  675. AddIniSection('fpcdircheckenv');
  676. if CheckVariable('default_fpcdir') then
  677. begin
  678. Add('ifeq ($(FPCDIR),wrong)');
  679. Add('override FPCDIR='+FInput.GetVariable('default_fpcdir',false));
  680. Add('ifeq ($(wildcard $(FPCDIR)/rtl),)');
  681. Add('ifeq ($(wildcard $(FPCDIR)/units),)');
  682. Add('override FPCDIR=wrong');
  683. Add('endif');
  684. Add('endif');
  685. Add('endif');
  686. end;
  687. AddIniSection('fpcdirdetect');
  688. { Package }
  689. AddVariable('package_name');
  690. AddVariable('package_version');
  691. { First add the required packages sections }
  692. // for i:=0 to FInput.RequireList.Count-1 do
  693. // AddCustomSection(FInput.Requirelist[i]);
  694. { prerules section }
  695. if assigned(FInput['prerules']) then
  696. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  697. { Default }
  698. AddVariable('default_dir');
  699. { Targets }
  700. AddTargetVariable('target_dirs');
  701. AddTargetVariable('target_programs');
  702. AddTargetVariable('target_units');
  703. AddTargetVariable('target_loaders');
  704. AddTargetVariable('target_rsts');
  705. AddTargetVariable('target_examples');
  706. AddTargetVariable('target_exampledirs');
  707. { Clean }
  708. AddTargetVariable('clean_units');
  709. AddTargetVariable('clean_files');
  710. { Install }
  711. AddTargetVariable('install_units');
  712. AddTargetVariable('install_files');
  713. AddVariable('install_prefixdir');
  714. AddVariable('install_basedir');
  715. AddVariable('install_datadir');
  716. AddVariable('install_fpcpackage');
  717. { Dist }
  718. AddVariable('dist_zipname');
  719. AddVariable('dist_ziptarget');
  720. { Compiler }
  721. AddTargetVariable('compiler_options');
  722. AddTargetVariable('compiler_version');
  723. AddTargetVariable('compiler_includedir');
  724. AddTargetVariable('compiler_unitdir');
  725. AddTargetVariable('compiler_sourcedir');
  726. AddTargetVariable('compiler_objectdir');
  727. AddTargetVariable('compiler_librarydir');
  728. AddTargetVariable('compiler_targetdir');
  729. AddTargetVariable('compiler_unittargetdir');
  730. { Add default tools }
  731. AddDefaultTools;
  732. { default dirs/tools/extensions }
  733. AddIniSection('extensions');
  734. AddIniSection('defaultdirs');
  735. if FInput.CheckLibcRequire then
  736. AddIniSection('dirlibc');
  737. { Required packages }
  738. AddRequiredPackages;
  739. { commandline }
  740. AddIniSection('command_begin');
  741. if FInput.CheckLibcRequire then
  742. AddIniSection('command_libc');
  743. AddIniSection('command_end');
  744. { compile }
  745. if FHasSection[sec_loaders] then
  746. AddIniSection('loaderrules');
  747. if FHasSection[sec_units] then
  748. AddIniSection('unitrules');
  749. if FHasSection[sec_exes] then
  750. AddIniSection('exerules');
  751. if FHasSection[sec_rsts] then
  752. AddIniSection('rstrules');
  753. if FHasSection[sec_examples] then
  754. AddIniSection('examplerules');
  755. if FHasSection[sec_compile] then
  756. AddIniSection('compilerules');
  757. if FHasSection[sec_libs] then
  758. AddIniSection('libraryrules');
  759. { install }
  760. if FHasSection[sec_install] then
  761. AddIniSection('installrules');
  762. if FHasSection[sec_distinstall] then
  763. AddIniSection('distinstallrules');
  764. if FHasSection[sec_zipinstall] then
  765. AddIniSection('zipinstallrules');
  766. { clean }
  767. AddIniSection('cleanrules');
  768. { info }
  769. AddIniSection('inforules');
  770. { Subdirs }
  771. AddTargetDirs('target_dirs');
  772. AddTargetDirs('target_exampledirs');
  773. { Tools }
  774. AddTools('require_tools');
  775. { Rules }
  776. AddRules;
  777. { Users own rules }
  778. AddIniSection('localmakefile');
  779. AddIniSection('userrules');
  780. if assigned(FInput['rules']) then
  781. AddStrings(TFPCMakeSection(FInput['rules']).List);
  782. end;
  783. { write to disk }
  784. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  785. Fixtab(FOutput);
  786. FOutput.SaveToFile(FFileName);
  787. end;
  788. end.
  789. {
  790. $Log$
  791. Revision 1.13 2001-07-13 21:01:59 peter
  792. * cygdrive support
  793. * fixed cygwin detection
  794. * fixed some duplicate and extraeous spaces
  795. Revision 1.12 2001/06/07 21:21:38 peter
  796. * remove ppufiles
  797. * fix staticlib prefix that is now libp instead of lib
  798. Revision 1.11 2001/06/06 21:58:25 peter
  799. * Win32 fixes for Makefile so it doesn't require sh.exe
  800. Revision 1.10 2001/06/04 22:18:16 peter
  801. * Still process subdirs if a target has no section defined
  802. Revision 1.9 2001/06/04 21:42:57 peter
  803. * Arguments added
  804. * Start of Package.fpc creation
  805. Revision 1.8 2001/05/30 21:39:17 peter
  806. * gecho, gdate fixes
  807. * distinstall target rewrite to not install things twice
  808. Revision 1.7 2001/05/03 21:35:10 peter
  809. * Makefile fixes
  810. Revision 1.6 2001/02/24 10:44:33 peter
  811. * another fix for internal variable checking
  812. Revision 1.5 2001/02/22 21:11:24 peter
  813. * fpcdir detection added
  814. * fixed loading of variables in fpcmake itself
  815. Revision 1.4 2001/02/20 21:49:31 peter
  816. * fixed change variable accessing using _ instead of .
  817. Revision 1.3 2001/02/01 22:00:10 peter
  818. * default.fpcdir is back
  819. * subdir requirement checking works, but not very optimal yet as
  820. it can load the same Makefile.fpc multiple times
  821. Revision 1.2 2001/01/29 21:49:10 peter
  822. * lot of updates
  823. Revision 1.1 2001/01/24 21:59:36 peter
  824. * first commit of new fpcmake
  825. }