Przeglądaj źródła

+ Use of native Solaris linker

git-svn-id: trunk@14270 -
pierre 15 lat temu
rodzic
commit
ca11bcd6cb
1 zmienionych plików z 152 dodań i 10 usunięć
  1. 152 10
      compiler/systems/t_sunos.pas

+ 152 - 10
compiler/systems/t_sunos.pas

@@ -29,7 +29,7 @@ interface
 { copy from t_linux
 { copy from t_linux
 // Up to now we use gld since the solaris ld seems not support .res-files}
 // Up to now we use gld since the solaris ld seems not support .res-files}
 {-$DEFINE LinkTest} { DON't del link.res and write Info }
 {-$DEFINE LinkTest} { DON't del link.res and write Info }
-{$DEFINE GnuLd} {The other is not implemented }
+{$DEFINE GnuLd}{The other is not implemented }
 
 
 implementation
 implementation
 
 
@@ -58,6 +58,8 @@ implementation
     private
     private
       Glibc2,
       Glibc2,
       Glibc21 : boolean;
       Glibc21 : boolean;
+      use_gnu_ld : boolean;
+      linkres : TLinkRes;
       Function  WriteResponseFile(isdll:boolean) : Boolean;
       Function  WriteResponseFile(isdll:boolean) : Boolean;
     public
     public
       constructor Create;override;
       constructor Create;override;
@@ -168,7 +170,7 @@ begin
          end;
          end;
       end
       end
      else
      else
-      Message1(parser_e_no_export_of_variables_for_target,'linux');
+      Message1(parser_e_no_export_of_variables_for_target,'solaris');
      hp2:=texported_item(hp2.next);
      hp2:=texported_item(hp2.next);
    end;
    end;
 end;
 end;
@@ -181,8 +183,20 @@ end;
 Constructor TLinkersolaris.Create;
 Constructor TLinkersolaris.Create;
 begin
 begin
   Inherited Create;
   Inherited Create;
+{$ifndef x86_64}
+  use_gnu_ld:=true;
+{$endif}
+
+  if cs_link_native in init_settings.globalswitches then
+    use_gnu_ld:=false
+  else
+    use_gnu_ld:=true;
   if NOT Dontlinkstdlibpath Then
   if NOT Dontlinkstdlibpath Then
+{$ifdef x86_64}
+   LibrarySearchPath.AddPath(sysrootpath,'/lib/64;/usr/lib/64;/usr/X11R6/lib/64;/opt/sfw/lib/64',true);
+{$else not x86_64}
    LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib;/opt/sfw/lib',true);
    LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib;/opt/sfw/lib',true);
+{$endif not x86_64}
 {$ifdef  LinkTest}
 {$ifdef  LinkTest}
      if (cs_link_staticflag in current_settings.globalswitches) then  WriteLN('ForceLinkStaticFlag');
      if (cs_link_staticflag in current_settings.globalswitches) then  WriteLN('ForceLinkStaticFlag');
      if (cs_link_static in current_settings.globalswitches) then  WriteLN('LinkStatic-Flag');
      if (cs_link_static in current_settings.globalswitches) then  WriteLN('LinkStatic-Flag');
@@ -195,14 +209,24 @@ procedure TLinkersolaris.SetDefaultInfo;
 {
 {
   This will also detect which libc version will be used
   This will also detect which libc version will be used
 }
 }
+{$ifdef x86_64}
+const
+  gld = 'gld -m elf_x86_64 ';
+  solaris_ld = '/usr/bin/ld -64 ';
+{$else}
+const
+  gld = 'gld ';
+  solaris_ld = 'ld ';
+{$endif}
 begin
 begin
   Glibc2:=false;
   Glibc2:=false;
   Glibc21:=false;
   Glibc21:=false;
   with Info do
   with Info do
    begin
    begin
 {$IFDEF GnuLd}
 {$IFDEF GnuLd}
-     ExeCmd[1]:='gld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
-     DllCmd[1]:='gld $OPT -shared -L. -o $EXE $RES';
+     ExeCmd[1]:=gld + '$OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
+     ExeCmd[2]:=solaris_ld + '$OPT $DYNLINK $STATIC $STRIP -L . -o $EXE $RESDATA';
+     DllCmd[1]:=gld + '$OPT -shared -L. -o $EXE $RES';
      DllCmd[2]:='gstrip --strip-unneeded $EXE';
      DllCmd[2]:='gstrip --strip-unneeded $EXE';
      DynamicLinker:=''; { Gnu uses the default }
      DynamicLinker:=''; { Gnu uses the default }
      Glibc21:=false;
      Glibc21:=false;
@@ -220,7 +244,7 @@ begin
         else
         else
          Glibc21:=true;
          Glibc21:=true;
       end
       end
-     else
+     else 
       DynamicLinker:='/lib/ld-linux.so.1';
       DynamicLinker:='/lib/ld-linux.so.1';
 *)
 *)
    end;
    end;
@@ -230,7 +254,6 @@ end;
 
 
 Function TLinkersolaris.WriteResponseFile(isdll:boolean) : Boolean;
 Function TLinkersolaris.WriteResponseFile(isdll:boolean) : Boolean;
 Var
 Var
-  linkres      : TLinkRes;
   i            : longint;
   i            : longint;
 {  cprtobj,
 {  cprtobj,
   gprtobj,
   gprtobj,
@@ -239,6 +262,7 @@ Var
   s,s2         : TCmdStr;
   s,s2         : TCmdStr;
   linkdynamic,
   linkdynamic,
   linklibc     : boolean;
   linklibc     : boolean;
+
 begin
 begin
   WriteResponseFile:=False;
   WriteResponseFile:=False;
 { set special options for some targets }
 { set special options for some targets }
@@ -266,6 +290,8 @@ begin
        AddSharedLibrary('c'); { quick hack: this solaris implementation needs alwys libc }
        AddSharedLibrary('c'); { quick hack: this solaris implementation needs alwys libc }
    end;
    end;
 
 
+  if use_gnu_ld then
+    begin
   { Open link.res file }
   { Open link.res file }
   LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
   LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
 
 
@@ -366,7 +392,103 @@ begin
 { Write and Close response }
 { Write and Close response }
   linkres.writetodisk;
   linkres.writetodisk;
   LinkRes.Free;
   LinkRes.Free;
+    end
+  else { not use_gnu_ld }
+    begin
+   { Open link.res file }
+  LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+  HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+  while assigned(HPath) do
+   begin
+     LinkRes.Add('-L '+maybequoted(HPath.Str));
+     HPath:=TCmdStrListItem(HPath.Next);
+   end;
+  HPath:=TCmdStrListItem(LibrarySearchPath.First);
+  while assigned(HPath) do
+   begin
+     LinkRes.Add('-L '+maybequoted(HPath.Str));
+     HPath:=TCmdStrListItem(HPath.Next);
+   end;
+
+  { add objectfiles, start with prt0 always }
+  { solaris port contains _start inside the system unit, it
+    needs only one entry because it is linked always against libc
+  if prtobj<>'' then
+   LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+  }
+  { try to add crti and crtbegin if linking to C }
+  if linklibc then { Needed in solaris? }
+   begin
+{     if librarysearchpath.FindFile('crtbegin.o',s) then
+      LinkRes.AddFileName(s);}
+     if librarysearchpath.FindFile('crti.o',false,s) then
+      LinkRes.AddFileName(s);
+   end;
+  { main objectfiles }
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.GetFirst;
+     if s<>'' then
+      LinkRes.AddFileName(maybequoted(s));
+   end;
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.GetFirst;
+        LinkRes.AddFileName(maybequoted(s))
+      end;
+   end;
 
 
+  { 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) }
+  if not SharedLibFiles.Empty then
+   begin
+     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
+           linklibc:=true;
+           linkdynamic:=false; { libc will include the ld-solaris (war ld-linux) for us }
+         end;
+      end;
+     { be sure that libc is the last lib }
+     if linklibc then
+      LinkRes.Add('-lc');
+     { when we have -static for the linker the we also need libgcc }
+     if (cs_link_staticflag in current_settings.globalswitches) then begin
+      LinkRes.Add('-lgcc');
+     end;
+     if linkdynamic and (Info.DynamicLinker<>'') then { gld has a default, DynamicLinker is not set in solaris }
+       LinkRes.AddFileName(Info.DynamicLinker);
+   end;
+  { objects which must be at the end }
+  if linklibc then {needed in solaris ? }
+   begin
+     if {librarysearchpath.FindFile('crtend.o',s1) or}
+        librarysearchpath.FindFile('crtn.o',false,s2) then
+      begin
+{        LinkRes.AddFileName(s1);}
+        LinkRes.AddFileName(s2);
+      end;
+   end;
+{ Write and Close response }
+  //linkres.writetodisk;
+  //LinkRes.Free;
+
+    end;
   WriteResponseFile:=True;
   WriteResponseFile:=True;
 end;
 end;
 
 
@@ -374,6 +496,7 @@ end;
 function TLinkersolaris.MakeExecutable:boolean;
 function TLinkersolaris.MakeExecutable:boolean;
 var
 var
   binstr,
   binstr,
+  s, linkstr,
   cmdstr  : TCmdStr;
   cmdstr  : TCmdStr;
   success : boolean;
   success : boolean;
   DynLinkStr : string[60];
   DynLinkStr : string[60];
@@ -399,18 +522,37 @@ begin
   WriteResponseFile(false);
   WriteResponseFile(false);
 
 
 { Call linker }
 { Call linker }
-  SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+  if use_gnu_ld then
+    SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr)
+  else
+    SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
   Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
   Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
   Replace(cmdstr,'$OPT',Info.ExtraOptions);
   Replace(cmdstr,'$OPT',Info.ExtraOptions);
-  Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+  if use_gnu_ld then
+    Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName))
+  else
+    begin
+      linkstr:='';
+      while not linkres.data.Empty do
+        begin
+          s:=linkres.data.GetFirst;
+          linkstr:=linkstr+s+' ';
+        end;
+      linkres.free;
+      Replace(cmdstr,'$RESDATA',linkstr);
+    end;
   Replace(cmdstr,'$STATIC',StaticStr);
   Replace(cmdstr,'$STATIC',StaticStr);
   Replace(cmdstr,'$STRIP',StripStr);
   Replace(cmdstr,'$STRIP',StripStr);
   Replace(cmdstr,'$DYNLINK',DynLinkStr);
   Replace(cmdstr,'$DYNLINK',DynLinkStr);
-  success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+  if use_gnu_ld then
+    success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false)
+  else { Using utilsprefix has no sense on /usr/bin/ld }
+    success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
 
 
 { Remove ReponseFile }
 { Remove ReponseFile }
 {$IFNDEF LinkTest}
 {$IFNDEF LinkTest}
-  if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+  if (success) and use_gnu_ld and
+     not(cs_link_nolink in current_settings.globalswitches) then
    DeleteFile(outputexedir+Info.ResName);
    DeleteFile(outputexedir+Info.ResName);
 {$ENDIF}
 {$ENDIF}
   MakeExecutable:=success;   { otherwise a recursive call to link method }
   MakeExecutable:=success;   { otherwise a recursive call to link method }