The answer of @Sergey L. is excellent, and will solve the problem. However, it doesn't capture the essence of what's going on. The behavior is actually in the OS X archiver ar
, which doesn't list common symbols in the table of contents (TOC) of an archive. I created the files as above, and here's a session with the archiver (OS X 10.9.4, Xcode 5.1.1):
$ gcc -c algorithm.c
$ gcc -c data.c
$ ar rcs libtestlibrary.a data.o algorithm.o
$ ar x libtestlibrary.a '__.SYMDEF SORTED'
$ od -c __.SYMDEF\ SORTED
0000000 \b \0 \0 \0 \0 \0 \0 \0 \0 002 \0 \0 020 \0 \0 \0
0000020 _ a l g o r i t h m \0 \0 \0 \0 \0 240
0000040
The TOC appears in the archive as an entry named __.SYMDEF SORTED
. As you can see the TOC doesn't contain my_var
. This is the essence of the problem.
You can add common symbols to the TOC using ranlib -c
. Here's how this works:
$ ranlib -c libtestlibrary.a
$ ar x libtestlibrary.a '__.SYMDEF SORTED'
$ od -c __.SYMDEF\ SORTED
0000000 020 \0 \0 \0 \b \0 \0 \0 020 002 \0 \0 \0 \0 \0 \0
0000020 210 \0 \0 \0 030 \0 \0 \0 _ m y _ v a r \0
0000040 _ a l g o r i t h m \0 Ѓ ** 177 \0 \0
0000060
As you can see, ranlib -c
added my_var
to the TOC.
Now the link step will work:
$ gcc -L . -o testapp main.o -ltestlibrary
$
Thus, it's not absolutely necessary to recompile the code to get the link to work.
The man page for ranlib says this:
-c Include common symbols as definitions with respect to the table
of contents. This is seldom the intended behavior for linking
from a library, as it forces the linking of a library member
just because it uses an uninitialized global that is undefined
at that point in the linking. This option is included only
because this was the original behavior of ranlib. This option
is not the default.
So, this is an intentional deviation from traditional behavior, to avoid linking unneeded modules into the output. I'll probably use -fno-common
in my own development.