Questions about Makefile - what is “$+” & where are .c files/dependencies called here ?

假如想象 提交于 2019-12-10 16:54:51

问题


I came across this Makefile (found it through an open source project called sendip)

I have two confusions regarding this file -

  1. Where are .c files being specified as dependencies here? Although all the libraries like ipv6.so, tcp.so are being generated fine, but which line here is responsible for it?

I think this is the line ..... Right ??

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

but $(LIBS) only specify some .o files. IS this $+ doing something ?

2.I have never heard of $+. I tried to find it out and came across many others like $?, $@, $<, etc. but never seen this one. I think it behaves like $? but still it also demands .c depndencies to be specified.

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

回答1:


Yes you're right.

When a target definition start with the % character it defines a target pattern, not a specific pattern. So %.so means a target to generate all .so files needed by other targets or required by the user. The %.c also is a pattern and means all .c files.

So the $(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS) means the command output will have the name of the target being generated ($@ -> name of the target that matched the pattern) ... and the $+ means all the files that matched with the prerequisite pattern (i.e: %.c).

Take a look at the GNU make manual, specifically at the Catalogue of Rules to see what $+, $^, ... mean.




回答2:


Some of these are extensions to GNU Make (aka "gmake"):

  • http://www.gnu.org/software/make/manual/make.html#Reading-Makefiles

    Variable definitions are parsed as follows:

     immediate = deferred
     immediate ?= deferred
     immediate := immediate
     immediate += deferred or immediate
    

GNU make does its work in two distinct phases. During the first phase it reads all the makefiles, included makefiles, etc. and internalizes all the variables and their values, implicit and explicit rules, and constructs a dependency graph of all the targets and their prerequisites. During the second phase, make uses these internal structures to determine what targets will need to be rebuilt and to invoke the rules necessary to do so.

... We say that expansion is immediate if it happens during the first phase: in this case make will expand any variables or functions in that section of a construct as the makefile is parsed. We say that expansion is deferred if expansion is not performed immediately. Expansion of a deferred construct is not performed until either the construct appears later in an immediate context, or until the second phase.



来源:https://stackoverflow.com/questions/14431581/questions-about-makefile-what-is-where-are-c-files-dependencies-called

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!