fpcmake.pp 30 KB

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