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.)