fpcmake.pp 27 KB

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