fpcmake.pp 26 KB

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