fpcmake.pp 33 KB

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