fpcmake.pp 15 KB

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