向Makefile添加功能会产生错误: - "这里有多个definitoon ......"

Udi*_*pta 0 gcc makefile static-libraries static-linking

我已经获得了一个已经正常工作的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
Run Code Online (Sandbox Code Playgroud)

还有这个

 linklayer.o:    linklayer.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+
Run Code Online (Sandbox Code Playgroud)

我已经声明了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
Run Code Online (Sandbox Code Playgroud)

为什么这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
Run Code Online (Sandbox Code Playgroud)

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

我想它无法帮助我....实际问题在于我对场景本身的理解.请帮我摆脱一塌糊涂.

uml*_*ute 5

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

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

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

 %.so: %.c $(LIBS)
        $(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)
Run Code Online (Sandbox Code Playgroud)

在这个目标中,$+将扩展到目标的所有依赖关系(即:%.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) $+
Run Code Online (Sandbox Code Playgroud)

顺便说一下,你得到的remake关于不存在的文件的错误是因为all并且subdirs确实没有文件,而是虚假的目标(没有生成在目标名称之后调用的文件的目标).

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

.PHONY: all subdirs
Run Code Online (Sandbox Code Playgroud)