0

我得到了一个已经在工作的 Makefile,它实际上工作正常。

Makefile 的内容可以在这篇文章中找到...

关于 Makefile 的问题 - 什么是“$+”&这里调用的 .c 文件/依赖项在哪里?

我将这个问题与上面提到的我之前的帖子分开提出,因为它涉及一个不同的问题,并且将其添加到该问题会不必要地增加其长度。

现在我又添加了一个在很多地方都非常频繁使用的功能,所以我认为创建一个单独的文件会是一个好主意,所以我创建linklayer.c并添加linklayer.o$LIBOBJS.

我加了这个...

 LIBOBJS= linklayer.o csum.o compact.o protoname.o headers.o 
 parseargs.o cryptomod.o crc32.o

和这个

 linklayer.o:    linklayer.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

我已经声明了sendip_module.h已经在项目中存在的每个模块中声明和访问的函数。

但是现在这个多重定义错误来了......我做错了什么或误解了什么?

注意: “ipv6_opts”在 ipv6.h 中定义

$ make all
for subdir in mec ; do \
    cd $subdir ;\
    make  ;\
    cd ..  ;\
    done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
  gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith 
 -Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror
 -g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c
  libsendipaux.a libsendipaux.a

 libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
                              : multiple definition of `ipv6_opts'
 /tmp/ccxa4tMX.o:(.data.rel.local+0x0): first defined here
 collect2: ld returned 1 exit status
 make: *** [ipv6.so] Error 1

为什么这libsendipaux.a libsendipaux.a两次?Makefile 本身是否有问题。

我是否首先需要手动编译它然后将其添加到 libsendipaux.a ?

我是这个 Makefile 东西的新手,所以请帮助我了解这一切是如何在这里工作的?

谢谢。

编辑 :

重新制作调试输出 -

 remake -x

Reading makefiles...
Updating goal targets....
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:33 File `all' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 File `subdirs' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Must remake target `subdirs'.
for subdir in mec ; do \
    cd $subdir ;\
    make  ;\
    cd ..  ;\
    done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Successfully remade target file    
`subdirs'.
File `ipv6.so' does not exist.
Must remake target `ipv6.so'.
gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith 
-Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror 
-g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c 
 libsendipaux.a libsendipaux.a
 libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
                                  : multiple definition of `ipv6_opts'
 /tmp/ccb0oaXR.o:(.data.rel.local+0x0): first defined here
 collect2: ld returned 1 exit status
 remake: *** [ipv6.so] Error 1

 #0  ipv6.so at ??
 #1  all at /home/udit/Desktop/sendip-2.5-mec-2/Makefile:33

33rd line -> all: $(LIBS) subdirs sendip $(PROTOS) sendip.1 sendip.spec

我想这对我没有帮助....实际问题在于我对场景本身的理解。请帮我摆脱混乱。

4

1 回答 1

5

您面临的问题是,您将几个对象链接在一起,其中至少两个对象定义了 de function ipv6_opts。由于该函数有两种实现,因此您的链接器无法决定使用哪一种并引发错误。

问题很可能来自您将libsendipaux.a两次链接到最终二进制文件的事实。

发生这种情况的原因在这里:

 %.so: %.c $(LIBS)
        $(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)

在此目标中,$+将扩展到您的目标的所有依赖项(即:%.c $(LIBS),这又将被解析为ipv4.c libsendipaux.a

然后,对编译器的实际调用可以读取为$(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) ipv4.c $(LIBS) $(LIBS)$(LIBS) $(LIBS)并将扩展为libsendipaux.a libsendipaux.a,这将产生错误的双链接。

所以解决方案是从 .so 目标中删除无关的 $(LIBS) :

 %.so: %.c $(LIBS)
        $(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+

顺便说一句,您在不存在文件中遇到的错误remake是因为all并且subdirs确实没有文件,而是虚假目标(不生成在目标名称之后调用的文件的目标)。

为防止出现这些警告,请在 makefile 中添加以下内容:

.PHONY: all subdirs
于 2013-01-22T18:08:45.267 回答