Search code examples
cgccstatic-librariesstatic-linking

gcc static linking undefined references


I made a static library using ar to make a simple word counter, but when I reach the linking stage in my makefile, I get the following error:

g++ -o wordcount obj/word.o obj/main.o   -Wall -L lib  -llinkedlist
obj/word.o: In function `cleanUp(linkedList*)':
word.c:(.text+0x83): undefined reference to `ll_clear(linkedList*)'
obj/word.o: In function `initialize(linkedList*)':
word.c:(.text+0xa7): undefined reference to `ll_init(linkedList*)'
obj/word.o: In function `getTotalWordCount(linkedList*)':
word.c:(.text+0xbd): undefined reference to `ll_getIterator(linkedList*)'
word.c:(.text+0xd7): undefined reference to `ll_next(linkedListIterator*)'
word.c:(.text+0xea): undefined reference to `ll_hasNext(linkedListIterator*)'
obj/word.o: In function `getWord(linkedList*, unsigned int)':
word.c:(.text+0x118): undefined reference to `ll_get(linkedList*, unsigned int)'
obj/word.o: In function `findWord(linkedList*, char*)':
word.c:(.text+0x12e): undefined reference to `ll_getIterator(linkedList*)'
word.c:(.text+0x148): undefined reference to `ll_next(linkedListIterator*)'
word.c:(.text+0x178): undefined reference to `ll_hasNext(linkedListIterator*)'
obj/word.o: In function `combineCounts(linkedList*, wordData*)':
word.c:(.text+0x26e): undefined reference to `ll_add(linkedList*, void const*, unsigned int)'
obj/main.o: In function `main':
main.c:(.text+0x1df): undefined reference to `ll_getIterator(linkedList*)'
main.c:(.text+0x1f2): undefined reference to `ll_next(linkedListIterator*)'
main.c:(.text+0x25c): undefined reference to `ll_hasNext(linkedListIterator*)'
collect2: error: ld returned 1 exit status
makefile:38: recipe for target 'wordcount' failed
make: *** [wordcount] Error 1

However, using nm to look at the symbol table for my library produces these results (truncated for readability):

linkedlist.o:
00000028 T ll_add
00000124 T ll_addIndex
000003b7 T ll_clear
00000363 T ll_get
00000438 T ll_getIterator
00000477 T ll_hasNext
00000000 T ll_init
00000493 T ll_next
00000285 T ll_remove
00000420 T ll_size

All the answers I've found for similar questions mention that the order in which you specify libraries matters, but I already am adding my library after all my other object files. Does anyone have any ideas where I might be going wrong?


Solution

  • The issue is that the library was compiled by a C compiler, but I had compiled my new sources that reference the library with a C++ compiler. The object file output is different between these two methods. Take the following code for example:

    // main.c
    #include <stdio.h>
    
    void foo(int x) {
      printf("%d\n");
    }
    
    int main(int argc, char** argv) {
      foo(argc);
      return 0;
    }
    

    Compiling this file into an object file as a C program will produce different symbols than compiling as a C++ program. Example:

    # Compile as C program
    $ gcc -c main.c; nm main.o
    00000000 T foo
    00000018 T main
             U printf
    
    # Compile as C++ program
    $ g++ -c main.c; nm main.o
    00000018 T main
             U printf
    00000000 T _Z3fooi
    

    As you can see the foo function compiled with two different symbols. Since the new source files were compiled as C++, the linker expected C++ style symbols while the library contained C style symbols. The linker couldn't match the symbols and therefore throws an error since the C++ symbols are undefined.