Reputation: 23732
I have the following in a Makefile for the purpose of recreating my database including destroying it if necessary. It does not work.
.PHONY: rebuilddb
exists=$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM pg_database WHERE datname='the_db'")
if [ $(exists) -eq 1 ]; then
dropdb the_db
fi
createdb -E UTF8 the_db
Running it results in an error:
$ make rebuilddb
exists=
if [ -eq 1 ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [rebuilddb_postgres] Error 2
Why is this wrong? It looks like valid Bash as far as I can tell? Are there special considerations I must make when doing this in a Makefile?
UPDATE:
Using the answer I arrived at a working version:
.PHONY: rebuilddb
exists=$$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM pg_database WHERE datname='the_db'"); \
if [ "$$exists" == "1" ]; then \
dropdb the_db; \
fi;
createdb -E UTF8 the_db
Upvotes: 50
Views: 51190
Reputation: 107
The usage in dynamic generation rules you have to escape the shell variables with $$$$.
MY_LIBS=a b c
a_objs=a1.o a2.o
b_objs=b1.o b2.o b3.o
c_objs=c1.o c2.o c3.o c4.odefault: libs
# function lib_rule(name, objs)
define lib_rule
lib$(1).a: $(2)
exit 1 | tee make.log ; test $$$${PIPESTATUS[0]} -eq 0
endef# generate rules
$(foreach L,$(MY_LIBS),$(eval $(call lib_rule,$(L),$($(L)_objs))))# call generated rules
libs: $(patsubst %,lib%.a,$(MY_LIBS))# dummy object generation
%.o:%.c
touch $@
# dummy source generation
%.c:
touch $@
clean::
rm -f *.c *.o lib*.a make.log
The output: 'make -Rr'
exit 1 | tee make.log ; test ${PIPESTATUS[0]} -eq 0
make: *** [Makefile:18: liba.a] Error 1
Result of last command in pipe is true from tee. You can see bash variable PIPESTATUS[0] has the value false from exit 1
Watch the Database: 'make -Rrp'
define lib_rule
lib$(1).a: $(2)
exit 1 | tee make.log ; test $$$${PIPESTATUS[0]} -eq 0
endef
...
libc.a: c1.o c2.o c3.o c4.o
exit 1 | tee make.log ; test $${PIPESTATUS[0]} -eq 0
Upvotes: 0
Reputation: 212654
There are at least two considerations. $()
references a Make variable. You must escape the $
to do command substitution. Also, the shell commands must be all on one line. Try:
exists=$$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM \
pg_database WHERE datname='the_db'"); \
if [ "$$exists" -eq 1 ]; then \
dropdb the_db; \
fi; \
createdb -E UTF8 the_db
On the other hand, it seems like it would be simpler to just always try to drop the database, and allow failure:
rebuilddb:
-dropdb the_db # Leading - instructs make to not abort on error
createdb -E UTF8 the_db
Upvotes: 61