fpcmwr.pp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. {
  2. Copyright (c) 2001 by Peter Vreman
  3. FPCMake - Makefile writer
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$ifdef fpc}{$mode objfpc}{$endif}
  11. {$H+}
  12. unit fpcmwr;
  13. interface
  14. uses
  15. sysutils,classes,
  16. fpcmmain;
  17. type
  18. tsections=(sec_none,
  19. sec_units,sec_exes,sec_loaders,sec_examples,sec_rsts,
  20. sec_compile,sec_install,
  21. sec_distinstall,sec_zipinstall,sec_clean,sec_shared,
  22. sec_command,sec_exts,sec_dirs,sec_tools,sec_info,sec_makefile
  23. );
  24. trules=(
  25. r_all,r_debug,r_smart,r_release,r_units,
  26. r_examples,
  27. r_shared,
  28. r_install,r_sourceinstall,r_exampleinstall,r_distinstall,
  29. r_zipinstall,r_zipsourceinstall,r_zipexampleinstall,r_zipdistinstall,
  30. r_clean,r_distclean,r_cleanall,
  31. r_info,r_makefiles
  32. );
  33. const
  34. rule2str : array[trules] of string=(
  35. 'all','debug','smart','release','units',
  36. 'examples',
  37. 'shared',
  38. 'install','sourceinstall','exampleinstall','distinstall',
  39. 'zipinstall','zipsourceinstall','zipexampleinstall','zipdistinstall',
  40. 'clean','distclean','cleanall',
  41. 'info','makefiles'
  42. );
  43. rule2sec : array[trules] of tsections=(
  44. sec_compile,sec_compile,sec_compile,sec_compile,sec_compile,
  45. sec_examples,
  46. sec_shared,
  47. sec_install,sec_install,sec_install,sec_distinstall,
  48. sec_zipinstall,sec_zipinstall,sec_zipinstall,sec_zipinstall,
  49. sec_clean,sec_clean,sec_clean,
  50. sec_info,sec_makefile
  51. );
  52. type
  53. TMakefileWriter=class
  54. private
  55. FFileName : string;
  56. FIni : TFPCMake;
  57. FInput : TFPCMake;
  58. FOutput : TStringList;
  59. FPhony : string;
  60. FHasSection : array[tsections] of boolean;
  61. procedure LoadFPCMakeIni;
  62. procedure AddIniSection(const s:string);
  63. procedure AddCustomSection(const s:string);
  64. procedure AddTargetVariable(const inivar:string);
  65. procedure AddVariable(const inivar:string);
  66. function AddTargetDefines(const inivar,prefix:string):string;
  67. procedure AddMainPackage(const pack: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. procedure AddDefaultTools;
  76. procedure AddMakefileTargets;
  77. procedure OptimizeSections;
  78. public
  79. constructor Create(AFPCMake:TFPCMake;const AFileName:string);
  80. destructor Destroy;override;
  81. procedure WriteGenericMakefile;
  82. end;
  83. implementation
  84. {$i fpcmake.inc}
  85. type
  86. TMyMemoryStream=class(TMemoryStream)
  87. public
  88. constructor Create(p:pointer;mysize:integer);
  89. end;
  90. {*****************************************************************************
  91. Helpers
  92. *****************************************************************************}
  93. function FixVariable(s:string):string;
  94. var
  95. i : integer;
  96. begin
  97. Result:=UpperCase(s);
  98. i:=pos('.',Result);
  99. if i>0 then
  100. Result[i]:='_';
  101. end;
  102. function VarName(const s:string):string;
  103. var
  104. i,j : longint;
  105. begin
  106. i:=0;
  107. result:=s;
  108. while i<length(result) do
  109. begin
  110. inc(i);
  111. case result[i] of
  112. '{' :
  113. begin
  114. { this are pkgs which are hold the dirs between the accolades }
  115. j:=PosIdx('}',result,i);
  116. if j>0 then
  117. Delete(result,i,j-i+1)
  118. else
  119. Delete(result,i,1);
  120. dec(i);
  121. end;
  122. '$','(',')' :
  123. begin
  124. Delete(result,i,1);
  125. dec(i);
  126. end;
  127. 'a'..'z' :
  128. result[i]:=chr(ord(result[i])-32);
  129. end;
  130. end;
  131. end;
  132. procedure FixTab(sl:TStringList);
  133. var
  134. i,j,k : integer;
  135. s,s2 : string;
  136. begin
  137. i:=0;
  138. while (i<sl.Count) do
  139. begin
  140. if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
  141. begin
  142. s:=sl[i];
  143. k:=0;
  144. j:=0;
  145. repeat
  146. inc(j);
  147. case s[j] of
  148. ' ' :
  149. inc(k);
  150. #9 :
  151. k:=(k+7) and not(7);
  152. else
  153. break;
  154. end;
  155. until (j=length(s));
  156. if k>7 then
  157. begin
  158. s2:='';
  159. Delete(s,1,j-1);
  160. while (k>7) do
  161. begin
  162. s2:=s2+#9;
  163. dec(k,8);
  164. end;
  165. while (k>0) do
  166. begin
  167. s2:=s2+' ';
  168. dec(k);
  169. end;
  170. sl[i]:=s2+s;
  171. end;
  172. end;
  173. inc(i);
  174. end;
  175. end;
  176. {*****************************************************************************
  177. TMyMemoryStream
  178. *****************************************************************************}
  179. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  180. begin
  181. inherited Create;
  182. SetPointer(p,mysize);
  183. end;
  184. {*****************************************************************************
  185. TMakefileWriter
  186. *****************************************************************************}
  187. constructor TMakefileWriter.Create(AFPCMake:TFPCMake;const AFileName:string);
  188. begin
  189. FInput:=AFPCMake;
  190. FFileName:=AFileName;
  191. FOutput:=TStringList.Create;
  192. FPhony:='';
  193. FillChar(FHasSection,sizeof(FHasSection),1);
  194. LoadFPCMakeIni;
  195. end;
  196. destructor TMakefileWriter.Destroy;
  197. begin
  198. FOutput.Free;
  199. FIni.Free;
  200. end;
  201. procedure TMakefileWriter.LoadFPCMakeIni;
  202. var
  203. IniStream : TStream;
  204. begin
  205. try
  206. IniStream:=TMyMemoryStream.Create(@fpcmakeini,sizeof(fpcmakeini));
  207. FIni:=TFPCMake.CreateFromStream(IniStream,'fpcmake.ini');
  208. { Leave the '#' comments in the output }
  209. // FIni.CommentChars:=[';'];
  210. FIni.LoadSections;
  211. finally
  212. IniStream.Destroy;
  213. end;
  214. end;
  215. procedure TMakefileWriter.AddIniSection(const s:string);
  216. var
  217. Sec : TFPCMakeSection;
  218. begin
  219. Sec:=TFPCMakeSection(FIni[s]);
  220. if assigned(Sec) then
  221. FOutput.AddStrings(Sec.List)
  222. else
  223. Raise Exception.Create(Format('Section "%s" doesn''t exists in fpcmake.ini',[s]));
  224. end;
  225. procedure TMakefileWriter.AddCustomSection(const s:string);
  226. var
  227. Sec : TFPCMakeSection;
  228. begin
  229. Sec:=TFPCMakeSection(FInput[s]);
  230. if assigned(Sec) then
  231. begin
  232. Sec.BuildMakefile;
  233. FOutput.AddStrings(Sec.List);
  234. end;
  235. end;
  236. procedure TMakefileWriter.AddTargetVariable(const inivar:string);
  237. var
  238. s : string;
  239. T : TOs;
  240. C : TCpu;
  241. begin
  242. for c:=low(TCpu) to high(TCpu) do
  243. for t:=low(TOS) to high(TOS) do
  244. if FInput.IncludeTargets[c,t] then
  245. begin
  246. s:=FInput.GetTargetVariable(c,t,IniVar,false);
  247. if s<>'' then
  248. begin
  249. FOutput.Add('ifeq ($(FULL_TARGET),'+CPUStr[c]+'-'+OSStr[t]+')');
  250. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  251. FOutput.Add('endif');
  252. end;
  253. end;
  254. end;
  255. procedure TMakefileWriter.AddVariable(const inivar:string);
  256. var
  257. s : string;
  258. begin
  259. s:=FInput.GetVariable(IniVar,false);
  260. if s<>'' then
  261. FOutput.Add('override '+FixVariable(IniVar)+'='+s)
  262. end;
  263. function TMakefileWriter.AddTargetDefines(const inivar,prefix:string):string;
  264. procedure addtokens(s:string);
  265. var
  266. name : string;
  267. k1,k2 : integer;
  268. begin
  269. repeat
  270. Name:=GetToken(s,' ');
  271. if Name='' then
  272. break;
  273. { Remove (..) }
  274. k1:=pos('(',name);
  275. if k1>0 then
  276. begin
  277. k2:=PosIdx(')',name,k1);
  278. if k2=0 then
  279. k2:=length(name)+1;
  280. Delete(Name,k1,k2);
  281. end;
  282. FOutput.Add(prefix+VarName(name)+'=1');
  283. { add to the list of dirs without duplicates }
  284. AddTokenNoDup(result,name,' ');
  285. until false;
  286. end;
  287. var
  288. s : string;
  289. T : TOs;
  290. C : TCpu;
  291. begin
  292. for c:=low(TCpu) to high(TCpu) do
  293. for t:=low(TOS) to high(TOS) do
  294. if FInput.IncludeTargets[c,t] then
  295. begin
  296. s:=FInput.GetTargetVariable(c,t,IniVar,false);
  297. if s<>'' then
  298. begin
  299. FOutput.Add('ifeq ($(FULL_TARGET),'+CpuStr[c]+'-'+OSStr[t]+')');
  300. AddTokens(s);
  301. FOutput.Add('endif');
  302. end;
  303. end;
  304. end;
  305. procedure TMakefileWriter.AddTool(const varname,exename,altexename:string);
  306. begin
  307. with FOutput do
  308. begin
  309. Add('ifndef '+varname);
  310. Add(varname+':=$(strip $(wildcard $(addsuffix /'+exename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  311. if altexename<>'' then
  312. begin
  313. Add('ifeq ($('+varname+'),)');
  314. Add(varname+':=$(strip $(wildcard $(addsuffix /'+altexename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  315. end;
  316. Add('ifeq ($('+varname+'),)');
  317. Add(varname+'= __missing_command_'+varname); {This is to be shure make stops,
  318. if the command is not found. Otherwise if the command was set to the
  319. empty string, options to the command would be interpreted as command,
  320. and because options is preceeded by a "-", make will ignore the error
  321. that the command is not found.}
  322. Add('else');
  323. Add(varname+':=$(firstword $('+varname+'))');
  324. Add('endif');
  325. if altexename<>'' then
  326. begin
  327. Add('else');
  328. Add(varname+':=$(firstword $('+varname+'))');
  329. Add('endif');
  330. end;
  331. Add('endif');
  332. Add('export '+varname);
  333. end;
  334. end;
  335. procedure TMakefileWriter.AddTools(const inivar:string);
  336. var
  337. hs,tool : string;
  338. begin
  339. hs:=FInput.GetVariable(inivar,false);
  340. repeat
  341. Tool:=GetToken(hs,' ');
  342. if Tool='' then
  343. break;
  344. AddTool(FixVariable(Tool),Tool,'');
  345. until false;
  346. end;
  347. procedure TMakefileWriter.AddRules;
  348. procedure AddRule(rule:trules);
  349. var
  350. i : integer;
  351. hs : string;
  352. Sec : TFPCMakeSection;
  353. Rules : TStringList;
  354. begin
  355. Sec:=TFPCMakeSection(FInput['rules']);
  356. if assigned(Sec) then
  357. begin
  358. Rules:=Sec.List;
  359. for i:=0 to Rules.Count-1 do
  360. begin
  361. if (length(rules[i])>length(rule2str[rule])) and
  362. (rules[i][1]=rule2str[rule][1]) and
  363. ((rules[i][length(rule2str[rule])+1]=':') or
  364. ((length(rules[i])>length(rule2str[rule])+1) and
  365. (rules[i][length(rule2str[rule])+2]=':'))) and
  366. (Copy(rules[i],1,length(rule2str[rule]))=rule2str[rule]) then
  367. exit;
  368. end;
  369. end;
  370. hs:='';
  371. if FHasSection[Rule2Sec[rule]] then
  372. hs:=hs+' fpc_'+rule2str[rule];
  373. { include target dirs, but not for info and targets that
  374. call other targets with a only extra settings, if the
  375. section was not included, then still process the targets }
  376. if FInput.HasTargetVariable('target_dirs') and
  377. (not(rule in [r_info,r_shared,r_smart,r_debug,r_release,r_zipdistinstall,r_distinstall]) or
  378. not FHasSection[Rule2Sec[rule]]) then
  379. begin
  380. if FInput.HasVariable('default_dir') then
  381. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(DEFAULT_DIR))'
  382. else
  383. if not(rule in [r_sourceinstall,r_zipinstall,r_zipsourceinstall,
  384. r_makefiles]) or
  385. not(FInput.HasVariable('package_name')) then
  386. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_DIRS))';
  387. end;
  388. { include cleaning of example dirs }
  389. if (rule=r_clean) and
  390. FInput.HasTargetVariable('target_exampledirs') then
  391. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_EXAMPLEDIRS))';
  392. { Add the rule }
  393. AddPhony(Rule2Str[Rule]);
  394. FOutput.Add(rule2str[rule]+':'+hs);
  395. end;
  396. var
  397. rule : trules;
  398. begin
  399. for rule:=low(trules) to high(trules) do
  400. AddRule(rule);
  401. WritePhony;
  402. end;
  403. procedure TMakefileWriter.AddPhony(const s:string);
  404. begin
  405. FPhony:=FPhony+' '+s;
  406. end;
  407. procedure TMakefileWriter.WritePhony;
  408. begin
  409. if FPhony<>'' then
  410. begin
  411. FOutput.Add('.PHONY:'+FPhony);
  412. FPhony:='';
  413. end;
  414. end;
  415. procedure TMakefileWriter.AddTargetDirs(const inivar:string);
  416. procedure AddTargetDir(const s,defpref:string);
  417. var
  418. j : trules;
  419. begin
  420. FOutput.Add('ifdef '+defpref+VarName(s));
  421. for j:=low(trules) to high(trules) do
  422. begin
  423. FOutput.Add(s+'_'+rule2str[j]+':');
  424. FOutput.Add(#9+'$(MAKE) -C '+s+' '+rule2str[j]);
  425. AddPhony(s+'_'+rule2str[j]);
  426. end;
  427. FOutput.Add(s+':');
  428. FOutput.Add(#9+'$(MAKE) -C '+s+' all');
  429. AddPhony(s);
  430. WritePhony;
  431. FOutput.Add('endif');
  432. end;
  433. var
  434. hs,dir : string;
  435. prefix : string;
  436. begin
  437. prefix:=FixVariable(inivar)+'_';
  438. hs:=AddTargetDefines(inivar,prefix);
  439. repeat
  440. Dir:=GetToken(hs,' ');
  441. if Dir='' then
  442. break;
  443. AddTargetDir(Dir,prefix);
  444. until false;
  445. end;
  446. procedure TMakefileWriter.AddMainPackage(const pack:string);
  447. var
  448. packdirvar : string;
  449. begin
  450. { create needed variables }
  451. packdirvar:='PACKAGEDIR_MAIN';
  452. { Search packagedir by looking for Makefile.fpc }
  453. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  454. end;
  455. procedure TMakefileWriter.AddRequiredPackages;
  456. procedure AddPackage(const pack,prefix:string);
  457. var
  458. packdirvar,unitdirvar,unitfpmakedirvar : string;
  459. fpcmadedirvar : string;
  460. begin
  461. FOutput.Add('ifdef '+Prefix+VarName(pack));
  462. { create needed variables }
  463. packdirvar:='PACKAGEDIR_'+VarName(pack);
  464. unitdirvar:='UNITDIR_'+VarName(pack);
  465. unitfpmakedirvar:='UNITDIR_FPMAKE_'+VarName(pack);
  466. { Search packagedir by looking for Makefile.fpc }
  467. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  468. FOutput.Add('ifneq ($('+packdirvar+'),)');
  469. { Create unit dir, check if os dependent dir exists }
  470. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/units/$(TARGETSUFFIX)),)');
  471. FOutput.Add(unitdirvar+'=$('+packdirvar+')/units/$(TARGETSUFFIX)');
  472. FOutput.Add('else');
  473. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  474. FOutput.Add('endif');
  475. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/units/$(SOURCESUFFIX)),)');
  476. FOutput.Add(unitfpmakedirvar+'=$('+packdirvar+')/units/$(SOURCESUFFIX)');
  477. FOutput.Add('else');
  478. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/units_bs/$(SOURCESUFFIX)),)');
  479. FOutput.Add(unitfpmakedirvar+'=$('+packdirvar+')/units_bs/$(SOURCESUFFIX)');
  480. FOutput.Add('else');
  481. FOutput.Add(unitfpmakedirvar+'=$('+packdirvar+')');
  482. FOutput.Add('endif');
  483. FOutput.Add('endif');
  484. FOutput.Add('ifdef CHECKDEPEND');
  485. { rtl needs special handling for FPCMADE }
  486. if pack='rtl' then
  487. fpcmadedirvar:='/$(OS_TARGET)'
  488. else
  489. fpcmadedirvar:='';
  490. FOutput.Add('$('+packdirvar+')'+fpcmadedirvar+'/$(FPCMADE):');
  491. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+')'+fpcmadedirvar+' $(FPCMADE)');
  492. FOutput.Add('override ALLDEPENDENCIES+=$('+packdirvar+')'+fpcmadedirvar+'/$(FPCMADE)');
  493. FOutput.Add('endif');
  494. { Package dir doesn't exists, check unit dir }
  495. FOutput.Add('else');
  496. FOutput.Add(packdirvar+'=');
  497. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  498. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  499. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  500. FOutput.Add('else');
  501. FOutput.Add(unitdirvar+'=');
  502. FOutput.Add('endif');
  503. FOutput.Add('endif');
  504. { Add Unit dir to the command line -Fu }
  505. FOutput.Add('ifdef '+unitdirvar);
  506. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  507. FOutput.Add('endif');
  508. FOutput.Add('ifdef '+unitfpmakedirvar);
  509. FOutput.Add('override COMPILER_FPMAKE_UNITDIR+=$('+unitfpmakedirvar+')');
  510. FOutput.Add('endif');
  511. { endif for package }
  512. FOutput.Add('endif');
  513. end;
  514. var
  515. i : integer;
  516. reqs,req,prefix : string;
  517. t : TOS;
  518. c : TCpu;
  519. sl : TStringList;
  520. begin
  521. prefix:='REQUIRE_PACKAGES_';
  522. reqs:='';
  523. { Add target defines }
  524. for c:=low(tcpu) to high(tcpu) do
  525. for t:=low(tos) to high(tos) do
  526. if FInput.IncludeTargets[c,t] then
  527. begin
  528. sl:=FInput.GetTargetRequires(c,t);
  529. { show info }
  530. FInput.Verbose(FPCMakeInfo,CpuStr[c]+'-'+OSStr[t]+' requires: '+sl.CommaText);
  531. if sl.count>0 then
  532. begin
  533. FOutput.Add('ifeq ($(FULL_TARGET),'+CPUStr[c]+'-'+OSStr[t]+')');
  534. for i:=0 to sl.count-1 do
  535. begin
  536. FOutput.Add(prefix+VarName(sl[i])+'=1');
  537. AddTokenNoDup(reqs,sl[i],' ');
  538. end;
  539. FOutput.Add('endif');
  540. end;
  541. sl.Free;
  542. end;
  543. { Add all require packages }
  544. repeat
  545. req:=GetToken(reqs,' ');
  546. if Req='' then
  547. break;
  548. AddPackage(req,prefix);
  549. until false;
  550. WritePhony;
  551. end;
  552. procedure TMakefileWriter.AddDefaultTools;
  553. begin
  554. AddTool('ECHO','gecho','echo');
  555. AddTool('DATE','gdate','date');
  556. AddTool('GINSTALL','ginstall','install');
  557. AddTool('CPPROG','cp','');
  558. AddTool('RMPROG','rm','');
  559. AddTool('MVPROG','mv','');
  560. AddTool('MKDIRPROG','gmkdir','mkdir');
  561. AddIniSection('shelltools');
  562. AddTool('PPUMOVE','ppumove','');
  563. AddTool('FPCMAKE','fpcmake','');
  564. AddTool('ZIPPROG','zip','');
  565. AddTool('TARPROG','gtar','tar');
  566. AddIniSection('defaulttools');
  567. end;
  568. procedure TMakefileWriter.AddMakefileTargets;
  569. var
  570. s : string;
  571. c : TCpu;
  572. t : Tos;
  573. begin
  574. s:='';
  575. for c:=low(tcpu) to high(tcpu) do
  576. for t:=low(tos) to high(tos) do
  577. if FInput.IncludeTargets[c,t] then
  578. AddToken(s,CpuStr[c]+'-'+OSStr[t],' ');
  579. FOutput.Add('MAKEFILETARGETS='+s);
  580. end;
  581. procedure TMakefileWriter.OptimizeSections;
  582. var
  583. SkippedSecs :integer;
  584. begin
  585. { Turn some sections off, depending if files are
  586. provided }
  587. if not FInput.IsPackage then
  588. begin
  589. FHasSection[sec_zipinstall]:=false;
  590. FHasSection[sec_distinstall]:=false;
  591. end;
  592. { Remove unused sections for targets }
  593. SkippedSecs:=0;
  594. if (not FInput.HasTargetVariable('target_units')) and (not FInput.HasTargetVariable('target_implicitunits')) then
  595. begin
  596. inc(SkippedSecs);
  597. FHasSection[sec_units]:=false;
  598. end;
  599. if (not FInput.HasTargetVariable('target_programs')) then
  600. begin
  601. inc(SkippedSecs);
  602. FHasSection[sec_exes]:=false;
  603. end;
  604. if (not FInput.HasTargetVariable('target_examples')) then
  605. begin
  606. inc(SkippedSecs);
  607. { example dirs also requires the fpc_examples target, because
  608. it also depends on the all target }
  609. if (not FInput.HasTargetVariable('target_exampledirs')) then
  610. FHasSection[sec_examples]:=false;
  611. end;
  612. if (not FInput.HasTargetVariable('target_loaders')) then
  613. begin
  614. inc(SkippedSecs);
  615. FHasSection[sec_loaders]:=false;
  616. end;
  617. { if all 4 sections are not available we can skip also the
  618. generic compile rules }
  619. if SkippedSecs=4 then
  620. begin
  621. FHasSection[sec_shared]:=false;
  622. FHasSection[sec_compile]:=false;
  623. if (not FInput.HasTargetVariable('package_name')) and
  624. (not FInput.HasTargetVariable('install_units')) and
  625. (not FInput.HasTargetVariable('install_files')) and
  626. (not FInput.HasTargetVariable('install_createpackagefpc')) then
  627. FHasSection[sec_install]:=false;
  628. { Package.fpc also needs to be cleaned }
  629. if (not FInput.HasTargetVariable('clean_units')) and
  630. (not FInput.HasTargetVariable('clean_files')) and
  631. (not FInput.HasTargetVariable('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 FInput.HasVariable('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 misc defines }
  653. AddIniSection('defines');
  654. { Add automatic detect sections }
  655. AddIniSection('osdetect');
  656. { Forced target }
  657. if FInput.HasVariable('require_target') then
  658. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  659. else if FInput.HasVariable('default_target') then
  660. Add('override OS_TARGET_DEFAULT='+FInput.GetVariable('default_target',false));
  661. if FInput.HasVariable('require_cpu') then
  662. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  663. else if FInput.HasVariable('default_cpu') then
  664. Add('override CPU_TARGET_DEFAULT='+FInput.GetVariable('default_cpu',false));
  665. { FPC Detection }
  666. AddVariable('default_fpcdir');
  667. AddIniSection('fpcdetect');
  668. AddIniSection('fpcdircheckenv');
  669. AddIniSection('fpcdirdetect');
  670. AddIniSection('fpmakefpcdetect');
  671. { Package }
  672. AddVariable('package_name');
  673. AddVariable('package_version');
  674. AddVariable('package_targets');
  675. { Directory of main package }
  676. if FInput.HasVariable('package_main') then
  677. AddMainPackage(FInput.GetVariable('package_main',false));
  678. { LCL rules }
  679. if FInput.UsesLCL then
  680. begin
  681. AddVariable('default_lcldir');
  682. AddVariable('lcl_platform');
  683. AddIniSection('lclrules');
  684. end;
  685. { First add the required packages sections }
  686. // for i:=0 to FInput.RequireList.Count-1 do
  687. // AddCustomSection(FInput.Requirelist[i]);
  688. { prerules section }
  689. if assigned(FInput['prerules']) then
  690. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  691. { Default }
  692. AddVariable('default_dir');
  693. { Targets }
  694. AddTargetVariable('target_dirs');
  695. AddTargetVariable('target_programs');
  696. AddTargetVariable('target_units');
  697. AddTargetVariable('target_implicitunits');
  698. AddTargetVariable('target_loaders');
  699. AddTargetVariable('target_rsts');
  700. AddTargetVariable('target_examples');
  701. AddTargetVariable('target_exampledirs');
  702. { Clean }
  703. AddTargetVariable('clean_units');
  704. AddTargetVariable('clean_files');
  705. AddTargetVariable('clean_programs');
  706. { Install }
  707. AddTargetVariable('install_units');
  708. AddTargetVariable('install_files');
  709. AddVariable('install_buildunit');
  710. AddVariable('install_prefix');
  711. AddVariable('install_basedir');
  712. AddVariable('install_datadir');
  713. AddVariable('install_fpcpackage');
  714. AddVariable('install_fpcsubdir');
  715. AddVariable('install_createpackagefpc');
  716. { Dist }
  717. AddVariable('dist_destdir');
  718. AddVariable('dist_zipname');
  719. AddVariable('dist_ziptarget');
  720. { Compiler }
  721. AddTargetVariable('compiler_options');
  722. AddTargetVariable('compiler_version');
  723. AddTargetVariable('compiler_includedir');
  724. AddTargetVariable('compiler_unitdir');
  725. AddTargetVariable('compiler_sourcedir');
  726. AddTargetVariable('compiler_objectdir');
  727. AddTargetVariable('compiler_librarydir');
  728. AddTargetVariable('compiler_targetdir');
  729. AddTargetVariable('compiler_unittargetdir');
  730. { shared }
  731. AddVariable('shared_build');
  732. AddVariable('shared_libname');
  733. AddVariable('shared_libversion');
  734. AddVariable('shared_libunits');
  735. AddVariable('shared_build');
  736. { default Dirs and extensions }
  737. AddIniSection('defaultdirs');
  738. if FInput.CheckLibcRequire then
  739. AddIniSection('dirlibc');
  740. AddIniSection('extensions');
  741. { Add default tools }
  742. AddDefaultTools;
  743. { Required packages }
  744. AddVariable('require_packages');
  745. AddRequiredPackages;
  746. { commandline }
  747. AddIniSection('command_begin');
  748. if FInput.CheckLibcRequire then
  749. AddIniSection('command_libc');
  750. AddIniSection('command_end');
  751. { compile }
  752. if FHasSection[sec_loaders] then
  753. AddIniSection('loaderrules');
  754. if FHasSection[sec_units] then
  755. AddIniSection('unitrules');
  756. if FHasSection[sec_exes] then
  757. AddIniSection('exerules');
  758. if FHasSection[sec_rsts] then
  759. AddIniSection('rstrules');
  760. if FHasSection[sec_examples] then
  761. AddIniSection('examplerules');
  762. if FHasSection[sec_compile] then
  763. AddIniSection('compilerules');
  764. if FHasSection[sec_shared] then
  765. AddIniSection('sharedrules');
  766. { install }
  767. if FHasSection[sec_install] then
  768. AddIniSection('installrules');
  769. if FHasSection[sec_distinstall] then
  770. AddIniSection('distinstallrules');
  771. if FHasSection[sec_zipinstall] then
  772. AddIniSection('zipinstallrules');
  773. { clean }
  774. AddIniSection('cleanrules');
  775. { info }
  776. AddIniSection('baseinforules');
  777. if FInput.UsesLCL then
  778. AddIniSection('lclinforules');
  779. AddIniSection('inforules');
  780. { info }
  781. AddIniSection('makefilerules');
  782. { Subdirs }
  783. AddTargetDirs('target_dirs');
  784. AddTargetDirs('target_exampledirs');
  785. { Tools }
  786. AddTools('require_tools');
  787. { Rules }
  788. AddRules;
  789. { Users own rules }
  790. AddIniSection('localmakefile');
  791. AddIniSection('userrules');
  792. if assigned(FInput['rules']) then
  793. AddStrings(TFPCMakeSection(FInput['rules']).List);
  794. end;
  795. { write to disk }
  796. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  797. Fixtab(FOutput);
  798. FOutput.SaveToFile(FFileName);
  799. end;
  800. end.