定义 SHELL:为什么有些目标因错误 "invalid syntax" 而失败,而另一个却没有失败?

Defining SHELL: why some targets fail with error "invalid syntax" while another doesn't fail?

我有一个 Makefile 如下(摘录):

# be a POSIX guy!
SHELL = /bin/dash

# avoid accursed tabs
.RECIPEPREFIX +=

PROJECT = my_project

# before-commit stuff
CHANGED_FILES = $(shell git ls-files --modified)

files ?= $(CHANGED_FILES)

lint:
    pyflakes $(files)

lint-all:
    pyflakes $(PROJECT)

STAGING_DB_PORT = 5437

staging-db-start:
    ssh -fNL 0.0.0.0:$(STAGING_DB_PORT):localhost:$(STAGING_DB_PORT) staging-db
    ss -tlpn sport eq :$(STAGING_DB_PORT)

staging-db-stop:
    ssh -O check staging-db
    ssh -O stop staging-db
    ss -tlpn sport eq :$(STAGING_DB_PORT)

staging-db-check:
    ss -tlpn sport eq :$(STAGING_DB_PORT)
    ssh -O check staging-db

.PHONY: lint, lint-all, staging-db-start, staging-db-stop, staging-db-check

当我 运行 目标时,说 staging-db-check 它工作得很好。虽然,当我 运行 目标 lint 时,它失败并显示错误:

Makefile:2:9: invalid syntax
SHELL = /bin/dash
        ^

对我来说,很奇怪。我读了文档,他们说你 always 必须设置 SHELL 变量,所以我决定这样做。但是我想不通哪里出错了?

我有 GNU make,版本 4.2.1。

GNU Make 从不生成以下形式的诊断:

Makefile:2:9: invalid syntax
SHELL = /bin/dash
    ^

但是 pyflakes 可以,这是您 lint 目标的食谱 运行 的程序:

lint:
    pyflakes $(files)

如您所知,pyflakes lints Python 源文件。您的 $(files),已分配 通过:

# before-commit stuff
CHANGED_FILES = $(shell git ls-files --modified)

files ?= $(CHANGED_FILES)

扩展为包含 Makefile 的文件列表。你的 Makefile 不是 一个 Python 源文件和 Makefile 中的第一行在语法上不是 有效 Python 是:

SHELL = /bin/dash

这是一个较短的 makefile:

生成文件

# be a POSIX guy!
SHELL = /bin/dash

.PHONY: all

all:
    echo "Hello World"

用于重现您的错误:

$ pyflakes Makefile
Makefile:2:9: invalid syntax
SHELL = /bin/dash
        ^

以后

Is there a way to exclude non-python files from $files variable?

是的。假设Python个文件是扩展名为.py的文件,更改:

CHANGED_FILES = $(shell git ls-files --modified)

至:

CHANGED_FILES = $(filter %.py,$(shell git ls-files --modified))

查看功能:

$(filter pattern...,text)
$(filter-out pattern...,text)

8.2 Functions for String Substitution and Analysisthe GNU Make manual

如果你这样做,也许最好将 CHANGED_FILES 更改为 CHANGED_PYTHON_FILES