Переглянути джерело

atari: added an external linker implementation, supporting GNU LD and VLink in theory. however the GNU LD version I have segfaults when I try to link the executable...

git-svn-id: trunk@34602 -
Károly Balogh 8 роки тому
батько
коміт
8d56d60d78
1 змінених файлів з 218 додано та 5 видалено
  1. 218 5
      compiler/systems/t_atari.pas

+ 218 - 5
compiler/systems/t_atari.pas

@@ -1,8 +1,8 @@
 {
-    Copyright (c) 2001-2002 by Peter Vreman
+    Copyright (c) 2016 by Free Pascal Development Team
 
-    This unit implements support import,export,link routines
-    for the (i386) Amiga target
+    This unit implements support import, export, link routines
+    for the m68k Atari 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
@@ -26,18 +26,231 @@ unit t_atari;
 
 interface
 
+    uses
+      rescmn, comprsrc, link;
+
+type
+  PLinkerAtari = ^TLinkerAtari;
+  TLinkerAtari = class(texternallinker)
+    private
+      UseVLink: boolean;
+      function WriteResponseFile(isdll: boolean): boolean;
+      procedure SetAtariInfo;
+      function MakeAtariExe: boolean;
+    public
+      constructor Create; override;
+      procedure SetDefaultInfo; override;
+      function  MakeExecutable: boolean; override;
+  end;
+
 
 implementation
 
     uses
-       link,
-       cutils,cclasses,
+       sysutils,cutils,cfileutl,cclasses,
        globtype,globals,systems,verbose,script,fmodule,i_atari;
 
+
+constructor TLinkerAtari.Create;
+begin
+  UseVLink:=(cs_link_vlink in current_settings.globalswitches);
+
+  Inherited Create;
+  { allow duplicated libs (PM) }
+  SharedLibFiles.doubles:=true;
+  StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerAtari.SetAtariInfo;
+begin
+  with Info do
+   begin
+    if not UseVLink then
+     begin
+      ExeCmd[1]:='ld $DYNLINK $OPT -d -n -o $EXE $RES';
+     end
+    else
+     begin
+      ExeCmd[1]:='vlink -b ataritos $OPT $STRIP -o $EXE -T $RES';
+     end;
+   end;
+end;
+
+
+procedure TLinkerAtari.SetDefaultInfo;
+begin
+  case (target_info.system) of
+    system_m68k_Atari:      SetAtariInfo;
+  end;
+end;
+
+
+function TLinkerAtari.WriteResponseFile(isdll: boolean): boolean;
+var
+  linkres  : TLinkRes;
+  i        : longint;
+  HPath    : TCmdStrListItem;
+  s        : string;
+  linklibc : boolean;
+begin
+  WriteResponseFile:=False;
+
+  { Open link.res file }
+  LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
+
+  { Write path to search libraries }
+  HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+  while assigned(HPath) do
+   begin
+    s:=HPath.Str;
+    if (cs_link_on_target in current_settings.globalswitches) then
+     s:=ScriptFixFileName(s);
+    LinkRes.Add('-L'+s);
+    HPath:=TCmdStrListItem(HPath.Next);
+   end;
+  HPath:=TCmdStrListItem(LibrarySearchPath.First);
+  while assigned(HPath) do
+   begin
+    s:=HPath.Str;
+    if s<>'' then
+     LinkRes.Add('SEARCH_DIR("'+s+'")');
+    HPath:=TCmdStrListItem(HPath.Next);
+   end;
+
+  LinkRes.Add('INPUT (');
+  { add objectfiles, start with prt0 always }
+  s:=FindObjectFile('prt0','',false);
+  LinkRes.AddFileName(s);
+  while not ObjectFiles.Empty do
+   begin
+    s:=ObjectFiles.GetFirst;
+    if s<>'' then
+     begin
+      { vlink doesn't use SEARCH_DIR for object files }
+      if UseVLink then
+       s:=FindObjectFile(s,'',false);
+      LinkRes.AddFileName(maybequoted(s));
+     end;
+   end;
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     { vlink doesn't need, and doesn't support GROUP }
+    if not UseVLink then
+     begin
+      LinkRes.Add(')');
+      LinkRes.Add('GROUP(');
+     end;
+    while not StaticLibFiles.Empty do
+     begin
+      S:=StaticLibFiles.GetFirst;
+      LinkRes.AddFileName(maybequoted(s));
+     end;
+   end;
+
+  if not UseVLink then
+   begin
+    LinkRes.Add(')');
+
+    { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+      here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+    linklibc:=false;
+    while not SharedLibFiles.Empty do
+     begin
+      S:=SharedLibFiles.GetFirst;
+      if s<>'c' then
+       begin
+        i:=Pos(target_info.sharedlibext,S);
+        if i>0 then
+         Delete(S,i,255);
+        LinkRes.Add('-l'+s);
+       end
+      else
+       begin
+        LinkRes.Add('-l'+s);
+        linklibc:=true;
+       end;
+     end;
+    { be sure that libc&libgcc is the last lib }
+    if linklibc then
+     begin
+      LinkRes.Add('-lc');
+      LinkRes.Add('-lgcc');
+     end;
+   end
+  else
+   begin
+    while not SharedLibFiles.Empty do
+     begin
+      S:=SharedLibFiles.GetFirst;
+      LinkRes.Add('lib'+s+target_info.staticlibext);
+     end;
+    LinkRes.Add(')');
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.free;
+
+  WriteResponseFile:=True;
+end;
+
+
+function TLinkerAtari.MakeAtariExe: boolean;
+var
+  BinStr,
+  CmdStr  : TCmdStr;
+  StripStr: string[40];
+  DynLinkStr : string;
+begin
+  StripStr:='';
+  if (cs_link_strip in current_settings.globalswitches) then StripStr:='-s';
+
+  { Call linker }
+  SplitBinCmd(Info.ExeCmd[1],BinStr,CmdStr);
+  binstr:=FindUtil(utilsprefix+BinStr);
+  Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename)));
+  Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+  Replace(cmdstr,'$STRIP',StripStr);
+  if rlinkpath<>'' Then
+    DynLinkStr:='--rpath-link '+rlinkpath
+  else
+    DynLinkStr:='';
+  Replace(cmdstr,'$DYNLINK',DynLinkStr);
+  MakeAtariExe:=DoExec(BinStr,CmdStr,true,false);
+end;
+
+
+function TLinkerAtari.MakeExecutable:boolean;
+var
+  success : boolean;
+begin
+  if not(cs_link_nolink in current_settings.globalswitches) then
+    Message1(exec_i_linking,current_module.exefilename);
+
+  { Write used files and libraries }
+  WriteResponseFile(false);
+
+  success:=MakeAtariExe;
+
+  { Remove ReponseFile }
+  if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+    DeleteFile(outputexedir+Info.ResName);
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
+
+
+
+
 {*****************************************************************************
                                      Initialize
 *****************************************************************************}
 
 initialization
+  RegisterLinker(ld_atari,TLinkerAtari);
   RegisterTarget(system_m68k_atari_info);
 end.