mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-26 10:59:19 +02:00
602 lines
15 KiB
ObjectPascal
602 lines
15 KiB
ObjectPascal
{
|
|
$Id$
|
|
Copyright (c) 1999 by Peter Vreman
|
|
|
|
Convert Makefile.fpc to Makefile
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
{$ifdef fpc}{$mode objfpc}{$endif}
|
|
{$H+}
|
|
program fpcmake;
|
|
uses
|
|
{$ifdef go32v2}
|
|
dpmiexcp,
|
|
{$endif}
|
|
dos,
|
|
sysutils,classes,inifiles;
|
|
|
|
const
|
|
Version='v0.99.13';
|
|
Title='fpcmake '+Version;
|
|
|
|
EnvVar='FPCMAKEINI'; { should be FPCMAKE in the future }
|
|
TimeFormat='yyyy/mm/dd hh:nn';
|
|
|
|
targets=4;
|
|
targetstr : array[1..targets] of string=(
|
|
'linux','go32v2','win32','os2'
|
|
);
|
|
|
|
{ Sections in Makefile.fpc }
|
|
sec_sections='sections';
|
|
sec_install='install';
|
|
sec_clean='clean';
|
|
sec_dirs='dirs';
|
|
sec_libs='libs';
|
|
sec_targets='targets';
|
|
sec_info='info';
|
|
sec_defaults='defaults';
|
|
sec_tools='tools';
|
|
|
|
type
|
|
TTargetsString=array[0..targets] of string;
|
|
TFpcMake=record
|
|
TargetLoaders,
|
|
TargetUnits,
|
|
TargetPrograms,
|
|
InstallUnits,
|
|
InstallFiles,
|
|
CleanUnits,
|
|
CleanFiles : TTargetsString;
|
|
DefaultUnits : boolean;
|
|
DefaultRule,
|
|
DefaultTarget,
|
|
DefaultCPU,
|
|
DefaultOptions : string;
|
|
DirFpc,
|
|
DirUnit,
|
|
DirLib,
|
|
DirObj,
|
|
DirTarget,
|
|
DirUnitTarget,
|
|
DirInc : string;
|
|
LibGCC,
|
|
LibOther : boolean;
|
|
InfoCfg,
|
|
InfoDirs,
|
|
InfoTools,
|
|
InfoInstall,
|
|
InfoObjects,
|
|
InfoFiles : boolean;
|
|
SectionTools,
|
|
SectionInfo : boolean;
|
|
ToolsSed,
|
|
ToolsDiff,
|
|
ToolsCmp,
|
|
ToolsUpx,
|
|
ToolsDate,
|
|
ToolsZip : boolean;
|
|
PreSettings,
|
|
PostSettings,
|
|
Rules : TStringList;
|
|
end;
|
|
|
|
var
|
|
userini : TFpcMake;
|
|
fpcini : TIniFile;
|
|
|
|
{*****************************************************************************
|
|
Helpers
|
|
*****************************************************************************}
|
|
|
|
procedure Verbose(s:string);
|
|
begin
|
|
writeln(s);
|
|
end;
|
|
|
|
|
|
procedure Error(s:string);
|
|
begin
|
|
Writeln(s);
|
|
Halt(1);
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
Makefile.fpc reading
|
|
*****************************************************************************}
|
|
|
|
function ReadMakefilefpc:boolean;
|
|
var
|
|
fn : string;
|
|
ini : TIniFile;
|
|
|
|
procedure ReadTargetsString(var t:Ttargetsstring;const sec,name,def:string);
|
|
var
|
|
i : integer;
|
|
begin
|
|
t[0]:=ini.ReadString(sec,name,def);
|
|
for i:=1 to targets do
|
|
t[i]:=ini.ReadString(sec,name+'_'+targetstr[i],'');
|
|
end;
|
|
|
|
begin
|
|
ReadMakefilefpc:=false;
|
|
if FileExists('Makefile.fpc') then
|
|
fn:='Makefile.fpc'
|
|
else
|
|
if FileExists('makefile.fpc') then
|
|
fn:='makefile.fpc'
|
|
else
|
|
exit;
|
|
|
|
Verbose('Reading '+fn);
|
|
ini:=TIniFile.Create(fn);
|
|
|
|
with userini,ini do
|
|
begin
|
|
{ targets }
|
|
ReadTargetsString(TargetLoaders,sec_targets,'loaders','');
|
|
ReadTargetsString(TargetUnits,sec_targets,'units','');
|
|
ReadTargetsString(TargetPrograms,sec_targets,'programs','');
|
|
{ clean }
|
|
ReadTargetsString(CleanUnits,sec_clean,'units','');
|
|
ReadTargetsString(CleanFiles,sec_clean,'files','');
|
|
{ install }
|
|
ReadTargetsString(InstallUnits,sec_install,'units','');
|
|
ReadTargetsString(InstallFiles,sec_install,'files','');
|
|
{ defaults }
|
|
DefaultUnits:=ReadBool(sec_defaults,'defaultunits',false);
|
|
DefaultRule:=ReadString(sec_defaults,'defaultrule','all');
|
|
DefaultTarget:=ReadString(sec_defaults,'defaulttarget','');
|
|
DefaultCPU:=ReadString(sec_defaults,'defaultcpu','');
|
|
DefaultOptions:=ReadString(sec_defaults,'defaultoptions','');
|
|
{ dirs }
|
|
DirFpc:=ReadString(sec_dirs,'fpcdir','');
|
|
DirUnit:=ReadString(sec_dirs,'unitdir','');
|
|
DirLib:=ReadString(sec_dirs,'libdir','');
|
|
DirObj:=ReadString(sec_dirs,'objdir','');
|
|
DirTarget:=ReadString(sec_dirs,'targetdir','');
|
|
DirUnitTarget:=ReadString(sec_dirs,'unittargetdir','');
|
|
DirInc:=ReadString(sec_dirs,'incdir','');
|
|
{ libs }
|
|
LibGcc:=ReadBool(sec_libs,'libgcc',false);
|
|
LibOther:=ReadBool(sec_libs,'libother',false);
|
|
{ tools }
|
|
ToolsSed:=ReadBool(sec_tools,'toolsed',false);
|
|
ToolsDiff:=ReadBool(sec_tools,'tooldiff',false);
|
|
ToolsCmp:=ReadBool(sec_tools,'toolcmp',false);
|
|
ToolsUpx:=ReadBool(sec_tools,'toolupx',true);
|
|
ToolsDate:=ReadBool(sec_tools,'tooldate',true);
|
|
ToolsZip:=ReadBool(sec_tools,'toolzip',true);
|
|
{ sections }
|
|
SectionInfo:=ReadBool(sec_sections,'info',true);
|
|
SectionTools:=ReadBool(sec_sections,'tools',true);
|
|
{ info }
|
|
InfoCfg:=ReadBool(sec_info,'infoconfig',true);
|
|
InfoDirs:=ReadBool(sec_info,'infodirs',false);
|
|
InfoTools:=ReadBool(sec_info,'infotools',false);
|
|
InfoInstall:=ReadBool(sec_info,'infoinstall',true);
|
|
InfoObjects:=ReadBool(sec_info,'infoobjects',true);
|
|
InfoFiles:=ReadBool(sec_info,'infofiles',false);
|
|
{ rules }
|
|
PreSettings:=TStringList.Create;
|
|
ReadSectionRaw('presettings',PreSettings);
|
|
{ rules }
|
|
PostSettings:=TStringList.Create;
|
|
ReadSectionRaw('postsettings',PostSettings);
|
|
{ rules }
|
|
rules:=TStringList.Create;
|
|
ReadSectionRaw('rules',rules);
|
|
end;
|
|
|
|
ini.Destroy;
|
|
ReadMakefilefpc:=true;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
userini.ini loading
|
|
*****************************************************************************}
|
|
|
|
function ReadFpcMakeIni:TIniFile;
|
|
var
|
|
fn : string;
|
|
begin
|
|
ReadFpcMakeIni:=nil;
|
|
if FileExists('fpcmake.ini') then
|
|
fn:='fpcmake.ini'
|
|
else
|
|
if (FileExists(GetEnv(envvar))) then
|
|
fn:=GetEnv(envvar)
|
|
else
|
|
{$ifdef linux}
|
|
if FileExists('/usr/lib/fpc/fpcmake.ini') then
|
|
fn:='/usr/lib/fpc/fpcmake.ini'
|
|
{$else}
|
|
if FileExists(ChangeFileExt(paramstr(0),'.ini')) then
|
|
fn:=ChangeFileExt(paramstr(0),'.ini')
|
|
{$endif}
|
|
else
|
|
exit;
|
|
|
|
Verbose('Opening '+fn);
|
|
result:=TIniFile.Create(fn);
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
Makefile writing
|
|
*****************************************************************************}
|
|
|
|
function WriteMakefile:boolean;
|
|
var
|
|
mf : TStringList;
|
|
ss : TStringList;
|
|
|
|
procedure FixTab(sl:TStringList);
|
|
var
|
|
i,j,k : integer;
|
|
s,s2 : string;
|
|
begin
|
|
i:=0;
|
|
while (i<sl.Count) do
|
|
begin
|
|
if (sl[i]<>'') and (sl[i][1] in [' ',#9]) then
|
|
begin
|
|
s:=sl[i];
|
|
k:=0;
|
|
j:=0;
|
|
repeat
|
|
inc(j);
|
|
case s[j] of
|
|
' ' :
|
|
inc(k);
|
|
#9 :
|
|
k:=(k+7) and not(7);
|
|
else
|
|
break;
|
|
end;
|
|
until (j=length(s));
|
|
if k>7 then
|
|
begin
|
|
s2:='';
|
|
Delete(s,1,j-1);
|
|
while (k>7) do
|
|
begin
|
|
s2:=s2+#9;
|
|
dec(k,8);
|
|
end;
|
|
while (k>0) do
|
|
begin
|
|
s2:=s2+' ';
|
|
dec(k);
|
|
end;
|
|
sl[i]:=s2+s;
|
|
end;
|
|
end;
|
|
inc(i);
|
|
end;
|
|
end;
|
|
|
|
procedure AddSection(b:boolean;s:string);
|
|
begin
|
|
if b then
|
|
begin
|
|
ss.Clear;
|
|
fpcini.ReadSectionRaw(s,ss);
|
|
mf.AddStrings(ss);
|
|
mf.Add('');
|
|
end;
|
|
end;
|
|
|
|
procedure AddRule(s:string);
|
|
var
|
|
i : integer;
|
|
begin
|
|
i:=0;
|
|
while (i<userini.rules.Count) do
|
|
begin
|
|
if (userini.rules[i]<>'') and
|
|
(userini.rules[i][1]=s[1]) and
|
|
(Copy(userini.rules[i],1,length(s))=s) then
|
|
exit;
|
|
inc(i);
|
|
end;
|
|
mf.Add(s+': fpc_'+s);
|
|
mf.Add('');
|
|
end;
|
|
|
|
procedure AddTargets(const pre:string;var t:TTargetsString);
|
|
var
|
|
i : integer;
|
|
begin
|
|
if t[0]<>'' then
|
|
mf.Add(pre+'='+t[0]);
|
|
for i:=1to targets do
|
|
if (t[i]<>'') then
|
|
begin
|
|
mf.Add('ifeq ($(OS_TARGET),'+targetstr[i]+')');
|
|
if t[i]<>'' then
|
|
mf.Add(pre+'+='+t[i]);
|
|
mf.Add('endif');
|
|
end;
|
|
end;
|
|
|
|
procedure AddHead(const s:string);
|
|
begin
|
|
mf.Add('');
|
|
mf.Add('# '+s);
|
|
mf.Add('');
|
|
end;
|
|
|
|
var
|
|
hs : string;
|
|
begin
|
|
{ Open the Makefile }
|
|
Verbose('Creating Makefile');
|
|
mf:=TStringList.Create;
|
|
{ Buffer for reading and writing the sections }
|
|
ss:=TStringList.Create;
|
|
|
|
with mf do
|
|
begin
|
|
{ write header & autodetection }
|
|
Add('#');
|
|
Add('# Makefile generated from Makefile.fpc on '+FormatDateTime(TimeFormat,Now));
|
|
Add('#');
|
|
Add('');
|
|
Add('defaultrule: Makefile '+userini.defaultrule);
|
|
Add('');
|
|
AddSection(true,'makefilerule');
|
|
AddSection(true,'osdetect');
|
|
|
|
{ set the forced target os/cpu }
|
|
if (userini.defaulttarget<>'') or (userini.defaultcpu<>'') then
|
|
begin
|
|
AddSection(true,'defaulttarget');
|
|
if userini.defaulttarget<>'' then
|
|
Add('override OS_TARGET:='+userini.defaulttarget);
|
|
if userini.defaultcpu<>'' then
|
|
Add('override CPU_TARGET:='+userini.defaultcpu);
|
|
Add('');
|
|
end;
|
|
|
|
{ fpc detection }
|
|
AddSection(true,'fpcdetect');
|
|
|
|
{ write the default & user settings }
|
|
AddSection(true,'defaultsettings');
|
|
AddSection(true,'usersettings');
|
|
|
|
{ Pre Settings }
|
|
if userini.PreSettings.count>0 then
|
|
begin
|
|
AddHead('Pre Settings');
|
|
AddStrings(userini.PreSettings);
|
|
end;
|
|
|
|
{ Targets }
|
|
AddHead('Targets');
|
|
AddTargets('LOADEROBJECTS',userini.targetloaders);
|
|
AddTargets('UNITOBJECTS',userini.targetunits);
|
|
AddTargets('EXEOBJECTS',userini.targetprograms);
|
|
|
|
{ Clean }
|
|
AddHead('Clean');
|
|
AddTargets('EXTRACLEANUNITS',userini.cleanunits);
|
|
AddTargets('EXTRACLEANFILES',userini.cleanfiles);
|
|
|
|
{ Install }
|
|
AddHead('Install');
|
|
AddTargets('EXTRAINSTALLUNITS',userini.installunits);
|
|
AddTargets('EXTRAINSTALLFILES',userini.installfiles);
|
|
|
|
{ Defaults }
|
|
AddHead('Defaults');
|
|
if userini.defaultunits then
|
|
Add('DEFAULTUNITS=1');
|
|
if userini.defaultoptions<>'' then
|
|
Add('override NEEDOPT='+userini.defaultoptions);
|
|
|
|
{ Dirs }
|
|
AddHead('Directories');
|
|
if userini.dirfpc<>'' then
|
|
begin
|
|
{ this dir can be set in the environment, it's more a default }
|
|
Add('ifndef FPCDIR');
|
|
Add('FPCDIR='+userini.dirfpc);
|
|
Add('endif');
|
|
end;
|
|
if userini.dirunit<>'' then
|
|
Add('override NEEDUNITDIR='+userini.dirunit);
|
|
if userini.dirlib<>'' then
|
|
Add('override NEEDLIBDIR='+userini.dirlib);
|
|
if userini.dirobj<>'' then
|
|
Add('override NEEDOBJDIR='+userini.dirobj);
|
|
if userini.dirinc<>'' then
|
|
Add('override NEEDINCDIR='+userini.dirinc);
|
|
if userini.dirtarget<>'' then
|
|
begin
|
|
Add('ifndef TARGETDIR');
|
|
Add('TARGETDIR='+userini.dirtarget);
|
|
Add('endif');
|
|
end;
|
|
if userini.dirunittarget<>'' then
|
|
begin
|
|
Add('ifndef UNITTARGETDIR');
|
|
Add('UNITTARGETDIR='+userini.dirunittarget);
|
|
Add('endif');
|
|
end;
|
|
|
|
{ Libs }
|
|
AddHead('Libraries');
|
|
if userini.libgcc then
|
|
Add('override NEEDGCCLIB=1');
|
|
if userini.libother then
|
|
Add('override NEEDOTHERLIB=1');
|
|
|
|
{ Info }
|
|
if userini.SectionInfo then
|
|
begin
|
|
AddHead('Info');
|
|
hs:='';
|
|
if userini.infocfg then
|
|
hs:=hs+'fpc_infocfg ';
|
|
if userini.infodirs then
|
|
hs:=hs+'fpc_infodirs ';
|
|
if userini.infotools then
|
|
hs:=hs+'fpc_infotools ';
|
|
if userini.infoobjects then
|
|
hs:=hs+'fpc_infoobjects ';
|
|
if userini.infoinstall then
|
|
hs:=hs+'fpc_infoinstall ';
|
|
if userini.infofiles then
|
|
hs:=hs+'fpc_infofiles ';
|
|
Add('FPCINFO='+hs);
|
|
end;
|
|
|
|
{ Post Settings }
|
|
if userini.PostSettings.count>0 then
|
|
begin
|
|
AddHead('Post Settings');
|
|
AddStrings(userini.PostSettings);
|
|
end;
|
|
|
|
{ commandline }
|
|
Add('');
|
|
AddSection(true,'command_begin');
|
|
AddSection(true,'command_rtl');
|
|
AddSection(true,'command_needopt');
|
|
AddSection((userini.dirfpc<>''),'command_fpcdir');
|
|
AddSection((userini.dirunit<>''),'command_needunit');
|
|
AddSection((userini.dirlib<>''),'command_needlib');
|
|
AddSection((userini.dirobj<>''),'command_needobj');
|
|
AddSection((userini.dirinc<>''),'command_needinc');
|
|
AddSection(userini.libgcc,'command_gcclib');
|
|
AddSection(userini.libother,'command_otherlib');
|
|
AddSection((userini.dirinc<>''),'command_inc');
|
|
AddSection((userini.dirtarget<>''),'command_target');
|
|
AddSection((userini.dirunittarget<>''),'command_unittarget');
|
|
AddSection(true,'command_smartlink');
|
|
AddSection(true,'command_end');
|
|
|
|
{ write tools }
|
|
if userini.sectiontools then
|
|
begin
|
|
AddSection(true,'shelltools');
|
|
AddSection(true,'tool_default');
|
|
AddSection(userini.toolsupx,'tool_upx');
|
|
AddSection(userini.toolssed,'tool_sed');
|
|
AddSection(userini.toolsdate,'tool_date');
|
|
AddSection(userini.toolszip,'tool_zip');
|
|
AddSection(userini.toolscmp,'tool_cmp');
|
|
AddSection(userini.toolsdiff,'tool_diff');
|
|
end;
|
|
|
|
{ write dirs }
|
|
AddSection(true,'dir_default');
|
|
AddSection(true,'dir_rtl');
|
|
AddSection(true,'dir_units');
|
|
AddSection(true,'dir_gcclib');
|
|
AddSection(true,'dir_otherlib');
|
|
AddSection(true,'dir_install');
|
|
|
|
{ extensions }
|
|
AddSection(true,'extensions');
|
|
|
|
{ add default rules }
|
|
AddSection(true,'defaultrules');
|
|
AddRule('all');
|
|
AddRule('staticlib');
|
|
AddRule('sharedlib');
|
|
AddRule('showinstall');
|
|
AddRule('install');
|
|
AddRule('staticinstall');
|
|
AddRule('sharedinstall');
|
|
AddRule('libinstall');
|
|
AddRule('zipinstall');
|
|
AddRule('zipinstalladd');
|
|
AddRule('clean');
|
|
AddRule('clean_all');
|
|
AddRule('depend');
|
|
AddRule('info');
|
|
|
|
{ default fpc_ rules }
|
|
AddSection(true,'compilerules');
|
|
AddSection(true,'libraryrules');
|
|
AddSection(true,'installrules');
|
|
AddSection(true,'zipinstallrules');
|
|
AddSection(true,'cleanrules');
|
|
AddSection(true,'dependrules');
|
|
if userini.SectionInfo then
|
|
begin
|
|
AddSection(true,'inforules');
|
|
AddSection(userini.infocfg,'info_cfg');
|
|
AddSection(userini.infodirs,'info_dirs');
|
|
AddSection(userini.infotools,'info_tools');
|
|
AddSection(userini.infoobjects,'info_objects');
|
|
AddSection(userini.infoinstall,'info_install');
|
|
AddSection(userini.infofiles,'info_files');
|
|
end;
|
|
|
|
{ insert users rules }
|
|
if userini.rules.count>0 then
|
|
begin
|
|
AddSection(true,'userrules');
|
|
AddStrings(userini.rules);
|
|
end;
|
|
end;
|
|
|
|
{ Write the Makefile and cleanup }
|
|
Verbose('Writing Makefile');
|
|
FixTab(mf);
|
|
mf.SaveToFile('Makefile');
|
|
mf.Destroy;
|
|
ss.Destroy;
|
|
WriteMakefile:=true;
|
|
end;
|
|
|
|
|
|
begin
|
|
{ Open userini.ini }
|
|
fpcini:=ReadFpcMakeIni;
|
|
if not assigned(fpcini) then
|
|
Error('Can''t read fpcmake.ini');
|
|
|
|
{ Open Makefile.fpc }
|
|
if not ReadMakefilefpc then
|
|
Error('Can''t read Makefile.fpc');
|
|
|
|
{ Write Makefile }
|
|
if not WriteMakefile then
|
|
Error('Can''t write Makefile');
|
|
|
|
fpcini.destroy;
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.5 1999-11-09 14:38:32 peter
|
|
* sections section to leave out whole info/tools
|
|
|
|
Revision 1.4 1999/11/08 15:01:39 peter
|
|
* fpcmake support
|
|
|
|
Revision 1.3 1999/11/04 12:07:13 michael
|
|
+ Now envvar is used
|
|
|
|
Revision 1.2 1999/11/03 23:39:53 peter
|
|
* lot of updates
|
|
|
|
Revision 1.1 1999/11/02 23:57:40 peter
|
|
* initial version
|
|
|
|
}
|