fpcmake.pp 30 KB

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