Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

% and * together on the dependency line

I have been using strange rules like this for a long time, but suddenly they are breaking on a new environment.

Is there a robust way to do this?

all: test.1.out

test.%.out: %/test*.out
    /bin/cp -f $< $@

On my box (ubuntu):

alishan:~/Dropbox/make_insanity> make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-pc-linux-gnu
alishan:~/Dropbox/make_insanity> make
/bin/cp -f 1/test.out test.1.out

No problem with this kind of code on other people's Macs, ubuntu machines, ubuntu virtual machines. Don't know all their make versions, but it seems like OK code.

On my mageia server in the same directory after clearing.

[dushoff@yushan make_insanity]$ make --version
GNU Make 3.82
Built for x86_64-mageia-linux-gnu
Copyright (C) 2010  Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[dushoff@yushan make_insanity]$ make
make: *** No rule to make target `test.1.out', needed by `all'.  Stop.
[dushoff@yushan make_insanity]$ 

Changing either the % or * to appropriate text "fixes" the problem, but of course does not produce the desired generality.

like image 332
Jonathan Dushoff Avatar asked Nov 10 '22 01:11

Jonathan Dushoff


1 Answers

I'm not absolutely sure but I think you want

test.<name>.out

to be made from

<name>/test.out

(if it exists). If that's right, you can do it robustly by reverse-engineering the name of the prerequisite for each target from the name of the target, e.g.

targs := test.1.out test.a.out

define src_of =
$(patsubst .%,%,$(suffix $(basename $(1))))/$(basename $(basename $(1)))$(suffix $(1))
endef

all: $(targs)

test.%.out: $(call src_of,test.%.out)
    cp -f $< $@

clean:
    rm -f *.*.out

It's a bit of a mouthful, admittedly.

So if we pre-arrange a demo where the prerequisites exist:

$ ls -LR
.:
1  a  Makefile

./1:
test.out

./a:
test.out
$ make
cp -f 1/test.out test.1.out
cp -f a/test.out test.a.out
like image 117
Mike Kinghan Avatar answered Jan 01 '23 00:01

Mike Kinghan