Home > Back-end >  **Undefined reference** error while linking two libraries referring to one-another
**Undefined reference** error while linking two libraries referring to one-another

Time:06-02

I am getting undefined reference error while trying to compile main that refers to two libraries. I have two files lib1/func1.c and lib2/func2.c in separate folders. Those files contain two functions print1() and print2(), function print1() is calling print2(). I am compiling those separately into two libraries libfunc1.a and libfunc2.a. But when I am trying to compile main which is calling print1(), I get the following error:

/usr/bin/ld: /home/sv/ztest2/lib1/libfunc1.a(func1.o): in function print1:
/home/sv/ztest2/lib1/func1.c:7: undefined reference to print2
collect2: error: ld returned 1 exit status
make: *** [Makefile:21: DP] Error 1

Here is the code and Makefiles:

Makefile:

TARGET = DP
HOME = /home/slav/FORECAST/ztest2

INCDIRS = -I./ \
      -I$(HOME)/lib1 \
      -I$(HOME)/lib2

LIBDIRS = -L$(HOME)/lib1 \
      -L$(HOME)/lib2

SRCFILES = DP.c
OBJFILES = DP.o

CFLAGS = -g -O3 $(INCDIRS)

all: $(TARGET)

$(TARGET): $(OBJFILES)
    cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1

clean:
    -rm *.o $(TARGET)

DP.c:

#include "func1.h"
int main()
{
    print1();
    return 0;
}

func1.h:

void print1();

func1.c:

#include <stdio.h>
void print1()
{
    printf("print1 is called!\n");
    print2();
}

func2.h:

extern void print2();

func2.c:

#include <stdio.h>
void print2()
{
    printf("print2 is called!\n");
}

CodePudding user response:

Libraries must be listed in the order their symbols are needed.

The command cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1 tells the linker to first use the func2 library to resolve any pending references in the executable it is building and then to use the func1 library.

Since the linker processes func2 first, and, at the time it does so, there is no pending reference to print2, the linker does not include the module with print2 in the executable.

Later, when the linker is processing func1, it includes the module with print1 in the executable because main uses it. That module print1 uses print2, so including that module adds a new reference to print2. Then, when the linker is done processing func1, it has an unresolved reference. The linker does not go back to func2 to check it again.

Since the func1 library depends on func2, change the link command to cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2.

(If the func2 library also depends on func1, that is a bad design and should be reconsidered. If it is not changed, asking the linker to reconsider the libraries multiple times, as with -lfunc1 -lfunc2 -lfunc1, might fix the immediate problem, but others can arise.)

  • Related