fpcmake.pp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Peter Vreman
  4. Convert Makefile.fpc to Makefile
  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. program fpcmake;
  14. uses
  15. {$ifdef go32v2}
  16. dpmiexcp,
  17. {$endif}
  18. dos,
  19. sysutils,classes,inifiles;
  20. const
  21. Version='v0.99.13';
  22. Title='fpcmake '+Version;
  23. { Include default fpcmake.ini }
  24. {$i fpcmake.inc}
  25. type
  26. tsections=(sec_none,
  27. sec_units,sec_exes,sec_loaders,sec_examples,sec_package,
  28. sec_compile,sec_depend,sec_install,sec_sourceinstall,sec_zipinstall,
  29. sec_clean,sec_libs,sec_command,sec_exts,sec_dirs,sec_tools,sec_info
  30. );
  31. const
  32. EnvVar='FPCMAKEINI'; { should be FPCMAKE in the future }
  33. TimeFormat='yyyy/mm/dd hh:nn';
  34. sectionstr : array[tsections] of string=('none',
  35. 'units','exes','loaders','examples','package',
  36. 'compile','depend','install','sourceinstall','zipinstall',
  37. 'clean','libs','command','exts','dirs','tools','info'
  38. );
  39. sectiondef : array[tsections] of boolean=(false,
  40. true,true,false,false,false,
  41. true,false,true,true,true,
  42. true,true,true,true,true,true,true
  43. );
  44. targets=4;
  45. targetstr : array[1..targets] of string=(
  46. 'linux','go32v2','win32','os2'
  47. );
  48. rules=15;
  49. rulestr : array[1..rules] of string=(
  50. 'all','debug',
  51. 'examples','test',
  52. 'smart','shared',
  53. 'showinstall','install','sourceinstall','zipinstall','zipinstalladd',
  54. 'clean','cleanall',
  55. 'depend','info'
  56. );
  57. rule2sec : array[1..rules] of tsections=(
  58. sec_compile,sec_compile,
  59. sec_examples,sec_examples,
  60. sec_libs,sec_libs,
  61. sec_install,sec_install,sec_sourceinstall,sec_zipinstall,sec_zipinstall,
  62. sec_clean,sec_clean,
  63. sec_depend,sec_info
  64. );
  65. { Sections in Makefile.fpc }
  66. ini_sections='sections';
  67. ini_install='install';
  68. ini_zip='zip';
  69. ini_clean='clean';
  70. ini_dirs='dirs';
  71. ini_packages='packages';
  72. ini_libs='libs';
  73. ini_targets='targets';
  74. ini_info='info';
  75. ini_defaults='defaults';
  76. ini_tools='tools';
  77. type
  78. TTargetsString=array[0..targets] of string;
  79. TFpcMake=record
  80. TargetDirs,
  81. TargetLoaders,
  82. TargetUnits,
  83. TargetPrograms,
  84. TargetExamples : TTargetsString;
  85. InstallPrefix,
  86. InstallBase : string;
  87. InstallUnits,
  88. InstallFiles : TTargetsString;
  89. CleanUnits,
  90. CleanFiles : TTargetsString;
  91. ZipName,
  92. ZipTarget : string;
  93. DefaultRule,
  94. DefaultDir,
  95. DefaultTarget,
  96. DefaultCPU,
  97. DefaultOptions : string;
  98. DirFpc,
  99. DirPackage,
  100. DirComponent,
  101. DirUnit,
  102. DirLib,
  103. DirObj,
  104. DirTarget,
  105. DirUnitTarget,
  106. DirSources,
  107. DirInc : string;
  108. PackageRTL,
  109. PackageFCL : boolean;
  110. Components,
  111. Packages : TTargetsString;
  112. LibName,
  113. LibUnits : string;
  114. LibGCC,
  115. LibOther : boolean;
  116. InfoCfg,
  117. InfoDirs,
  118. InfoTools,
  119. InfoInstall,
  120. InfoObjects : boolean;
  121. Section : array[tsections] of boolean;
  122. ToolsPPDep,
  123. ToolsPPUMove,
  124. ToolsPPUFiles,
  125. ToolsData2Inc,
  126. ToolsSed,
  127. ToolsDiff,
  128. ToolsCmp,
  129. ToolsUpx,
  130. ToolsDate,
  131. ToolsZip : boolean;
  132. PreSettings,
  133. PostSettings,
  134. Rules : TStringList;
  135. end;
  136. TMyMemoryStream=class(TMemoryStream)
  137. public
  138. constructor Create(p:pointer;mysize:integer);
  139. end;
  140. var
  141. userini : TFpcMake;
  142. fpcini : TIniFile;
  143. IniStream : TMyMemoryStream;
  144. {*****************************************************************************
  145. Helpers
  146. *****************************************************************************}
  147. procedure Verbose(s:string);
  148. begin
  149. writeln(s);
  150. end;
  151. procedure Error(s:string);
  152. begin
  153. Writeln(s);
  154. Halt(1);
  155. end;
  156. function TargetStringEmpty(const t:TTargetsString):boolean;
  157. var
  158. i : integer;
  159. begin
  160. for i:=0 to targets do
  161. if t[i]<>'' then
  162. begin
  163. TargetStringEmpty:=false;
  164. exit;
  165. end;
  166. TargetStringEmpty:=true;
  167. end;
  168. procedure AddStrNoDup(var s:string;const s2:string);
  169. var
  170. i : longint;
  171. add : boolean;
  172. begin
  173. add:=false;
  174. i:=pos(s2,s);
  175. if (i=0) then
  176. add:=true
  177. else
  178. if (i=1) then
  179. begin
  180. if (length(s)>length(s2)) and
  181. (s[length(s2)+1]<>' ') then
  182. add:=true;
  183. end
  184. else
  185. if (i>1) and
  186. ((s[i-1]<>' ') or
  187. ((length(s)>=i+length(s2)) and (s[i+length(s2)]<>' '))) then
  188. add:=true;
  189. if add then
  190. begin
  191. if s='' then
  192. s:=s2
  193. else
  194. s:=s+' '+s2;
  195. end;
  196. end;
  197. {*****************************************************************************
  198. TMyMemoryStream
  199. *****************************************************************************}
  200. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  201. begin
  202. inherited Create;
  203. SetPointer(p,mysize);
  204. end;
  205. {*****************************************************************************
  206. Makefile.fpc reading
  207. *****************************************************************************}
  208. function ReadMakefilefpc(const fn:string):boolean;
  209. var
  210. ini : TIniFile;
  211. procedure ReadTargetsString(var t:Ttargetsstring;const sec,name,def:string);
  212. var
  213. i : integer;
  214. begin
  215. t[0]:=ini.ReadString(sec,name,def);
  216. for i:=1 to targets do
  217. t[i]:=ini.ReadString(sec,name+'_'+targetstr[i],'');
  218. end;
  219. var
  220. sec : tsections;
  221. begin
  222. ReadMakefilefpc:=false;
  223. Verbose('Reading '+fn);
  224. ini:=TIniFile.Create(fn);
  225. with userini,ini do
  226. begin
  227. { targets }
  228. ReadTargetsString(TargetDirs,ini_targets,'dirs','');
  229. ReadTargetsString(TargetLoaders,ini_targets,'loaders','');
  230. ReadTargetsString(TargetUnits,ini_targets,'units','');
  231. ReadTargetsString(TargetPrograms,ini_targets,'programs','');
  232. ReadTargetsString(TargetExamples,ini_targets,'examples','');
  233. { clean }
  234. ReadTargetsString(CleanUnits,ini_clean,'units','');
  235. ReadTargetsString(CleanFiles,ini_clean,'files','');
  236. { install }
  237. InstallPrefix:=ReadString(ini_install,'dirprefix','');
  238. InstallBase:=ReadString(ini_install,'dirbase','');
  239. ReadTargetsString(InstallUnits,ini_install,'units','');
  240. ReadTargetsString(InstallFiles,ini_install,'files','');
  241. { zip }
  242. ZipName:=ReadString(ini_zip,'zipname','');
  243. ZipTarget:=ReadString(ini_zip,'ziptarget','install');
  244. { defaults }
  245. DefaultDir:=ReadString(ini_defaults,'defaultdir','');
  246. DefaultRule:=ReadString(ini_defaults,'defaultrule','all');
  247. DefaultTarget:=ReadString(ini_defaults,'defaulttarget','');
  248. DefaultCPU:=ReadString(ini_defaults,'defaultcpu','');
  249. DefaultOptions:=ReadString(ini_defaults,'defaultoptions','');
  250. { packages }
  251. ReadTargetsString(Components,ini_packages,'components','');
  252. ReadTargetsString(Packages,ini_packages,'packages','');
  253. PackageRTL:=ReadBool(ini_packages,'rtl',true);
  254. PackageFCL:=ReadBool(ini_packages,'fcl',false);
  255. { dirs }
  256. DirFpc:=ReadString(ini_dirs,'fpcdir','');
  257. DirPackage:=ReadString(ini_dirs,'packagedir','$(FPCDIR)/packages');
  258. DirComponent:=ReadString(ini_dirs,'componentdir','$(FPCDIR)/components');
  259. DirUnit:=ReadString(ini_dirs,'unitdir','');
  260. DirLib:=ReadString(ini_dirs,'libdir','');
  261. DirObj:=ReadString(ini_dirs,'objdir','');
  262. DirTarget:=ReadString(ini_dirs,'targetdir','');
  263. DirSources:=ReadString(ini_dirs,'sourcesdir','');
  264. DirUnitTarget:=ReadString(ini_dirs,'unittargetdir','');
  265. DirInc:=ReadString(ini_dirs,'incdir','');
  266. { libs }
  267. LibName:=ReadString(ini_libs,'libname','');
  268. LibUnits:=ReadString(ini_libs,'libunits','');
  269. LibGcc:=ReadBool(ini_libs,'libgcc',false);
  270. LibOther:=ReadBool(ini_libs,'libother',false);
  271. { tools }
  272. ToolsPPDep:=ReadBool(ini_tools,'toolppdep',true);
  273. ToolsPPUMove:=ReadBool(ini_tools,'toolppumove',true);
  274. ToolsPPUFiles:=ReadBool(ini_tools,'toolppufiles',true);
  275. ToolsSed:=ReadBool(ini_tools,'toolsed',false);
  276. ToolsData2Inc:=ReadBool(ini_tools,'tooldata2inc',false);
  277. ToolsDiff:=ReadBool(ini_tools,'tooldiff',false);
  278. ToolsCmp:=ReadBool(ini_tools,'toolcmp',false);
  279. ToolsUpx:=ReadBool(ini_tools,'toolupx',true);
  280. ToolsDate:=ReadBool(ini_tools,'tooldate',true);
  281. ToolsZip:=ReadBool(ini_tools,'toolzip',true);
  282. { sections, but allow overriding the 'none' option to include a few sects only }
  283. for sec:=low(tsections) to high(tsections) do
  284. Section[sec]:=sectiondef[sec];
  285. Section[sec_None]:=ReadBool(ini_sections,sectionstr[sec_none],sectiondef[sec_none]);
  286. if Section[sec_None] then
  287. FillChar(Section,sizeof(Section),0);
  288. for sec:=low(tsections) to high(tsections) do
  289. Section[sec]:=ReadBool(ini_sections,sectionstr[sec],section[sec]);
  290. { turn on needed sections }
  291. if not TargetStringEmpty(TargetLoaders) then
  292. section[sec_loaders]:=true;
  293. if not TargetStringEmpty(TargetUnits) then
  294. section[sec_units]:=true;
  295. if not TargetStringEmpty(TargetPrograms) then
  296. section[sec_exes]:=true;
  297. if not TargetStringEmpty(TargetExamples) then
  298. section[sec_examples]:=true;
  299. { info }
  300. InfoCfg:=ReadBool(ini_info,'infoconfig',true);
  301. InfoDirs:=ReadBool(ini_info,'infodirs',false);
  302. InfoTools:=ReadBool(ini_info,'infotools',false);
  303. InfoInstall:=ReadBool(ini_info,'infoinstall',true);
  304. InfoObjects:=ReadBool(ini_info,'infoobjects',true);
  305. { rules }
  306. PreSettings:=TStringList.Create;
  307. ReadSectionRaw('presettings',PreSettings);
  308. { rules }
  309. PostSettings:=TStringList.Create;
  310. ReadSectionRaw('postsettings',PostSettings);
  311. { rules }
  312. rules:=TStringList.Create;
  313. ReadSectionRaw('rules',rules);
  314. end;
  315. ini.Destroy;
  316. ReadMakefilefpc:=true;
  317. end;
  318. {*****************************************************************************
  319. userini.ini loading
  320. *****************************************************************************}
  321. function ReadFpcMakeIni:TIniFile;
  322. var
  323. fn : string;
  324. begin
  325. ReadFpcMakeIni:=nil;
  326. if FileExists('fpcmake.ini') then
  327. fn:='fpcmake.ini'
  328. else
  329. if (FileExists(GetEnv(envvar))) then
  330. fn:=GetEnv(envvar)
  331. else
  332. {$ifdef linux}
  333. if FileExists('/usr/lib/fpc/fpcmake.ini') then
  334. fn:='/usr/lib/fpc/fpcmake.ini'
  335. {$else}
  336. if FileExists(ChangeFileExt(paramstr(0),'.ini')) then
  337. fn:=ChangeFileExt(paramstr(0),'.ini')
  338. {$endif}
  339. else
  340. fn:='';
  341. if fn='' then
  342. begin
  343. Verbose('Opening internal ini');
  344. IniStream:=TMyMemoryStream.Create(@fpcmakeini,sizeof(fpcmakeini));
  345. result:=TIniFile.Create(IniStream);
  346. end
  347. else
  348. begin
  349. Verbose('Opening '+fn);
  350. result:=TIniFile.Create(fn);
  351. end;
  352. end;
  353. {*****************************************************************************
  354. Makefile writing
  355. *****************************************************************************}
  356. function WriteMakefile(const fn:string):boolean;
  357. var
  358. mf : TStringList;
  359. ss : TStringList;
  360. Phony : string;
  361. procedure FixTab(sl:TStringList);
  362. var
  363. i,j,k : integer;
  364. s,s2 : string;
  365. begin
  366. i:=0;
  367. while (i<sl.Count) do
  368. begin
  369. if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
  370. begin
  371. s:=sl[i];
  372. k:=0;
  373. j:=0;
  374. repeat
  375. inc(j);
  376. case s[j] of
  377. ' ' :
  378. inc(k);
  379. #9 :
  380. k:=(k+7) and not(7);
  381. else
  382. break;
  383. end;
  384. until (j=length(s));
  385. if k>7 then
  386. begin
  387. s2:='';
  388. Delete(s,1,j-1);
  389. while (k>7) do
  390. begin
  391. s2:=s2+#9;
  392. dec(k,8);
  393. end;
  394. while (k>0) do
  395. begin
  396. s2:=s2+' ';
  397. dec(k);
  398. end;
  399. sl[i]:=s2+s;
  400. end;
  401. end;
  402. inc(i);
  403. end;
  404. end;
  405. procedure AddHead(const s:string);
  406. begin
  407. mf.Add('');
  408. mf.Add('# '+s);
  409. mf.Add('');
  410. end;
  411. procedure AddSection(b:boolean;s:string);
  412. begin
  413. if b then
  414. begin
  415. ss.Clear;
  416. fpcini.ReadSectionRaw(s,ss);
  417. mf.AddStrings(ss);
  418. mf.Add('');
  419. end;
  420. end;
  421. procedure AddRule(rule:integer);
  422. var
  423. i : integer;
  424. hs : string;
  425. begin
  426. i:=0;
  427. while (i<userini.rules.Count) do
  428. begin
  429. if (length(userini.rules[i])>length(rulestr[rule])) and
  430. (userini.rules[i][1]=rulestr[rule][1]) and
  431. ((userini.rules[i][length(rulestr[rule])+1]=':') or
  432. ((length(userini.rules[i])>length(rulestr[rule])+1) and
  433. (userini.rules[i][length(rulestr[rule])+2]=':'))) and
  434. (Copy(userini.rules[i],1,length(rulestr[rule]))=rulestr[rule]) then
  435. exit;
  436. inc(i);
  437. end;
  438. hs:='';
  439. if userini.section[rule2sec[rule]] then
  440. hs:=hs+' fpc_'+rulestr[rule];
  441. if userini.DefaultDir<>'' then
  442. hs:=hs+' '+userini.defaultdir+'_'+rulestr[rule]
  443. else
  444. if not TargetStringEmpty(userini.targetdirs) then
  445. hs:=hs+' $(addsuffix _'+rulestr[rule]+',$(DIROBJECTS))';
  446. if hs<>'' then
  447. begin
  448. Phony:=Phony+' '+rulestr[rule];
  449. mf.Add(rulestr[rule]+':'+hs);
  450. mf.Add('');
  451. end;
  452. end;
  453. procedure AddTargets(const pre:string;var t:TTargetsString;wildcard:boolean);
  454. var
  455. i : integer;
  456. begin
  457. for i:=0 to targets do
  458. if (t[i]<>'') then
  459. begin
  460. if i<>0 then
  461. mf.Add('ifeq ($(OS_TARGET),'+targetstr[i]+')');
  462. if t[i]<>'' then
  463. begin
  464. if wildcard then
  465. mf.Add('override '+pre+'+=$(wildcard '+t[i]+')')
  466. else
  467. mf.Add('override '+pre+'+='+t[i]);
  468. end;
  469. if i<>0 then
  470. mf.Add('endif');
  471. end;
  472. end;
  473. procedure AddTargetDir(const s:string);
  474. var
  475. j : integer;
  476. hs : string;
  477. begin
  478. AddHead('Dir '+s);
  479. mf.Add('ifdef OBJECTDIR'+Uppercase(s));
  480. hs:='.PHONY: ';
  481. for j:=1to rules do
  482. hs:=hs+' '+s+'_'+rulestr[j];
  483. mf.Add(hs);
  484. mf.Add('');
  485. for j:=1to rules do
  486. begin
  487. mf.Add(s+'_'+rulestr[j]+':');
  488. mf.Add(#9+'$(MAKE) -C '+s+' '+rulestr[j]);
  489. if j<rules then
  490. mf.Add('');
  491. end;
  492. mf.Add('endif');
  493. end;
  494. procedure AddPackageDep(const packagedir,s,s2:string;ifdefneed:boolean);
  495. var
  496. s3 : string;
  497. begin
  498. if s<>'' then
  499. s3:='/'+s
  500. else
  501. s3:='';
  502. if ifdefneed then
  503. mf.Add('ifdef PACKAGE'+Uppercase(s));
  504. mf.Add('ifneq ($(wildcard '+packagedir+s3+'),)');
  505. mf.Add('ifeq ($(wildcard '+packagedir+s3+'/$(FPCMADE)),)');
  506. mf.Add('override COMPILEPACKAGES+='+s2);
  507. mf.Add(s2+'_package:');
  508. mf.Add(#9'$(MAKE) -C '+packagedir+s3+' all');
  509. mf.Add('endif');
  510. mf.Add('endif');
  511. if ifdefneed then
  512. mf.Add('endif');
  513. Phony:=Phony+' '+s2+'_package';
  514. end;
  515. procedure AddComponentDep(const s:string);
  516. begin
  517. mf.Add('ifdef COMPONENT'+Uppercase(s));
  518. mf.Add('ifneq ($(wildcard $(COMPONENTDIR)/'+s+'),)');
  519. mf.Add('ifeq ($(wildcard $(COMPONENTDIR)/'+s+'/$(FPCMADE)),)');
  520. mf.Add('override COMPILECOMPONENTS+='+s);
  521. mf.Add(s+'_component:');
  522. mf.Add(#9'$(MAKE) -C $(COMPONENTDIR)/'+s+' all');
  523. mf.Add('endif');
  524. mf.Add('endif');
  525. mf.Add('endif');
  526. Phony:=Phony+' '+s+'_component';
  527. end;
  528. function AddTargetDefines(const ts:TTargetsString;const prefix:string):string;
  529. var
  530. j,i : integer;
  531. hs,hs2 : string;
  532. begin
  533. hs2:='';
  534. for j:=0 to targets do
  535. if (ts[j]<>'') then
  536. begin
  537. if j<>0 then
  538. mf.Add('ifeq ($(OS_TARGET),'+targetstr[j]+')');
  539. hs:=ts[j];
  540. repeat
  541. i:=pos(' ',hs);
  542. if i=0 then
  543. i:=length(hs)+1;
  544. mf.Add(prefix+Uppercase(Copy(hs,1,i-1))+'=1');
  545. { add to the list of dirs without duplicates }
  546. AddStrNoDup(hs2,Copy(hs,1,i-1));
  547. system.delete(hs,1,i);
  548. until hs='';
  549. if j<>0 then
  550. mf.Add('endif');
  551. end;
  552. AddTargetDefines:=hs2;
  553. end;
  554. var
  555. hs : string;
  556. i : integer;
  557. begin
  558. { Open the Makefile }
  559. mf:=TStringList.Create;
  560. { Buffer for reading and writing the sections }
  561. ss:=TStringList.Create;
  562. with mf do
  563. begin
  564. { write header & autodetection }
  565. Add('#');
  566. Add('# Makefile generated by '+title+' on '+FormatDateTime(TimeFormat,Now));
  567. Add('#');
  568. Add('');
  569. Add('defaultrule: '+userini.defaultrule);
  570. Add('');
  571. AddSection(true,'osdetect');
  572. { set the forced target os/cpu }
  573. if (userini.defaulttarget<>'') or (userini.defaultcpu<>'') then
  574. begin
  575. AddSection(true,'defaulttarget');
  576. if userini.defaulttarget<>'' then
  577. Add('override OS_TARGET:='+userini.defaulttarget);
  578. if userini.defaultcpu<>'' then
  579. Add('override CPU_TARGET:='+userini.defaultcpu);
  580. Add('');
  581. end;
  582. { fpc detection }
  583. AddSection(true,'fpcdetect');
  584. { write the default & user settings }
  585. AddSection(true,'defaultsettings');
  586. AddSection(true,'usersettings');
  587. { Pre Settings }
  588. if userini.PreSettings.count>0 then
  589. begin
  590. AddHead('Pre Settings');
  591. AddStrings(userini.PreSettings);
  592. end;
  593. { Targets }
  594. AddHead('Targets');
  595. AddTargets('DIROBJECTS',userini.targetdirs,true);
  596. AddTargets('LOADEROBJECTS',userini.targetloaders,false);
  597. AddTargets('UNITOBJECTS',userini.targetunits,false);
  598. AddTargets('EXEOBJECTS',userini.targetprograms,false);
  599. AddTargets('EXAMPLEOBJECTS',userini.targetexamples,false);
  600. { Clean }
  601. AddHead('Clean');
  602. AddTargets('EXTRACLEANUNITS',userini.cleanunits,false);
  603. AddTargets('EXTRACLEANFILES',userini.cleanfiles,false);
  604. { Install }
  605. AddHead('Install');
  606. AddTargets('EXTRAINSTALLUNITS',userini.installunits,false);
  607. AddTargets('EXTRAINSTALLFILES',userini.installfiles,false);
  608. if userini.installprefix<>'' then
  609. Add('PREFIXINSTALLDIR='+userini.installprefix);
  610. if userini.installbase<>'' then
  611. Add('BASEINSTALLDIR='+userini.installbase);
  612. { Zip }
  613. if userini.zipname<>'' then
  614. Add('ZIPNAME='+userini.zipname);
  615. if userini.ziptarget<>'' then
  616. Add('ZIPTARGET='+userini.ziptarget);
  617. { Defaults }
  618. AddHead('Defaults');
  619. if userini.defaultoptions<>'' then
  620. Add('override NEEDOPT='+userini.defaultoptions);
  621. { Dirs }
  622. AddHead('Directories');
  623. if userini.dirsources<>'' then
  624. Add('vpath %$(PASEXT) '+userini.dirsources);
  625. if userini.dirfpc<>'' then
  626. begin
  627. { this dir can be set in the environment, it's more a default }
  628. Add('ifndef FPCDIR');
  629. Add('FPCDIR='+userini.dirfpc);
  630. Add('endif');
  631. end;
  632. if userini.dirpackage<>'' then
  633. begin
  634. { this dir can be set in the environment, it's more a default }
  635. Add('ifndef PACKAGEDIR');
  636. Add('PACKAGEDIR='+userini.dirpackage);
  637. Add('endif');
  638. end;
  639. if userini.dircomponent<>'' then
  640. begin
  641. { this dir can be set in the environment, it's more a default }
  642. Add('ifndef COMPONENTDIR');
  643. Add('COMPONENTDIR='+userini.dircomponent);
  644. Add('endif');
  645. end;
  646. if userini.dirunit<>'' then
  647. Add('override NEEDUNITDIR='+userini.dirunit);
  648. if userini.dirlib<>'' then
  649. Add('override NEEDLIBDIR='+userini.dirlib);
  650. if userini.dirobj<>'' then
  651. Add('override NEEDOBJDIR='+userini.dirobj);
  652. if userini.dirinc<>'' then
  653. Add('override NEEDINCDIR='+userini.dirinc);
  654. if userini.dirtarget<>'' then
  655. begin
  656. Add('ifndef TARGETDIR');
  657. Add('TARGETDIR='+userini.dirtarget);
  658. Add('endif');
  659. end;
  660. if userini.dirunittarget<>'' then
  661. begin
  662. Add('ifndef UNITTARGETDIR');
  663. Add('UNITTARGETDIR='+userini.dirunittarget);
  664. Add('endif');
  665. end;
  666. { Packages }
  667. AddHead('Packages');
  668. AddTargets('PACKAGES',userini.packages,false);
  669. AddTargets('COMPONENTS',userini.components,false);
  670. if userini.PackageFCL then
  671. Add('override NEEDUNITDIR+=$(FPCDIR)/fcl/$(OS_TARGET)');
  672. if not TargetStringEmpty(userini.Packages) then
  673. Add('override NEEDUNITDIR+=$(addprefix $(PACKAGEDIR)/,$(PACKAGES))');
  674. if not TargetStringEmpty(userini.Components) then
  675. Add('override NEEDUNITDIR+=$(addprefix $(COMPONENTDIR)/,$(COMPONENTS))');
  676. { Libs }
  677. AddHead('Libraries');
  678. if userini.libname<>'' then
  679. Add('LIBNAME='+userini.libname);
  680. if userini.libunits<>'' then
  681. Add('SHAREDLIBOBJECTUNITS='+userini.libunits);
  682. if userini.libgcc then
  683. Add('override NEEDGCCLIB=1');
  684. if userini.libother then
  685. Add('override NEEDOTHERLIB=1');
  686. { Info }
  687. if userini.Section[sec_Info] then
  688. begin
  689. AddHead('Info');
  690. hs:='';
  691. if userini.infocfg then
  692. hs:=hs+'fpc_infocfg ';
  693. if userini.infodirs then
  694. hs:=hs+'fpc_infodirs ';
  695. if userini.infotools then
  696. hs:=hs+'fpc_infotools ';
  697. if userini.infoobjects then
  698. hs:=hs+'fpc_infoobjects ';
  699. if userini.infoinstall then
  700. hs:=hs+'fpc_infoinstall ';
  701. Add('INFOTARGET='+hs);
  702. end;
  703. { Post Settings }
  704. if userini.PostSettings.count>0 then
  705. begin
  706. AddHead('Post Settings');
  707. AddStrings(userini.PostSettings);
  708. end;
  709. Add('');
  710. { write dirs }
  711. if userini.section[sec_dirs] then
  712. begin
  713. AddSection(true,'dir_default');
  714. AddSection(userini.libgcc,'dir_gcclib');
  715. AddSection(userini.libother,'dir_otherlib');
  716. AddSection(true,'dir_install');
  717. end;
  718. { commandline }
  719. if userini.section[sec_command] then
  720. begin
  721. Add('');
  722. AddSection(true,'command_begin');
  723. AddSection((userini.defaultoptions<>''),'command_needopt');
  724. AddSection((userini.dirfpc<>''),'command_rtldir');
  725. AddSection((userini.dirfpc<>''),'command_unitsdir');
  726. AddSection((userini.dirunit<>'') or
  727. (userini.packagefcl) or
  728. (not TargetStringEmpty(userini.packages)) or
  729. (not TargetStringEmpty(userini.components))
  730. ,'command_needunit');
  731. AddSection((userini.dirlib<>''),'command_needlib');
  732. AddSection((userini.dirobj<>''),'command_needobj');
  733. AddSection((userini.dirinc<>''),'command_needinc');
  734. AddSection(userini.libgcc,'command_gcclib');
  735. AddSection(userini.libother,'command_otherlib');
  736. AddSection((userini.dirinc<>''),'command_inc');
  737. AddSection((userini.dirtarget<>''),'command_target');
  738. AddSection((userini.dirunittarget<>''),'command_unittarget');
  739. AddSection(true,'command_end');
  740. end;
  741. { write tools }
  742. if userini.section[sec_tools] then
  743. begin
  744. AddSection(true,'shelltools');
  745. AddSection(true,'tool_default');
  746. AddSection(userini.toolsppdep,'tool_ppdep');
  747. AddSection(userini.toolsppumove,'tool_ppumove');
  748. AddSection(userini.toolsppufiles,'tool_ppufiles');
  749. AddSection(userini.toolsdata2inc,'tool_data2inc');
  750. AddSection(userini.toolsupx,'tool_upx');
  751. AddSection(userini.toolssed,'tool_sed');
  752. AddSection(userini.toolsdate,'tool_date');
  753. AddSection(userini.toolszip,'tool_zip');
  754. AddSection(userini.toolscmp,'tool_cmp');
  755. AddSection(userini.toolsdiff,'tool_diff');
  756. end;
  757. { extensions }
  758. if userini.section[sec_exts] then
  759. AddSection(true,'extensions');
  760. { add default rules }
  761. AddSection(true,'standardrules');
  762. Phony:='';
  763. for i:=1 to rules do
  764. AddRule(i);
  765. if Phony<>'' then
  766. begin
  767. Add('.PHONY: '+Phony);
  768. Add('');
  769. end;
  770. { Package depends, must be before the other rules so it's done first! }
  771. AddSection(true,'packagedependrules');
  772. Phony:='';
  773. if userini.packagertl then
  774. AddPackageDep('$(RTLDIR)','','rtl',false);
  775. if userini.packagefcl then
  776. AddPackageDep('$(FCLDIR)','','fcl',false);
  777. Add('');
  778. if not TargetStringEmpty(userini.Packages) then
  779. begin
  780. hs:=AddTargetDefines(userini.Packages,'PACKAGE');
  781. repeat
  782. i:=pos(' ',hs);
  783. if i=0 then
  784. i:=length(hs)+1;
  785. AddPackageDep('$(PACKAGEDIR)',Copy(hs,1,i-1),Copy(hs,1,i-1),true);
  786. system.delete(hs,1,i);
  787. until hs='';
  788. Add('');
  789. end;
  790. if Phony<>'' then
  791. begin
  792. Add('.PHONY: '+Phony);
  793. Add('');
  794. end;
  795. { Components }
  796. Phony:='';
  797. if not TargetStringEmpty(userini.Components) then
  798. begin
  799. hs:=AddTargetDefines(userini.Components,'COMPONENT');
  800. repeat
  801. i:=pos(' ',hs);
  802. if i=0 then
  803. i:=length(hs)+1;
  804. AddComponentDep(Copy(hs,1,i-1));
  805. system.delete(hs,1,i);
  806. until hs='';
  807. Add('');
  808. end;
  809. if Phony<>'' then
  810. begin
  811. Add('.PHONY: '+Phony);
  812. Add('');
  813. end;
  814. { compile rules for making loaders/units/exes/examples }
  815. AddSection(not TargetStringEmpty(userini.targetloaders),'loaderrules');
  816. AddSection(not TargetStringEmpty(userini.targetunits),'unitrules');
  817. AddSection(not TargetStringEmpty(userini.targetprograms),'exerules');
  818. AddSection(not TargetStringEmpty(userini.targetexamples),'examplerules');
  819. { default fpc_ rules }
  820. AddSection(userini.Section[sec_Compile],'compilerules');
  821. AddSection(userini.Section[sec_Libs],'libraryrules');
  822. AddSection(userini.Section[sec_Install],'installrules');
  823. AddSection(userini.Section[sec_SourceInstall],'sourceinstallrules');
  824. AddSection(userini.Section[sec_ZipInstall],'zipinstallrules');
  825. AddSection(userini.Section[sec_Clean],'cleanrules');
  826. AddSection(userini.Section[sec_Depend],'dependrules');
  827. if userini.Section[sec_Info] then
  828. begin
  829. AddSection(true,'inforules');
  830. AddSection(userini.infocfg,'info_cfg');
  831. AddSection(userini.infodirs,'info_dirs');
  832. AddSection(userini.infotools,'info_tools');
  833. AddSection(userini.infoobjects,'info_objects');
  834. AddSection(userini.infoinstall,'info_install');
  835. end;
  836. { Target dirs }
  837. if not TargetStringEmpty(userini.targetdirs) then
  838. begin
  839. AddHead('Target Dirs');
  840. hs:=AddTargetDefines(userini.targetdirs,'OBJECTDIR');
  841. repeat
  842. i:=pos(' ',hs);
  843. if i=0 then
  844. i:=length(hs)+1;
  845. AddTargetDir(Copy(hs,1,i-1));
  846. system.delete(hs,1,i);
  847. until hs='';
  848. Add('');
  849. end;
  850. { insert users rules }
  851. if userini.rules.count>0 then
  852. begin
  853. AddSection(true,'userrules');
  854. AddStrings(userini.rules);
  855. end;
  856. end;
  857. { Write the Makefile and cleanup }
  858. Verbose('Writing '+fn);
  859. FixTab(mf);
  860. mf.SaveToFile(fn);
  861. mf.Destroy;
  862. ss.Destroy;
  863. WriteMakefile:=true;
  864. end;
  865. procedure UseMakefilefpc;
  866. var
  867. fn : string;
  868. begin
  869. if FileExists('Makefile.fpc') then
  870. fn:='Makefile.fpc'
  871. else
  872. fn:='makefile.fpc';
  873. { Open Makefile.fpc }
  874. if not ReadMakefilefpc(fn) then
  875. Error('Can''t read '+fn);
  876. { Write Makefile }
  877. if not WriteMakefile('Makefile') then
  878. Error('Can''t write Makefile');
  879. end;
  880. procedure UseParameters;
  881. var
  882. i : integer;
  883. fn : string;
  884. begin
  885. for i:=1 to ParamCount do
  886. begin
  887. fn:=ParamStr(i);
  888. { Open Makefile.fpc }
  889. if not ReadMakefilefpc(fn) then
  890. Error('Can''t read '+fn);
  891. { Write Makefile }
  892. if not WriteMakefile(ExtractFilePath(fn)+'Makefile') then
  893. Error('Can''t write '+ExtractFilePath(fn)+'Makefile');
  894. end;
  895. end;
  896. begin
  897. { Open userini.ini }
  898. fpcini:=ReadFpcMakeIni;
  899. if not assigned(fpcini) then
  900. Error('Can''t read fpcmake.ini');
  901. if ParamCount=0 then
  902. UseMakefilefpc
  903. else
  904. UseParameters;
  905. fpcini.destroy;
  906. end.
  907. {
  908. $Log$
  909. Revision 1.12 1999-12-19 15:15:04 peter
  910. * fpcmade.<TARGET> added
  911. * parameter support. So it can be using with "find -name 'Makefile.fpc'"
  912. Revision 1.11 1999/12/02 11:30:24 peter
  913. * better dup checking
  914. Revision 1.10 1999/11/26 00:20:15 peter
  915. * fpcmake updated
  916. Revision 1.9 1999/11/25 20:23:01 peter
  917. * package dependencies
  918. Revision 1.8 1999/11/24 23:53:00 peter
  919. * packages
  920. * lot of other changes
  921. Revision 1.7 1999/11/23 09:43:35 peter
  922. + internal .ini file
  923. + packages support
  924. * ppufiles,data2inc support
  925. Revision 1.6 1999/11/10 22:10:49 peter
  926. * fpcmake updated
  927. Revision 1.5 1999/11/09 14:38:32 peter
  928. * sections section to leave out whole info/tools
  929. Revision 1.4 1999/11/08 15:01:39 peter
  930. * fpcmake support
  931. Revision 1.3 1999/11/04 12:07:13 michael
  932. + Now envvar is used
  933. Revision 1.2 1999/11/03 23:39:53 peter
  934. * lot of updates
  935. Revision 1.1 1999/11/02 23:57:40 peter
  936. * initial version
  937. }