Reputation: 41
Lets assume, i want to call
make somepath/abc.pot
which depends on somepath/somefiles.c
My target I've created so far looks like
%.pot: $(dir $@)*.c
@echo "it works"
ifeq (,$(wildcard $@))
# pot-file does not exist, do something
else
# pot-file already exists, do something else
endif
but does not work as the Automatic Variables like $@ are not available in the prerequisites.
If found, that i can enable second expansion
.SECONDEXPANSION:
%.pot: $$(dir $$@)*.c
@echo "it works"
ifeq (,$(wildcard $@))
# pot-file does not exist, do something
else
# pot-file already exists, do something else
endif
which allows me to use $@ in the prerequisites but breaks my ifeq statement which then always results in the first branch. If I change the ifeq to
ifeq (,$$(wildcard $$@))
it's working again but I really don't get why.
Now there a two questions:
A) Is there another way but to enable second expansion to have the path of the target in my prerequisites?
B) Why does the ifeq (,$(wildcard $@))
statement always result in the first branch if second expansion is enabled?
Upvotes: 1
Views: 552
Reputation: 80931
Don't use ifeq
in the recipe at all. Just use normal shell functionality. It works better.
.SECONDEXPANSION:
%.pot: $$(dir $$@)*.c
@echo "it works"
if [ ! -f $@ ]; then \
: pot-file does not exist, do something; \
else \
: pot-file already exists, do something else; \
fi
That said using wildcard in prerequisite lists is generally a bad idea because the time that they are globbed is not reliable and can cause odd behaviors. See Pitfalls of Using Wildcards for one example of a problem.
If you need to write different recipe contents based on some external factor (like OS) then you need to detect that at make parse time and have two copies of your recipes/makefile that you switch between correctly. You can do that inline but you can't do that per-recipe inline.
Your original attempts (using ifeq
in a recipe) do not work. They don't do what you think they do. They may appear to work but they aren't working the way you expect.
Consider this makefile:
all: c
a:
@touch a
c: a
.SECONDEXPANSION:
c d:
ifeq (,$(wildcard a))
@echo "a doesn't exist (make)"
else
@echo 'a does exist (make)'
endif
@if [ ! -f a ]; then \
echo "a doesn't exist (sh)"; \
else \
echo 'a does exist (sh)'; \
fi
ifeq (,$$(wildcard a))
@echo "a doesn't exist (make se)"
else
@echo 'a does exist (make se)'
endif
In an empty directory you would expect make
to output (assuming ifeq
works the way you want it to):
a does exist (make)
a does exist (sh)
a does exist (make se)
Right? But it doesn't. You get:
a doesn't exist (make)
a does exist (sh)
a does exist (make se)
Ok, you think, that's just things not working without secondary expansion. But the secondary expansion version is working correctly. But it isn't.
If you run make d
in an empty directory (note the d
target doesn't list a
as a prerequisite so it won't create it) you would expect the following output:
a doesn't exist (make)
a doesn' exist (sh)
a doesn' exist (make se)
Right? But what you actually get is:
a doesn't exist (make)
a doesn't exist (sh)
a does exist (make se)
So it appears that the secondary expansion version isn't working either.
A look at the make database explains why not.
Run make -qprR | awk '/c: a/,/^$/; /d:/,/^$/'
in an empty directory and you see:
c: a
# Implicit rule search has not been done.
# File does not exist.
# File has been updated.
# Needs to be updated (-q is set).
# variable set hash-table stats:
# Load=0/32=0%, Rehash=0, Collisions=0/2=0%
# commands to execute (from `Makefile', line 12):
@echo "a doesn't exist (make)"
@if [ ! -f a ]; then \
echo "a doesn't exist (sh)"; \
else \
echo 'a does exist (sh)'; \
fi
@echo 'a does exist (make se)'
d:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# commands to execute (from `Makefile', line 12):
@echo "a doesn't exist (make)"
@if [ ! -f a ]; then \
echo "a doesn't exist (sh)"; \
else \
echo 'a does exist (sh)'; \
fi
@echo 'a does exist (make se)'
Which, as you can see, doesn't contain the ifeq
lines but just the "correct" branch of the ifeq
logic.
And that's the problem, the ifeq
conditionals are evaluated at make parse time which is well before any recipes run (and thus before any files can be created, etc.).
Upvotes: 0