Linking Error of Undefined Ref in the static lib

M

micropentium

Hi,

First of all, I know my compilation should fail anyway. Let's focus on
this link error.

I was writing some dummy code to test xulrunner sdk (probably I picked
the wrong way, but it's not important here) and then a weird error pop
up when I tried to link my code with its static library:
libembed_base_s.a

The compile looks like:
g++ -o test -g -Wall -Wno-non-virtual-dtor libembed_base_s.a test.o

The error I got was: ./test.cpp:40: undefined reference to
`NS_InitEmbedding'

So, I thought I must link with the wrong lib. Therefore, I did nm
libembed_base_s.a. Here is what I got:

nsEmbedAPI.o:
0000000000000000 r .LC0
000000000000002d r .LC1
0000000000000039 r .LC2
000000000000005a r .LC3
000000000000005e T NS_InitEmbedding
U NS_InitXPCOM3
U NS_ShutdownXPCOM
0000000000000000 T NS_TermEmbedding
U _GLOBAL_OFFSET_TABLE_
0000000000000000 V _ZN11nsIObserver11COMTypeInfoIiE4kIIDE
0000000000000000 V _ZN19nsIComponentManager11COMTypeInfoIiE4kIIDE
0000000000000000 V _ZN22nsIStringBundleService11COMTypeInfoIiE4kIIDE
0000000000000000 b sInitCounter
0000000000000010 b sRegistryInitializedFlag
0000000000000008 b sServiceManager

It seems the symbol is defined and exported in the object file. Yes, I
know there are undefined functions in
NS_InitEmbedding, such as NS_InitXPCOM3. But according to the error,
the linker actually didn't find the NS_InitEmbedding at all! So,
anyone could kindly explain to me what's going on?

In order to make this topic more interesting, I did: objdump -t
libembed_base_s.a
Then you could see:

000000000000005e g F .text 000000000000014a .hidden
NS_InitEmbedding

There is a hidden flag for this symbol, I know it's because the
declaration of __attribute__((visibility("hidden"))) on this function.
But, imho, I believe it only affects DSO, not static library archive.

So, I still do not know what kind of trick it plays to prevent linker
to detect this symbol. I have been on this for 1 days, and no clue so
far.

Your help will be highly appreciated!

Many Thanks!
 
A

Antoninus Twink

g++ -o test -g -Wall -Wno-non-virtual-dtor libembed_base_s.a test.o

The error I got was: ./test.cpp:40: undefined reference to
`NS_InitEmbedding'

Order matters. Try
g++ -o test -g -Wall -Wno-non-virtual-dtor test.o libembed_base_s.a

(Note that test is a poor choice of name for an executable, as the name
is already taken under POSIX.)
 
M

micropentium

Order matters. Try
g++ -o test -g -Wall -Wno-non-virtual-dtor test.o libembed_base_s.a

(Note that test is a poor choice of name for an executable, as the name
is already taken under POSIX.)

Got it! It's a shame that I was not aware of it...

From GCC Manual:

It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, `foo.o -lz bar.o' searches library `z' after
file foo.o but before bar.o. If bar.o refers to functions in `z',
those functions may not be loaded.

Does it mean that it's always good to pub ${LDFLAGS} at the end?

AT: Thank you for your comment on naming convention.
 
A

Antoninus Twink

Got it! It's a shame that I was not aware of it...

Yes, it's an annoying gotcha.
Does it mean that it's always good to pub ${LDFLAGS} at the end?

No, it means that it's good to put flags into LDFLAGS, and list your
libraries in LDLIBS, which automatically gets put at the end in make's
implicit rules.
 
M

micropentium

Yes, it's an annoying gotcha.


No, it means that it's good to put flags into LDFLAGS, and list your
libraries in LDLIBS, which automatically gets put at the end in make's
implicit rules.

AT: how to make this implicit rule works? I mean "automatically put
$LDFLAGS $LIBS at the end of the command'? It didn't work for me if I
remove ${LDFLAGS} ${LIBS}, make did complain. So, I think I did
something that disabled the implicit rule? But I could do this:
LIBS='-lz -laaa' make

Well, this is off tangle...:)
 
K

Keith Thompson

micropentium said:
First of all, I know my compilation should fail anyway. Let's focus on
this link error.

I was writing some dummy code to test xulrunner sdk (probably I picked
the wrong way, but it's not important here) and then a weird error pop
up when I tried to link my code with its static library:
libembed_base_s.a

The compile looks like:
g++ -o test -g -Wall -Wno-non-virtual-dtor libembed_base_s.a test.o

The error I got was: ./test.cpp:40: undefined reference to
`NS_InitEmbedding'
[...]

Since you're using g++, you're compiling C++, not C, but you posted to
comp.lang.c.

In any case, your question is really more about the tools you're using
than about the language. You'll get better help either in
gnu.gcc.help or in comp.unix.programmer.
 
A

Antoninus Twink

AT: how to make this implicit rule works?

To make foo from foo.o, make uses the rule
$(CC) $(LDFLAGS) foo.o $(LOADLIBES) $(LDLIBS)
I mean "automatically put $LDFLAGS $LIBS at the end of the command'?

It's LDLIBS, not LIBS. For example:

$ cat foo.c
extern double sin();
int main(void) { return (int) sin(0.); }
$ make foo
cc foo.c -o foo
/tmp/cc4vIYDI.o: In function `main':
/tmp/foo.c:2: undefined reference to `sin'
collect2: ld returned 1 exit status
$ make foo LDLIBS=-lm
cc foo.c -lm -o foo
$
 
M

micropentium

micropentium said:
First of all, I know my compilation should fail anyway. Let's focus on
this link error.
I was writing some dummy code to test xulrunner sdk (probably I picked
the wrong way, but it's not important here) and then a weird error pop
up when I tried to link my code with its static library:
libembed_base_s.a
The compile looks like:
g++ -o test -g -Wall -Wno-non-virtual-dtor libembed_base_s.a test.o
The error I got was: ./test.cpp:40: undefined reference to
`NS_InitEmbedding'

[...]

Since you're using g++, you're compiling C++, not C, but you posted to
comp.lang.c.

In any case, your question is really more about the tools you're using
than about the language. You'll get better help either in
gnu.gcc.help or in comp.unix.programmer.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

KT,
You are right. Next time I would put this kind of question out of this
group, this problem can occur with C though. Thank you for your
suggestions!
 
M

micropentium

To make foo from foo.o, make uses the rule
$(CC) $(LDFLAGS) foo.o $(LOADLIBES) $(LDLIBS)


It's LDLIBS, not LIBS. For example:

$ cat foo.c
extern double sin();
int main(void) { return (int) sin(0.); }
$ make foo
cc foo.c -o foo
/tmp/cc4vIYDI.o: In function `main':
/tmp/foo.c:2: undefined reference to `sin'
collect2: ld returned 1 exit status
$ make foo LDLIBS=-lm
cc foo.c -lm -o foo
$
AT,
I think I know what you mean. I just can't reproduce it on my RH Linux
machine. make with -v flog exposed that a lot of going on under the
hood so foo.c can be compiled successfully even without LDLIBS
defined.
 
A

Antoninus Twink

[the usual - i.e. "go to hell"]

You are right. Next time I would put this kind of question out of this
group, this problem can occur with C though.

Please be aware that "Keith Thomson" is a troll who seeks to disrupt
this newsgroup by discouraging new posters from contributing. He won't
provide you with any help, so it's best just to ignore him.
 
M

micropentium

Order matters. Try
g++ -o test -g  -Wall -Wno-non-virtual-dtor test.o libembed_base_s.a

(Note that test is a poor choice of name for an executable, as the name
is already taken under POSIX.)

Hi AT:

I did a test on my RH machine, the quote below from GNU site seems
only work for object file and static library

"It makes a difference where in the command you write this option;
the
linker searches and processes libraries and object files in the order
they are specified. Thus, `foo.o -lz bar.o' searches library `z'
after
file foo.o but before bar.o. If bar.o refers to functions in `z',
those functions may not be loaded."

If the executable was linked with shared library, then linker could
find the symobl even the order is not correct!
So, linker treats a and so differently? Why doesn't GNU manual mention
this?
 
A

Andrew Poelstra

[the usual - i.e. "go to hell"]

You are right. Next time I would put this kind of question out of this
group, this problem can occur with C though.

Please be aware that "Keith Thomson" is a troll who seeks to disrupt
this newsgroup by discouraging new posters from contributing. He won't
provide you with any help, so it's best just to ignore him.

OP, please be advised that Keith is not a troll. Makefile syntax is
indeed unrelated to the C programming language.
 
J

jacob navia

Andrew Poelstra a écrit :
OP, please be advised that Keith is not a troll. Makefile syntax is
indeed unrelated to the C programming language.

I do not think so. The make utility has been used to build
C programs since the dawn of Unix, quite a lot of years ago!

Note that this is not comp.std.c, but this group concerns itself
with all the things related to the language too, for instance
building a C program.
 
E

Eric Sosman

Andrew Poelstra a écrit :

I do not think so. The make utility has been used to build
C programs since the dawn of Unix, quite a lot of years ago!

... and shells have been used to launch C compilations
even longer than that. Do you conclude that the quoting
conventions for shell command lines are related to the C
programming language?
 
M

Mark Bluemel

You can't build or run a C program without [...] coffee

I don't drink coffee. Time for a flame war about the superiority of
tea, methinks.

(For that matter, I used to work with a Mormon programmmer - anyone
for a nice cup of Carob?)
 
S

Seebs

I do not think so. The make utility has been used to build
C programs since the dawn of Unix, quite a lot of years ago!

It has also been used to build Ruby programs, perl programs, python
programs, shell scripts, XML documents, Berkeley DB files, custom database
formats used by various programs...
Note that this is not comp.std.c, but this group concerns itself
with all the things related to the language too, for instance
building a C program.

"comp.std.c" is not about "standard C" but "the C standard" -- a significant
distinction.

The underlying issue: You can use bitbake, ant, GNU make, Berkeley make, SysV
make, shell scripts, various IDEs, and a few other things to build C programs.
There's no obvious reason for which "make" should be specially privileged, but
a group in which we discuss all of those rapidly ceases to be much use as
a group in which we discuss C.

-s
 
E

Ersek, Laszlo

[the usual - i.e. "go to hell"]

You are right. Next time I would put this kind of question out of this
group, this problem can occur with C though.

Please be aware that "Keith Thomson" is a troll who seeks to disrupt
this newsgroup by discouraging new posters from contributing. He won't
provide you with any help, so it's best just to ignore him.

I'm a new poster and he provided me with ample help (perhaps in c.l.c.m
and not here, I can't remember) and didn't "discourage" me in the least.

http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction#topicalityrationale

I think there's a way to differentiate between people reacting in a
knee-jerk "go away!" manner and people caring about topicality for the
reasons outlined in the clc wiki. The former group pollutes the group
even more, while the latter one actually helps by pointing out places
where the question is, well, more topical. In place of >>the usual -
i.e. "go to hell"<<,

You'll get better help either in
gnu.gcc.help or in comp.unix.programmer.


Also, misspelling someone's name isn't very polite.

Cheers,
lacos
 
A

Antoninus Twink

Build tools have their own newsgroups -

Are you arguing that nothing can be topical on more than one newsgroup?
for example, it took just a few seconds to identify these
likely-sounding groups:

Fantastic! I'll look up them up on Google groups right now.
comp.os-ms-windows.programmer.tools,

Hmmm, last non-spam post was May 12 2004.
comp.os.os2.programmer.tools,

Last non-spam post was Jun 3 2009.
comp.sys.mac.programmer.tools.

Last non-spam post was Oct 26 2009.

Wonderful! I bet the OP is kicking himself that he didn't post to one of
these bustling groups that are so full of life! He could have
single-handedly increased their post count for 2010 by an infinite
factor.
 
A

Antoninus Twink

If the executable was linked with shared library, then linker could
find the symobl even the order is not correct!
So, linker treats a and so differently?

Yes. If you think about what's going on under the hood, if you're
linking statically then each library function used by your program
needs to be copied into your executable. To avoid bloating the
executable, it makes sense only to include those functions that you
actually use. Of course, the linker *could* go back through the -l
arguments if there are still unresolved symbols after it's processed
them in order. I don't know why it doesn't.

For shared libraries, when your program starts up, the entire externally
visible symbol table of the library will be available, so there's no
reason for the compiler not to remember all the symbols when it sees
them - whether you use or don't use a function from the library in your
code makes no difference at all to the size of the executable.
Why doesn't GNU manual mention this?

I don't know - why don't you suggest it to them?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top