I'm trying to check if a variable contains a particular string. I've tried a solution posted here: Makefile : contains string but in my case it does not seem wot work.
@echo $(findstring 2025, $(basename $(<F)))`
returns 2025
, but :
ifeq ($(findstring 2025, $(basename $(<F))),2025)
@echo $(findstring 2025, $(basename $(<F)))
endif
does not return 2025
. Why?
I'm trying to check if a variable contains a particular string. I've tried a solution posted here: Makefile : contains string but in my case it does not seem wot work.
@echo $(findstring 2025, $(basename $(<F)))`
returns 2025
, but :
ifeq ($(findstring 2025, $(basename $(<F))),2025)
@echo $(findstring 2025, $(basename $(<F)))
endif
does not return 2025
. Why?
2 Answers
Reset to default 1If you want help, especially with makefiles, you have to provide a minimal but fully-functioning example. Makefiles are extremely context dependent, so often how something behaves depends entirely on where in the makefile it appears: is it in a recipe? In a variable assignment? Etc.
In your case, you're using ifeq
and since you don't say that you got a syntax error it must be that this is not in a recipe. ifeq
is a make keyword not a valid shell command, so it can't be in a recipe.
If you check the documentation for automatic variables like $(<F)
you'll find that they are only set in a recipe context. So you can't ever use automatic variables in ifeq
conditionals: they will always be the empty string.
Without more information on what you want to do, that's about all we can say.
Your problem has to do with the stages of makefile running. I'm assuming you're running something like this:
file:=file2025.c
all: $(file)
@echo "building $@ (echo) F=$(<F)"
$(info building $@ (info) F=$(<F))
ifeq ($(findstring 2025, $(basename $(<F))),2025$(info processing ifeq... F=[$(<F)]))
$(info this is not run, as it is ifeqed out)
@echo "2: (in ifeq)" $(findstring 2025, $(basename $(<F)))
endif
.PHONY: $(file)
This outputs:
> make
processing ifeq... <F=[]
building all (info)
building all (echo)
1: 2025
Explanation:
Note: $(info)
's are makefile constructs -- they expand to nothing, but they have the side effect of spitting out text to the console at the point they are expanded. (this means I can stick a $(info...)
to the end of the ifeq
without effecting what it does... It will output something at the point the ifeq is evaluated).
Make will start by parsing everything in the global context (lines that do not start with a tab...). Once it's done this, it decides what recipes to run etc, it will parse the recipe lines right before it runs the recipe, and then execute them.
In this case, notice that the ifeq
statement is parsed before the recipe is even being considered to run because it does not start with a tab. At this time $(<F)
is blank, and nothing within the ifeq
is expanded.
You should also notice that the output from the info
is run before the output of the echo
, as the $(info)
is expanded before the recipe is actually run.
The long and the short of it is, that you should avoid using makefile conditionals within recipes, unless you really know what your doing. A better approach would be to use your makefile variables in a bash conditional within the recipe as so:
all2: $(file)
@echo building $@ -- F=$(<F)
@if [ $(findstring 2025, $(basename $(<F))) ]; then \
echo "file has 2025" \
fi