fpcmake.pp 34 KB

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