if condition in a function - Makefile - makefile

I'm working with makefile and the very simple things like if-conditions are not straight forward. it gives me an error that is not readable.
Any idea what's wrong with my following small function?
prepare-test-example:
ifeq ($(ENGINE),'aurora-postgresql')
#cat examples/example.yaml > /tmp/stack_test.yaml
else
#cat examples/example.yaml examples/example_test.yaml > /tmp/stack_test.yaml
endif
The call:
make test ENGINE=aurora-postgresql
/Library/Developer/CommandLineTools/usr/bin/make prepare-test-example ENGINE=aurora-postgresql
ifeq (aurora-postgresql,'aurora-postgresql')
/bin/sh: -c: line 0: syntax error near unexpected token `aurora-postgresql,'aurora-postgresql''
/bin/sh: -c: line 0: `ifeq (aurora-postgresql,'aurora-postgresql')'
make[1]: *** [prepare-test-example] Error 2

You have indented the ifeq so it looks to make like something it should pass to the shell.
Try either
ifeq ($(ENGINE),'aurora-postgresql')
files := examples/example.yaml
else
files := examples/example.yaml examples/example_test.yaml
endif
prepare-test-example:
#cat $(files) > /tmp/stack_test.yaml
or
prepare-test-example:
#if [ "$(ENGINE)" = "'aurora-postgresql'" ]; then \
cat examples/example.yaml \
; else \
cat examples/example.yaml examples/example_test.yaml \
; fi > /tmp/stack_test.yaml
For fun, I refactored out the redirection in the latter (pure shell script) example.
Perhaps you meant ifeq('$(ENGINE)','aurora-postgresql') which would make more sense, and allow for the above code to be simplified somewhat.

Related

Dollar in conditional variable assignment operator in Makefile

Is it possible to pass value with single dollar from shell to Makefile, or I it is only way to put double dollar in bash and then to call make?
Makefile is:
HASH ?= $$6$$salt$$val
.PHONY: tst
tst:
echo '$(HASH)'
Command to run:
> make HASH='$6$salt$val'
echo 'altal'
altal
If I use double quotes, all is fine:
> make HASH='$$6$$salt$$val'
echo '$6$salt$val'
$6$salt$val
But is it possible do not make substitution $ to $$ in bash?
How about writing the initialisation within the file identical to the one coming from the command line? The below script demonstrates how to rewrite a variable with the override directive:
quote-one-level = $(eval override $1=$(subst $,$$$$,$(value $1)))
var-info = $(info $1=$(value $1) flavour=$(flavor $1) origin=$(origin $1))
A ?= $abc
$(call var-info,A)
$(call quote-one-level,A)
$(call var-info,A)
$(call var-info,B)
$(call quote-one-level,B)
$(call var-info,B)
export A
export B
all:
#echo A = '$(A)'
#echo B = '$(B)'
ifeq ($(MAKELEVEL),0)
$(MAKE)
endif
Inflating one $ to $$$$ (and not just $$) is necessary because the eval command literally generates make code, thereby obviously reducing the quoting level by one. Resulting output:
$ make B='$abc'
A=$abc flavour=recursive origin=file
A=$$abc flavour=recursive origin=override
B=$abc flavour=recursive origin=command line
B=$$abc flavour=recursive origin=override
A = $abc
B = $abc
make
make[1]: Entering directory
A=$abc flavour=recursive origin=environment
A=$$abc flavour=recursive origin=override
B=$abc flavour=recursive origin=command line
B=$$abc flavour=recursive origin=override
A = $abc
B = $abc
make[1]: Leaving directory
Try this:
In console:
export HASH='$6$salt$val'; make
in Makefile:
.PHONY: tst
tst:
#echo "$$HASH"
Result:
$6$salt$val

Trying to echo a variable in a makefile but getting "missing separator"

I would like to print the variable K_INCLUDE in a make file. This is probably very simple but the examples I'm finding online are giving an error.
Here's some of the code:
#Include flags
HEADER_INCLUDE = ../include
ifeq ($(SYSTEM_TYPE), Linux)
K_INCLUDE = /bla2
endif
ifeq ($(SYSTEM_TYPE), Darwin)
K_INCLUDE = /bla
endif
GLOBAL_INCLUDE = -I$(HEADER_INCLUDE) -I$(K_INCLUDE)
# The below line gives the error
echo "k_include: $K_INCLUDE"
Produces the error:
make.include:28: *** missing separator. Stop.
make: *** [clean] Error 2

gnu makefile: if condition inside multirow assignment

Is it possible to have if condition inside multiple-rows assignment of a variable?
The following code triggers an error:
MY_FILES= \
Path/To/IncludeFolder_1 \
ifeq ($(USE_ALTERNATIVE),1) \
Path/To/IncludeFolder_2a \
else \
Path/To/IncludeFolder_2b \
endif \
Path/To/IncludeFolder_3 \
Result:
/bin/sh: -c: line 0: syntax error near unexpected token `('
make: *** [target] Error 2
But the following code also triggers an error:
MY_FILES= \
Path/To/IncludeFolder_1 \
ifeq ($(USE_ALTERNATIVE),1)
Path/To/IncludeFolder_2a \
else
Path/To/IncludeFolder_2b \
endif
Path/To/IncludeFolder_3 \
Result:
Makefile:4: *** missing separator. Stop.
"make" terminated with exit code 2. Build might be incomplete.
If not possible, are there other simple alternatives to achieve this? The use case is a long list of include folders, which can have differences from place to place in function of some defines.
You're making this too complicated.
MY_FILES := Path/To/IncludeFolder_1
ifeq ($(USE_ALTERNATIVE),1)
MY_FILES += Path/To/IncludeFolder_2a
else
MY_FILES += Path/To/IncludeFolder_2b
endif
MY_FILES += Path/To/IncludeFolder_3
You can craft a string-comparison function with relative ease yourself, so that you can facilitate the $(if ) builtin function:
###### $(call str-eq,_string1_,_string2_)
## Compare two strings on equality. Strings are allowed to have blanks.
## Return non-empty if string $1 and $2 are identical, empty string otherwise.
## - `$(call str-eq,yes,no)` --> ` ` (empty string)
## - `$(call str-eq,yes ,yes)` --> ` ` (empty string)
## - `$(call str-eq,yes ,yes )` --> `t`
str-eq = $(if $(subst x$1,,x$2),,t)
MY_FILES= \
Path/To/IncludeFolder_1 \
$(if $(call str-eq,$(USE_ALTERNATIVE),1) \
Path/To/IncludeFolder_2a, \
Path/To/IncludeFolder_2b \
) \
Path/To/IncludeFolder_3
The str-eq and many more utility functions can be found at https://github.com/markpiffer/gmtt.

Define "continue if error" policy directly in target dependencies

Here's a simple Makefile with 4 targets (a, b, c and all). Target b can fail (represented here with exit 1).
a:
echo "a"
b:
exit 1
c:
echo "c"
all: a b c
When running make all, c is never printed as b fails and target c is consequently not run. But in my particular case, I want c to be run, even if b fails.
I'm wondering if there is a way to define the "continue if error" policy directly inside the dependencies of target all.
I know that the desired behaviour can be reached by :
running make -i all (--ignore-errors) or make -k all (--keep-going)
using a "recursive" make
prefixing failing command in b with - (like -exit 1)
running tasks separately with make a; make b || make c
but all of these options implies to modify targets a, b or c, or modify the way make all is called.
Is there a way to have the expected behaviour by just modifying the all target dependencies (something like all: a -b c, but that definition does not work, obviously)?
Additional requirement : make all should return with exit code 1 if b fails, even if c target succeeds.
If you want to run all recipes of a, -b, c even if the -<something> ones fail you can use a pattern rule for -<something> targets:
a c:
#echo "$#"
b:
#echo "$#"; exit 1
all: a -b c
-%:
-#$(MAKE) $*
Demo (with --no-print-directory for simpler output):
$ make --no-print-directory all
a
b
Makefile:5: recipe for target 'b' failed
make[1]: *** [b] Error 1
Makefile:10: recipe for target '-b' failed
make: [-b] Error 2 (ignored)
c
But if you also want to "remember" their exit status, things are a bit more difficult. We need to store the exit status somewhere, for instance in a file and reuse it for the all recipe:
a c:
#echo "$#"
b:
#echo "$#"; exit 1
all: a -b c
#exit_status=`cat b_exit_status`; exit $$exit_status
-%:
-#$(MAKE) $*; echo "$$?" > $*_exit_status
Demo:
$ make --no-print-directory all
a
b
Makefile:5: recipe for target 'b' failed
make[1]: *** [b] Error 1
c
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
Hard-wiring the name of the potentially failing target in the recipe of all is not very elegant. But it should be quite easy to solve:
a b c:
#echo "$#"
d:
#echo "$#"; exit 1
all: a -b c -d
#for f in $(patsubst -%,%_exit_status,$(filter -%,$^)); do \
tmp=`cat $$f`; \
printf '%s: %s\n' "$$f" "$$tmp"; \
if [ "$$tmp" -ne 0 ]; then exit $$tmp; fi; \
done
-%:
-#$(MAKE) $*; echo "$$?" > $*_exit_status
.PHONY: clean
clean:
rm -f *_exit_status
Demo:
$ make --no-print-directory all
a
b
c
d
Makefile:5: recipe for target 'd' failed
make[1]: *** [d] Error 1
b_exit_status: 0
d_exit_status: 2
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
While you can't transmit parameters through prerequisite names (or at least only if you change the prerequisites completely), you could employ target-specific variables. But the solution isn't exactly pretty, with an additional variable leading every recipe line:
CIE_DASH = $(if $(filter $#,$(CONTINUE_SET)),-)
all: a b c
all: CONTINUE_SET += b
a:
$(CIE_DASH)echo "a"
b: CONTINUE_SET += e
b: e
$(CIE_DASH)exit 1
e:
$(CIE_DASH)exit 1
c:
$(CIE_DASH)echo "c"

make: Error in ifneq: word unexpected (expecting ")")

I would like to create a makefile for LaTeX documents (in this minimal
example). When there is no file "makeindexstyle.ist", it should be created (by
running make makeindexstyle.ist) and used for formatting the index. The rule for
%.pdf reflects this. However, it is not working yet, I receive the error
ifneq (, ) {
/bin/sh: 1: Syntax error: word unexpected (expecting ")")
make: *** [master.pdf] Error 2
What's wrong?
Parts from Makefile:
MASTER = master
TEX = slave
TEXI = texi2dvi -p
all: $(MASTER:=.pdf)
%.pdf: %.tex $(TEX:=.tex)
ifneq ($(wildcard makeindexstyle.ist), ) { # if makeindexstyle.ist exists, compile and build index
$(TEXI) $<
make makeindexstyle.ist
makeindex -c -s makeindexstyle.ist $(MASTER:=.idx)
}
endif
$(TEXI) $<
makeindexstyle.ist:
#(echo "...") > makeindexstyle.ist
UPDATE:
I tried to make it as simple as possible to see where the error comes from. Among other things (like quoting), I tried this:
%.pdf: %.tex $(TEX:=.tex)
exist := $(wildcard "absolute-path-to-makeindexstyle.ist")
ifneq ($strip $(exist)),)
echo "foo"
endif
$(TEXI) $<
but the result is
exists :=
make: exists: Command not found
make: *** [book.pdf] Error 127
In the meanwhile, I could solve it on the shell side:
IDX = "makeindexstyle.ist"
%.pdf: %.tex $(TEX:=.tex)
#if test -f $(IDX); then \
echo "foo"; \
fi
$(TEXI) $<
This sounds like a duplicate of How do I check if file exists in Makefile? or How to conditional set up a Makefile variable by testing if a file exists.
Try
ifneq ($(wildcard makeindexstyle.ist),)
without the space. Alternatively, throw "" around the arguments?

Resources