0

私は実際に正常に動作しているすでに動作しているMakefileを与えられました。

Makefileの内容はこの投稿で見つけることができます...

Makefileに関する質問-「$+」とは何ですか?ここで.cファイル/依存関係はどこで呼び出されますか?

この質問は、上記の以前の投稿とは別に質問しています。これは別の問題を含み、その質問に追加すると、その長さが不必要に長くなるためです。

これで、多くの場所で非常に頻繁に使用される機能をもう1つ追加したので、別のファイルを作成するのは良い考えだと思ったので、を作成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.a2回?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

あなたが直面している問題は、少なくとも2つのオブジェクトがdefunctionを定義しているいくつかのオブジェクトをリンクしていることですipv6_opts。関数には2つの実装があるため、リンカはどちらを使用するかを決定できず、エラーをスローします。

問題はおそらくlibsendipaux.a、最終的なバイナリに2回リンクしているという事実に起因します。

これが発生する理由はここにあります:

 %.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ところで、存在しないファイルに関して発生するエラーは、実際allsubdirsはファイルがないためですが、偽のターゲット(ターゲット名の後に呼び出されるファイルを生成しないターゲット)です。

これらの警告を防ぐには、makefileに次のようなものを追加します。

.PHONY: all subdirs
于 2013-01-22T18:08:45.267 に答える