diff --git a/compiler/cclasses.pas b/compiler/cclasses.pas index 90a1ca3351..e335d7994e 100644 --- a/compiler/cclasses.pas +++ b/compiler/cclasses.pas @@ -520,7 +520,7 @@ type end; -Const WeightDefault = 100; +Const WeightDefault = 1000; Type TLinkRec = record @@ -3344,7 +3344,7 @@ end; function TLinkStrMap.AddWeight(keyvalue:String):boolean; -var i : Longint; +var i,j : Longint; Code : Word; s : AnsiString; @@ -3354,10 +3354,10 @@ begin if i=0 then exit; s:=Copy(KeyValue,i+1,length(KeyValue)-i); - val(s,i,code); - if code<>0 Then + val(s,j,code); + if code=0 Then begin - Add(Copy(KeyValue,1,i-1),'',i); + Add(Copy(KeyValue,1,i-1),'',j); AddWeight:=True; end; end; @@ -3371,7 +3371,7 @@ begin while i<=k do begin j:=i; - while (i<=k) and (keys[i]<>';') do + while (i<=k) and (keys[i]<>',') do inc(i); add(copy(keys,j,i-j),'',weight); inc(i); @@ -3407,7 +3407,8 @@ begin lookup:=-1; i:=0; {$B-} - while (ikey) do inc(i); + while (ikey) do + inc(i); {$B+} if i<>itemcnt then lookup:=i; @@ -3452,7 +3453,6 @@ begin dest.add(LibN) else dest.addseries(fmap[r].value); - end; end; @@ -3470,3 +3470,4 @@ end; end. + \ No newline at end of file diff --git a/compiler/globtype.pas b/compiler/globtype.pas index 03ad58ecbf..39ab8893ee 100644 --- a/compiler/globtype.pas +++ b/compiler/globtype.pas @@ -142,7 +142,7 @@ than 255 characters. That's why using Ansi Strings} cs_link_nolink,cs_link_static,cs_link_smart,cs_link_shared,cs_link_deffile, cs_link_strip,cs_link_staticflag,cs_link_on_target,cs_link_extern,cs_link_opt_vtable, cs_link_opt_used_sections, - cs_link_map,cs_link_pthread + cs_link_map,cs_link_pthread,cs_link_no_default_lib_order ); tglobalswitches = set of tglobalswitch; diff --git a/compiler/link.pas b/compiler/link.pas index d363570c4d..67b7afc326 100644 --- a/compiler/link.pas +++ b/compiler/link.pas @@ -65,6 +65,7 @@ Type Function MakeStaticLibrary:boolean;virtual; procedure ExpandAndApplyOrder(var Src:TStringList); procedure LoadPredefinedLibraryOrder;virtual; + function ReOrderEntries : boolean; end; TExternalLinker = class(TLinker) @@ -507,10 +508,11 @@ begin if (LinkLibraryAliases.count=0) and (LinkLibraryOrder.Count=0) Then exit; p:=TLinkStrMap.Create; - + // expand libaliases, clears src LinkLibraryAliases.expand(src,p); + // writeln(src.count,' ',p.count,' ',linklibraryorder.count,' ',linklibraryaliases.count); // apply order p.UpdateWeights(LinkLibraryOrder); p.SortOnWeight; @@ -526,6 +528,12 @@ procedure TLinker.LoadPredefinedLibraryOrder; begin end; +function TLinker.ReOrderEntries : boolean; + +begin + result:=(LinkLibraryOrder.count>0) or (LinkLibraryAliases.count>0); +end; + {***************************************************************************** TEXTERNALLINKER *****************************************************************************} diff --git a/compiler/options.pas b/compiler/options.pas index ce4e63d0f0..7ff12db929 100644 --- a/compiler/options.pas +++ b/compiler/options.pas @@ -1277,8 +1277,9 @@ begin DefaultReplacements(utilsprefix); More:=''; end; - 'L' : begin // -XLO is link order -XLA is link alias - if (j=length(more)) or not ((more[j+1]='O') or (more[j+1]='A')) then + 'L' : begin // -XLO is link order -XLA is link alias. -XLD avoids load defaults. + // these are not aggregable. + if (j=length(more)) or not (more[j+1] in ['O','A','D']) then IllegalPara(opt) else begin @@ -1290,11 +1291,15 @@ begin end; 'O' : begin s:=Copy(more,3,length(More)-2); - if not LinkLibraryAliases.AddWeight(s) Then + if not LinkLibraryOrder.AddWeight(s) Then IllegalPara(opt); end; - end; - end; + 'D' : include(initglobalswitches,cs_link_no_default_lib_order) + else + IllegalPara(opt); + end; {case} + j:=length(more); + end; {else begin} end; 'S' : begin diff --git a/compiler/systems/t_bsd.pas b/compiler/systems/t_bsd.pas index c66d32dc20..6ccf84b29f 100644 --- a/compiler/systems/t_bsd.pas +++ b/compiler/systems/t_bsd.pas @@ -79,6 +79,7 @@ implementation procedure SetDefaultInfo;override; function MakeExecutable:boolean;override; function MakeSharedLibrary:boolean;override; + procedure LoadPredefinedLibraryOrder; override; end; @@ -292,27 +293,30 @@ begin DllCmd[2]:='strip --strip-unneeded $EXE' else DllCmd[2]:='strip -x $EXE'; - { first try glibc2 } -{$ifdef GLIBC2} {Keep linux code in place. FBSD might go to a different - glibc too once} - DynamicLinker:='/lib/ld-linux.so.2'; - if FileExists(DynamicLinker) then - begin - Glibc2:=true; - { Check for 2.0 files, else use the glibc 2.1 stub } - if FileExists('/lib/ld-2.0.*') then - Glibc21:=false - else - Glibc21:=true; - end - else - DynamicLinker:='/lib/ld-linux.so.1'; -{$else} DynamicLinker:=''; -{$endif} end; end; +procedure TLinkerBSD.LoadPredefinedLibraryOrder; +// put your linkorder/linkalias overrides here. +// Note: assumes only called when reordering/aliasing is used. +Begin + if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then + begin + if (target_info.system =system_i386_freebsd) and + not (cs_link_no_default_lib_order in aktglobalswitches) Then + Begin + LinkLibraryOrder.add('gcc','',15); + LinkLibraryOrder.add('c','',50); // c and c_p mutual. excl? + LinkLibraryOrder.add('c_p','',55); + LinkLibraryOrder.add('pthread','',75); // pthread and c_r should be mutually exclusive + LinkLibraryOrder.add('c_r','',76); + LinkLibraryOrder.add('kvm','',80); // must be before ncurses + if (cs_link_pthread in aktglobalswitches) Then // convert libpthread to libc_r. + LinkLibraryAliases.add('pthread','c_r'); + end; + end; +End; Function TLinkerBSD.WriteResponseFile(isdll:boolean) : Boolean; Var @@ -327,27 +331,29 @@ Var linkdynamic, linklibc : boolean; Fl1,Fl2 : Boolean; - + IsDarwin : Boolean; + ReOrder : Boolean; + begin WriteResponseFile:=False; + ReOrder:=False; + IsDarwin:=target_info.system in [system_powerpc_darwin,system_i386_darwin]; { set special options for some targets } - if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then + if not IsDarwin Then begin - linkdynamic:=not(SharedLibFiles.empty); - linklibc:=(SharedLibFiles.Find('c')<>nil); - linkpthread:=(SharedLibFiles.Find('pthread')<>nil); - if (target_info.system =system_i386_freebsd) and linkpthread Then - Begin - if not (cs_link_pthread in aktglobalswitches) Then - begin - {delete pthreads from list, in this case it is in libc_r} - SharedLibFiles.Remove(SharedLibFiles.Find('pthread').str); - LibrarySuffix:='r'; - end; - End; prtobj:='prt0'; cprtobj:='cprt0'; gprtobj:='gprt0'; + linkdynamic:=not(SharedLibFiles.empty); + linklibc:=(SharedLibFiles.Find('c')<>nil); + // this one is a bit complex. + // Only reorder for now if -XL or -XO params are given + // or when -Xf. + reorder:= linklibc and + ( + ReorderEntries + or + (cs_link_pthread in aktglobalswitches)); if cs_profile in aktmoduleswitches then begin prtobj:=gprtobj; @@ -360,6 +366,9 @@ begin if linklibc then prtobj:=cprtobj; end; + if reorder Then + ExpandAndApplyOrder(SharedLibFiles); + // after this point addition of shared libs not allowed. end else begin @@ -419,7 +428,7 @@ begin LinkRes.AddFileName(FindObjectFile(prtobj,'',false)); { try to add crti and crtbegin if linking to C } if linklibc and - not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then + not IsDarwin Then begin if librarysearchpath.FindFile('crtbegin.o',s) then LinkRes.AddFileName(s); @@ -459,7 +468,7 @@ begin While not SharedLibFiles.Empty do begin S:=SharedLibFiles.GetFirst; - if s<>'c' then + if (s<>'c') or reorder then begin i:=Pos(target_info.sharedlibext,S); if i>0 then @@ -473,7 +482,7 @@ begin end; end; { be sure that libc is the last lib } - if linklibc then + if linklibc and not reorder then Begin If LibrarySuffix=' ' Then LinkRes.Add('-lc') @@ -492,7 +501,7 @@ begin end; { objects which must be at the end } if linklibc and - not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then + not IsDarwin Then begin Fl1:=librarysearchpath.FindFile('crtend.o',s1); Fl2:=librarysearchpath.FindFile('crtn.o',s2); @@ -508,8 +517,7 @@ begin end; { ignore the fact that our relocations are in non-writable sections, } { will be fixed once we have pic support } - if isdll and - (target_info.system in [system_powerpc_darwin,system_i386_darwin]) then + if isdll and IsDarwin Then LinkRes.Add('-read_only_relocs suppress'); { Write and Close response } linkres.writetodisk;