fpcmwr.pp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  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. { Package dir doesn't exists, check unit dir }
  502. FOutput.Add('else');
  503. FOutput.Add(packdirvar+'=');
  504. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  505. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  506. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  507. FOutput.Add('else');
  508. FOutput.Add(unitdirvar+'=');
  509. FOutput.Add('endif');
  510. FOutput.Add('endif');
  511. { Add Unit dir to the command line -Fu }
  512. FOutput.Add('ifdef '+unitdirvar);
  513. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  514. FOutput.Add('endif');
  515. { endif for package }
  516. FOutput.Add('endif');
  517. end;
  518. var
  519. i : integer;
  520. reqs,req,prefix : string;
  521. t : Ttarget;
  522. sl : TStringList;
  523. begin
  524. prefix:='REQUIRE_PACKAGES_';
  525. reqs:='';
  526. { Add target defines }
  527. for t:=low(ttarget) to high(ttarget) do
  528. if t in FInput.IncludeTargets then
  529. begin
  530. sl:=FInput.GetTargetRequires(t);
  531. { show info }
  532. FInput.Verbose(FPCMakeInfo,TargetStr[t]+' requires: '+sl.CommaText);
  533. if sl.count>0 then
  534. begin
  535. FOutput.Add('ifeq ($(OS_TARGET),'+TargetStr[t]+')');
  536. for i:=0 to sl.count-1 do
  537. begin
  538. FOutput.Add(prefix+VarName(sl[i])+'=1');
  539. AddTokenNoDup(reqs,sl[i],' ');
  540. end;
  541. FOutput.Add('endif');
  542. end;
  543. sl.Free;
  544. end;
  545. { Add all require packages }
  546. repeat
  547. req:=GetToken(reqs,' ');
  548. if Req='' then
  549. break;
  550. AddPackage(req,prefix);
  551. until false;
  552. WritePhony;
  553. end;
  554. procedure TMakefileWriter.AddDefaultTools;
  555. begin
  556. AddTool('ECHO','gecho','echo');
  557. AddTool('DATE','gdate','date');
  558. AddTool('GINSTALL','ginstall','install');
  559. AddTool('CPPROG','cp','');
  560. AddTool('RMPROG','rm','');
  561. AddTool('MVPROG','mv','');
  562. AddIniSection('shelltools');
  563. AddTool('PPUMOVE','ppumove','');
  564. AddTool('FPCMAKE','fpcmake','');
  565. AddTool('ZIPPROG','zip','');
  566. AddTool('TARPROG','tar','');
  567. AddIniSection('defaulttools');
  568. end;
  569. procedure TMakefileWriter.AddMakefileTargets;
  570. var
  571. s : string;
  572. t : Ttarget;
  573. begin
  574. s:='';
  575. for t:=low(ttarget) to high(ttarget) do
  576. if t in FInput.IncludeTargets then
  577. begin
  578. AddToken(s,TargetStr[t],' ');
  579. end;
  580. FOutput.Add('MAKEFILETARGETS='+s);
  581. end;
  582. procedure TMakefileWriter.OptimizeSections;
  583. var
  584. SkippedSecs :integer;
  585. begin
  586. { Turn some sections off, depending if files are
  587. provided }
  588. if not FInput.IsPackage then
  589. begin
  590. FHasSection[sec_zipinstall]:=false;
  591. FHasSection[sec_distinstall]:=false;
  592. end;
  593. FHasSection[sec_libs]:=CheckVariable('lib_name');
  594. { Remove unused sections for targets }
  595. SkippedSecs:=0;
  596. if (not CheckTargetVariable('target_units')) then
  597. begin
  598. inc(SkippedSecs);
  599. FHasSection[sec_units]:=false;
  600. end;
  601. if (not CheckTargetVariable('target_programs')) then
  602. begin
  603. inc(SkippedSecs);
  604. FHasSection[sec_exes]:=false;
  605. end;
  606. if (not CheckTargetVariable('target_examples')) then
  607. begin
  608. inc(SkippedSecs);
  609. { example dirs also requires the fpc_examples target, because
  610. it also depends on the all target }
  611. if (not CheckTargetVariable('target_exampledirs')) then
  612. FHasSection[sec_examples]:=false;
  613. end;
  614. if (not CheckTargetVariable('target_loaders')) then
  615. begin
  616. inc(SkippedSecs);
  617. FHasSection[sec_loaders]:=false;
  618. end;
  619. { if all 4 sections are not available we can skip also the
  620. generic compile rules }
  621. if SkippedSecs=4 then
  622. begin
  623. FHasSection[sec_compile]:=false;
  624. if (not CheckTargetVariable('install_units')) and
  625. (not CheckTargetVariable('install_files')) and
  626. (not CheckTargetVariable('install_createpackagefpc')) then
  627. FHasSection[sec_install]:=false;
  628. { Package.fpc also needs to be cleaned }
  629. if (not CheckTargetVariable('clean_units')) and
  630. (not CheckTargetVariable('clean_files')) and
  631. (not CheckTargetVariable('install_createpackagefpc')) then
  632. FHasSection[sec_clean]:=false;
  633. end;
  634. end;
  635. procedure TMakefileWriter.WriteGenericMakefile;
  636. begin
  637. { Remove unused sections }
  638. OptimizeSections;
  639. { Generate Output }
  640. with FOutput do
  641. begin
  642. { Header }
  643. Add('#');
  644. Add('# Don''t edit, this file is generated by '+TitleDate);
  645. Add('#');
  646. if CheckVariable('default_rule') then
  647. Add('default: '+FInput.GetVariable('default_rule',false))
  648. else
  649. Add('default: all');
  650. { Supported targets by this Makefile }
  651. AddMakefileTargets;
  652. { Add automatic detect sections }
  653. AddIniSection('osdetect');
  654. { Forced target }
  655. if CheckVariable('require_target') then
  656. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  657. else if CheckVariable('default_target') then
  658. Add('OS_TARGET='+FInput.GetVariable('default_target',false));
  659. if CheckVariable('require_cpu') then
  660. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  661. else if CheckVariable('default_cpu') then
  662. Add('CPU_TARGET='+FInput.GetVariable('default_cpu',false));
  663. { FPC Detection }
  664. AddVariable('default_fpcdir');
  665. AddIniSection('fpcdetect');
  666. AddIniSection('fpcdircheckenv');
  667. AddIniSection('fpcdirdetect');
  668. { Package }
  669. AddVariable('package_name');
  670. AddVariable('package_version');
  671. AddVariable('package_targets');
  672. { LCL rules }
  673. if FInput.UsesLCL then
  674. begin
  675. AddVariable('default_lcldir');
  676. AddVariable('lcl_platform');
  677. AddIniSection('lclrules');
  678. end;
  679. { First add the required packages sections }
  680. // for i:=0 to FInput.RequireList.Count-1 do
  681. // AddCustomSection(FInput.Requirelist[i]);
  682. { prerules section }
  683. if assigned(FInput['prerules']) then
  684. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  685. { Default }
  686. AddVariable('default_dir');
  687. { Targets }
  688. AddTargetVariable('target_dirs');
  689. AddTargetVariable('target_programs');
  690. AddTargetVariable('target_units');
  691. AddTargetVariable('target_implicitunits');
  692. AddTargetVariable('target_loaders');
  693. AddTargetVariable('target_rsts');
  694. AddTargetVariable('target_examples');
  695. AddTargetVariable('target_exampledirs');
  696. { Clean }
  697. AddTargetVariable('clean_units');
  698. AddTargetVariable('clean_files');
  699. { Install }
  700. AddTargetVariable('install_units');
  701. AddTargetVariable('install_files');
  702. AddVariable('install_buildunit');
  703. AddVariable('install_prefix');
  704. AddVariable('install_basedir');
  705. AddVariable('install_datadir');
  706. AddVariable('install_fpcpackage');
  707. AddVariable('install_createpackagefpc');
  708. { Dist }
  709. AddVariable('dist_destdir');
  710. AddVariable('dist_zipname');
  711. AddVariable('dist_ziptarget');
  712. { Compiler }
  713. AddTargetVariable('compiler_options');
  714. AddTargetVariable('compiler_version');
  715. AddTargetVariable('compiler_includedir');
  716. AddTargetVariable('compiler_unitdir');
  717. AddTargetVariable('compiler_sourcedir');
  718. AddTargetVariable('compiler_objectdir');
  719. AddTargetVariable('compiler_librarydir');
  720. AddTargetVariable('compiler_targetdir');
  721. AddTargetVariable('compiler_unittargetdir');
  722. { default Dirs and extensions }
  723. AddIniSection('defaultdirs');
  724. if FInput.CheckLibcRequire then
  725. AddIniSection('dirlibc');
  726. AddIniSection('extensions');
  727. { Add default tools }
  728. AddDefaultTools;
  729. { Required packages }
  730. AddVariable('require_packages');
  731. AddRequiredPackages;
  732. { commandline }
  733. AddIniSection('command_begin');
  734. if FInput.CheckLibcRequire then
  735. AddIniSection('command_libc');
  736. AddIniSection('command_end');
  737. { compile }
  738. if FHasSection[sec_loaders] then
  739. AddIniSection('loaderrules');
  740. if FHasSection[sec_units] then
  741. AddIniSection('unitrules');
  742. if FHasSection[sec_exes] then
  743. AddIniSection('exerules');
  744. if FHasSection[sec_rsts] then
  745. AddIniSection('rstrules');
  746. if FHasSection[sec_examples] then
  747. AddIniSection('examplerules');
  748. if FHasSection[sec_compile] then
  749. AddIniSection('compilerules');
  750. if FHasSection[sec_libs] then
  751. AddIniSection('libraryrules');
  752. { install }
  753. if FHasSection[sec_install] then
  754. AddIniSection('installrules');
  755. if FHasSection[sec_distinstall] then
  756. AddIniSection('distinstallrules');
  757. if FHasSection[sec_zipinstall] then
  758. AddIniSection('zipinstallrules');
  759. { clean }
  760. AddIniSection('cleanrules');
  761. { info }
  762. AddIniSection('baseinforules');
  763. if FInput.UsesLCL then
  764. AddIniSection('lclinforules');
  765. AddIniSection('inforules');
  766. { info }
  767. AddIniSection('makefilerules');
  768. { Subdirs }
  769. AddTargetDirs('target_dirs');
  770. AddTargetDirs('target_exampledirs');
  771. { Tools }
  772. AddTools('require_tools');
  773. { Rules }
  774. AddRules;
  775. { Users own rules }
  776. AddIniSection('localmakefile');
  777. AddIniSection('userrules');
  778. if assigned(FInput['rules']) then
  779. AddStrings(TFPCMakeSection(FInput['rules']).List);
  780. end;
  781. { write to disk }
  782. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  783. Fixtab(FOutput);
  784. FOutput.SaveToFile(FFileName);
  785. end;
  786. end.
  787. {
  788. $Log$
  789. Revision 1.20 2002-01-27 21:42:35 peter
  790. * -r option to process target dirs also
  791. * default changed to build only for current target
  792. * removed auto building of required packages
  793. * removed makefile target because it causes problems with
  794. an internal rule of make
  795. Revision 1.19 2002/01/06 21:50:05 peter
  796. * lcl updates
  797. * small optimizes for package check
  798. Revision 1.18 2001/10/14 21:38:33 peter
  799. * cross compiling support
  800. Revision 1.17 2001/09/11 11:04:51 pierre
  801. * handle default cpu and target without override, use require section for override
  802. Revision 1.16 2001/08/22 20:45:19 peter
  803. * firstword added
  804. * pathexist fix to include sysfile
  805. Revision 1.15 2001/08/02 20:50:29 peter
  806. * -T<target> support
  807. * better error reporting for not found dirs
  808. * some cleanups and nicer strings
  809. Revision 1.14 2001/07/31 22:02:32 peter
  810. * install Package.fpc
  811. Revision 1.13 2001/07/13 21:01:59 peter
  812. * cygdrive support
  813. * fixed cygwin detection
  814. * fixed some duplicate and extraeous spaces
  815. Revision 1.12 2001/06/07 21:21:38 peter
  816. * remove ppufiles
  817. * fix staticlib prefix that is now libp instead of lib
  818. Revision 1.11 2001/06/06 21:58:25 peter
  819. * Win32 fixes for Makefile so it doesn't require sh.exe
  820. Revision 1.10 2001/06/04 22:18:16 peter
  821. * Still process subdirs if a target has no section defined
  822. Revision 1.9 2001/06/04 21:42:57 peter
  823. * Arguments added
  824. * Start of Package.fpc creation
  825. Revision 1.8 2001/05/30 21:39:17 peter
  826. * gecho, gdate fixes
  827. * distinstall target rewrite to not install things twice
  828. Revision 1.7 2001/05/03 21:35:10 peter
  829. * Makefile fixes
  830. Revision 1.6 2001/02/24 10:44:33 peter
  831. * another fix for internal variable checking
  832. Revision 1.5 2001/02/22 21:11:24 peter
  833. * fpcdir detection added
  834. * fixed loading of variables in fpcmake itself
  835. Revision 1.4 2001/02/20 21:49:31 peter
  836. * fixed change variable accessing using _ instead of .
  837. Revision 1.3 2001/02/01 22:00:10 peter
  838. * default.fpcdir is back
  839. * subdir requirement checking works, but not very optimal yet as
  840. it can load the same Makefile.fpc multiple times
  841. Revision 1.2 2001/01/29 21:49:10 peter
  842. * lot of updates
  843. Revision 1.1 2001/01/24 21:59:36 peter
  844. * first commit of new fpcmake
  845. }