fpcmwr.pp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  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,r_units,
  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','units',
  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,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 AddMainPackage(const pack:string);
  69. procedure AddRequiredPackages;
  70. procedure AddTool(const varname,exename,altexename:string);
  71. procedure AddTools(const inivar:string);
  72. procedure AddRules;
  73. procedure AddPhony(const s:string);
  74. procedure WritePhony;
  75. procedure AddTargetDirs(const inivar:string);
  76. procedure AddDefaultTools;
  77. procedure AddMakefileTargets;
  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 FixTab(sl:TStringList);
  134. var
  135. i,j,k : integer;
  136. s,s2 : string;
  137. begin
  138. i:=0;
  139. while (i<sl.Count) do
  140. begin
  141. if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
  142. begin
  143. s:=sl[i];
  144. k:=0;
  145. j:=0;
  146. repeat
  147. inc(j);
  148. case s[j] of
  149. ' ' :
  150. inc(k);
  151. #9 :
  152. k:=(k+7) and not(7);
  153. else
  154. break;
  155. end;
  156. until (j=length(s));
  157. if k>7 then
  158. begin
  159. s2:='';
  160. Delete(s,1,j-1);
  161. while (k>7) do
  162. begin
  163. s2:=s2+#9;
  164. dec(k,8);
  165. end;
  166. while (k>0) do
  167. begin
  168. s2:=s2+' ';
  169. dec(k);
  170. end;
  171. sl[i]:=s2+s;
  172. end;
  173. end;
  174. inc(i);
  175. end;
  176. end;
  177. {*****************************************************************************
  178. TMyMemoryStream
  179. *****************************************************************************}
  180. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  181. begin
  182. inherited Create;
  183. SetPointer(p,mysize);
  184. end;
  185. {*****************************************************************************
  186. TMakefileWriter
  187. *****************************************************************************}
  188. constructor TMakefileWriter.Create(AFPCMake:TFPCMake;const AFileName:string);
  189. begin
  190. FInput:=AFPCMake;
  191. FFileName:=AFileName;
  192. FOutput:=TStringList.Create;
  193. FPhony:='';
  194. FillChar(FHasSection,sizeof(FHasSection),1);
  195. LoadFPCMakeIni;
  196. end;
  197. destructor TMakefileWriter.Destroy;
  198. begin
  199. FOutput.Free;
  200. FIni.Free;
  201. end;
  202. procedure TMakefileWriter.LoadFPCMakeIni;
  203. var
  204. IniStream : TStream;
  205. begin
  206. try
  207. IniStream:=TMyMemoryStream.Create(@fpcmakeini,sizeof(fpcmakeini));
  208. FIni:=TFPCMake.CreateFromStream(IniStream,'fpcmake.ini');
  209. { Leave the '#' comments in the output }
  210. // FIni.CommentChars:=[';'];
  211. FIni.LoadSections;
  212. finally
  213. IniStream.Destroy;
  214. end;
  215. end;
  216. procedure TMakefileWriter.AddIniSection(const s:string);
  217. var
  218. Sec : TFPCMakeSection;
  219. begin
  220. Sec:=TFPCMakeSection(FIni[s]);
  221. if assigned(Sec) then
  222. FOutput.AddStrings(Sec.List)
  223. else
  224. Raise Exception.Create(Format('Section "%s" doesn''t exists in fpcmake.ini',[s]));
  225. end;
  226. procedure TMakefileWriter.AddCustomSection(const s:string);
  227. var
  228. Sec : TFPCMakeSection;
  229. begin
  230. Sec:=TFPCMakeSection(FInput[s]);
  231. if assigned(Sec) then
  232. begin
  233. Sec.BuildMakefile;
  234. FOutput.AddStrings(Sec.List);
  235. end;
  236. end;
  237. procedure TMakefileWriter.AddTargetVariable(const inivar:string);
  238. var
  239. s : string;
  240. T : TOs;
  241. C : TCpu;
  242. begin
  243. for c:=low(TCpu) to high(TCpu) do
  244. for t:=low(TOS) to high(TOS) do
  245. if FInput.IncludeTargets[c,t] then
  246. begin
  247. s:=FInput.GetTargetVariable(c,t,IniVar,false);
  248. if s<>'' then
  249. begin
  250. FOutput.Add('ifeq ($(FULL_TARGET),'+CPUStr[c]+'-'+OSStr[t]+')');
  251. FOutput.Add('override '+FixVariable(IniVar)+'+='+s);
  252. FOutput.Add('endif');
  253. end;
  254. end;
  255. end;
  256. procedure TMakefileWriter.AddVariable(const inivar:string);
  257. var
  258. s : string;
  259. begin
  260. s:=FInput.GetVariable(IniVar,false);
  261. if s<>'' then
  262. FOutput.Add('override '+FixVariable(IniVar)+'='+s)
  263. end;
  264. function TMakefileWriter.AddTargetDefines(const inivar,prefix:string):string;
  265. procedure addtokens(s:string);
  266. var
  267. name : string;
  268. k1,k2 : integer;
  269. begin
  270. repeat
  271. Name:=GetToken(s,' ');
  272. if Name='' then
  273. break;
  274. { Remove (..) }
  275. k1:=pos('(',name);
  276. if k1>0 then
  277. begin
  278. k2:=PosIdx(')',name,k1);
  279. if k2=0 then
  280. k2:=length(name)+1;
  281. Delete(Name,k1,k2);
  282. end;
  283. FOutput.Add(prefix+VarName(name)+'=1');
  284. { add to the list of dirs without duplicates }
  285. AddTokenNoDup(result,name,' ');
  286. until false;
  287. end;
  288. var
  289. s : string;
  290. T : TOs;
  291. C : TCpu;
  292. begin
  293. for c:=low(TCpu) to high(TCpu) do
  294. for t:=low(TOS) to high(TOS) do
  295. if FInput.IncludeTargets[c,t] then
  296. begin
  297. s:=FInput.GetTargetVariable(c,t,IniVar,false);
  298. if s<>'' then
  299. begin
  300. FOutput.Add('ifeq ($(FULL_TARGET),'+CpuStr[c]+'-'+OSStr[t]+')');
  301. AddTokens(s);
  302. FOutput.Add('endif');
  303. end;
  304. end;
  305. end;
  306. procedure TMakefileWriter.AddTool(const varname,exename,altexename:string);
  307. begin
  308. with FOutput do
  309. begin
  310. Add('ifndef '+varname);
  311. Add(varname+':=$(strip $(wildcard $(addsuffix /'+exename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  312. if altexename<>'' then
  313. begin
  314. Add('ifeq ($('+varname+'),)');
  315. Add(varname+':=$(strip $(wildcard $(addsuffix /'+altexename+'$(SRCEXEEXT),$(SEARCHPATH))))');
  316. end;
  317. Add('ifeq ($('+varname+'),)');
  318. Add(varname+'= __missing_command_'+varname); {This is to be shure make stops,
  319. if the command is not found. Otherwise if the command was set to the
  320. empty string, options to the command would be interpreted as command,
  321. and because options is preceeded by a "-", make will ignore the error
  322. that the command is not found.}
  323. Add('else');
  324. Add(varname+':=$(firstword $('+varname+'))');
  325. Add('endif');
  326. if altexename<>'' then
  327. begin
  328. Add('else');
  329. Add(varname+':=$(firstword $('+varname+'))');
  330. Add('endif');
  331. end;
  332. Add('endif');
  333. Add('export '+varname);
  334. end;
  335. end;
  336. procedure TMakefileWriter.AddTools(const inivar:string);
  337. var
  338. hs,tool : string;
  339. begin
  340. hs:=FInput.GetVariable(inivar,false);
  341. repeat
  342. Tool:=GetToken(hs,' ');
  343. if Tool='' then
  344. break;
  345. AddTool(FixVariable(Tool),Tool,'');
  346. until false;
  347. end;
  348. procedure TMakefileWriter.AddRules;
  349. procedure AddRule(rule:trules);
  350. var
  351. i : integer;
  352. hs : string;
  353. Sec : TFPCMakeSection;
  354. Rules : TStringList;
  355. begin
  356. Sec:=TFPCMakeSection(FInput['rules']);
  357. if assigned(Sec) then
  358. begin
  359. Rules:=Sec.List;
  360. for i:=0 to Rules.Count-1 do
  361. begin
  362. if (length(rules[i])>length(rule2str[rule])) and
  363. (rules[i][1]=rule2str[rule][1]) and
  364. ((rules[i][length(rule2str[rule])+1]=':') or
  365. ((length(rules[i])>length(rule2str[rule])+1) and
  366. (rules[i][length(rule2str[rule])+2]=':'))) and
  367. (Copy(rules[i],1,length(rule2str[rule]))=rule2str[rule]) then
  368. exit;
  369. end;
  370. end;
  371. hs:='';
  372. if FHasSection[Rule2Sec[rule]] then
  373. hs:=hs+' fpc_'+rule2str[rule];
  374. { include target dirs, but not for info and targets that
  375. call other targets with a only extra settings, if the
  376. section was not included, then still process the targets }
  377. if FInput.HasTargetVariable('target_dirs') and
  378. (not(rule in [r_info,r_shared,r_smart,r_debug,r_release,r_zipdistinstall,r_distinstall]) or
  379. not FHasSection[Rule2Sec[rule]]) then
  380. begin
  381. if FInput.HasVariable('default_dir') then
  382. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(DEFAULT_DIR))'
  383. else
  384. if not(rule in [r_sourceinstall,r_zipinstall,r_zipsourceinstall,
  385. r_makefiles]) or
  386. not(FInput.HasVariable('package_name')) then
  387. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_DIRS))';
  388. end;
  389. { include cleaning of example dirs }
  390. if (rule=r_clean) and
  391. FInput.HasTargetVariable('target_exampledirs') then
  392. hs:=hs+' $(addsuffix _'+rule2str[rule]+',$(TARGET_EXAMPLEDIRS))';
  393. { Add the rule }
  394. AddPhony(Rule2Str[Rule]);
  395. FOutput.Add(rule2str[rule]+':'+hs);
  396. end;
  397. var
  398. rule : trules;
  399. begin
  400. for rule:=low(trules) to high(trules) do
  401. AddRule(rule);
  402. WritePhony;
  403. end;
  404. procedure TMakefileWriter.AddPhony(const s:string);
  405. begin
  406. FPhony:=FPhony+' '+s;
  407. end;
  408. procedure TMakefileWriter.WritePhony;
  409. begin
  410. if FPhony<>'' then
  411. begin
  412. FOutput.Add('.PHONY:'+FPhony);
  413. FPhony:='';
  414. end;
  415. end;
  416. procedure TMakefileWriter.AddTargetDirs(const inivar:string);
  417. procedure AddTargetDir(const s,defpref:string);
  418. var
  419. j : trules;
  420. begin
  421. FOutput.Add('ifdef '+defpref+VarName(s));
  422. for j:=low(trules) to high(trules) do
  423. begin
  424. FOutput.Add(s+'_'+rule2str[j]+':');
  425. FOutput.Add(#9+'$(MAKE) -C '+s+' '+rule2str[j]);
  426. AddPhony(s+'_'+rule2str[j]);
  427. end;
  428. FOutput.Add(s+':');
  429. FOutput.Add(#9+'$(MAKE) -C '+s+' all');
  430. AddPhony(s);
  431. WritePhony;
  432. FOutput.Add('endif');
  433. end;
  434. var
  435. hs,dir : string;
  436. prefix : string;
  437. begin
  438. prefix:=FixVariable(inivar)+'_';
  439. hs:=AddTargetDefines(inivar,prefix);
  440. repeat
  441. Dir:=GetToken(hs,' ');
  442. if Dir='' then
  443. break;
  444. AddTargetDir(Dir,prefix);
  445. until false;
  446. end;
  447. procedure TMakefileWriter.AddMainPackage(const pack:string);
  448. var
  449. packdirvar : string;
  450. begin
  451. { create needed variables }
  452. packdirvar:='PACKAGEDIR_MAIN';
  453. { Search packagedir by looking for Makefile.fpc }
  454. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  455. end;
  456. procedure TMakefileWriter.AddRequiredPackages;
  457. procedure AddPackage(const pack,prefix:string);
  458. var
  459. packdirvar,unitdirvar : 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. { Search packagedir by looking for Makefile.fpc }
  466. FOutput.Add(packdirvar+':=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Makefile.fpc,$(PACKAGESDIR))))))');
  467. FOutput.Add('ifneq ($('+packdirvar+'),)');
  468. { Create unit dir, check if os dependent dir exists }
  469. FOutput.Add('ifneq ($(wildcard $('+packdirvar+')/units/$(TARGETSUFFIX)),)');
  470. FOutput.Add(unitdirvar+'=$('+packdirvar+')/units/$(TARGETSUFFIX)');
  471. FOutput.Add('else');
  472. FOutput.Add(unitdirvar+'=$('+packdirvar+')');
  473. FOutput.Add('endif');
  474. FOutput.Add('ifdef CHECKDEPEND');
  475. FOutput.Add('$('+packdirvar+')/$(FPCMADE):');
  476. FOutput.Add(#9'$(MAKE) -C $('+packdirvar+') $(FPCMADE)');
  477. FOutput.Add('override ALLDEPENDENCIES+=$('+packdirvar+')/$(FPCMADE)');
  478. FOutput.Add('endif');
  479. { Package dir doesn't exists, check unit dir }
  480. FOutput.Add('else');
  481. FOutput.Add(packdirvar+'=');
  482. FOutput.Add(unitdirvar+':=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /'+pack+'/Package.fpc,$(UNITSDIR)))))');
  483. FOutput.Add('ifneq ($('+unitdirvar+'),)');
  484. FOutput.Add(unitdirvar+':=$(firstword $('+unitdirvar+'))');
  485. FOutput.Add('else');
  486. FOutput.Add(unitdirvar+'=');
  487. FOutput.Add('endif');
  488. FOutput.Add('endif');
  489. { Add Unit dir to the command line -Fu }
  490. FOutput.Add('ifdef '+unitdirvar);
  491. FOutput.Add('override COMPILER_UNITDIR+=$('+unitdirvar+')');
  492. FOutput.Add('endif');
  493. { endif for package }
  494. FOutput.Add('endif');
  495. end;
  496. var
  497. i : integer;
  498. reqs,req,prefix : string;
  499. t : TOS;
  500. c : TCpu;
  501. sl : TStringList;
  502. begin
  503. prefix:='REQUIRE_PACKAGES_';
  504. reqs:='';
  505. { Add target defines }
  506. for c:=low(tcpu) to high(tcpu) do
  507. for t:=low(tos) to high(tos) do
  508. if FInput.IncludeTargets[c,t] then
  509. begin
  510. sl:=FInput.GetTargetRequires(c,t);
  511. { show info }
  512. FInput.Verbose(FPCMakeInfo,CpuStr[c]+'-'+OSStr[t]+' requires: '+sl.CommaText);
  513. if sl.count>0 then
  514. begin
  515. FOutput.Add('ifeq ($(FULL_TARGET),'+CPUStr[c]+'-'+OSStr[t]+')');
  516. for i:=0 to sl.count-1 do
  517. begin
  518. FOutput.Add(prefix+VarName(sl[i])+'=1');
  519. AddTokenNoDup(reqs,sl[i],' ');
  520. end;
  521. FOutput.Add('endif');
  522. end;
  523. sl.Free;
  524. end;
  525. { Add all require packages }
  526. repeat
  527. req:=GetToken(reqs,' ');
  528. if Req='' then
  529. break;
  530. AddPackage(req,prefix);
  531. until false;
  532. WritePhony;
  533. end;
  534. procedure TMakefileWriter.AddDefaultTools;
  535. begin
  536. AddTool('ECHO','gecho','echo');
  537. AddTool('DATE','gdate','date');
  538. AddTool('GINSTALL','ginstall','install');
  539. AddTool('CPPROG','cp','');
  540. AddTool('RMPROG','rm','');
  541. AddTool('MVPROG','mv','');
  542. AddTool('MKDIRPROG','gmkdir','mkdir');
  543. AddIniSection('shelltools');
  544. AddTool('PPUMOVE','ppumove','');
  545. AddTool('FPCMAKE','fpcmake','');
  546. AddTool('ZIPPROG','zip','');
  547. AddTool('TARPROG','tar','');
  548. AddIniSection('defaulttools');
  549. end;
  550. procedure TMakefileWriter.AddMakefileTargets;
  551. var
  552. s : string;
  553. c : TCpu;
  554. t : Tos;
  555. begin
  556. s:='';
  557. for c:=low(tcpu) to high(tcpu) do
  558. for t:=low(tos) to high(tos) do
  559. if FInput.IncludeTargets[c,t] then
  560. AddToken(s,CpuStr[c]+'-'+OSStr[t],' ');
  561. FOutput.Add('MAKEFILETARGETS='+s);
  562. end;
  563. procedure TMakefileWriter.OptimizeSections;
  564. var
  565. SkippedSecs :integer;
  566. begin
  567. { Turn some sections off, depending if files are
  568. provided }
  569. if not FInput.IsPackage then
  570. begin
  571. FHasSection[sec_zipinstall]:=false;
  572. FHasSection[sec_distinstall]:=false;
  573. end;
  574. FHasSection[sec_libs]:=FInput.HasVariable('lib_name');
  575. { Remove unused sections for targets }
  576. SkippedSecs:=0;
  577. if (not FInput.HasTargetVariable('target_units')) then
  578. begin
  579. inc(SkippedSecs);
  580. FHasSection[sec_units]:=false;
  581. end;
  582. if (not FInput.HasTargetVariable('target_programs')) then
  583. begin
  584. inc(SkippedSecs);
  585. FHasSection[sec_exes]:=false;
  586. end;
  587. if (not FInput.HasTargetVariable('target_examples')) then
  588. begin
  589. inc(SkippedSecs);
  590. { example dirs also requires the fpc_examples target, because
  591. it also depends on the all target }
  592. if (not FInput.HasTargetVariable('target_exampledirs')) then
  593. FHasSection[sec_examples]:=false;
  594. end;
  595. if (not FInput.HasTargetVariable('target_loaders')) then
  596. begin
  597. inc(SkippedSecs);
  598. FHasSection[sec_loaders]:=false;
  599. end;
  600. { if all 4 sections are not available we can skip also the
  601. generic compile rules }
  602. if SkippedSecs=4 then
  603. begin
  604. FHasSection[sec_compile]:=false;
  605. if (not FInput.HasTargetVariable('package_name')) and
  606. (not FInput.HasTargetVariable('install_units')) and
  607. (not FInput.HasTargetVariable('install_files')) and
  608. (not FInput.HasTargetVariable('install_createpackagefpc')) then
  609. FHasSection[sec_install]:=false;
  610. { Package.fpc also needs to be cleaned }
  611. if (not FInput.HasTargetVariable('clean_units')) and
  612. (not FInput.HasTargetVariable('clean_files')) and
  613. (not FInput.HasTargetVariable('install_createpackagefpc')) then
  614. FHasSection[sec_clean]:=false;
  615. end;
  616. end;
  617. procedure TMakefileWriter.WriteGenericMakefile;
  618. begin
  619. { Remove unused sections }
  620. OptimizeSections;
  621. { Generate Output }
  622. with FOutput do
  623. begin
  624. { Header }
  625. Add('#');
  626. Add('# Don''t edit, this file is generated by '+TitleDate);
  627. Add('#');
  628. if FInput.HasVariable('default_rule') then
  629. Add('default: '+FInput.GetVariable('default_rule',false))
  630. else
  631. Add('default: all');
  632. { Supported targets by this Makefile }
  633. AddMakefileTargets;
  634. { Add misc defines }
  635. AddIniSection('defines');
  636. { Add automatic detect sections }
  637. AddIniSection('osdetect');
  638. { Forced target }
  639. if FInput.HasVariable('require_target') then
  640. Add('override OS_TARGET='+FInput.GetVariable('require_target',false))
  641. else if FInput.HasVariable('default_target') then
  642. Add('override OS_TARGET_DEFAULT='+FInput.GetVariable('default_target',false));
  643. if FInput.HasVariable('require_cpu') then
  644. Add('override CPU_TARGET='+FInput.GetVariable('require_cpu',false))
  645. else if FInput.HasVariable('default_cpu') then
  646. Add('override CPU_TARGET_DEFAULT='+FInput.GetVariable('default_cpu',false));
  647. { FPC Detection }
  648. AddVariable('default_fpcdir');
  649. AddIniSection('fpcdetect');
  650. AddIniSection('fpcdircheckenv');
  651. AddIniSection('fpcdirdetect');
  652. { Package }
  653. AddVariable('package_name');
  654. AddVariable('package_version');
  655. AddVariable('package_targets');
  656. { Directory of main package }
  657. if FInput.HasVariable('package_main') then
  658. AddMainPackage(FInput.GetVariable('package_main',false));
  659. { LCL rules }
  660. if FInput.UsesLCL then
  661. begin
  662. AddVariable('default_lcldir');
  663. AddVariable('lcl_platform');
  664. AddIniSection('lclrules');
  665. end;
  666. { First add the required packages sections }
  667. // for i:=0 to FInput.RequireList.Count-1 do
  668. // AddCustomSection(FInput.Requirelist[i]);
  669. { prerules section }
  670. if assigned(FInput['prerules']) then
  671. AddStrings(TFPCMakeSection(FInput['prerules']).List);
  672. { Default }
  673. AddVariable('default_dir');
  674. { Targets }
  675. AddTargetVariable('target_dirs');
  676. AddTargetVariable('target_programs');
  677. AddTargetVariable('target_units');
  678. AddTargetVariable('target_implicitunits');
  679. AddTargetVariable('target_loaders');
  680. AddTargetVariable('target_rsts');
  681. AddTargetVariable('target_examples');
  682. AddTargetVariable('target_exampledirs');
  683. { Clean }
  684. AddTargetVariable('clean_units');
  685. AddTargetVariable('clean_files');
  686. { Install }
  687. AddTargetVariable('install_units');
  688. AddTargetVariable('install_files');
  689. AddVariable('install_buildunit');
  690. AddVariable('install_prefix');
  691. AddVariable('install_basedir');
  692. AddVariable('install_datadir');
  693. AddVariable('install_fpcpackage');
  694. AddVariable('install_fpcsubdir');
  695. AddVariable('install_createpackagefpc');
  696. { Dist }
  697. AddVariable('dist_destdir');
  698. AddVariable('dist_zipname');
  699. AddVariable('dist_ziptarget');
  700. { Compiler }
  701. AddTargetVariable('compiler_options');
  702. AddTargetVariable('compiler_version');
  703. AddTargetVariable('compiler_includedir');
  704. AddTargetVariable('compiler_unitdir');
  705. AddTargetVariable('compiler_sourcedir');
  706. AddTargetVariable('compiler_objectdir');
  707. AddTargetVariable('compiler_librarydir');
  708. AddTargetVariable('compiler_targetdir');
  709. AddTargetVariable('compiler_unittargetdir');
  710. { default Dirs and extensions }
  711. AddIniSection('defaultdirs');
  712. if FInput.CheckLibcRequire then
  713. AddIniSection('dirlibc');
  714. AddIniSection('extensions');
  715. { Add default tools }
  716. AddDefaultTools;
  717. { Required packages }
  718. AddVariable('require_packages');
  719. AddRequiredPackages;
  720. { commandline }
  721. AddIniSection('command_begin');
  722. if FInput.CheckLibcRequire then
  723. AddIniSection('command_libc');
  724. AddIniSection('command_end');
  725. { compile }
  726. if FHasSection[sec_loaders] then
  727. AddIniSection('loaderrules');
  728. if FHasSection[sec_units] then
  729. AddIniSection('unitrules');
  730. if FHasSection[sec_exes] then
  731. AddIniSection('exerules');
  732. if FHasSection[sec_rsts] then
  733. AddIniSection('rstrules');
  734. if FHasSection[sec_examples] then
  735. AddIniSection('examplerules');
  736. if FHasSection[sec_compile] then
  737. AddIniSection('compilerules');
  738. if FHasSection[sec_libs] then
  739. AddIniSection('libraryrules');
  740. { install }
  741. if FHasSection[sec_install] then
  742. AddIniSection('installrules');
  743. if FHasSection[sec_distinstall] then
  744. AddIniSection('distinstallrules');
  745. if FHasSection[sec_zipinstall] then
  746. AddIniSection('zipinstallrules');
  747. { clean }
  748. AddIniSection('cleanrules');
  749. { info }
  750. AddIniSection('baseinforules');
  751. if FInput.UsesLCL then
  752. AddIniSection('lclinforules');
  753. AddIniSection('inforules');
  754. { info }
  755. AddIniSection('makefilerules');
  756. { Subdirs }
  757. AddTargetDirs('target_dirs');
  758. AddTargetDirs('target_exampledirs');
  759. { Tools }
  760. AddTools('require_tools');
  761. { Rules }
  762. AddRules;
  763. { Users own rules }
  764. AddIniSection('localmakefile');
  765. AddIniSection('userrules');
  766. if assigned(FInput['rules']) then
  767. AddStrings(TFPCMakeSection(FInput['rules']).List);
  768. end;
  769. { write to disk }
  770. FInput.Verbose(FPCMakeInfo,'Writing Makefile');
  771. Fixtab(FOutput);
  772. FOutput.SaveToFile(FFileName);
  773. end;
  774. end.
  775. {
  776. $Log$
  777. Revision 1.36 2005-01-10 20:33:09 peter
  778. * use cpu-os style
  779. Revision 1.35 2004/11/01 17:17:33 olle
  780. * __missing_command will now have the name of the missing command appended.
  781. Revision 1.34 2004/10/30 12:36:48 peter
  782. * units are now created in separate directory units/cpu-os/
  783. * distclean uses cleanall rule and removes units dir
  784. * cross compile support fixed, it is now possible to cycle a ppcsparc
  785. without deleting ppc386
  786. * bintutilsperfix defaults to cpu-os-
  787. Revision 1.33 2004/08/01 08:12:07 michael
  788. + Patch from Vincent Snijders to fix CPU-specific installs
  789. Revision 1.32 2004/07/12 06:42:52 michael
  790. * Patch from peter to fix writing of target dir rules for cpu specific dirs
  791. Revision 1.31 2004/07/11 18:58:19 peter
  792. * support varaiable_cpu
  793. Revision 1.30 2004/04/20 22:59:31 olle
  794. * support for new fpcini section [defines]
  795. Revision 1.29 2004/04/01 12:26:56 olle
  796. + a tool not found is replaced by the fake command __missing_command__, so that make stops, if it tries to run the command.
  797. Revision 1.28 2003/04/25 20:53:33 peter
  798. * target_dir variable generation was not cpu dependent yet
  799. Revision 1.27 2003/04/24 23:21:01 peter
  800. * support different cpu target
  801. Revision 1.26 2003/03/24 10:56:02 marco
  802. * fix recursive zip making that corrupted utilsxxx.zip
  803. Revision 1.25 2002/09/27 06:54:54 pierre
  804. * translate default_cpu/os into CPU/OS_TARGET_DEFAULT
  805. Revision 1.24 2002/09/07 15:40:32 peter
  806. * old logs removed and tabs fixed
  807. Revision 1.23 2002/03/19 19:37:09 peter
  808. * fix source location in zips for packages and demos
  809. Revision 1.22 2002/03/11 19:10:36 peter
  810. * Regenerated with updated fpcmake
  811. Revision 1.21 2002/02/28 17:03:47 pierre
  812. + CHECKDEPEND var to check if packages are up to date
  813. Revision 1.20 2002/01/27 21:42:35 peter
  814. * -r option to process target dirs also
  815. * default changed to build only for current target
  816. * removed auto building of required packages
  817. * removed makefile target because it causes problems with
  818. an internal rule of make
  819. Revision 1.19 2002/01/06 21:50:05 peter
  820. * lcl updates
  821. * small optimizes for package check
  822. }