fpc/compiler/systems/t_aix.pas
2012-04-11 18:00:29 +00:00

345 lines
10 KiB
ObjectPascal

{
Copyright (c) 2011 by Jonas Maebe
This unit implements support import,export,link routines
for the AIX target
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit t_aix;
{$i fpcdefs.inc}
interface
uses
aasmdata,
symsym,symdef,ppu,
import,export,expunix,link;
type
timportlibaix=class(timportlib)
procedure generatelib;override;
end;
texportlibaix=class(texportlibunix)
procedure setfininame(list: TAsmList; const s: string); override;
end;
TLinkerAIX=class(texternallinker)
private
prtobj : string[80];
Function WriteResponseFile(isdll:boolean) : Boolean;
public
constructor Create;override;
procedure SetDefaultInfo;override;
function MakeExecutable:boolean;override;
function MakeSharedLibrary:boolean;override;
end;
implementation
uses
SysUtils,
cutils,cfileutl,cclasses,
verbose,systems,globtype,globals,
symconst,script,
fmodule,
aasmbase,aasmtai,aasmcpu,cpubase,
cgbase,cgobj,cgutils,ogbase,ncgutil,
comprsrc,
rescmn, i_aix
;
{*****************************************************************************
timportlibaix
*****************************************************************************}
procedure timportlibaix.generatelib;
var
i : longint;
ImportLibrary : TImportLibrary;
begin
for i:=0 to current_module.ImportLibraryList.Count-1 do
begin
ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
end;
end;
{*****************************************************************************
texportlibaix
*****************************************************************************}
procedure texportlibaix.setfininame(list: TAsmList; const s: string);
begin
inherited setfininame(list,s);
end;
{*****************************************************************************
TLinkerAIX
*****************************************************************************}
Constructor TLinkerAIX.Create;
begin
Inherited Create;
if not Dontlinkstdlibpath then
if not(cs_profile in current_settings.moduleswitches) then
LibrarySearchPath.AddPath(sysrootpath,'/usr/lib;/usr/X11R6/lib;/opt/freeware/lib',true)
else
LibrarySearchPath.AddPath(sysrootpath,'/usr/lib/profiled;/usr/X11R6/lib;/opt/freeware/lib',true)
end;
procedure TLinkerAIX.SetDefaultInfo;
const
{$ifdef powerpc}platform_select='-b32';{$endif}
{$ifdef POWERPC64} platform_select='-b64';{$endif}
begin
with Info do
begin
ExeCmd[1]:='ld '+platform_select+' $OPT $STRIP -L. -o $EXE $CATRES';
DllCmd[1]:='ld '+platform_select+' $OPT $INITFINI $STRIP -L. -o $EXE $CATRES';
end;
{$if defined(powerpc)}
if not(cs_profile in current_settings.moduleswitches) then
prtobj:=sysrootpath+'/lib/crt0.o'
else
prtobj:=sysrootpath+'/lib/gcrt0.o';
{$elseif defined(powerpc64)}
if not(cs_profile in current_settings.moduleswitches) then
prtobj:=sysrootpath+'/lib/crt0_64.o'
else
prtobj:=sysrootpath+'/lib/gcrt0_64.o';
{$else}
{$error unsupported AIX architecture}
{$endif}
end;
Function TLinkerAIX.WriteResponseFile(isdll:boolean) : Boolean;
Var
linkres : TLinkRes;
i : longint;
HPath : TCmdStrListItem;
s,s1 : TCmdStr;
begin
result:=False;
{ Open link.res file }
LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
with linkres do
begin
{ Write path to search libraries }
HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
while assigned(HPath) do
begin
Add('-L'+HPath.Str);
HPath:=TCmdStrListItem(HPath.Next);
end;
HPath:=TCmdStrListItem(LibrarySearchPath.First);
while assigned(HPath) do
begin
Add('-L'+HPath.Str);
HPath:=TCmdStrListItem(HPath.Next);
end;
{ add objectfiles, start with prt0 always }
AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
{ main objectfiles }
while not ObjectFiles.Empty do
begin
s:=ObjectFiles.GetFirst;
if s<>'' then
AddFileName(maybequoted(s));
end;
{ Write staticlibraries }
if not StaticLibFiles.Empty then
begin
While not StaticLibFiles.Empty do
begin
S:=StaticLibFiles.GetFirst;
AddFileName(maybequoted(s))
end;
end;
{ Write sharedlibraries like -l<lib> }
While not SharedLibFiles.Empty do
begin
S:=SharedLibFiles.GetFirst;
i:=Pos(target_info.sharedlibext,S);
if i>0 then
Delete(S,i,255);
Add('-l'+s);
end;
{ when we have -static for the linker the we also need libgcc }
if (cs_link_staticflag in current_settings.globalswitches) then
begin
Add('-lgcc');
if librarysearchpath.FindFile('libgcc_eh.a',false,s1) then
Add('-lgcc_eh');
end;
{ Write and Close response }
writetodisk;
Free;
end;
WriteResponseFile:=True;
end;
function TLinkerAIX.MakeExecutable:boolean;
var
linkscript: TAsmScript;
binstr,
cmdstr : TCmdStr;
success : boolean;
StripStr : string[40];
begin
if not(cs_link_nolink in current_settings.globalswitches) then
Message1(exec_i_linking,current_module.exefilename^);
{ Create some replacements }
StripStr:='';
if (cs_link_strip in current_settings.globalswitches) and
not(cs_link_separate_dbg_file in current_settings.globalswitches) then
StripStr:='-s';
if (cs_link_map in current_settings.globalswitches) then
StripStr:='-bmap:'+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
{ Write used files and libraries }
WriteResponseFile(false);
{ Call linker }
SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
binstr:=FindUtil(utilsprefix+BinStr);
Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
Replace(cmdstr,'$OPT',Info.ExtraOptions);
Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
Replace(cmdstr,'$STRIP',StripStr);
{ create dynamic symbol table? }
if HasExports then
cmdstr:=cmdstr+' -E';
{ custom sysroot? (for cross-compiling -> assume gnu ld) }
if sysrootpath<>'' then
cmdstr:=cmdstr+' --sysroot='+sysrootpath;
if not(cs_link_nolink in current_settings.globalswitches) and
not(tf_no_backquote_support in source_info.flags) then
begin
{ we have to use a script to use the IFS hack }
linkscript:=TAsmScriptUnix.create(outputexedir+'ppaslink');
linkscript.AddLinkCommand(binstr,CmdStr,'');
// if (extdbgbinstr<>'') then
// linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
linkscript.WriteToDisk;
BinStr:=linkscript.fn;
if not path_absolute(BinStr) then
BinStr:='./'+BinStr;
CmdStr:='';
end;
success:=DoExec(BinStr,cmdstr,true,true);
{ Remove ReponseFile }
if (success) and not(cs_link_nolink in current_settings.globalswitches) then
begin
DeleteFile(outputexedir+Info.ResName);
DeleteFile(outputexedir+'ppaslink.sh');
end;
MakeExecutable:=success; { otherwise a recursive call to link method }
end;
Function TLinkerAIX.MakeSharedLibrary:boolean;
var
exportedsyms: text;
InitFiniStr : string[80];
StripStr,
binstr,
cmdstr : TCmdStr;
success : boolean;
begin
MakeSharedLibrary:=false;
if not(cs_link_nolink in current_settings.globalswitches) then
Message1(exec_i_linking,current_module.sharedlibfilename^);
{ Write used files and libraries }
WriteResponseFile(true);
{ Create some replacements }
InitFiniStr:='-binitfini:'+exportlib.initname+':'+exportlib.fininame;
if cs_link_strip in current_settings.globalswitches then
StripStr:='-s'
else
StripStr:='';
{ Call linker }
SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
Replace(cmdstr,'$OPT',Info.ExtraOptions);
Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
Replace(cmdstr,'$INITFINI',InitFiniStr);
Replace(cmdstr,'$STRIP',StripStr);
success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
{ exported symbols }
if not texportlibunix(exportlib).exportedsymnames.empty then
begin
assign(exportedsyms,outputexedir+'linksyms.fpc');
rewrite(exportedsyms);
repeat
writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
until texportlibunix(exportlib).exportedsymnames.empty;
close(exportedsyms);
cmdstr:=cmdstr+' -bE:'+maybequoted(outputexedir)+'linksyms.fpc';
end;
{ Remove ReponseFile }
if (success) and not(cs_link_nolink in current_settings.globalswitches) then
begin
DeleteFile(outputexedir+Info.ResName);
DeleteFile(outputexedir+'linksyms.fpc');
end;
MakeSharedLibrary:=success; { otherwise a recursive call to link method }
end;
{*****************************************************************************
Initialize
*****************************************************************************}
initialization
{$ifdef powerpc}
RegisterExternalLinker(system_powerpc_aix_info,TLinkerAIX);
RegisterImport(system_powerpc_aix,timportlibaix);
RegisterExport(system_powerpc_aix,texportlibaix);
RegisterTarget(system_powerpc_aix_info);
{$endif powerpc}
{$ifdef powerpc64}
RegisterExternalLinker(system_powerpc64_aix_info,TLinkerAIX);
RegisterImport(system_powerpc64_aix,timportlibaix);
RegisterExport(system_powerpc64_aix,texportlibaix);
RegisterTarget(system_powerpc64_aix_info);
{$endif powerpc64}
RegisterRes(res_elf_info,TWinLikeResourceFile);
end.