**未定义的引用** 链接两个相互引用的库时出错
**Undefined reference** error while linking two libraries referring to one-another
我在尝试编译引用两个库的 main 时收到 undefined reference 错误。我有两个文件 lib1/func1.c 和 lib2/func2.c 在不同的文件夹中。这些文件包含两个函数 print1()
和 print2()
,函数 print1()
正在调用 print2()
。
我将它们分别编译成两个库 libfunc1.a
和 libfunc2.a
。
但是,当我尝试编译调用 print1()
的 main 时,出现以下错误:
/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
这是代码和 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");
}
库必须按照需要它们的符号的顺序列出。
命令 cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1
告诉 linker 首先使用 func2
库来解析它正在构建的可执行文件中的任何未决引用,然后使用 func1
图书馆。
由于 linker 首先处理 func2
,并且在它这样做时,没有对 print2
的挂起引用,因此 linker 确实不在可执行文件中包含带有 print2
的模块。
稍后,当 linker 处理 func1
时,它在可执行文件中包含带有 print1
的模块,因为 main
使用它。该模块 print1
使用 print2
,因此包含该模块会添加对 print2
的新引用。然后,当 linker 完成处理 func1
时,它有一个未解析的引用。 linker 没有返回 func2
再次检查。
由于 func1
库依赖于 func2
,将 link 命令更改为 cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2
。
(如果func2
库也依赖func1
,那是一个糟糕的设计,应该重新考虑。如果不改变,请linker重新考虑库多次,如 -lfunc1 -lfunc2 -lfunc1
,可能会解决眼前的问题,但其他问题可能会出现。)
我在尝试编译引用两个库的 main 时收到 undefined reference 错误。我有两个文件 lib1/func1.c 和 lib2/func2.c 在不同的文件夹中。这些文件包含两个函数 print1()
和 print2()
,函数 print1()
正在调用 print2()
。
我将它们分别编译成两个库 libfunc1.a
和 libfunc2.a
。
但是,当我尝试编译调用 print1()
的 main 时,出现以下错误:
/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
这是代码和 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");
}
库必须按照需要它们的符号的顺序列出。
命令 cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1
告诉 linker 首先使用 func2
库来解析它正在构建的可执行文件中的任何未决引用,然后使用 func1
图书馆。
由于 linker 首先处理 func2
,并且在它这样做时,没有对 print2
的挂起引用,因此 linker 确实不在可执行文件中包含带有 print2
的模块。
稍后,当 linker 处理 func1
时,它在可执行文件中包含带有 print1
的模块,因为 main
使用它。该模块 print1
使用 print2
,因此包含该模块会添加对 print2
的新引用。然后,当 linker 完成处理 func1
时,它有一个未解析的引用。 linker 没有返回 func2
再次检查。
由于 func1
库依赖于 func2
,将 link 命令更改为 cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2
。
(如果func2
库也依赖func1
,那是一个糟糕的设计,应该重新考虑。如果不改变,请linker重新考虑库多次,如 -lfunc1 -lfunc2 -lfunc1
,可能会解决眼前的问题,但其他问题可能会出现。)