fpcmake.pp 28 KB

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