fpcmake.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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. EnvVar='FPCMAKEINI'; { should be FPCMAKE in the future }
  24. TimeFormat='yyyy/mm/dd hh:nn';
  25. targets=4;
  26. targetstr : array[1..targets] of string=(
  27. 'linux','go32v2','win32','os2'
  28. );
  29. { Sections in Makefile.fpc }
  30. sec_install='install';
  31. sec_clean='clean';
  32. sec_dirs='dirs';
  33. sec_libs='libs';
  34. sec_targets='targets';
  35. sec_info='info';
  36. sec_defaults='defaults';
  37. sec_tools='tools';
  38. type
  39. TTargetsString=array[0..targets] of string;
  40. TFpcMake=record
  41. TargetLoaders,
  42. TargetUnits,
  43. TargetPrograms,
  44. InstallUnits,
  45. InstallFiles,
  46. CleanUnits,
  47. CleanFiles : TTargetsString;
  48. DefaultUnits : boolean;
  49. DefaultRule,
  50. DefaultTarget,
  51. DefaultCPU,
  52. DefaultOptions : string;
  53. DirFpc,
  54. DirUnit,
  55. DirLib,
  56. DirObj,
  57. DirTarget,
  58. DirUnitTarget,
  59. DirInc : string;
  60. LibGCC,
  61. LibOther : boolean;
  62. InfoCfg,
  63. InfoDirs,
  64. InfoTools,
  65. InfoInstall,
  66. InfoObjects,
  67. InfoFiles : boolean;
  68. ToolsSed,
  69. ToolsDiff,
  70. ToolsCmp,
  71. ToolsUpx,
  72. ToolsDate,
  73. ToolsZip : boolean;
  74. PreSettings,
  75. PostSettings,
  76. Rules : TStringList;
  77. end;
  78. var
  79. userini : TFpcMake;
  80. fpcini : TIniFile;
  81. {*****************************************************************************
  82. Helpers
  83. *****************************************************************************}
  84. procedure Verbose(s:string);
  85. begin
  86. writeln(s);
  87. end;
  88. procedure Error(s:string);
  89. begin
  90. Writeln(s);
  91. Halt(1);
  92. end;
  93. {*****************************************************************************
  94. Makefile.fpc reading
  95. *****************************************************************************}
  96. function ReadMakefilefpc:boolean;
  97. var
  98. fn : string;
  99. ini : TIniFile;
  100. procedure ReadTargetsString(var t:Ttargetsstring;const sec,name,def:string);
  101. var
  102. i : integer;
  103. begin
  104. t[0]:=ini.ReadString(sec,name,def);
  105. for i:=1 to targets do
  106. t[i]:=ini.ReadString(sec,name+'_'+targetstr[i],'');
  107. end;
  108. begin
  109. ReadMakefilefpc:=false;
  110. if FileExists('Makefile.fpc') then
  111. fn:='Makefile.fpc'
  112. else
  113. if FileExists('makefile.fpc') then
  114. fn:='makefile.fpc'
  115. else
  116. exit;
  117. Verbose('Reading '+fn);
  118. ini:=TIniFile.Create(fn);
  119. with userini,ini do
  120. begin
  121. { targets }
  122. ReadTargetsString(TargetLoaders,sec_targets,'loaders','');
  123. ReadTargetsString(TargetUnits,sec_targets,'units','');
  124. ReadTargetsString(TargetPrograms,sec_targets,'programs','');
  125. { clean }
  126. ReadTargetsString(CleanUnits,sec_clean,'units','');
  127. ReadTargetsString(CleanFiles,sec_clean,'files','');
  128. { install }
  129. ReadTargetsString(InstallUnits,sec_install,'units','');
  130. ReadTargetsString(InstallFiles,sec_install,'files','');
  131. { defaults }
  132. DefaultUnits:=ReadBool(sec_defaults,'defaultunits',false);
  133. DefaultRule:=ReadString(sec_defaults,'defaultrule','all');
  134. DefaultTarget:=ReadString(sec_defaults,'defaulttarget','');
  135. DefaultCPU:=ReadString(sec_defaults,'defaultcpu','');
  136. DefaultOptions:=ReadString(sec_defaults,'defaultoptions','');
  137. { dirs }
  138. DirFpc:=ReadString(sec_dirs,'fpcdir','');
  139. DirUnit:=ReadString(sec_dirs,'unitdir','');
  140. DirLib:=ReadString(sec_dirs,'libdir','');
  141. DirObj:=ReadString(sec_dirs,'objdir','');
  142. DirTarget:=ReadString(sec_dirs,'targetdir','');
  143. DirUnitTarget:=ReadString(sec_dirs,'unittargetdir','');
  144. DirInc:=ReadString(sec_dirs,'incdir','');
  145. { libs }
  146. LibGcc:=ReadBool(sec_libs,'libgcc',false);
  147. LibOther:=ReadBool(sec_libs,'libother',false);
  148. { tools }
  149. ToolsSed:=ReadBool(sec_tools,'toolsed',false);
  150. ToolsDiff:=ReadBool(sec_tools,'tooldiff',false);
  151. ToolsCmp:=ReadBool(sec_tools,'toolcmp',false);
  152. ToolsUpx:=ReadBool(sec_tools,'toolupx',true);
  153. ToolsDate:=ReadBool(sec_tools,'tooldate',true);
  154. ToolsZip:=ReadBool(sec_tools,'toolzip',true);
  155. { info }
  156. InfoCfg:=ReadBool(sec_info,'infoconfig',true);
  157. InfoDirs:=ReadBool(sec_info,'infodirs',false);
  158. InfoTools:=ReadBool(sec_info,'infotools',false);
  159. InfoInstall:=ReadBool(sec_info,'infoinstall',true);
  160. InfoObjects:=ReadBool(sec_info,'infoobjects',true);
  161. InfoFiles:=ReadBool(sec_info,'infofiles',false);
  162. { rules }
  163. PreSettings:=TStringList.Create;
  164. ReadSectionRaw('presettings',PreSettings);
  165. { rules }
  166. PostSettings:=TStringList.Create;
  167. ReadSectionRaw('postsettings',PostSettings);
  168. { rules }
  169. rules:=TStringList.Create;
  170. ReadSectionRaw('rules',rules);
  171. end;
  172. ini.Destroy;
  173. ReadMakefilefpc:=true;
  174. end;
  175. {*****************************************************************************
  176. userini.ini loading
  177. *****************************************************************************}
  178. function ReadFpcMakeIni:TIniFile;
  179. var
  180. fn : string;
  181. begin
  182. ReadFpcMakeIni:=nil;
  183. if FileExists('fpcmake.ini') then
  184. fn:='fpcmake.ini'
  185. else
  186. if (FileExists(GetEnv(envvar))) then
  187. fn:=GetEnv(envvar)
  188. else
  189. {$ifdef linux}
  190. if FileExists('/usr/lib/fpc/fpcmake.ini') then
  191. fn:='/usr/lib/fpc/fpcmake.ini'
  192. {$else}
  193. if FileExists(ChangeFileExt(paramstr(0),'.ini')) then
  194. fn:=ChangeFileExt(paramstr(0),'.ini')
  195. {$endif}
  196. else
  197. exit;
  198. Verbose('Opening '+fn);
  199. result:=TIniFile.Create(fn);
  200. end;
  201. {*****************************************************************************
  202. Makefile writing
  203. *****************************************************************************}
  204. function WriteMakefile:boolean;
  205. var
  206. mf : TStringList;
  207. ss : TStringList;
  208. procedure FixTab(sl:TStringList);
  209. var
  210. i,j,k : integer;
  211. s,s2 : string;
  212. begin
  213. i:=0;
  214. while (i<sl.Count) do
  215. begin
  216. if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
  217. begin
  218. s:=sl[i];
  219. k:=0;
  220. j:=0;
  221. repeat
  222. inc(j);
  223. case s[j] of
  224. ' ' :
  225. inc(k);
  226. #9 :
  227. k:=(k+7) and not(7);
  228. else
  229. break;
  230. end;
  231. until (j=length(s));
  232. if k>7 then
  233. begin
  234. s2:='';
  235. Delete(s,1,j-1);
  236. while (k>7) do
  237. begin
  238. s2:=s2+#9;
  239. dec(k,8);
  240. end;
  241. while (k>0) do
  242. begin
  243. s2:=s2+' ';
  244. dec(k);
  245. end;
  246. sl[i]:=s2+s;
  247. end;
  248. end;
  249. inc(i);
  250. end;
  251. end;
  252. procedure AddSection(b:boolean;s:string);
  253. begin
  254. if b then
  255. begin
  256. ss.Clear;
  257. fpcini.ReadSectionRaw(s,ss);
  258. mf.AddStrings(ss);
  259. mf.Add('');
  260. end;
  261. end;
  262. procedure AddRule(s:string);
  263. var
  264. i : integer;
  265. begin
  266. i:=0;
  267. while (i<userini.rules.Count) do
  268. begin
  269. if (userini.rules[i]<>'') and
  270. (userini.rules[i][1]=s[1]) and
  271. (Copy(userini.rules[i],1,length(s))=s) then
  272. exit;
  273. inc(i);
  274. end;
  275. mf.Add(s+': fpc_'+s);
  276. mf.Add('');
  277. end;
  278. procedure AddTargets(const pre:string;var t:TTargetsString);
  279. var
  280. i : integer;
  281. begin
  282. if t[0]<>'' then
  283. mf.Add(pre+'='+t[0]);
  284. for i:=1to targets do
  285. if (t[i]<>'') then
  286. begin
  287. mf.Add('ifeq ($(OS_TARGET),'+targetstr[i]+')');
  288. if t[i]<>'' then
  289. mf.Add(pre+'+='+t[i]);
  290. mf.Add('endif');
  291. end;
  292. end;
  293. procedure AddHead(const s:string);
  294. begin
  295. mf.Add('');
  296. mf.Add('# '+s);
  297. mf.Add('');
  298. end;
  299. var
  300. hs : string;
  301. begin
  302. { Open the Makefile }
  303. Verbose('Creating Makefile');
  304. mf:=TStringList.Create;
  305. { Buffer for reading and writing the sections }
  306. ss:=TStringList.Create;
  307. with mf do
  308. begin
  309. { write header & autodetection }
  310. Add('#');
  311. Add('# Makefile generated from Makefile.fpc on '+FormatDateTime(TimeFormat,Now));
  312. Add('#');
  313. Add('');
  314. Add('defaultrule: Makefile '+userini.defaultrule);
  315. Add('');
  316. AddSection(true,'makefilerule');
  317. AddSection(true,'osdetect');
  318. { set the forced target os/cpu }
  319. if (userini.defaulttarget<>'') or (userini.defaultcpu<>'') then
  320. begin
  321. AddSection(true,'defaulttarget');
  322. if userini.defaulttarget<>'' then
  323. Add('override OS_TARGET:='+userini.defaulttarget);
  324. if userini.defaultcpu<>'' then
  325. Add('override CPU_TARGET:='+userini.defaultcpu);
  326. Add('');
  327. end;
  328. { fpc detection }
  329. AddSection(true,'fpcdetect');
  330. { write the default & user settings }
  331. AddSection(true,'defaultsettings');
  332. AddSection(true,'usersettings');
  333. { Pre Settings }
  334. if userini.PreSettings.count>0 then
  335. begin
  336. AddHead('Pre Settings');
  337. AddStrings(userini.PreSettings);
  338. end;
  339. { Targets }
  340. AddHead('Targets');
  341. AddTargets('LOADEROBJECTS',userini.targetloaders);
  342. AddTargets('UNITOBJECTS',userini.targetunits);
  343. AddTargets('EXEOBJECTS',userini.targetprograms);
  344. { Clean }
  345. AddHead('Clean');
  346. AddTargets('EXTRACLEANUNITS',userini.cleanunits);
  347. AddTargets('EXTRACLEANFILES',userini.cleanfiles);
  348. { Install }
  349. AddHead('Install');
  350. AddTargets('EXTRAINSTALLUNITS',userini.installunits);
  351. AddTargets('EXTRAINSTALLFILES',userini.installfiles);
  352. { Defaults }
  353. AddHead('Defaults');
  354. if userini.defaultunits then
  355. Add('DEFAULTUNITS=1');
  356. if userini.defaultoptions<>'' then
  357. Add('override NEEDOPT='+userini.defaultoptions);
  358. { Dirs }
  359. AddHead('Directories');
  360. if userini.dirfpc<>'' then
  361. begin
  362. { this dir can be set in the environment, it's more a default }
  363. Add('ifndef FPCDIR');
  364. Add('FPCDIR='+userini.dirfpc);
  365. Add('endif');
  366. end;
  367. if userini.dirunit<>'' then
  368. Add('override NEEDUNITDIR='+userini.dirunit);
  369. if userini.dirlib<>'' then
  370. Add('override NEEDLIBDIR='+userini.dirlib);
  371. if userini.dirobj<>'' then
  372. Add('override NEEDOBJDIR='+userini.dirobj);
  373. if userini.dirinc<>'' then
  374. Add('override NEEDINCDIR='+userini.dirinc);
  375. if userini.dirtarget<>'' then
  376. begin
  377. Add('ifndef TARGETDIR');
  378. Add('TARGETDIR='+userini.dirtarget);
  379. Add('endif');
  380. end;
  381. if userini.dirunittarget<>'' then
  382. begin
  383. Add('ifndef UNITTARGETDIR');
  384. Add('UNITTARGETDIR='+userini.dirunittarget);
  385. Add('endif');
  386. end;
  387. { Libs }
  388. AddHead('Libraries');
  389. if userini.libgcc then
  390. Add('override NEEDGCCLIB=1');
  391. if userini.libother then
  392. Add('override NEEDOTHERLIB=1');
  393. { Info }
  394. AddHead('Info');
  395. hs:='';
  396. if userini.infocfg then
  397. hs:=hs+'fpc_infocfg ';
  398. if userini.infodirs then
  399. hs:=hs+'fpc_infodirs ';
  400. if userini.infotools then
  401. hs:=hs+'fpc_infotools ';
  402. if userini.infoobjects then
  403. hs:=hs+'fpc_infoobjects ';
  404. if userini.infoinstall then
  405. hs:=hs+'fpc_infoinstall ';
  406. if userini.infofiles then
  407. hs:=hs+'fpc_infofiles ';
  408. Add('FPCINFO='+hs);
  409. { Post Settings }
  410. if userini.PostSettings.count>0 then
  411. begin
  412. AddHead('Post Settings');
  413. AddStrings(userini.PostSettings);
  414. end;
  415. { commandline }
  416. Add('');
  417. AddSection(true,'command_begin');
  418. AddSection(true,'command_rtl');
  419. AddSection(true,'command_needopt');
  420. AddSection((userini.dirfpc<>''),'command_fpcdir');
  421. AddSection((userini.dirunit<>''),'command_needunit');
  422. AddSection((userini.dirlib<>''),'command_needlib');
  423. AddSection((userini.dirobj<>''),'command_needobj');
  424. AddSection((userini.dirinc<>''),'command_needinc');
  425. AddSection(userini.libgcc,'command_gcclib');
  426. AddSection(userini.libother,'command_otherlib');
  427. AddSection((userini.dirinc<>''),'command_inc');
  428. AddSection((userini.dirtarget<>''),'command_target');
  429. AddSection((userini.dirunittarget<>''),'command_unittarget');
  430. AddSection(true,'command_smartlink');
  431. AddSection(true,'command_end');
  432. { write tools }
  433. AddSection(true,'shelltools');
  434. AddSection(true,'tool_default');
  435. AddSection(userini.toolsupx,'tool_upx');
  436. AddSection(userini.toolssed,'tool_sed');
  437. AddSection(userini.toolsdate,'tool_date');
  438. AddSection(userini.toolszip,'tool_zip');
  439. AddSection(userini.toolscmp,'tool_cmp');
  440. AddSection(userini.toolsdiff,'tool_diff');
  441. { write dirs }
  442. AddSection(true,'dir_default');
  443. AddSection(true,'dir_rtl');
  444. AddSection(true,'dir_units');
  445. AddSection(true,'dir_gcclib');
  446. AddSection(true,'dir_otherlib');
  447. AddSection(true,'dir_install');
  448. { extensions }
  449. AddSection(true,'extensions');
  450. { add default rules }
  451. AddSection(true,'defaultrules');
  452. AddRule('all');
  453. AddRule('staticlib');
  454. AddRule('sharedlib');
  455. AddRule('showinstall');
  456. AddRule('install');
  457. AddRule('staticinstall');
  458. AddRule('sharedinstall');
  459. AddRule('libinstall');
  460. AddRule('zipinstall');
  461. AddRule('zipinstalladd');
  462. AddRule('clean');
  463. AddRule('clean_all');
  464. AddRule('depend');
  465. AddRule('info');
  466. { default fpc_ rules }
  467. AddSection(true,'compilerules');
  468. AddSection(true,'libraryrules');
  469. AddSection(true,'installrules');
  470. AddSection(true,'zipinstallrules');
  471. AddSection(true,'cleanrules');
  472. AddSection(true,'dependrules');
  473. AddSection(true,'inforules');
  474. AddSection(userini.infocfg,'info_cfg');
  475. AddSection(userini.infodirs,'info_dirs');
  476. AddSection(userini.infotools,'info_tools');
  477. AddSection(userini.infoobjects,'info_objects');
  478. AddSection(userini.infoinstall,'info_install');
  479. AddSection(userini.infofiles,'info_files');
  480. { insert users rules }
  481. if userini.rules.count>0 then
  482. begin
  483. AddSection(true,'userrules');
  484. AddStrings(userini.rules);
  485. end;
  486. end;
  487. { Write the Makefile and cleanup }
  488. Verbose('Writing Makefile');
  489. FixTab(mf);
  490. mf.SaveToFile('Makefile');
  491. mf.Destroy;
  492. ss.Destroy;
  493. WriteMakefile:=true;
  494. end;
  495. begin
  496. { Open userini.ini }
  497. fpcini:=ReadFpcMakeIni;
  498. if not assigned(fpcini) then
  499. Error('Can''t read fpcmake.ini');
  500. { Open Makefile.fpc }
  501. if not ReadMakefilefpc then
  502. Error('Can''t read Makefile.fpc');
  503. { Write Makefile }
  504. if not WriteMakefile then
  505. Error('Can''t write Makefile');
  506. fpcini.destroy;
  507. end.
  508. {
  509. $Log$
  510. Revision 1.4 1999-11-08 15:01:39 peter
  511. * fpcmake support
  512. Revision 1.3 1999/11/04 12:07:13 michael
  513. + Now envvar is used
  514. Revision 1.2 1999/11/03 23:39:53 peter
  515. * lot of updates
  516. Revision 1.1 1999/11/02 23:57:40 peter
  517. * initial version
  518. }