fpcmake.pp 32 KB

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