1

g++ 5.4.0

Ubuntu 16.04

i have several shared libraries and here is the abstraction of them:

libtest0.so: definition of `void foo()`
libtest1.so: `extern void foo()`, and not depends on libtest0.so
libtest2.so: use libtest1.so and depends on libtest1.so

and now i have a binary:

a.out: use libtest2.so

of course a.out has undefined symbol of foo(). To resolve it, i tried:

g++ main.cc -L. -ltest2 -ltest0

since libtest0.so has definition of foo().

However, it does not work:

$g++ -g main.cc -L. -ltest2 -ltest0
libtest1.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status

My questions are:

  1. why does this "undefined reference" happen?
  2. any solution to tell the linker that libtest0.so has definition of foo()?

thanks.

Update1:

if i link libtest0 when compile libtest2, then compile:

g++ -g main.cc -L. -ltest2

everything is fine now. However, in the real world problem, i cannot change the linkage of libtest2.so

Update2

clang++ works with this cmd: (and the linker is ld, not lld)

# clang version 11.0.0
clang++ -g main.cc -L. -ltest2 -ltest0

Update3

an example is: https://gist.github.com/xgwang/da93edcc06542264157f600eb64bc082

just bash it on linux. Tested on Ubuntu 16.

xgwang
  • 614
  • 7
  • 21
  • Where is libtest1 being linked? – Bayleef May 13 '20 at 13:44
  • @Evg it does not help: `g++ -std=c++11 -g main.cc -L. -ltest2 -ltest0` `libtest1.so: undefined reference to foo` – xgwang May 14 '20 at 02:32
  • @BaileyKocin libtest1 is a dependency of libtest2, it can be shown by `ldd libtest2.so` – xgwang May 14 '20 at 02:36
  • Can you link ltest0 then ltest2 then ltest0 again. – Bayleef May 14 '20 at 02:42
  • @BaileyKocin still it does not work. here is my gcc cmd: `g++ -shared -fPIC so0.cc -o libtest0.so` `g++ -shared -fPIC so1.cc -o libtest1.so` `g++ -shared -fPIC so2.cc -o libtest2.so -L. -ltest1` `g++ -g main.cc -L. -ltest0 -ltest2 -ltest0` `/path/to/libtest1.so: undefined reference to foo` `collect2: error: ld returned 1 exit status` sorry for the formatting. – xgwang May 14 '20 at 13:01
  • @Evg pls take a look at https://gist.github.com/xgwang/da93edcc06542264157f600eb64bc082 as an example. – xgwang May 28 '20 at 09:54

1 Answers1

2

First, a quote from here (emphasis is mine):

Failure in final linking, undefined symbols

This is the most common error that happens while using --as-needed. It happens during the final linking stage of an executable (libraries don't create problems, because they are allowed to have undefined symbols). The executable linking stage dies because of an undefined symbol that is present in one of the libraries fed to the command line. However, the library is not used by the executable itself, thus it gets removed by --as-needed. This usually means that a library was not linked to another library, but was using it, and then relying on the final executable to link them together. This behavior is also an extra encumbrance on developers using that library because they have to check for the requirements.

As a workaround, instead of

g++ main.cc -L. -ltest2 -ltest0

try

g++ main.cc -L. -ltest2 -Wl,--no-as-needed -ltest0

to disable --as-needed behaviour.

The minimal complete example that works for me:

#!/bin/bash

export LD_LIBRARY_PATH=.

g++ -fPIC -shared test0.cc -o libtest0.so
g++ -fPIC -shared test1.cc -o libtest1.so
g++ -fPIC -shared test2.cc -o libtest2.so -L. -ltest1

g++ main.cc -L. -ltest2 -Wl,--no-as-needed -ltest0
Evg
  • 25,259
  • 5
  • 41
  • 83