4

私はこのMakefileに出くわしました(sendipと呼ばれるオープンソースプロジェクトを通して見つけました)

このファイルに関して2つの混乱があります-

  1. ここで.c依存関係としてファイルが指定されているのはどこですか?ipv6.soのようなすべてのライブラリtcp.soは正常に生成されていますが、ここのどの行がそれを担当していますか?

これが線だと思います.....そうですか??

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

ただし、$(LIBS)一部の.oファイルのみを指定してください。これ$+は何かをしていますか?

2.聞いたことがない$+$?私はそれを見つけようとしました、そして$@、、、などのような他の多くに出くわしました$<が、これを見たことがありませんでした。動作は同じだと思います$?が、それでも.c依存関係を指定する必要があります。

Makefile:

#configureable stuff 

PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/share/man/man1
LIBDIR ?= $(PREFIX)/lib/sendip

#For most systems, this works
INSTALL ?= install

#For Solaris, you may need
#INSTALL=/usr/ucb/install

CFLAGS= -fPIC -fsigned-char -pipe -Wall -Wpointer-arith -Wwrite-strings \
-Wstrict-prototypes -Wnested-externs -Winline -Werror -g -Wcast-align \
-DSENDIP_LIBS=\"$(LIBDIR)\"

#-Wcast-align causes problems on solaris, but not serious ones

LDFLAGS=        -g -rdynamic -lm -ldl
#LDFLAGS_SOLARIS= -g -lsocket -lnsl -lm
LDFLAGS_SOLARIS= -g -lsocket -lnsl -lm -ldl
LDFLAGS_LINUX= -g  -rdynamic -lm -ldl
LIBCFLAGS= -shared
CC=     gcc-4.4

PROGS= sendip
BASEPROTOS= ipv4.so ipv6.so
IPPROTOS= tcp.so udp.so icmp.so
UDPPROTOS= rip.so ripng.so ntp.so
TCPPROTOS= bgp.so
PROTOS= $(BASEPROTOS) $(IPPROTOS) $(UDPPROTOS) $(TCPPROTOS)
LIBS= libsendipaux.a
LIBOBJS= csum.o compact.o protoname.o headers.o parseargs.o 
         cryptomod.o crc32.o
SUBDIRS= mec

all:    $(LIBS) subdirs sendip $(PROTOS) sendip.1 sendip.spec

#there has to be a nice way to do this

sendip: sendip.o        gnugetopt.o gnugetopt1.o compact.o
    sh -c "if [ `uname` = Linux ] ; then \
$(CC) -o $@ $(LDFLAGS_LINUX) $(CFLAGS) $+ ; \
elif [ `uname` = SunOS ] ; then \
   $(CC) -o $@ $(LDFLAGS_SOLARIS) $(CFLAGS) $+ ;\
else \
$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $+ ; \
fi"

libsendipaux.a: $(LIBOBJS)
    ar vr $@ $?

subdirs:
    for subdir in $(SUBDIRS) ; do \
            cd $$subdir ;\
            make  ;\
            cd ..  ;\
            done

protoname.o:    mec/protoname.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

headers.o:      mec/headers.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

parseargs.o:    mec/parseargs.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

cryptomod.o:    mec/cryptomod.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

crc32.o: mec/crc32table.h mec/crc32.c
    $(CC) -o $@ -c -I. $(CFLAGS) mec/crc32.c

mec/crc32table.h: mec/gen_crc32table
    mec/gen_crc32table > mec/crc32table.h

sendip.1:       ./help2man $(PROGS) $(PROTOS) subdirs VERSION
                    ./help2man -n "Send arbitrary IP packets" -N >sendip.1
4

2 に答える 2

5

はい、あなたが正しい。

ターゲット定義が文字で始まる場合%、特定のパターンではなく、ターゲット パターンを定義します。So%.soは、他のターゲットが必要とする、またはユーザーが必要とするすべての .so ファイルを生成するターゲットを意味します。%.cもパターンで、すべてのファイルを意味します.c

したがって、$(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)コマンド出力には、生成されるターゲットの名前 ($@ -> パターンに一致したターゲットの名前) が$+含まれることを意味し、パターンに一致したすべてのファイルprerequisite(つまり: %.c) を意味します。

GNU make マニュアル、特にCatalog of Rulesを見て$+、 , $^, ... の意味を確認してください。

于 2013-01-21T02:38:43.730 に答える
1

これらのいくつかは、GNU Make(別名「gmake」)の拡張機能です。

GNU makeは、2つの異なるフェーズで機能します。最初のフェーズでは、すべてのmakefile、含まれているmakefileなどを読み取り、すべての変数とその値、暗黙的および明示的なルールを内部化し、すべてのターゲットとその前提条件の依存関係グラフを作成します。2番目のフェーズでは、makeはこれらの内部構造を使用して、再構築する必要のあるターゲットを決定し、そのために必要なルールを呼び出します。

...最初のフェーズで展開が発生した場合、すぐに展開されると言います。この場合、makeは、makefileが解析されるときに、構成のそのセクションにある変数または関数を展開します。拡張がすぐに実行されない場合、拡張は延期されると言います。据え置きコンストラクトの拡張は、コンストラクトが後ですぐに表示されるまで、または2番目のフェーズまで実行されません。

于 2013-01-21T02:29:31.557 に答える