User Tools

Site Tools


developingpld:advanceddeveloping:fixingasneeded

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
developingpld:advanceddeveloping:fixingasneeded [2006-08-07 02:53]
SamChi
developingpld:advanceddeveloping:fixingasneeded [2007-05-27 20:51] (current)
arekm
Line 4: Line 4:
  
  
-==== Quick Workaround ​==== +===== Quick and ugly workaround (DON'T USE IT!) ===== 
-Put in spec file this line+Put this line in ''​spec'' ​file: 
  
-<​file>​%devine filterout_ld -Wl,​--as-needed 
-</​file>​ 
-But **don'​t use it** unless you really need.  
  
-Why ? Because it's very stupid. If something fails to build normally ​it's a sign ''​--as-needed''​ did well it's job and disabled unneeded libraries. ​+ 
 +<​file>​%define filterout_ld -Wl,​--as-needed 
 +</​file>​ 
 +But **don't use it** unless you really need to quickly ​build a package. Never ever try to commit such a change. It might be tempting to do so but if you think about it ''​--as-needed''​ did it's job well and disabled unneeded libraries. If building fails, it's the package that needs to get fixed, not the linker flags
  
  
  
 ===== How --as-needed works ===== ===== How --as-needed works =====
-With ''​--as-needed''​ enabled only libraries ​which contain ​symbols required by __object files__ are linked. ​+With ''​--as-needed''​ enabledonly libraries ​containing ​symbols required by __object files__ are linked.  
 + 
 + 
 + 
 +==== Why it fails for some packages ==== 
 +In other words, if you list 10 libraries and only 3 of them contain referenced symbols, others are silently discarded. This is a good thing but unfortunately some projects fail to list all their dependencies properly.  
 + 
 +This normally works because if project requires libraries //A// and //B// and //A// itself lists //B// as a dependency, both //A// and //B// get pulled in even if the project itself only lists //A//.  
 + 
 +Now assume that //A// is a superfluous (unneeded) dependency which gets dropped (or //A// requiring //B// is superfluous and //B// gets dropped from //A//). The symbols are no longer available
  
  
  
-== About positions == +==== About positions ​==== 
-Linker options are positional, and position is very important. ​Because it looks for missing symbols only in libraries coming after object file. +Linker options are positional, and position is very important. ​It looks for missing symbols only in libraries coming after object file. 
  
-Correct ​ones are: +Correct ​positions ​are: 
  
 <​file>​$ gcc $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS) <​file>​$ gcc $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
Line 41: Line 50:
 <​file>​$ gcc -l<​library>​ -Wl,​--as-needed <​objects.o>​ <​file>​$ gcc -l<​library>​ -Wl,​--as-needed <​objects.o>​
 </​file>​ </​file>​
-library will allways ​be linked, even if it's not required. ​+library will __allways__ ​be linked, even if it isn'required. ​
  
  
  
 ==== Short examples ==== ==== Short examples ====
-Most of problems are with readline/​ncurses and tinfo, and it's nice example: tinfo is required by both readline and ncurses, and both are linked with this library (now, when I'​ve ​[[http://​cvs.pld-linux.org/​cgi-bin/​cvsweb/​SOURCES/​readline-shared.patch?​r1=1.6&​amp;​r2=1.7|fixed readline]];). +Most of problems are with readline/​ncurses and tinfo, and it's nice example: tinfo is required by both readline and ncurses, and both are linked with this library (now, when [[http://​cvs.pld-linux.org/​cgi-bin/​cvsweb/​SOURCES/​readline-shared.patch?​r1=1.6&​amp;​r2=1.7|fixed readline]] ​is fixed). 
  
-But some packages link with readline or ncurses while they use __only__ symbols from tinfo. //Without// ''​--as-needed''​ those executables work because they are linked with tinfo from readline/​ncurses library. //With// ''​--as-needed'' ​it will not work, because readline/​ncurses contain no symbols required by executable so they are not linked, it's dependencies naturally are neither linked. Thats why there is a need to pass ''​-ltinfo''​. If it requires only symbols from tinfo it's ok to ''​s/​ncurses/​tinfo/''​. But if it really requires readline/​ncurses but there is some executable (or ./​configure) which requires only tinfo both ''​-lreadline''/''​-lncurses''​ and ''​-ltinfo''​ should be passed. ​+But some packages link with readline or ncurses while they use __only__ symbols from tinfo. //Without// ''​--as-needed''​ those executables work because they are linked with tinfo from readline/​ncurses library. //With// ''​--as-needed'' ​linking ​will not work, because readline/​ncurses contain no symbols required by executable so they are not linked, it's dependencies naturally are neither linked. Thats why there is a need to pass ''​-ltinfo''​. If it requires only symbols from tinfo it's ok to ''​s/​ncurses/​tinfo/''​. But if it really requires readline/​ncurses but there is some executable (or ./​configure) which requires only tinfo both ''​-lreadline''/''​-lncurses''​ and ''​-ltinfo''​ should be passed. ​
  
 For a longer example take a look at real example nr. 1.  For a longer example take a look at real example nr. 1. 
Line 61: Line 70:
 <​file>​$ gcc -Wl,​--as-needed -o executable <​objects.o>​ -l2 -l1 <​file>​$ gcc -Wl,​--as-needed -o executable <​objects.o>​ -l2 -l1
 </​file>​ </​file>​
-it's usual when object files require only library 2, and -l1 is required by -l2. As I said linker only checks for symbols from objects, so -l1 is not linked. Normally it is easy to fix it, simply make sure while linking -l2 it is linked to -l1 (take a look at the second real example). ​+It's usual situation ​when object files require only library 2, and //-l1// is required by //-l2//. As I said linker only checks for symbols from objects, so //-l1// is not linked. Normally it is easy to fix it, simply make sure while linking ​//-l2// it is linked to //-l1// (take a look at the second real example). ​
  
  
Line 75: Line 84:
  
  
-<​file>​x86_64-pld-linux-g++ -DNOMMGR -Wall -DGAMEDATADIR=\"/​usr/​share/​xmoto\" ​ -ggdb -O2 -Wl,​--as-needed -o xmoto-edit ​ BuiltInFont.o [...object files...] Packager.o -lGL -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lbz2 -lz -lpng -ljpeg+<​file>​g++ -Wl,​--as-needed -o xmoto-edit BuiltInFont.o [...object files...] Packager.o -lGL -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lbz2 -lz -lpng -ljpeg
  
 VApp.o: In function `vapp::​App::​getRealTime()':​ VApp.o: In function `vapp::​App::​getRealTime()':​
Line 100: Line 109:
 Binary file /​usr/​lib64/​libSDL.so matches Binary file /​usr/​lib64/​libSDL.so matches
 </​file>​ </​file>​
-they are in ''​-lSDL'',​ but binary does not link with ''​-lSDL''​; edit Makefile by hand and add ''​-lSDL''​ at the same place ''​-lSDL_mixer''​ is: ''​LIBS = -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lbz2 -lz -lpng -ljpeg'' ​+They are in ''​-lSDL'',​ but binary does not link with ''​-lSDL''​. Edit Makefile by hand and add ''​-lSDL''​ at the same place ''​-lSDL_mixer''​ is: ''​LIBS = -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lbz2 -lz -lpng -ljpeg'' ​
  
 What we get after running make in build tree:  What we get after running make in build tree: 
Line 106: Line 115:
  
  
-<​file>​x86_64-pld-linux-g++ -DNOMMGR -Wall -DGAMEDATADIR=\"/​usr/​share/​xmoto\"​ -ggdb -O2 -Wl,​--as-needed -o xmoto-edit BuiltInFont.o [...object files...] Packager.o ​ -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lbz2 -lz -lpng -ljpeg+<​file>​g++ -Wl,​--as-needed -o xmoto-edit BuiltInFont.o [...object files...] Packager.o -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lbz2 -lz -lpng -ljpeg
  
 VApp.o: In function `vapp::​App::​grabScreen()':​ VApp.o: In function `vapp::​App::​grabScreen()':​
Line 139: Line 148:
  
  
-<​file>​x86_64-pld-linux-g++ -DNOMMGR -Wall -DGAMEDATADIR=\"/​usr/​share/​xmoto\" ​ -ggdb -O2 -Wl,​--as-needed -o xmoto-edit ​ BuiltInFont.o [...object files...] Packager.o ​ -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lGL -lbz2 -lz -lpng -ljpeg+<​file>​g++ -Wl,​--as-needed -o xmoto-edit BuiltInFont.o [...object files...] Packager.o -lcurl -lode -llualib50 -llua50 -lSDL_mixer -lSDL -lGL -lbz2 -lz -lpng -ljpeg
  
 make[1]: Leaving directory `/​home/​users/​sparky/​rpm/​BUILD/​xmoto-0.2.0'​ make[1]: Leaving directory `/​home/​users/​sparky/​rpm/​BUILD/​xmoto-0.2.0'​
 </​file>​ </​file>​
-//It worked !// +**It worked !** 
  
  
Line 180: Line 189:
  
  
-<​file>/​bin/​sh ../libtool --tag=CC --mode=link ​x86_64-pld-linux-gcc -ggdb -O2 -Wall  ​-Wl,​--as-needed -o test-source-selector ​ test-source-selector.o libedataserverui-1.2.la ../​libedataserver/​libedataserver-1.2.la -pthread -lglade-2.0 [...many -l libraries...]+<​file>/​bin/​sh ../libtool --tag=CC --mode=link gcc -Wl,​--as-needed -o test-source-selector ​ test-source-selector.o libedataserverui-1.2.la ../​libedataserver/​libedataserver-1.2.la -pthread -lglade-2.0 [...many -l libraries...]
 -lgnome-keyring -lpthread -lgnome-keyring -lpthread
  
-x86_64-pld-linux-gcc -ggdb -O2 -Wall -Wl,​--as-needed -o .libs/​test-source-selector test-source-selector.o -pthread ./​.libs/​libedataserverui-1.2.so [many, many .so and -l libraries] -lpthread+gcc -Wl,​--as-needed -o .libs/​test-source-selector test-source-selector.o -pthread ./​.libs/​libedataserverui-1.2.so [...many, many .so and -l libraries...] -lpthread
  
 ./​.libs/​libedataserverui-1.2.so:​ undefined reference to `glade_xml_new'​ ./​.libs/​libedataserverui-1.2.so:​ undefined reference to `glade_xml_new'​
Line 212: Line 221:
 ''​GNOME_KEYRING_LIBS = -lgnome-keyring -lglib-2.0'' ​ ''​GNOME_KEYRING_LIBS = -lgnome-keyring -lglib-2.0'' ​
  
-So add this one and glade to that library deps: +So add this one and ''​-lglade-2.0'' ​to that library deps: 
  
  
Line 235: Line 244:
  
 == Why was it working without --as-needed ? == == Why was it working without --as-needed ? ==
-test-source-selector binary was linked with all libraries needed by libedataserverui-1.2.so,​ and the binary was the one who provided missing symbols to libedataserverui-1.2.so ​+''​test-source-selector'' ​binary was linked with all libraries needed by libedataserverui-1.2.so,​ and the binary was the one who provided missing symbols to libedataserverui-1.2.so ​ 
 + 
 + 
 + 
 +=== What if broken library comes from other package ? === 
 +You can check manually does library has all required symbols, simply running ' gcc //library// ', like this:  
 + 
 +This is an example of correctly linked library:  
 + 
 +<​file>​$ gcc /​usr/​lib64/​liblftp-tasks.so.0.0.0 
 +/​usr/​lib64/​gcc/​x86_64-pld-linux/​4.1.2/​../​../​../​../​lib64/​crt1.o:​ In function `_start':​ 
 +(.text+0x20):​ undefined reference to `main'​ 
 +collect2: ld returned 1 exit status 
 +</​file>​ 
 +And incorrectly linked one:  
 + 
 +<​file>​$ gcc /​usr/​lib64/​liblftp-jobs.so.0.0.0 
 +/​usr/​lib64/​gcc/​x86_64-pld-linux/​4.1.2/​../​../​../​../​lib64/​crt1.o:​ In function `_start':​ 
 +(.text+0x20):​ undefined reference to `main'​ 
 +/​usr/​lib64/​liblftp-jobs.so.0.0.0:​ undefined reference to `StringSet::​Remove(int)'​ 
 +/​usr/​lib64/​liblftp-jobs.so.0.0.0:​ undefined reference to `Buffer::​Format(char const*, ...)'​ 
 +[...] 
 +/​usr/​lib64/​liblftp-jobs.so.0.0.0:​ undefined reference to `SMTask::​SuspendSlave()'​ 
 +collect2: ld returned 1 exit status 
 +</​file>​ 
 +**Warning:​** some libraries may require to have unresolved symbols. ​
  
  
Line 258: Line 292:
  
  
-<​file>​x86_64-pld-linux-gcc -o conftest -ggdb -O2 -DORBIT2=1 -pthread -I/​usr/​include/​libgnome-2.0 [...many -I...] -I/​usr/​include/​libxml2 -Wl,​--as-needed -pthread -lgpilotd [...many -l...] -lglib-2.0 conftest.c >&5+<​file>​gcc -o conftest -ggdb -O2 -DORBIT2=1 -pthread -I/​usr/​include/​libgnome-2.0 [...many -I...] -I/​usr/​include/​libxml2 -Wl,​--as-needed -pthread -lgpilotd [...many -l...] -lglib-2.0 conftest.c >&5
  
 /​home/​users/​sparky/​tmp/​ccgrL9ll.o:​ In function `main':​ /​home/​users/​sparky/​tmp/​ccgrL9ll.o:​ In function `main':​
Line 265: Line 299:
 collect2: ld returned 1 exit status collect2: ld returned 1 exit status
 </​file>​ </​file>​
-function '''​convert_ToPilotChar''',​ may be found in passed library, but take a look at section about positions, arguments order is incorrect: libraries go before objects (conftest.c) ​it's very common when someone puts ''​-l<>''​ in ''​LDFLAGS''​ instead of ''​LIBS'',​ that was the case too +function '''​convert_ToPilotChar''',​ may be found in passed library, but take a look at section about positions, arguments order is incorrect: libraries go before objects (conftest.c). It's very common when someone puts ''​-l<>''​ in ''​LDFLAGS''​ instead of ''​LIBS'',​ that was the case too
  
-just take a look at my fix: +Just take a look at my fix: 
  
  
Line 279: Line 313:
 +       ​LIBS="​$LIBS_save"​ +       ​LIBS="​$LIBS_save"​
 </​file>​ </​file>​
-with this simple change everything works perfectly. ​+With this simple change everything works perfectly. ​
  
  
developingpld/advanceddeveloping/fixingasneeded.1154912017.txt.gz · Last modified: 2006-08-07 02:53 by SamChi