GNU make: nesting of $(foreach...) and $(call...) produces Error: *** multiple target patterns. Stop
GNU make: nesting of $(foreach...) and $(call...) produces Error: *** multiple target patterns. Stop
问题
我正在尝试使用 GNU make 中的通用规则设置多阶段数据处理管道。但是,我收到错误:
Makefile:29: *** multiple target patterns. Stop.
我怀疑这是因为我在嵌套 $(foreach...) 和 $(call...) 函数时犯了错误。
最小示例
项目层次结构
.
├── Makefile
├── data
│ ├── processed
│ └── raw
│ ├── annotations.csv
│ └── observations.csv
└── src
├── init.py
└── parser.py
Makefile
# targets
# lauch_code
# code_prereq
# data_prereq
# arguments
# Blank line at the beginning to have line breaks in $(foreach ...)!
define conprod
:
mkdir -p $(dir )
python3 \
$(foreach dp, , --consume $(dp)) \
$(foreach t, , --produce $(t)) \
endef
params = 60 600
define target_pattern
data/processed/resam_$(param)s/annotated_observations.csv
endef
launch_code = src/parser.py
code_prereq =
data_prereq = data/raw/observations.csv data/raw/annotations.csv
$(info Info start)
$(info $(foreach param,$(params),$(call conprod,$(call target_pattern,$(param)),$(launch_code),$(code_prereq),$(data_prereq),$(param))))
$(info Info end)
$(foreach param,$(params),$(call conprod,$(call target_pattern,$(param)),$(launch_code),$(code_prereq),$(data_prereq),$(param)))
.PHONY: data
data: $(foreach param,$(params),$(call target_pattern,$(param)))
控制台输出
/mnt/c/Users/Public/dummy_projects/minimake$ make data -Bnd
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'Makefile'...
Info start
data/processed/resam_60s/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_60s/
python3 src/parser.py --consume data/raw/observations.csv --consume data/raw/annotations.csv --produce data/processed/resam_60s/annotated_observations.csv 60
data/processed/resam_600s/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_600s/
python3 src/parser.py --consume data/raw/observations.csv --consume data/raw/annotations.csv --produce data/processed/resam_600s/annotated_observations.csv 600
Info end
Makefile:29: *** multiple target patterns. Stop.
潜在客户
我可以排除的可能原因:
- 缩进是 IDE 中的制表符(适用于其他目标)
- 子系统内的文件路径不包含冒号(如控制台输出所示)
“隐形”东西
- 由于$(foreach ...)生成的字符串,行尾有一个空格(分别在参数60或600之后)
我要冒险,猜想你是 Make 的新手。
如果我能猜出你真正想要什么,它看起来就像
params := 60 600
.PHONY: all data
all: data
data: $(patsubst %,data/processed/resam_%/annotated_observations.csv,$(params))
data/processed/resam_%/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_$*
python3 $< $(patsubst %,--consume %,$(filter-out $<,$^)) --produce $@ $*
(Stack Overflow 将制表符呈现为空格,因此您无法 copy/paste 不经修改直接将其放入您的 Makefile 中。)
这还是很笨拙的;通过避免讨厌的深层子目录结构,您可能可以将其重构为更简单、更优雅的东西。
问题
我正在尝试使用 GNU make 中的通用规则设置多阶段数据处理管道。但是,我收到错误:
Makefile:29: *** multiple target patterns. Stop.
我怀疑这是因为我在嵌套 $(foreach...) 和 $(call...) 函数时犯了错误。
最小示例
项目层次结构
.
├── Makefile
├── data
│ ├── processed
│ └── raw
│ ├── annotations.csv
│ └── observations.csv
└── src
├── init.py
└── parser.py
Makefile
# targets
# lauch_code
# code_prereq
# data_prereq
# arguments
# Blank line at the beginning to have line breaks in $(foreach ...)!
define conprod
:
mkdir -p $(dir )
python3 \
$(foreach dp, , --consume $(dp)) \
$(foreach t, , --produce $(t)) \
endef
params = 60 600
define target_pattern
data/processed/resam_$(param)s/annotated_observations.csv
endef
launch_code = src/parser.py
code_prereq =
data_prereq = data/raw/observations.csv data/raw/annotations.csv
$(info Info start)
$(info $(foreach param,$(params),$(call conprod,$(call target_pattern,$(param)),$(launch_code),$(code_prereq),$(data_prereq),$(param))))
$(info Info end)
$(foreach param,$(params),$(call conprod,$(call target_pattern,$(param)),$(launch_code),$(code_prereq),$(data_prereq),$(param)))
.PHONY: data
data: $(foreach param,$(params),$(call target_pattern,$(param)))
控制台输出
/mnt/c/Users/Public/dummy_projects/minimake$ make data -Bnd
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'Makefile'...
Info start
data/processed/resam_60s/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_60s/
python3 src/parser.py --consume data/raw/observations.csv --consume data/raw/annotations.csv --produce data/processed/resam_60s/annotated_observations.csv 60
data/processed/resam_600s/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_600s/
python3 src/parser.py --consume data/raw/observations.csv --consume data/raw/annotations.csv --produce data/processed/resam_600s/annotated_observations.csv 600
Info end
Makefile:29: *** multiple target patterns. Stop.
潜在客户
我可以排除的可能原因:
- 缩进是 IDE 中的制表符(适用于其他目标)
- 子系统内的文件路径不包含冒号(如控制台输出所示)
“隐形”东西
- 由于$(foreach ...)生成的字符串,行尾有一个空格(分别在参数60或600之后)
我要冒险,猜想你是 Make 的新手。
如果我能猜出你真正想要什么,它看起来就像
params := 60 600
.PHONY: all data
all: data
data: $(patsubst %,data/processed/resam_%/annotated_observations.csv,$(params))
data/processed/resam_%/annotated_observations.csv: src/parser.py data/raw/observations.csv data/raw/annotations.csv
mkdir -p data/processed/resam_$*
python3 $< $(patsubst %,--consume %,$(filter-out $<,$^)) --produce $@ $*
(Stack Overflow 将制表符呈现为空格,因此您无法 copy/paste 不经修改直接将其放入您的 Makefile 中。)
这还是很笨拙的;通过避免讨厌的深层子目录结构,您可能可以将其重构为更简单、更优雅的东西。