fpcmwr.pp 30 KB

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