echo 'int foo1;' | gcc -shared -fpic -o /usr/lib/libfoo.so -xc - -xnone -Wl,-soname,libfoo.so echo 'int foo1; int foo2;' | gcc -shared -fpic -o libfoo.so -xc - -xnone -Wl,-soname,libfoo.so echo 'int foo (void) { extern int foo2; return foo2; }' | gcc -shared -fpic -o libbar.so -xc - -xnone ./libfoo.so echo 'extern int foo (void); int main (void) { return foo (); }' \ | gcc -o test -xc - -xnone -Wl,--as-needed ./libfoo.so ./libbar.so -Wl,--no-as-needed fails to link because foo2 is undefined. Withouth -Wl,--as-needed this links just fine (and so does adding -Wl,--rpath-link,.), but I don't think --as-needed should make a difference whether something links or not and what the above script does is something that happens quite often - a project with several libraries adds a new symbol to one of them and as the library is explicitly listed on the command line, the user shouldn't be really requested to supply a rpath-link as well. The problem I'd say is in gld${EMULATION_NAME}_check_needed which ignores --as-needed libraries: /* If this input file was an as-needed entry, and wasn't found to be needed at the stage it was linked, then don't say we have loaded it. */ if (s->as_needed && (s->the_bfd == NULL || (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)) return; I think it should in this case either load that library again (as in, call gld${EMULATION_NAME}_try_needed on the same filename), or just mark the library not only DYN_AS_NEEDED, but also DYN_DT_NEEDED and handle that combination of flags.
Oops, actually, swap the order of libfoo.so and libbar.so on the last command line and then it is a regression from older binutils (e.g. 2.16.91.0.6 20060212). echo 'int foo1;' | gcc -shared -fpic -o /usr/lib/libfoo.so -xc - -xnone \ -Wl,-soname,libfoo.so echo 'int foo1; int foo2;' | gcc -shared -fpic -o libfoo.so -xc - -xnone \ -Wl,-soname,libfoo.so echo 'int foo (void) { extern int foo2; return foo2; }' \ | gcc -shared -fpic -o libbar.so -xc - -xnone ./libfoo.so echo 'extern int foo (void); int main (void) { return foo (); }' \ | gcc -o test -xc - -xnone -Wl,--as-needed ./libbar.so ./libfoo.so \ -Wl,--no-as-needed
http://sources.redhat.com/ml/binutils/2006-06/msg00009.html
Fixed mainline with http://sources.redhat.com/ml/binutils-cvs/2006-06/msg00018.html
This was fixed a while ago.