【问题标题】:Questions about Makefile - what is "$+" & where are .c files/dependencies called here ?关于 Makefile 的问题 - 什么是“$+”&这里调用的 .c 文件/依赖项在哪里?
【发布时间】:2013-01-04 02:11:11
【问题描述】:

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

我对这个文件有两个困惑 -

  1. .c 文件在哪里被指定为依赖项?虽然ipv6.sotcp.so 等所有库都生成正常,但这里的哪一行负责呢?

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

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

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

2.我从未听说过$+。我试图找到它并遇到了许多其他的,例如$?$@$< 等,但从未见过这个。我认为它的行为类似于$?,但它仍然要求指定.c depndencies。

生成文件:

#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

【问题讨论】:

    标签: gcc makefile dependencies gnu-make


    【解决方案1】:

    是的,你是对的。

    当目标定义以% 字符开头时,它定义了目标模式,而不是特定模式。所以%.so 表示一个目标,它可以生成其他目标需要或用户需要的所有 .so 文件。 %.c 也是一种模式,表示所有 .c 文件。

    所以$(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS) 表示命令输出将具有正在生成的目标的名称($@ -> 与模式匹配的目标的名称)......而$+ 表示与匹配的所有文件prerequisite 模式(即:%.c)。

    查看 GNU make 手册,特别是 Catalogue of Rules 以了解 $+$^、... 的含义。

    【讨论】:

      【解决方案2】:

      其中一些是 GNU Make(又名“gmake”)的扩展:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-10
        • 1970-01-01
        • 1970-01-01
        • 2019-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-26
        相关资源
        最近更新 更多