fpcmake.pp 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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. rulediralso : array[1..rules] of boolean=(
  66. true,true,
  67. true,true,
  68. true,true,
  69. true,true,true,false,false,
  70. true,true,
  71. true,false
  72. );
  73. { Sections in Makefile.fpc }
  74. ini_sections='sections';
  75. ini_install='install';
  76. ini_zip='zip';
  77. ini_clean='clean';
  78. ini_dirs='dirs';
  79. ini_packages='packages';
  80. ini_libs='libs';
  81. ini_targets='targets';
  82. ini_info='info';
  83. ini_defaults='defaults';
  84. ini_tools='tools';
  85. type
  86. TTargetsString=array[0..targets] of string;
  87. TFpcMake=record
  88. TargetDirs,
  89. TargetLoaders,
  90. TargetUnits,
  91. TargetPrograms,
  92. TargetExamples : TTargetsString;
  93. InstallPrefix,
  94. InstallBase : string;
  95. InstallUnits,
  96. InstallFiles : TTargetsString;
  97. CleanUnits,
  98. CleanFiles : TTargetsString;
  99. ZipName,
  100. ZipTarget : string;
  101. DefaultRule,
  102. DefaultDir,
  103. DefaultTarget,
  104. DefaultCPU,
  105. DefaultOptions : string;
  106. DirFpc,
  107. DirPackage,
  108. DirComponent,
  109. DirUnit,
  110. DirLib,
  111. DirObj,
  112. DirTarget,
  113. DirUnitTarget,
  114. DirSources,
  115. DirInc : string;
  116. PackageRTL,
  117. PackageFCL : boolean;
  118. Components,
  119. Packages : TTargetsString;
  120. LibName,
  121. LibUnits : string;
  122. LibGCC,
  123. LibOther : boolean;
  124. InfoCfg,
  125. InfoDirs,
  126. InfoTools,
  127. InfoInstall,
  128. InfoObjects : boolean;
  129. Section : array[tsections] of boolean;
  130. ToolsPPDep,
  131. ToolsPPUMove,
  132. ToolsPPUFiles,
  133. ToolsData2Inc,
  134. ToolsSed,
  135. ToolsDiff,
  136. ToolsCmp,
  137. ToolsUpx,
  138. ToolsDate,
  139. ToolsZip : boolean;
  140. PreSettings,
  141. PostSettings,
  142. Rules : TStringList;
  143. end;
  144. TMyMemoryStream=class(TMemoryStream)
  145. public
  146. constructor Create(p:pointer;mysize:integer);
  147. end;
  148. var
  149. userini : TFpcMake;
  150. fpcini : TIniFile;
  151. IniStream : TMyMemoryStream;
  152. {*****************************************************************************
  153. Helpers
  154. *****************************************************************************}
  155. procedure Verbose(s:string);
  156. begin
  157. writeln(s);
  158. end;
  159. procedure Error(s:string);
  160. begin
  161. Writeln(s);
  162. Halt(1);
  163. end;
  164. function TargetStringEmpty(const t:TTargetsString):boolean;
  165. var
  166. i : integer;
  167. begin
  168. for i:=0 to targets do
  169. if t[i]<>'' then
  170. begin
  171. TargetStringEmpty:=false;
  172. exit;
  173. end;
  174. TargetStringEmpty:=true;
  175. end;
  176. procedure AddStrNoDup(var s:string;const s2:string);
  177. var
  178. i : longint;
  179. add : boolean;
  180. begin
  181. add:=false;
  182. i:=pos(s2,s);
  183. if (i=0) then
  184. add:=true
  185. else
  186. if (i=1) then
  187. begin
  188. if (length(s)>length(s2)) and
  189. (s[length(s2)+1]<>' ') then
  190. add:=true;
  191. end
  192. else
  193. if (i>1) and
  194. ((s[i-1]<>' ') or
  195. ((length(s)>=i+length(s2)) and (s[i+length(s2)]<>' '))) then
  196. add:=true;
  197. if add then
  198. begin
  199. if s='' then
  200. s:=s2
  201. else
  202. s:=s+' '+s2;
  203. end;
  204. end;
  205. {*****************************************************************************
  206. TMyMemoryStream
  207. *****************************************************************************}
  208. constructor TMyMemoryStream.Create(p:pointer;mysize:integer);
  209. begin
  210. inherited Create;
  211. SetPointer(p,mysize);
  212. end;
  213. {*****************************************************************************
  214. Makefile.fpc reading
  215. *****************************************************************************}
  216. function ReadMakefilefpc(const fn:string):boolean;
  217. var
  218. ini : TIniFile;
  219. procedure ReadTargetsString(var t:Ttargetsstring;const sec,name,def:string);
  220. var
  221. i : integer;
  222. begin
  223. t[0]:=ini.ReadString(sec,name,def);
  224. for i:=1 to targets do
  225. t[i]:=ini.ReadString(sec,name+'_'+targetstr[i],'');
  226. end;
  227. var
  228. sec : tsections;
  229. begin
  230. ReadMakefilefpc:=false;
  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(const fn:string):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 rulediralso[rule] and (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+'/$(FPCMADE)),)');
  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+'/$(FPCMADE)),)');
  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. mf:=TStringList.Create;
  568. { Buffer for reading and writing the sections }
  569. ss:=TStringList.Create;
  570. with mf do
  571. begin
  572. { write header & autodetection }
  573. Add('#');
  574. Add('# Makefile generated by '+title+' on '+FormatDateTime(TimeFormat,Now));
  575. Add('#');
  576. Add('');
  577. Add('defaultrule: '+userini.defaultrule);
  578. Add('');
  579. AddSection(true,'osdetect');
  580. { set the forced target os/cpu }
  581. if (userini.defaulttarget<>'') or (userini.defaultcpu<>'') then
  582. begin
  583. AddSection(true,'defaulttarget');
  584. if userini.defaulttarget<>'' then
  585. Add('override OS_TARGET:='+userini.defaulttarget);
  586. if userini.defaultcpu<>'' then
  587. Add('override CPU_TARGET:='+userini.defaultcpu);
  588. Add('');
  589. end;
  590. { fpc detection }
  591. AddSection(true,'fpcdetect');
  592. { write the default & user settings }
  593. AddSection(true,'defaultsettings');
  594. AddSection(true,'usersettings');
  595. { Pre Settings }
  596. if userini.PreSettings.count>0 then
  597. begin
  598. AddHead('Pre Settings');
  599. AddStrings(userini.PreSettings);
  600. end;
  601. { Targets }
  602. AddHead('Targets');
  603. AddTargets('DIROBJECTS',userini.targetdirs,true);
  604. AddTargets('LOADEROBJECTS',userini.targetloaders,false);
  605. AddTargets('UNITOBJECTS',userini.targetunits,false);
  606. AddTargets('EXEOBJECTS',userini.targetprograms,false);
  607. AddTargets('EXAMPLEOBJECTS',userini.targetexamples,false);
  608. { Clean }
  609. AddHead('Clean');
  610. AddTargets('EXTRACLEANUNITS',userini.cleanunits,false);
  611. AddTargets('EXTRACLEANFILES',userini.cleanfiles,false);
  612. { Install }
  613. AddHead('Install');
  614. AddTargets('EXTRAINSTALLUNITS',userini.installunits,false);
  615. AddTargets('EXTRAINSTALLFILES',userini.installfiles,false);
  616. if userini.installprefix<>'' then
  617. Add('PREFIXINSTALLDIR='+userini.installprefix);
  618. if userini.installbase<>'' then
  619. Add('BASEINSTALLDIR='+userini.installbase);
  620. { Zip }
  621. if userini.zipname<>'' then
  622. Add('ZIPNAME='+userini.zipname);
  623. if userini.ziptarget<>'' then
  624. Add('ZIPTARGET='+userini.ziptarget);
  625. { Defaults }
  626. AddHead('Defaults');
  627. if userini.defaultoptions<>'' then
  628. Add('override NEEDOPT='+userini.defaultoptions);
  629. { Dirs }
  630. AddHead('Directories');
  631. if userini.dirsources<>'' then
  632. Add('vpath %$(PASEXT) '+userini.dirsources);
  633. if userini.dirfpc<>'' then
  634. begin
  635. { this dir can be set in the environment, it's more a default }
  636. Add('ifndef FPCDIR');
  637. Add('FPCDIR='+userini.dirfpc);
  638. Add('endif');
  639. end;
  640. if userini.dirpackage<>'' then
  641. begin
  642. { this dir can be set in the environment, it's more a default }
  643. Add('ifndef PACKAGEDIR');
  644. Add('PACKAGEDIR='+userini.dirpackage);
  645. Add('endif');
  646. end;
  647. if userini.dircomponent<>'' then
  648. begin
  649. { this dir can be set in the environment, it's more a default }
  650. Add('ifndef COMPONENTDIR');
  651. Add('COMPONENTDIR='+userini.dircomponent);
  652. Add('endif');
  653. end;
  654. if userini.dirunit<>'' then
  655. Add('override NEEDUNITDIR='+userini.dirunit);
  656. if userini.dirlib<>'' then
  657. Add('override NEEDLIBDIR='+userini.dirlib);
  658. if userini.dirobj<>'' then
  659. Add('override NEEDOBJDIR='+userini.dirobj);
  660. if userini.dirinc<>'' then
  661. Add('override NEEDINCDIR='+userini.dirinc);
  662. if userini.dirtarget<>'' then
  663. begin
  664. Add('ifndef TARGETDIR');
  665. Add('TARGETDIR='+userini.dirtarget);
  666. Add('endif');
  667. end;
  668. if userini.dirunittarget<>'' then
  669. begin
  670. Add('ifndef UNITTARGETDIR');
  671. Add('UNITTARGETDIR='+userini.dirunittarget);
  672. Add('endif');
  673. end;
  674. { Packages }
  675. AddHead('Packages');
  676. AddTargets('PACKAGES',userini.packages,false);
  677. AddTargets('COMPONENTS',userini.components,false);
  678. if userini.PackageFCL then
  679. Add('override NEEDUNITDIR+=$(FPCDIR)/fcl/$(OS_TARGET)');
  680. if not TargetStringEmpty(userini.Packages) then
  681. Add('override NEEDUNITDIR+=$(addprefix $(PACKAGEDIR)/,$(PACKAGES))');
  682. if not TargetStringEmpty(userini.Components) then
  683. Add('override NEEDUNITDIR+=$(addprefix $(COMPONENTDIR)/,$(COMPONENTS))');
  684. { Libs }
  685. AddHead('Libraries');
  686. if userini.libname<>'' then
  687. Add('LIBNAME='+userini.libname);
  688. if userini.libunits<>'' then
  689. Add('SHAREDLIBOBJECTUNITS='+userini.libunits);
  690. if userini.libgcc then
  691. Add('override NEEDGCCLIB=1');
  692. if userini.libother then
  693. Add('override NEEDOTHERLIB=1');
  694. { Info }
  695. if userini.Section[sec_Info] then
  696. begin
  697. AddHead('Info');
  698. hs:='';
  699. if userini.infocfg then
  700. hs:=hs+'fpc_infocfg ';
  701. if userini.infodirs then
  702. hs:=hs+'fpc_infodirs ';
  703. if userini.infotools then
  704. hs:=hs+'fpc_infotools ';
  705. if userini.infoobjects then
  706. hs:=hs+'fpc_infoobjects ';
  707. if userini.infoinstall then
  708. hs:=hs+'fpc_infoinstall ';
  709. Add('INFOTARGET='+hs);
  710. end;
  711. { Post Settings }
  712. if userini.PostSettings.count>0 then
  713. begin
  714. AddHead('Post Settings');
  715. AddStrings(userini.PostSettings);
  716. end;
  717. Add('');
  718. { write dirs }
  719. if userini.section[sec_dirs] then
  720. begin
  721. AddSection(true,'dir_default');
  722. AddSection(userini.libgcc,'dir_gcclib');
  723. AddSection(userini.libother,'dir_otherlib');
  724. AddSection(true,'dir_install');
  725. end;
  726. { commandline }
  727. if userini.section[sec_command] then
  728. begin
  729. Add('');
  730. AddSection(true,'command_begin');
  731. AddSection((userini.defaultoptions<>''),'command_needopt');
  732. AddSection((userini.dirfpc<>''),'command_rtldir');
  733. AddSection((userini.dirfpc<>''),'command_unitsdir');
  734. AddSection((userini.dirunit<>'') or
  735. (userini.packagefcl) or
  736. (not TargetStringEmpty(userini.packages)) or
  737. (not TargetStringEmpty(userini.components))
  738. ,'command_needunit');
  739. AddSection((userini.dirlib<>''),'command_needlib');
  740. AddSection((userini.dirobj<>''),'command_needobj');
  741. AddSection((userini.dirinc<>''),'command_needinc');
  742. AddSection(userini.libgcc,'command_gcclib');
  743. AddSection(userini.libother,'command_otherlib');
  744. AddSection((userini.dirinc<>''),'command_inc');
  745. AddSection((userini.dirtarget<>''),'command_target');
  746. AddSection((userini.dirunittarget<>''),'command_unittarget');
  747. AddSection(true,'command_end');
  748. end;
  749. { write tools }
  750. if userini.section[sec_tools] then
  751. begin
  752. AddSection(true,'shelltools');
  753. AddSection(true,'tool_default');
  754. AddSection(userini.toolsppdep,'tool_ppdep');
  755. AddSection(userini.toolsppumove,'tool_ppumove');
  756. AddSection(userini.toolsppufiles,'tool_ppufiles');
  757. AddSection(userini.toolsdata2inc,'tool_data2inc');
  758. AddSection(userini.toolsupx,'tool_upx');
  759. AddSection(userini.toolssed,'tool_sed');
  760. AddSection(userini.toolsdate,'tool_date');
  761. AddSection(userini.toolszip,'tool_zip');
  762. AddSection(userini.toolscmp,'tool_cmp');
  763. AddSection(userini.toolsdiff,'tool_diff');
  764. end;
  765. { extensions }
  766. if userini.section[sec_exts] then
  767. AddSection(true,'extensions');
  768. { add default rules }
  769. AddSection(true,'standardrules');
  770. Phony:='';
  771. for i:=1 to rules do
  772. AddRule(i);
  773. if Phony<>'' then
  774. begin
  775. Add('.PHONY: '+Phony);
  776. Add('');
  777. end;
  778. { Package depends, must be before the other rules so it's done first! }
  779. AddSection(true,'packagedependrules');
  780. Phony:='';
  781. if userini.packagertl then
  782. AddPackageDep('$(RTLDIR)','','rtl',false);
  783. if userini.packagefcl then
  784. AddPackageDep('$(FCLDIR)','','fcl',false);
  785. Add('');
  786. if not TargetStringEmpty(userini.Packages) then
  787. begin
  788. hs:=AddTargetDefines(userini.Packages,'PACKAGE');
  789. repeat
  790. i:=pos(' ',hs);
  791. if i=0 then
  792. i:=length(hs)+1;
  793. AddPackageDep('$(PACKAGEDIR)',Copy(hs,1,i-1),Copy(hs,1,i-1),true);
  794. system.delete(hs,1,i);
  795. until hs='';
  796. Add('');
  797. end;
  798. if Phony<>'' then
  799. begin
  800. Add('.PHONY: '+Phony);
  801. Add('');
  802. end;
  803. { Components }
  804. Phony:='';
  805. if not TargetStringEmpty(userini.Components) then
  806. begin
  807. hs:=AddTargetDefines(userini.Components,'COMPONENT');
  808. repeat
  809. i:=pos(' ',hs);
  810. if i=0 then
  811. i:=length(hs)+1;
  812. AddComponentDep(Copy(hs,1,i-1));
  813. system.delete(hs,1,i);
  814. until hs='';
  815. Add('');
  816. end;
  817. if Phony<>'' then
  818. begin
  819. Add('.PHONY: '+Phony);
  820. Add('');
  821. end;
  822. { compile rules for making loaders/units/exes/examples }
  823. AddSection(not TargetStringEmpty(userini.targetloaders),'loaderrules');
  824. AddSection(not TargetStringEmpty(userini.targetunits),'unitrules');
  825. AddSection(not TargetStringEmpty(userini.targetprograms),'exerules');
  826. AddSection(not TargetStringEmpty(userini.targetexamples),'examplerules');
  827. { default fpc_ rules }
  828. AddSection(userini.Section[sec_Compile],'compilerules');
  829. AddSection(userini.Section[sec_Libs],'libraryrules');
  830. AddSection(userini.Section[sec_Install],'installrules');
  831. AddSection(userini.Section[sec_SourceInstall],'sourceinstallrules');
  832. AddSection(userini.Section[sec_ZipInstall],'zipinstallrules');
  833. AddSection(userini.Section[sec_Clean],'cleanrules');
  834. AddSection(userini.Section[sec_Depend],'dependrules');
  835. if userini.Section[sec_Info] then
  836. begin
  837. AddSection(true,'inforules');
  838. AddSection(userini.infocfg,'info_cfg');
  839. AddSection(userini.infodirs,'info_dirs');
  840. AddSection(userini.infotools,'info_tools');
  841. AddSection(userini.infoobjects,'info_objects');
  842. AddSection(userini.infoinstall,'info_install');
  843. end;
  844. { Target dirs }
  845. if not TargetStringEmpty(userini.targetdirs) then
  846. begin
  847. AddHead('Target Dirs');
  848. hs:=AddTargetDefines(userini.targetdirs,'OBJECTDIR');
  849. repeat
  850. i:=pos(' ',hs);
  851. if i=0 then
  852. i:=length(hs)+1;
  853. AddTargetDir(Copy(hs,1,i-1));
  854. system.delete(hs,1,i);
  855. until hs='';
  856. Add('');
  857. end;
  858. { insert users rules }
  859. if userini.rules.count>0 then
  860. begin
  861. AddSection(true,'userrules');
  862. AddStrings(userini.rules);
  863. end;
  864. end;
  865. { Write the Makefile and cleanup }
  866. Verbose('Writing '+fn);
  867. FixTab(mf);
  868. mf.SaveToFile(fn);
  869. mf.Destroy;
  870. ss.Destroy;
  871. WriteMakefile:=true;
  872. end;
  873. procedure UseMakefilefpc;
  874. var
  875. fn : string;
  876. begin
  877. if FileExists('Makefile.fpc') then
  878. fn:='Makefile.fpc'
  879. else
  880. fn:='makefile.fpc';
  881. { Open Makefile.fpc }
  882. if not ReadMakefilefpc(fn) then
  883. Error('Can''t read '+fn);
  884. { Write Makefile }
  885. if not WriteMakefile('Makefile') then
  886. Error('Can''t write Makefile');
  887. end;
  888. procedure UseParameters;
  889. var
  890. i : integer;
  891. fn : string;
  892. begin
  893. for i:=1 to ParamCount do
  894. begin
  895. fn:=ParamStr(i);
  896. { Open Makefile.fpc }
  897. if not ReadMakefilefpc(fn) then
  898. Error('Can''t read '+fn);
  899. { Write Makefile }
  900. if not WriteMakefile(ExtractFilePath(fn)+'Makefile') then
  901. Error('Can''t write '+ExtractFilePath(fn)+'Makefile');
  902. end;
  903. end;
  904. begin
  905. { Open userini.ini }
  906. fpcini:=ReadFpcMakeIni;
  907. if not assigned(fpcini) then
  908. Error('Can''t read fpcmake.ini');
  909. if ParamCount=0 then
  910. UseMakefilefpc
  911. else
  912. UseParameters;
  913. fpcini.destroy;
  914. end.
  915. {
  916. $Log$
  917. Revision 1.13 1999-12-21 16:06:47 peter
  918. * don't call dirobjects for zipisntall,info
  919. Revision 1.12 1999/12/19 15:15:04 peter
  920. * fpcmade.<TARGET> added
  921. * parameter support. So it can be using with "find -name 'Makefile.fpc'"
  922. Revision 1.11 1999/12/02 11:30:24 peter
  923. * better dup checking
  924. Revision 1.10 1999/11/26 00:20:15 peter
  925. * fpcmake updated
  926. Revision 1.9 1999/11/25 20:23:01 peter
  927. * package dependencies
  928. Revision 1.8 1999/11/24 23:53:00 peter
  929. * packages
  930. * lot of other changes
  931. Revision 1.7 1999/11/23 09:43:35 peter
  932. + internal .ini file
  933. + packages support
  934. * ppufiles,data2inc support
  935. Revision 1.6 1999/11/10 22:10:49 peter
  936. * fpcmake updated
  937. Revision 1.5 1999/11/09 14:38:32 peter
  938. * sections section to leave out whole info/tools
  939. Revision 1.4 1999/11/08 15:01:39 peter
  940. * fpcmake support
  941. Revision 1.3 1999/11/04 12:07:13 michael
  942. + Now envvar is used
  943. Revision 1.2 1999/11/03 23:39:53 peter
  944. * lot of updates
  945. Revision 1.1 1999/11/02 23:57:40 peter
  946. * initial version
  947. }