T Lytle
T Lytle

Reputation: 199

How to Simplify Repeated Rules in Makefile (GNU Make)

Using GNU Make 3.81. This Makefile has some repeating rules that I feel can be simplified but I cannot figure out how to do it.

The Makefile needs to unpack a tarball if the directory does not exist. It should then copy in my versions of the source files in the tarball into the tarball and then run a configure and make on it to generate the target binary.

BLARG = blarg-1.8.6

blarg: $(BLARG)/get_key.c $(BLARG)/grab_key.c $(BLARG)/keys.c $(BLARG)/options.c $(BLARG)/blarg.c
        cd $(BLARG) && ./configure --disable-guile && $(MAKE) && cp blarg ../

$(BLARG):
        cp /pub/tars/$(BLARG).tar.gz .
        tar -xvf $(BLARG).tar.gz
        rm $(BLARG).tar.gz

$(BLARG)/get_key.c: get_key.c | $(BLARG)
       cp $< $@

$(BLARG)/grab_key.c: grab_key.c | $(BLARG)
       cp $< $@

$(BLARG)/keys.c: keys.c | $(BLARG)
       cp $< $@

$(BLARG)/options.c: options.c | $(BLARG)
       cp $< $@

$(BLARG)/blarg.c: blarg.c | $(BLARG)
       cp $< $@

$(BLARG)/options.h: options.h | $(BLARG)
       cp $< $@

I feel like there should be a way to do something like this instead:

BLARG = blarg-1.8.6
SRCS = $(addprefix $(BLARG)/,get_key.c grab_key.c keys.c options.c options.h blarg.c)

blarg: $(SRCS)
    cd $(BLARG) && ./configure --disable-guile && $(MAKE) && cp blarg ../

$(BLARG):
    cp /pub/tars/$(BLARG).tar.gz .
    tar -xvf $(BLARG).tar.gz
    rm $(BLARG).tar.gz

$(SRCS): $($@=$(BLARG)/%=%) | $(BLARG)
    cp $< $@

However, this gives me the following error:

cp  blarg-1.8.6/get_key.c
cp: missing destination file operand after `blarg-1.8.6/get_key.c'

Any suggestions?

Upvotes: 2

Views: 441

Answers (1)

Beta
Beta

Reputation: 99094

This:

$(SRCS): $($@=$(BLARG)/%=%) | $(BLARG)
    cp $< $@

doesn't work as you intend. The automatic variable $@ isn't available in the prerequisite field, so that whole term expands to nothing, so $< expands to nothing, so the command comes out:

cp DEST

I suggest a static pattern rule instead:

$(SRCS): $(BLARG)/%.c: %.c | $(BLARG)
    cp $< $@

P.S. You can also simplify the $(BLARG) rule. By default, tar unpacks a tarball into the working directory, so there's no need to copy, then unpack, then delete:

$(BLARG):
    tar -xvf /pub/tars/$(BLARG).tar.gz

Upvotes: 5

Related Questions