fpcmwr.pp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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 : string;
  459. begin
  460. FOutput.Add('ifdef '+Prefix+VarName(pack));
  461. { create needed variables }
  462. packdirvar:='PACKAGEDIR_'+VarName(pack);
  463. unitdirvar:='UNITDIR_'+VarName(pack);
  464. { Search packagedir by looking for Makefile.fpc }
  465. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  466. FOutput.Add('ifneq ($('+packdirvar+'),)');
  467. { Create unit dir, check if os dependent dir exists }
  468. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/units/$(TARGETSUFFIX)),)');
  469. FOutput.Add(unitdirvar+'=$('+packdirvar+')/units/$(TARGETSUFFIX)');
  470. FOutput.Add('else');
  471. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  472. FOutput.Add('endif');
  473. FOutput.Add('ifdef CHECKDEPEND');
  474. FOutput.Add('$('+packdirvar+')/$(FPCMADE):');
  475. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+') $(FPCMADE)');
  476. FOutput.Add('override ALLDEPENDENCIES+=$('+packdirvar+')/$(FPCMADE)');
  477. FOutput.Add('endif');
  478. { Package dir doesn't exists, check unit dir }
  479. FOutput.Add('else');
  480. FOutput.Add(packdirvar+'=');
  481. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  482. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  483. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  484. FOutput.Add('else');
  485. FOutput.Add(unitdirvar+'=');
  486. FOutput.Add('endif');
  487. FOutput.Add('endif');
  488. { Add Unit dir to the command line -Fu }
  489. FOutput.Add('ifdef '+unitdirvar);
  490. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  491. FOutput.Add('endif');
  492. { endif for package }
  493. FOutput.Add('endif');
  494. end;
  495. var
  496. i : integer;
  497. reqs,req,prefix : string;
  498. t : TOS;
  499. c : TCpu;
  500. sl : TStringList;
  501. begin
  502. prefix:='REQUIRE_PACKAGES_';
  503. reqs:='';
  504. { Add target defines }
  505. for c:=low(tcpu) to high(tcpu) do
  506. for t:=low(tos) to high(tos) do
  507. if FInput.IncludeTargets[c,t] then
  508. begin
  509. sl:=FInput.GetTargetRequires(c,t);
  510. { show info }
  511. FInput.Verbose(FPCMakeInfo,CpuStr[c]+'-'+OSStr[t]+' requires: '+sl.CommaText);
  512. if sl.count>0 then
  513. begin
  514. FOutput.Add('ifeq ($(FULL_TARGET),'+CPUStr[c]+'-'+OSStr[t]+')');
  515. for i:=0 to sl.count-1 do
  516. begin
  517. FOutput.Add(prefix+VarName(sl[i])+'=1');
  518. AddTokenNoDup(reqs,sl[i],' ');
  519. end;
  520. FOutput.Add('endif');
  521. end;
  522. sl.Free;
  523. end;
  524. { Add all require packages }
  525. repeat
  526. req:=GetToken(reqs,' ');
  527. if Req='' then
  528. break;
  529. AddPackage(req,prefix);
  530. until false;
  531. WritePhony;
  532. end;
  533. procedure TMakefileWriter.AddDefaultTools;
  534. begin
  535. AddTool('ECHO','gecho','echo');
  536. AddTool('DATE','gdate','date');
  537. AddTool('GINSTALL','ginstall','install');
  538. AddTool('CPPROG','cp','');
  539. AddTool('RMPROG','rm','');
  540. AddTool('MVPROG','mv','');
  541. AddTool('MKDIRPROG','gmkdir','mkdir');
  542. AddIniSection('shelltools');
  543. AddTool('PPUMOVE','ppumove','');
  544. AddTool('FPCMAKE','fpcmake','');
  545. AddTool('ZIPPROG','zip','');
  546. AddTool('TARPROG','gtar','tar');
  547. AddIniSection('defaulttools');
  548. end;
  549. procedure TMakefileWriter.AddMakefileTargets;
  550. var
  551. s : string;
  552. c : TCpu;
  553. t : Tos;
  554. begin
  555. s:='';
  556. for c:=low(tcpu) to high(tcpu) do
  557. for t:=low(tos) to high(tos) do
  558. if FInput.IncludeTargets[c,t] then
  559. AddToken(s,CpuStr[c]+'-'+OSStr[t],' ');
  560. FOutput.Add('MAKEFILETARGETS='+s);
  561. end;
  562. procedure TMakefileWriter.OptimizeSections;
  563. var
  564. SkippedSecs :integer;
  565. begin
  566. { Turn some sections off, depending if files are
  567. provided }
  568. if not FInput.IsPackage then
  569. begin
  570. FHasSection[sec_zipinstall]:=false;
  571. FHasSection[sec_distinstall]:=false;
  572. end;
  573. { Remove unused sections for targets }
  574. SkippedSecs:=0;
  575. if (not FInput.HasTargetVariable('target_units')) and (not FInput.HasTargetVariable('target_implicitunits')) then
  576. begin
  577. inc(SkippedSecs);
  578. FHasSection[sec_units]:=false;
  579. end;
  580. if (not FInput.HasTargetVariable('target_programs')) then
  581. begin
  582. inc(SkippedSecs);
  583. FHasSection[sec_exes]:=false;
  584. end;
  585. if (not FInput.HasTargetVariable('target_examples')) then
  586. begin
  587. inc(SkippedSecs);
  588. { example dirs also requires the fpc_examples target, because
  589. it also depends on the all target }
  590. if (not FInput.HasTargetVariable('target_exampledirs')) then
  591. FHasSection[sec_examples]:=false;
  592. end;
  593. if (not FInput.HasTargetVariable('target_loaders')) then
  594. begin
  595. inc(SkippedSecs);
  596. FHasSection[sec_loaders]:=false;
  597. end;
  598. { if all 4 sections are not available we can skip also the
  599. generic compile rules }
  600. if SkippedSecs=4 then
  601. begin
  602. FHasSection[sec_shared]:=false;
  603. FHasSection[sec_compile]:=false;
  604. if (not FInput.HasTargetVariable('package_name')) and
  605. (not FInput.HasTargetVariable('install_units')) and
  606. (not FInput.HasTargetVariable('install_files')) and
  607. (not FInput.HasTargetVariable('install_createpackagefpc')) then
  608. FHasSection[sec_install]:=false;
  609. { Package.fpc also needs to be cleaned }
  610. if (not FInput.HasTargetVariable('clean_units')) and
  611. (not FInput.HasTargetVariable('clean_files')) and
  612. (not FInput.HasTargetVariable('install_createpackagefpc')) then
  613. FHasSection[sec_clean]:=false;
  614. end;
  615. end;
  616. procedure TMakefileWriter.WriteGenericMakefile;
  617. begin
  618. { Remove unused sections }
  619. OptimizeSections;
  620. { Generate Output }
  621. with FOutput do
  622. begin
  623. { Header }
  624. Add('#');
  625. Add('# Don''t edit, this file is generated by '+TitleDate);
  626. Add('#');
  627. if FInput.HasVariable('default_rule') then
  628. Add('default: '+FInput.GetVariable('default_rule',false))
  629. else
  630. Add('default: all');
  631. { Supported targets by this Makefile }
  632. AddMakefileTargets;
  633. { Add misc defines }
  634. AddIniSection('defines');
  635. { Add automatic detect sections }
  636. AddIniSection('osdetect');
  637. { Forced target }
  638. if FInput.HasVariable('require_target') then
  639. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  640. else if FInput.HasVariable('default_target') then
  641. Add('override OS_TARGET_DEFAULT='+FInput.GetVariable('default_target',false));
  642. if FInput.HasVariable('require_cpu') then
  643. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  644. else if FInput.HasVariable('default_cpu') then
  645. Add('override CPU_TARGET_DEFAULT='+FInput.GetVariable('default_cpu',false));
  646. { FPC Detection }
  647. AddVariable('default_fpcdir');
  648. AddIniSection('fpcdetect');
  649. AddIniSection('fpcdircheckenv');
  650. AddIniSection('fpcdirdetect');
  651. { Package }
  652. AddVariable('package_name');
  653. AddVariable('package_version');
  654. AddVariable('package_targets');
  655. { Directory of main package }
  656. if FInput.HasVariable('package_main') then
  657. AddMainPackage(FInput.GetVariable('package_main',false));
  658. { LCL rules }
  659. if FInput.UsesLCL then
  660. begin
  661. AddVariable('default_lcldir');
  662. AddVariable('lcl_platform');
  663. AddIniSection('lclrules');
  664. end;
  665. { First add the required packages sections }
  666. // for i:=0 to FInput.RequireList.Count-1 do
  667. // AddCustomSection(FInput.Requirelist[i]);
  668. { prerules section }
  669. if assigned(FInput['prerules']) then
  670. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  671. { Default }
  672. AddVariable('default_dir');
  673. { Targets }
  674. AddTargetVariable('target_dirs');
  675. AddTargetVariable('target_programs');
  676. AddTargetVariable('target_units');
  677. AddTargetVariable('target_implicitunits');
  678. AddTargetVariable('target_loaders');
  679. AddTargetVariable('target_rsts');
  680. AddTargetVariable('target_examples');
  681. AddTargetVariable('target_exampledirs');
  682. { Clean }
  683. AddTargetVariable('clean_units');
  684. AddTargetVariable('clean_files');
  685. { Install }
  686. AddTargetVariable('install_units');
  687. AddTargetVariable('install_files');
  688. AddVariable('install_buildunit');
  689. AddVariable('install_prefix');
  690. AddVariable('install_basedir');
  691. AddVariable('install_datadir');
  692. AddVariable('install_fpcpackage');
  693. AddVariable('install_fpcsubdir');
  694. AddVariable('install_createpackagefpc');
  695. { Dist }
  696. AddVariable('dist_destdir');
  697. AddVariable('dist_zipname');
  698. AddVariable('dist_ziptarget');
  699. { Compiler }
  700. AddTargetVariable('compiler_options');
  701. AddTargetVariable('compiler_version');
  702. AddTargetVariable('compiler_includedir');
  703. AddTargetVariable('compiler_unitdir');
  704. AddTargetVariable('compiler_sourcedir');
  705. AddTargetVariable('compiler_objectdir');
  706. AddTargetVariable('compiler_librarydir');
  707. AddTargetVariable('compiler_targetdir');
  708. AddTargetVariable('compiler_unittargetdir');
  709. { shared }
  710. AddVariable('shared_build');
  711. AddVariable('shared_libname');
  712. AddVariable('shared_libversion');
  713. AddVariable('shared_libunits');
  714. AddVariable('shared_build');
  715. { default Dirs and extensions }
  716. AddIniSection('defaultdirs');
  717. if FInput.CheckLibcRequire then
  718. AddIniSection('dirlibc');
  719. AddIniSection('extensions');
  720. { Add default tools }
  721. AddDefaultTools;
  722. { Required packages }
  723. AddVariable('require_packages');
  724. AddRequiredPackages;
  725. { commandline }
  726. AddIniSection('command_begin');
  727. if FInput.CheckLibcRequire then
  728. AddIniSection('command_libc');
  729. AddIniSection('command_end');
  730. { compile }
  731. if FHasSection[sec_loaders] then
  732. AddIniSection('loaderrules');
  733. if FHasSection[sec_units] then
  734. AddIniSection('unitrules');
  735. if FHasSection[sec_exes] then
  736. AddIniSection('exerules');
  737. if FHasSection[sec_rsts] then
  738. AddIniSection('rstrules');
  739. if FHasSection[sec_examples] then
  740. AddIniSection('examplerules');
  741. if FHasSection[sec_compile] then
  742. AddIniSection('compilerules');
  743. if FHasSection[sec_shared] then
  744. AddIniSection('sharedrules');
  745. { install }
  746. if FHasSection[sec_install] then
  747. AddIniSection('installrules');
  748. if FHasSection[sec_distinstall] then
  749. AddIniSection('distinstallrules');
  750. if FHasSection[sec_zipinstall] then
  751. AddIniSection('zipinstallrules');
  752. { clean }
  753. AddIniSection('cleanrules');
  754. { info }
  755. AddIniSection('baseinforules');
  756. if FInput.UsesLCL then
  757. AddIniSection('lclinforules');
  758. AddIniSection('inforules');
  759. { info }
  760. AddIniSection('makefilerules');
  761. { Subdirs }
  762. AddTargetDirs('target_dirs');
  763. AddTargetDirs('target_exampledirs');
  764. { Tools }
  765. AddTools('require_tools');
  766. { Rules }
  767. AddRules;
  768. { Users own rules }
  769. AddIniSection('localmakefile');
  770. AddIniSection('userrules');
  771. if assigned(FInput['rules']) then
  772. AddStrings(TFPCMakeSection(FInput['rules']).List);
  773. end;
  774. { write to disk }
  775. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  776. Fixtab(FOutput);
  777. FOutput.SaveToFile(FFileName);
  778. end;
  779. end.