fpcmake.pp 30 KB

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