fpcmake.pp 14 KB

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