소스 검색

+ support for creating dynamic libraries on AIX

git-svn-id: trunk@20818 -
Jonas Maebe 13 년 전
부모
커밋
51e50f72be
1개의 변경된 파일94개의 추가작업 그리고 17개의 파일을 삭제
  1. 94 17
      compiler/systems/t_aix.pas

+ 94 - 17
compiler/systems/t_aix.pas

@@ -108,14 +108,23 @@ end;
 
 
 
 
 procedure TLinkerAIX.SetDefaultInfo;
 procedure TLinkerAIX.SetDefaultInfo;
-const
-{$ifdef powerpc}platform_select='-b32';{$endif}
-{$ifdef POWERPC64} platform_select='-b64';{$endif}
 begin
 begin
   with Info do
   with Info do
    begin
    begin
-     ExeCmd[1]:='ld '+platform_select+' $OPT $STRIP -L. -o $EXE $CATRES';
-     DllCmd[1]:='ld '+platform_select+' $OPT $INITFINI $STRIP -L. -o $EXE $CATRES';
+     { the -bpT and -bpD options set the base addresses for text and data
+       sections. They are required because otherwise they are both 0 and hence
+       overlap, which confuses gdb. GCC uses those same options. -btextro makes
+       sure that the binary does not contain any relocations in the text
+       section (otherwise you get an error at load time instead of at link time
+       in case something is wrong) }
+     ExeCmd[1]:='ld -bpT:0x10000000 -bpD:0x20000000 -btextro $OPT $STRIP -L. -o $EXE $CATRES' {$ifdef powerpc64}+' -b64'{$endif};
+     DllCmd[1]:='ld -bpT:0x10000000 -bpD:0x20000000 -btextro $OPT $INITFINI $STRIP -G -L. -o $EXE $CATRES' {$ifdef powerpc64}+' -b64'{$endif};
+     if cs_debuginfo in current_settings.moduleswitches then
+       begin
+         { debugging helpers }
+         ExeCmd[1]:=ExeCmd[1]+' -lg -bexport:/usr/lib/libg.exp';
+         DllCmd[1]:=DllCmd[1]+' -lg -bexport:/usr/lib/libg.exp';
+       end;
    end;
    end;
 {$if defined(powerpc)}
 {$if defined(powerpc)}
    if not(cs_profile in current_settings.moduleswitches) then
    if not(cs_profile in current_settings.moduleswitches) then
@@ -139,8 +148,12 @@ Var
   i            : longint;
   i            : longint;
   HPath        : TCmdStrListItem;
   HPath        : TCmdStrListItem;
   s,s1         : TCmdStr;
   s,s1         : TCmdStr;
+  assumebinutils : boolean;
 begin
 begin
   result:=False;
   result:=False;
+  assumebinutils:=
+    not(cs_link_on_target in current_settings.globalswitches) and
+    not(source_info.system in systems_aix) ;
   { Open link.res file }
   { Open link.res file }
   LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
   LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
   with linkres do
   with linkres do
@@ -149,16 +162,24 @@ begin
       HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
       HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
       while assigned(HPath) do
       while assigned(HPath) do
        begin
        begin
-         Add('-L'+HPath.Str);
+         if assumebinutils then
+           Add('SEARCH_DIR('+maybequoted(HPath.Str)+')')
+         else
+           Add('-L'+HPath.Str);
          HPath:=TCmdStrListItem(HPath.Next);
          HPath:=TCmdStrListItem(HPath.Next);
        end;
        end;
       HPath:=TCmdStrListItem(LibrarySearchPath.First);
       HPath:=TCmdStrListItem(LibrarySearchPath.First);
       while assigned(HPath) do
       while assigned(HPath) do
        begin
        begin
-         Add('-L'+HPath.Str);
+         if assumebinutils then
+           Add('SEARCH_DIR('+maybequoted(HPath.Str)+')')
+         else
+           Add('-L'+HPath.Str);
          HPath:=TCmdStrListItem(HPath.Next);
          HPath:=TCmdStrListItem(HPath.Next);
        end;
        end;
 
 
+       if assumebinutils then
+        StartSection('INPUT(');
       { add objectfiles, start with prt0 always }
       { add objectfiles, start with prt0 always }
       AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
       AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
       { main objectfiles }
       { main objectfiles }
@@ -195,6 +216,8 @@ begin
            if librarysearchpath.FindFile('libgcc_eh.a',false,s1) then
            if librarysearchpath.FindFile('libgcc_eh.a',false,s1) then
              Add('-lgcc_eh');
              Add('-lgcc_eh');
          end;
          end;
+       if assumebinutils then
+         EndSection(')');
 
 
       { Write and Close response }
       { Write and Close response }
       writetodisk;
       writetodisk;
@@ -216,6 +239,7 @@ begin
   if not(cs_link_nolink in current_settings.globalswitches) then
   if not(cs_link_nolink in current_settings.globalswitches) then
    Message1(exec_i_linking,current_module.exefilename^);
    Message1(exec_i_linking,current_module.exefilename^);
 
 
+  linkscript:=nil;
 { Create some replacements }
 { Create some replacements }
   StripStr:='';
   StripStr:='';
   if (cs_link_strip in current_settings.globalswitches) and
   if (cs_link_strip in current_settings.globalswitches) and
@@ -231,7 +255,16 @@ begin
   binstr:=FindUtil(utilsprefix+BinStr);
   binstr:=FindUtil(utilsprefix+BinStr);
   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,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+  { the native AIX linker does not support linkres files, so we need
+    CatFileContent(). The binutils cross-linker does support such files, so
+    use them when cross-compiling to avoid overflowing the Windows maximum
+    command line length
+  }
+  if not(cs_link_on_target in current_settings.globalswitches) and
+     not(source_info.system in systems_aix) then
+    Replace(cmdstr,'$CATRES',outputexedir+Info.ResName)
+  else
+    Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
   Replace(cmdstr,'$STRIP',StripStr);
   Replace(cmdstr,'$STRIP',StripStr);
 
 
   { create dynamic symbol table? }
   { create dynamic symbol table? }
@@ -246,14 +279,17 @@ begin
      not(tf_no_backquote_support in source_info.flags) then
      not(tf_no_backquote_support in source_info.flags) then
     begin
     begin
       { we have to use a script to use the IFS hack }
       { we have to use a script to use the IFS hack }
-      linkscript:=TAsmScriptUnix.create(outputexedir+'ppaslink');
+      linkscript:=GenerateScript(outputexedir+'ppaslink');
       linkscript.AddLinkCommand(binstr,CmdStr,'');
       linkscript.AddLinkCommand(binstr,CmdStr,'');
 //      if (extdbgbinstr<>'') then
 //      if (extdbgbinstr<>'') then
 //        linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
 //        linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
       linkscript.WriteToDisk;
       linkscript.WriteToDisk;
       BinStr:=linkscript.fn;
       BinStr:=linkscript.fn;
       if not path_absolute(BinStr) then
       if not path_absolute(BinStr) then
-        BinStr:='./'+BinStr;
+        if cs_link_on_target in current_settings.globalswitches then
+          BinStr:='.'+target_info.dirsep+BinStr
+        else
+          BinStr:='.'+source_info.dirsep+BinStr;
       CmdStr:='';
       CmdStr:='';
     end;
     end;
 
 
@@ -263,20 +299,30 @@ begin
   if (success) and not(cs_link_nolink in current_settings.globalswitches) then
   if (success) and not(cs_link_nolink in current_settings.globalswitches) then
     begin
     begin
       DeleteFile(outputexedir+Info.ResName);
       DeleteFile(outputexedir+Info.ResName);
-      DeleteFile(outputexedir+'ppaslink.sh');
+      if assigned(linkscript) then
+        DeleteFile(linkscript.fn);
     end;
     end;
+  linkscript.free;
 
 
   MakeExecutable:=success;   { otherwise a recursive call to link method }
   MakeExecutable:=success;   { otherwise a recursive call to link method }
 end;
 end;
 
 
 
 
 Function TLinkerAIX.MakeSharedLibrary:boolean;
 Function TLinkerAIX.MakeSharedLibrary:boolean;
+const
+{$ifdef cpu64bitaddr}
+  libobj = 'shr_64.o';
+{$else}
+  libobj = 'shr.o';
+{$endif}
 var
 var
+  linkscript  : TAsmScript;
   exportedsyms: text;
   exportedsyms: text;
   InitFiniStr : string[80];
   InitFiniStr : string[80];
   StripStr,
   StripStr,
   binstr,
   binstr,
-  cmdstr  : TCmdStr;
+  cmdstr,
+  libfn: TCmdStr;
   success : boolean;
   success : boolean;
 begin
 begin
   MakeSharedLibrary:=false;
   MakeSharedLibrary:=false;
@@ -288,6 +334,7 @@ begin
 
 
  { Create some replacements }
  { Create some replacements }
   InitFiniStr:='-binitfini:'+exportlib.initname+':'+exportlib.fininame;
   InitFiniStr:='-binitfini:'+exportlib.initname+':'+exportlib.fininame;
+  Replace(InitFiniStr,'$','.');
   if cs_link_strip in current_settings.globalswitches then
   if cs_link_strip in current_settings.globalswitches then
     StripStr:='-s'
     StripStr:='-s'
   else
   else
@@ -295,13 +342,19 @@ begin
 
 
 { Call linker }
 { Call linker }
   SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
   SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
-  Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+  binstr:=FindUtil(utilsprefix+BinStr);
+  { on AIX, shared libraries are special object files that are stored inside
+    an archive. In that archive, the 32 bit version of the library is called
+    shr.o and the 64 bit version shr_64.o }
+  Replace(cmdstr,'$EXE',maybequoted(libobj));
   Replace(cmdstr,'$OPT',Info.ExtraOptions);
   Replace(cmdstr,'$OPT',Info.ExtraOptions);
-  Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+  if not(cs_link_on_target in current_settings.globalswitches) and
+     not(source_info.system in systems_aix) then
+    Replace(cmdstr,'$CATRES',outputexedir+Info.ResName)
+  else
+    Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
   Replace(cmdstr,'$INITFINI',InitFiniStr);
   Replace(cmdstr,'$INITFINI',InitFiniStr);
   Replace(cmdstr,'$STRIP',StripStr);
   Replace(cmdstr,'$STRIP',StripStr);
-  success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
-
   { exported symbols }
   { exported symbols }
   if not texportlibunix(exportlib).exportedsymnames.empty then
   if not texportlibunix(exportlib).exportedsymnames.empty then
     begin
     begin
@@ -314,12 +367,36 @@ begin
       cmdstr:=cmdstr+' -bE:'+maybequoted(outputexedir)+'linksyms.fpc';
       cmdstr:=cmdstr+' -bE:'+maybequoted(outputexedir)+'linksyms.fpc';
     end;
     end;
 
 
-{ Remove ReponseFile }
+  libfn:=maybequoted(current_module.sharedlibfilename^);
+  { we have to use a script to use the IFS hack }
+  linkscript:=GenerateScript(outputexedir+'ppaslink');
+  linkscript.AddLinkCommand(binstr,CmdStr,'');
+  { delete the target static library containing the dynamic object file in
+    case it already existed }
+  if FileExists(libfn,true) then
+    linkscript.AddDeleteCommand(libfn);
+  { and create the new one }
+  linkscript.AddLinkCommand(FindUtil(utilsprefix+'ar'),' -X32_64 -q '+libfn+(' '+libobj),'');
+  linkscript.WriteToDisk;
+  BinStr:=linkscript.fn;
+  if not path_absolute(BinStr) then
+    if cs_link_on_target in current_settings.globalswitches then
+      BinStr:='.'+target_info.dirsep+BinStr
+    else
+      BinStr:='.'+source_info.dirsep+BinStr;
+  CmdStr:='';
+
+  success:=DoExec(BinStr,cmdstr,true,true);
+
+  { Remove ReponseFile }
   if (success) and not(cs_link_nolink in current_settings.globalswitches) then
   if (success) and not(cs_link_nolink in current_settings.globalswitches) then
     begin
     begin
+      DeleteFile(libobj);
       DeleteFile(outputexedir+Info.ResName);
       DeleteFile(outputexedir+Info.ResName);
       DeleteFile(outputexedir+'linksyms.fpc');
       DeleteFile(outputexedir+'linksyms.fpc');
+      DeleteFile(linkscript.fn);
     end;
     end;
+  linkscript.free;
   MakeSharedLibrary:=success;   { otherwise a recursive call to link method }
   MakeSharedLibrary:=success;   { otherwise a recursive call to link method }
 end;
 end;