0

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?

  • Is linked_list.o a C file or a C++ file? – Jonathan Leffler Sep 30 '15 at 07:06
  • 1
    so you definitely have lib at the same level as obj and linkedlist is placed inside it as as .a or .so file correct ? – asio_guy Sep 30 '15 at 07:08
  • 1
    Is `linkedlist` really a *library* and not an *object* file? – Some programmer dude Sep 30 '15 at 07:09
  • If you are indeed programming in C, don't use g++ to compile or link your code. If you're calling a C library from C++ code, do the header file of that C library have the necessary `extern "C"` wrappers ? – nos Sep 30 '15 at 07:09
  • suspecting it to be gcc -o wordcount obj/word.o obj/main.o /linkedlist.o – asio_guy Sep 30 '15 at 07:10
  • linkedlist.o is the object file that the static library was created. The actual library file is lib/liblinkedlist.a – maybe_confused Sep 30 '15 at 07:44
  • @nos The library, and all source files are in c. Switching my compiler from g++ to gcc actually solved the problem. Do you have any ideas why this happened? – maybe_confused Sep 30 '15 at 07:47
  • @maybe_confused You are compiling with g++, so you are really compiling C++ code, even though the file extension is .c, and the code is also valid C. (Your library however, seem to be compiled as C code). You need to take special actions when calling C code from C++ code, see e.g. http://stackoverflow.com/questions/16850992/call-a-c-function-from-c-code – nos Sep 30 '15 at 08:30

1 Answers1

0

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.