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