fpcmake.pp 32 KB

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