如何在Makefile操作中使用shell变量?

hek*_*ran 32 bash makefile

我在Makefile中有以下内容,用于重新创建我的数据库,包括在必要时销毁它.这是行不通的.

.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
Run Code Online (Sandbox Code Playgroud)

运行它会导致错误:

$ make rebuilddb
exists=
if [  -eq 1 ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [rebuilddb_postgres] Error 2
Run Code Online (Sandbox Code Playgroud)

为什么这是错的?据我所知,它看起来像有效的Bash?在Makefile中执行此操作时是否需要特别注意?

更新:

使用答案我得到了一个工作版本:

.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
Run Code Online (Sandbox Code Playgroud)

Wil*_*ell 46

至少有两个考虑因素. $()引用Make变量.您必须转义$to do命令替换.此外,shell命令必须全部在一行上.尝试:

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
Run Code Online (Sandbox Code Playgroud)

另一方面,似乎总是尝试删除数据库并允许失败更简单:

rebuilddb:
    -dropdb the_db  # Leading - instructs make to not abort on error
    createdb -E UTF8 the_db
Run Code Online (Sandbox Code Playgroud)

  • 关于"所有在一条线上"有一些值得讨论的细微差别:(传统上和便携式)你想要由同一个shell**执行的所有东西必须在一条逻辑_make_线上.所以`exists = ...`和`if ... fi`必须用分号和反斜杠组成一个命令行,但`createdb ...`可以很高兴地保留在配方中作为单独的第二个命令. (3认同)
  • 如https://www.gnu.org/software/make/manual/html_node/One-Shell.html#One-Shell 中所述,可以通过使用`.ONESHELL:` 来放松“一行” (2认同)