4

我遇到了这个 Makefile(通过一个名为 sendip 的开源项目找到它)

我对此文件有两个困惑-

  1. 文件在哪里.c被指定为依赖项?ipv6.so尽管像,之类的所有库tcp.so都可以正常生成,但是这里的哪一行负责呢?

我认为这是行.....对吗??

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

$(LIBS)只指定一些 .o 文件。这是$+在做什么吗?

2.没听说过$+。我试图找出它并遇到了许多其他人,例如,,,等$?,但从未见过这个。我认为它的行为就像但它仍然需要指定依赖关系。$@$<$?.c

生成文件:

#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 在两个不同的阶段完成它的工作。在第一阶段,它读取所有的 makefile、包含的 makefile 等,并内化所有变量及其值、隐式和显式规则,并构建所有目标及其先决条件的依赖图。在第二阶段,make 使用这些内部结构来确定需要重建哪些目标并调用必要的规则来这样做。

...我们说,如果它发生在第一阶段,扩展是立即的:在这种情况下,make 将在解析 makefile 时扩展该构造部分中的任何变量或函数。如果不立即执行扩展,我们说扩展是延迟的。直到构造稍后出现在直接上下文中或直到第二阶段才执行延迟构造的扩展。

于 2013-01-21T02:29:31.557 回答