• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

darn program won't link ...

ChristTrekker

Well-known member
So, what do you do when everything compiles but fails to link because of an "undefined symbol" error? I don't see how it's undefined, as the code includes the header files, and the requisite library is being linked to... Something else must be wonky but I don't know what to check.

 

II2II

Well-known member
IIRC, undefined symbol would be a linker error. It may mean that you're not using the right version of the library, or that you didn't tell the compiler to link against the library.

 

porter

Well-known member
1. generate a linker map to see what the linker thought it was doing.

2. use "nm" to confirm that the API actually exists in the library.

3. write a tiny program that just looks for that single function and just link to that library

4. the order of the libraries in the link line is important,

eg ld myobj1.o myobj2.o -ltom -ldick -lharry -lc -o banana

libharry.a cannot depend on a function in libtom.a unless that code was hauled in due to myobj1.o or myobj2.o

5. use the undefined symbol option in the linker to force the library to be referenced at the start

 

ChristTrekker

Well-known member
1. generate a linker map to see what the linker thought it was doing.
I didn't know about that. Guess it helps to read the man pages of the tools thoroughly...

2. use "nm" to confirm that the API actually exists in the library.
Both exist in libposix.a.

4. the order of the libraries in the link line is important,
eg ld myobj1.o myobj2.o -ltom -ldick -lharry -lc -o banana

libharry.a cannot depend on a function in libtom.a unless that code was hauled in due to myobj1.o or myobj2.o
I know you've said this before, and I still think that order looks backwards. I guess I really should read through the ld man page more closely to get some further hints about this, and think through the way my command line gets processed for linkage. FWIW...

Code:
gcc  -I/opt/include -D_POSIX_SOURCE  -lposix -o cvs add.o admin.o annotate.o  buffer.o checkin.o checkout.o  classify.o client.o commit.o  create_adm.o cvsrc.o diff.o  edit.o entries.o error.o  expand_path.o fileattr.o filesubr.o  find_names.o hardlink.o hash.o  history.o ignore.o import.o  lock.o log.o login.o logmsg.o  main.o mkmodules.o modules.o  myndbm.o no_diff.o parseinfo.o  patch.o rcs.o rcscmds.o  recurse.o release.o remove.o  repos.o root.o run.o  scramble.o server.o stack.o  status.o subr.o tag.o update.o  version.o vers_ts.o watch.o  wrapper.o zlib.o ../diff/libdiff.a  ../lib/libcvs.a  ../zlib/libz.a
collect2: ld returned 13 exit status
undefined               first referenced
symbol                     in file
tcgetattr                       ../lib/libcvs.a
tcsetattr                       ../lib/libcvs.a
ld fatal: Symbol referencing errors. No output written to cvs
Does any of this look wrong?

5. use the undefined symbol option in the linker to force the library to be referenced at the start
See? There's something else I'd know if I reread the ld man page.

Thanks...

 

ChristTrekker

Well-known member
4. the order of the libraries in the link line is important,
eg ld myobj1.o myobj2.o -ltom -ldick -lharry -lc -o banana
OK, I think I wrapped my brain around this now. I thought that you could reference any symbol that came before you, but rather, missing symbols may be resolved by anything that comes after you.

 
Last edited by a moderator:

ChristTrekker

Well-known member
I re-ran the line from above with the -lposix flag at the very end, and that fixed it. Now that I've got this drilled into my brain, I'll double-check the argument order whenever I have a linker error! Is there some foolproof way I can specify env vars to configure so that these kind of problems automatically go away?

 

porter

Well-known member
I know you've said this before, and I still think that order looks backwards.
Think of it this way, the linker only looks in a library when it is looking for something, and it only looks for currently unresolved symbols. When it finds it it (a) strikes it from the list of unresolved symbols ( B) checks for unresolved symbols in the object file it just hauled from the library.

At the start, the only unresolved symbol it has for an application is "main", as you add object files it increases the number of unsresolved symbols. Hence the order should always be object files then libraries.

 

ChristTrekker

Well-known member
At the start, the only unresolved symbol it has for an application is "main", as you add object files it increases the number of unsresolved symbols. Hence the order should always be object files then libraries.
I just happened upon this same thing again, but fortunately, I remembered the solution this time. Still, when I have to specify LDFLAGS="-lposix" at the command line (as is common with A/UX!), there has to be a way of making the library come after the objects rather than before.

 

porter

Well-known member
Still, when I have to specify LDFLAGS="-lposix" at the command line (as is common with A/UX!), there has to be a way of making the library come after the objects rather than before.
Yes, you set LD to

Code:
LD=myscriptwhichreorderstheargumentstoputdependentlibrariesintherightorderattheendthencallsoriginalld.sh
 

ChristTrekker

Well-known member
Heh.

Well I just realized this problem may have been due to bad advice I was given way back. If I specify these extra libs in LIBS instead of LDFLAGS on the command line, it seems more likely that configure will build the Makefile to put them in the right order. I'd been told that any linker/loader flags ought to be specified in LDFLAGS.

 

porter

Well-known member
I'd been told that any linker/loader flags ought to be specified in LDFLAGS.
Not quite. LDFLAGS are used with LD.

CFLAGS are used with CC.

LIBS could in theory be used by both CC or LD, however in A/UX and most statically linked environments there is no need to use LD at all.

Normally, LD is only needed on some platforms to generate shared libraries.

Of course, that doesn't mean the CC won't use LD, typically it will and provide it's own crt*.o and -lc.

 
Top