fpcmwr.pp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  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. C : TCpu;
  265. firsttarget,
  266. firstcpu : boolean;
  267. begin
  268. s:=FInput.GetVariable(IniVar,false);
  269. if s<>'' then
  270. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  271. for t:=low(TTarget) to high(TTarget) do
  272. if t in FInput.IncludeTargets then
  273. begin
  274. firsttarget:=true;
  275. firstcpu:=true;
  276. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  277. if s<>'' then
  278. begin
  279. if firsttarget then
  280. begin
  281. firsttarget:=false;
  282. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  283. end;
  284. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  285. end;
  286. for c:=low(TCpu) to high(TCpu) do
  287. if (TargetCpuPossible[t,c]) and (c in FInput.IncludeCpus) then
  288. begin
  289. s:=FInput.GetVariable(IniVar+TargetSuffix[t]+CpuSuffix[c],false);
  290. if s<>'' then
  291. begin
  292. if firsttarget then
  293. begin
  294. firsttarget:=false;
  295. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  296. end;
  297. if firstcpu then
  298. begin
  299. firstcpu:=false;
  300. FOutput.Add('ifeq ($(CPU_TARGET),'+CpuStr[c]+')');
  301. end;
  302. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  303. end;
  304. end;
  305. if not firstcpu then
  306. FOutput.Add('endif');
  307. if not firsttarget then
  308. FOutput.Add('endif');
  309. end;
  310. end;
  311. procedure TMakefileWriter.AddVariable(const inivar:string);
  312. var
  313. s : string;
  314. begin
  315. s:=FInput.GetVariable(IniVar,false);
  316. if s<>'' then
  317. FOutput.Add('override '+FixVariable(IniVar)+'='+s)
  318. end;
  319. function TMakefileWriter.AddTargetDefines(const inivar,prefix:string):string;
  320. procedure addtokens(s:string);
  321. var
  322. name : string;
  323. k1,k2 : integer;
  324. begin
  325. repeat
  326. Name:=GetToken(s,' ');
  327. if Name='' then
  328. break;
  329. { Remove (..) }
  330. k1:=pos('(',name);
  331. if k1>0 then
  332. begin
  333. k2:=PosIdx(')',name,k1);
  334. if k2=0 then
  335. k2:=length(name)+1;
  336. Delete(Name,k1,k2);
  337. end;
  338. FOutput.Add(prefix+VarName(name)+'=1');
  339. { add to the list of dirs without duplicates }
  340. AddTokenNoDup(result,name,' ');
  341. until false;
  342. end;
  343. var
  344. s : string;
  345. T : TTarget;
  346. c : TCpu;
  347. firsttarget,
  348. firstcpu : boolean;
  349. begin
  350. result:='';
  351. s:=FInput.GetVariable(IniVar,false);
  352. addtokens(s);
  353. for t:=low(TTarget) to high(TTarget) do
  354. if t in FInput.IncludeTargets then
  355. begin
  356. firsttarget:=true;
  357. firstcpu:=true;
  358. s:=FInput.GetVariable(IniVar+TargetSuffix[t],false);
  359. if s<>'' then
  360. begin
  361. if firsttarget then
  362. begin
  363. firsttarget:=false;
  364. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  365. end;
  366. addtokens(s);
  367. end;
  368. for c:=low(TCpu) to high(TCpu) do
  369. if (TargetCpuPossible[t,c]) and (c in FInput.IncludeCpus) then
  370. begin
  371. s:=FInput.GetVariable(IniVar+TargetSuffix[t]+CpuSuffix[c],false);
  372. if s<>'' then
  373. begin
  374. if firsttarget then
  375. begin
  376. firsttarget:=false;
  377. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  378. end;
  379. if firstcpu then
  380. begin
  381. firstcpu:=false;
  382. FOutput.Add('ifeq ($(CPU_TARGET),'+CpuStr[c]+')');
  383. end;
  384. addtokens(s);
  385. end;
  386. end;
  387. if not firstcpu then
  388. FOutput.Add('endif');
  389. if not firsttarget then
  390. FOutput.Add('endif');
  391. end;
  392. end;
  393. procedure TMakefileWriter.AddTool(const varname,exename,altexename:string);
  394. begin
  395. with FOutput do
  396. begin
  397. Add('ifndef '+varname);
  398. Add(varname+':=$(strip $(wildcard $(addsuffix /'+exename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  399. if altexename<>'' then
  400. begin
  401. Add('ifeq ($('+varname+'),)');
  402. Add(varname+':=$(strip $(wildcard $(addsuffix /'+altexename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  403. end;
  404. Add('ifeq ($('+varname+'),)');
  405. Add(varname+'=');
  406. Add('else');
  407. Add(varname+':=$(firstword $('+varname+'))');
  408. Add('endif');
  409. if altexename<>'' then
  410. begin
  411. Add('else');
  412. Add(varname+':=$(firstword $('+varname+'))');
  413. Add('endif');
  414. end;
  415. Add('endif');
  416. Add('export '+varname);
  417. end;
  418. end;
  419. procedure TMakefileWriter.AddTools(const inivar:string);
  420. var
  421. hs,tool : string;
  422. begin
  423. hs:=FInput.GetVariable(inivar,false);
  424. repeat
  425. Tool:=GetToken(hs,' ');
  426. if Tool='' then
  427. break;
  428. AddTool(FixVariable(Tool),Tool,'');
  429. until false;
  430. end;
  431. procedure TMakefileWriter.AddRules;
  432. procedure AddRule(rule:trules);
  433. var
  434. i : integer;
  435. hs : string;
  436. Sec : TFPCMakeSection;
  437. Rules : TStringList;
  438. begin
  439. Sec:=TFPCMakeSection(FInput['rules']);
  440. if assigned(Sec) then
  441. begin
  442. Rules:=Sec.List;
  443. for i:=0 to Rules.Count-1 do
  444. begin
  445. if (length(rules[i])>length(rule2str[rule])) and
  446. (rules[i][1]=rule2str[rule][1]) and
  447. ((rules[i][length(rule2str[rule])+1]=':') or
  448. ((length(rules[i])>length(rule2str[rule])+1) and
  449. (rules[i][length(rule2str[rule])+2]=':'))) and
  450. (Copy(rules[i],1,length(rule2str[rule]))=rule2str[rule]) then
  451. exit;
  452. end;
  453. end;
  454. hs:='';
  455. if FHasSection[Rule2Sec[rule]] then
  456. hs:=hs+' fpc_'+rule2str[rule];
  457. { include target dirs, but not for info and targets that
  458. call other targets with a only extra settings, if the
  459. section was not included, then still process the targets }
  460. if CheckTargetVariable('target_dirs') and
  461. (not(rule in [r_info,r_shared,r_smart,r_debug,r_release,r_zipdistinstall,r_distinstall]) or
  462. not FHasSection[Rule2Sec[rule]]) then
  463. begin
  464. if CheckVariable('default_dir') then
  465. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(DEFAULT_DIR))'
  466. else
  467. if not(rule in [r_sourceinstall,r_zipinstall,r_zipsourceinstall,
  468. r_makefiles]) or
  469. not(CheckVariable('package_name')) then
  470. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_DIRS))';
  471. end;
  472. { include cleaning of example dirs }
  473. if (rule=r_clean) and
  474. CheckTargetVariable('target_exampledirs') then
  475. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_EXAMPLEDIRS))';
  476. { Add the rule }
  477. AddPhony(Rule2Str[Rule]);
  478. FOutput.Add(rule2str[rule]+':'+hs);
  479. end;
  480. var
  481. rule : trules;
  482. begin
  483. for rule:=low(trules) to high(trules) do
  484. AddRule(rule);
  485. WritePhony;
  486. end;
  487. procedure TMakefileWriter.AddPhony(const s:string);
  488. begin
  489. FPhony:=FPhony+' '+s;
  490. end;
  491. procedure TMakefileWriter.WritePhony;
  492. begin
  493. if FPhony<>'' then
  494. begin
  495. FOutput.Add('.PHONY:'+FPhony);
  496. FPhony:='';
  497. end;
  498. end;
  499. procedure TMakefileWriter.AddTargetDirs(const inivar:string);
  500. procedure AddTargetDir(const s,defpref:string);
  501. var
  502. j : trules;
  503. begin
  504. FOutput.Add('ifdef '+defpref+VarName(s));
  505. for j:=low(trules) to high(trules) do
  506. begin
  507. FOutput.Add(s+'_'+rule2str[j]+':');
  508. FOutput.Add(#9+'$(MAKE) -C '+s+' '+rule2str[j]);
  509. AddPhony(s+'_'+rule2str[j]);
  510. end;
  511. FOutput.Add(s+':');
  512. FOutput.Add(#9+'$(MAKE) -C '+s+' all');
  513. AddPhony(s);
  514. WritePhony;
  515. FOutput.Add('endif');
  516. end;
  517. var
  518. hs,dir : string;
  519. prefix : string;
  520. begin
  521. prefix:=FixVariable(inivar)+'_';
  522. hs:=AddTargetDefines(inivar,prefix);
  523. repeat
  524. Dir:=GetToken(hs,' ');
  525. if Dir='' then
  526. break;
  527. AddTargetDir(Dir,prefix);
  528. until false;
  529. end;
  530. procedure TMakefileWriter.AddRequiredPackages;
  531. procedure AddPackage(const pack,prefix:string);
  532. var
  533. packdirvar,unitdirvar : string;
  534. begin
  535. FOutput.Add('ifdef '+Prefix+VarName(pack));
  536. { create needed variables }
  537. packdirvar:='PACKAGEDIR_'+VarName(pack);
  538. unitdirvar:='UNITDIR_'+VarName(pack);
  539. { Search packagedir by looking for Makefile.fpc, for the RTL look
  540. direct in the corresponding target directory }
  541. if pack='rtl' then
  542. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/$(OS_TARGET)/Makefile.fpc,$(PACKAGESDIR))))))')
  543. else
  544. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  545. FOutput.Add('ifneq ($('+packdirvar+'),)');
  546. { Create unit dir, check if os dependent dir exists }
  547. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/$(OS_TARGET)),)');
  548. FOutput.Add(unitdirvar+'=$('+packdirvar+')/$(OS_TARGET)');
  549. FOutput.Add('else');
  550. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  551. FOutput.Add('endif');
  552. FOutput.Add('ifdef CHECKDEPEND');
  553. FOutput.Add('$('+packdirvar+')/$(FPCMADE):');
  554. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+') $(FPCMADE)');
  555. FOutput.Add('override ALLDEPENDENCIES+=$('+packdirvar+')/$(FPCMADE)');
  556. FOutput.Add('endif');
  557. { Package dir doesn't exists, check unit dir }
  558. FOutput.Add('else');
  559. FOutput.Add(packdirvar+'=');
  560. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  561. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  562. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  563. FOutput.Add('else');
  564. FOutput.Add(unitdirvar+'=');
  565. FOutput.Add('endif');
  566. FOutput.Add('endif');
  567. { Add Unit dir to the command line -Fu }
  568. FOutput.Add('ifdef '+unitdirvar);
  569. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  570. FOutput.Add('endif');
  571. { endif for package }
  572. FOutput.Add('endif');
  573. end;
  574. var
  575. i : integer;
  576. reqs,req,prefix : string;
  577. t : Ttarget;
  578. c : TCpu;
  579. sl : TStringList;
  580. begin
  581. prefix:='REQUIRE_PACKAGES_';
  582. reqs:='';
  583. { Add target defines }
  584. for t:=low(ttarget) to high(ttarget) do
  585. if t in FInput.IncludeTargets then
  586. begin
  587. for c:=low(tcpu) to high(tcpu) do
  588. if (TargetCpuPossible[t,c]) and (c in FInput.IncludeCpus) then
  589. begin
  590. sl:=FInput.GetTargetRequires(t,c);
  591. { show info }
  592. FInput.Verbose(FPCMakeInfo,TargetStr[t]+'-'+CpuStr[c]+' requires: '+sl.CommaText);
  593. if sl.count>0 then
  594. begin
  595. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  596. FOutput.Add('ifeq ($(CPU_TARGET),'+CpuStr[c]+')');
  597. for i:=0 to sl.count-1 do
  598. begin
  599. FOutput.Add(prefix+VarName(sl[i])+'=1');
  600. AddTokenNoDup(reqs,sl[i],' ');
  601. end;
  602. FOutput.Add('endif');
  603. FOutput.Add('endif');
  604. end;
  605. sl.Free;
  606. end;
  607. end;
  608. { Add all require packages }
  609. repeat
  610. req:=GetToken(reqs,' ');
  611. if Req='' then
  612. break;
  613. AddPackage(req,prefix);
  614. until false;
  615. WritePhony;
  616. end;
  617. procedure TMakefileWriter.AddDefaultTools;
  618. begin
  619. AddTool('ECHO','gecho','echo');
  620. AddTool('DATE','gdate','date');
  621. AddTool('GINSTALL','ginstall','install');
  622. AddTool('CPPROG','cp','');
  623. AddTool('RMPROG','rm','');
  624. AddTool('MVPROG','mv','');
  625. AddIniSection('shelltools');
  626. AddTool('PPUMOVE','ppumove','');
  627. AddTool('FPCMAKE','fpcmake','');
  628. AddTool('ZIPPROG','zip','');
  629. AddTool('TARPROG','tar','');
  630. AddIniSection('defaulttools');
  631. end;
  632. procedure TMakefileWriter.AddMakefileTargets;
  633. var
  634. s : string;
  635. t : Ttarget;
  636. begin
  637. s:='';
  638. for t:=low(ttarget) to high(ttarget) do
  639. if t in FInput.IncludeTargets then
  640. begin
  641. AddToken(s,TargetStr[t],' ');
  642. end;
  643. FOutput.Add('MAKEFILETARGETS='+s);
  644. end;
  645. procedure TMakefileWriter.OptimizeSections;
  646. var
  647. SkippedSecs :integer;
  648. begin
  649. { Turn some sections off, depending if files are
  650. provided }
  651. if not FInput.IsPackage then
  652. begin
  653. FHasSection[sec_zipinstall]:=false;
  654. FHasSection[sec_distinstall]:=false;
  655. end;
  656. FHasSection[sec_libs]:=CheckVariable('lib_name');
  657. { Remove unused sections for targets }
  658. SkippedSecs:=0;
  659. if (not CheckTargetVariable('target_units')) then
  660. begin
  661. inc(SkippedSecs);
  662. FHasSection[sec_units]:=false;
  663. end;
  664. if (not CheckTargetVariable('target_programs')) then
  665. begin
  666. inc(SkippedSecs);
  667. FHasSection[sec_exes]:=false;
  668. end;
  669. if (not CheckTargetVariable('target_examples')) then
  670. begin
  671. inc(SkippedSecs);
  672. { example dirs also requires the fpc_examples target, because
  673. it also depends on the all target }
  674. if (not CheckTargetVariable('target_exampledirs')) then
  675. FHasSection[sec_examples]:=false;
  676. end;
  677. if (not CheckTargetVariable('target_loaders')) then
  678. begin
  679. inc(SkippedSecs);
  680. FHasSection[sec_loaders]:=false;
  681. end;
  682. { if all 4 sections are not available we can skip also the
  683. generic compile rules }
  684. if SkippedSecs=4 then
  685. begin
  686. FHasSection[sec_compile]:=false;
  687. if (not CheckTargetVariable('package_name')) and
  688. (not CheckTargetVariable('install_units')) and
  689. (not CheckTargetVariable('install_files')) and
  690. (not CheckTargetVariable('install_createpackagefpc')) then
  691. FHasSection[sec_install]:=false;
  692. { Package.fpc also needs to be cleaned }
  693. if (not CheckTargetVariable('clean_units')) and
  694. (not CheckTargetVariable('clean_files')) and
  695. (not CheckTargetVariable('install_createpackagefpc')) then
  696. FHasSection[sec_clean]:=false;
  697. end;
  698. end;
  699. procedure TMakefileWriter.WriteGenericMakefile;
  700. begin
  701. { Remove unused sections }
  702. OptimizeSections;
  703. { Generate Output }
  704. with FOutput do
  705. begin
  706. { Header }
  707. Add('#');
  708. Add('# Don''t edit, this file is generated by '+TitleDate);
  709. Add('#');
  710. if CheckVariable('default_rule') then
  711. Add('default: '+FInput.GetVariable('default_rule',false))
  712. else
  713. Add('default: all');
  714. { Supported targets by this Makefile }
  715. AddMakefileTargets;
  716. { Add automatic detect sections }
  717. AddIniSection('osdetect');
  718. { Forced target }
  719. if CheckVariable('require_target') then
  720. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  721. else if CheckVariable('default_target') then
  722. Add('override OS_TARGET_DEFAULT='+FInput.GetVariable('default_target',false));
  723. if CheckVariable('require_cpu') then
  724. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  725. else if CheckVariable('default_cpu') then
  726. Add('override CPU_TARGET_DEFAULT='+FInput.GetVariable('default_cpu',false));
  727. { FPC Detection }
  728. AddVariable('default_fpcdir');
  729. AddIniSection('fpcdetect');
  730. AddIniSection('fpcdircheckenv');
  731. AddIniSection('fpcdirdetect');
  732. { Package }
  733. AddVariable('package_name');
  734. AddVariable('package_version');
  735. AddVariable('package_targets');
  736. { LCL rules }
  737. if FInput.UsesLCL then
  738. begin
  739. AddVariable('default_lcldir');
  740. AddVariable('lcl_platform');
  741. AddIniSection('lclrules');
  742. end;
  743. { First add the required packages sections }
  744. // for i:=0 to FInput.RequireList.Count-1 do
  745. // AddCustomSection(FInput.Requirelist[i]);
  746. { prerules section }
  747. if assigned(FInput['prerules']) then
  748. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  749. { Default }
  750. AddVariable('default_dir');
  751. { Targets }
  752. AddTargetVariable('target_dirs');
  753. AddTargetVariable('target_programs');
  754. AddTargetVariable('target_units');
  755. AddTargetVariable('target_implicitunits');
  756. AddTargetVariable('target_loaders');
  757. AddTargetVariable('target_rsts');
  758. AddTargetVariable('target_examples');
  759. AddTargetVariable('target_exampledirs');
  760. { Clean }
  761. AddTargetVariable('clean_units');
  762. AddTargetVariable('clean_files');
  763. { Install }
  764. AddTargetVariable('install_units');
  765. AddTargetVariable('install_files');
  766. AddVariable('install_buildunit');
  767. AddVariable('install_prefix');
  768. AddVariable('install_basedir');
  769. AddVariable('install_datadir');
  770. AddVariable('install_fpcpackage');
  771. AddVariable('install_fpcsubdir');
  772. AddVariable('install_createpackagefpc');
  773. { Dist }
  774. AddVariable('dist_destdir');
  775. AddVariable('dist_zipname');
  776. AddVariable('dist_ziptarget');
  777. { Compiler }
  778. AddTargetVariable('compiler_options');
  779. AddTargetVariable('compiler_version');
  780. AddTargetVariable('compiler_includedir');
  781. AddTargetVariable('compiler_unitdir');
  782. AddTargetVariable('compiler_sourcedir');
  783. AddTargetVariable('compiler_objectdir');
  784. AddTargetVariable('compiler_librarydir');
  785. AddTargetVariable('compiler_targetdir');
  786. AddTargetVariable('compiler_unittargetdir');
  787. { default Dirs and extensions }
  788. AddIniSection('defaultdirs');
  789. if FInput.CheckLibcRequire then
  790. AddIniSection('dirlibc');
  791. AddIniSection('extensions');
  792. { Add default tools }
  793. AddDefaultTools;
  794. { Required packages }
  795. AddVariable('require_packages');
  796. AddRequiredPackages;
  797. { commandline }
  798. AddIniSection('command_begin');
  799. if FInput.CheckLibcRequire then
  800. AddIniSection('command_libc');
  801. AddIniSection('command_end');
  802. { compile }
  803. if FHasSection[sec_loaders] then
  804. AddIniSection('loaderrules');
  805. if FHasSection[sec_units] then
  806. AddIniSection('unitrules');
  807. if FHasSection[sec_exes] then
  808. AddIniSection('exerules');
  809. if FHasSection[sec_rsts] then
  810. AddIniSection('rstrules');
  811. if FHasSection[sec_examples] then
  812. AddIniSection('examplerules');
  813. if FHasSection[sec_compile] then
  814. AddIniSection('compilerules');
  815. if FHasSection[sec_libs] then
  816. AddIniSection('libraryrules');
  817. { install }
  818. if FHasSection[sec_install] then
  819. AddIniSection('installrules');
  820. if FHasSection[sec_distinstall] then
  821. AddIniSection('distinstallrules');
  822. if FHasSection[sec_zipinstall] then
  823. AddIniSection('zipinstallrules');
  824. { clean }
  825. AddIniSection('cleanrules');
  826. { info }
  827. AddIniSection('baseinforules');
  828. if FInput.UsesLCL then
  829. AddIniSection('lclinforules');
  830. AddIniSection('inforules');
  831. { info }
  832. AddIniSection('makefilerules');
  833. { Subdirs }
  834. AddTargetDirs('target_dirs');
  835. AddTargetDirs('target_exampledirs');
  836. { Tools }
  837. AddTools('require_tools');
  838. { Rules }
  839. AddRules;
  840. { Users own rules }
  841. AddIniSection('localmakefile');
  842. AddIniSection('userrules');
  843. if assigned(FInput['rules']) then
  844. AddStrings(TFPCMakeSection(FInput['rules']).List);
  845. end;
  846. { write to disk }
  847. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  848. Fixtab(FOutput);
  849. FOutput.SaveToFile(FFileName);
  850. end;
  851. end.
  852. {
  853. $Log$
  854. Revision 1.28 2003-04-25 20:53:33 peter
  855. * target_dir variable generation was not cpu dependent yet
  856. Revision 1.27 2003/04/24 23:21:01 peter
  857. * support different cpu target
  858. Revision 1.26 2003/03/24 10:56:02 marco
  859. * fix recursive zip making that corrupted utilsxxx.zip
  860. Revision 1.25 2002/09/27 06:54:54 pierre
  861. * translate default_cpu/os into CPU/OS_TARGET_DEFAULT
  862. Revision 1.24 2002/09/07 15:40:32 peter
  863. * old logs removed and tabs fixed
  864. Revision 1.23 2002/03/19 19:37:09 peter
  865. * fix source location in zips for packages and demos
  866. Revision 1.22 2002/03/11 19:10:36 peter
  867. * Regenerated with updated fpcmake
  868. Revision 1.21 2002/02/28 17:03:47 pierre
  869. + CHECKDEPEND var to check if packages are up to date
  870. Revision 1.20 2002/01/27 21:42:35 peter
  871. * -r option to process target dirs also
  872. * default changed to build only for current target
  873. * removed auto building of required packages
  874. * removed makefile target because it causes problems with
  875. an internal rule of make
  876. Revision 1.19 2002/01/06 21:50:05 peter
  877. * lcl updates
  878. * small optimizes for package check
  879. }