【问题标题】:Make function and "commands commence before first target"?使功能和“命令在第一个目标之前开始”?
【发布时间】:2026-02-07 17:00:01
【问题描述】:

这是我运行的命令

make -d -f dump.makefile

我得到的错误:

Reading makefile `dump.makefile'...
dump.makefile:31: *** commands commence before first target.  Stop.

来源

ifneq (,)
This makefile requires GNU Make.
endif

# force use of Bash
SHELL := /bin/bash


# function
today=$(shell date '+%Y-%m:%b-%d')
update-latest=$(shell ln -nf {$(call today),latest}.cfdict-"$(1)".localhot.sql)

# variables
credentials="$$HOME/.my.cfdict.cnf"

default: data-only structure-only csv-only all

data-only: what=data
    argList=( --defaults-file="${credentials}" --no-create-db --no-create-info ) \
    mysqldump "$${argList[@]}" cfdict > $(call today).cfdict-"${what}".localhot.sql
    $(call update-latest,${what})

触发错误的行是$(call update-latest,${what}),调用update-latest函数。

完整的gist available on github

问题

我检查制表符/空格,这似乎是正确的。 我是误用了call 还是错误地声明了update-latest

【问题讨论】:

  • 试试update-latest=$(shell echo ln ...看看shell得到了什么。我想知道 $(call today) 是否在 ln 命令移交给 shell 之前被替换。

标签: bash function makefile gnu-make


【解决方案1】:

导致您报告错误的问题是您没有将目标特定的变量定义与规则的定义分开。你目前有这种形式的规则:

data-only: what=data
        ... commands ...

您可能期望data-only: what=data 行定义特定于目标的变量和规则,但事实并非如此。

您需要为变量声明单独一行,然后重复规则的目标名称。像这样:

data-only: what=data
data-only:
        ... commands ...

所以data-only,仅举一个例子,会变成:

data-only: what=data
data-only:
    argList=( --defaults-file="${credentials}" --no-create-db --no-create-info ) \
    mysqldump "$${argList[@]}" cfdict > $(call today).cfdict-"${what}".localhot.sql
    $(call update-latest,${what})

我看到您将 argList 声明为 shell 变量,因此不需要更改。

您必须以类似方式更新 Makefile 中具有特定于目标的变量的所有目标。

【讨论】:

  • 感谢##workingset 上的@joshc 用户,我采用了更类似于make 的方法。见updated gist
  • 是的,这是一个彻底的转变。我在那里看到的是完整代码审查的结果。