[英]Makefile to create subdirectories and download some files by a file of ID list
我正在编写GNU make Makefile以从服务器下载一些文件(L1.txt,L2.txt等)。 我有一个目标,使他们每个或全部。
每个文件都包含ID列表。
对于每个列表文件(L1.txt,L2.txt等),我想创建一个与列表文件同名的子目录(例如,L1.txt-> ./L1 ..)-简单:)。
然后,对于每个列表文件,对于列表文件中的每个ID,我想将其他文件下载到特定目录(由列表文件创建的目录)中,并对其进行处理以制作一些二进制文件。 每个子目录中的所有二进制文件都应聚合到其他.merged.bin-complex:/
L1.txt:
10, 20, 30
L2.txt:
101, 102, 105
因此,make之后,我希望拥有:
./L1.merged.bin
./L2.merged.bin
./conf/L1.txt
./conf/L2.txt
./data/L1/10.txt
./data/L1/20.txt
./data/L1/30.txt
./data/L1/10.bin
./data/L1/20.bin
./data/L1/30.bin
./data/L2/101.txt
./data/L2/102.txt
./data/L2/105.txt
./data/L2/101.bin
./data/L2/102.bin
./data/L2/105.bin
LIST_FILES=$(wildcard conf/*.txt)
LIST_FOLDERS=$(patsubst conf/%.txt, data/%, ${LIST_FILES})
MERGED_FILES=$(patsubst conf/%.txt, %.merged.bin, ${LIST_FILES})
all: mergesubs
mergesubs: ${MERGED_FILES}
conf/%:
curl -sSL some-list-url/$*.txt > $@
data/%: conf/%.txt
test -d $@ || mkdir $@
# PSEUDO CODE STARTS HERE:
# template code to understand inner-workings.
# should not work as target should be made for each data sub directory.
data/*/%.bin: data/*/%.txt
my_process $< > $@
data/*/%.txt:
curl -sSL someurl/$* > $@
# PROBLEMS START HERE!
# prerequisite should be a list of files,
# with file extension .bin and generated from list file
# provided before. conf/L1.txt might be not downloaded
# so I need to add it to prerequisites,
# but make does not provide ordering for prerequisites
# Something similar
%.merged.bin: $(shell cat conf/%.txt) conf/%
cat $^ > $@
如何为这种情况编写依赖关系树? 我想保留所有gnu make的优良品质:仅下载一次文件,仅处理一次,依此类推。
请不要建议使用GNU Make以外的其他工具,因为我需要在Linux环境中使用Makefile进行此操作。
在阅读我的代码之前,请注意以下几点:
不要使用$(wildcard)
-到处都是个坏主意。 列出您期望的项目,就像我在LIST_FILE_STEMS
所做的一样
追加/.
告诉这个目录是一个好方法(仅添加/
不够-将其剥离)。 但是,我对%/.
进行规则的方式%/.
在此,仅对存在父目录时创建的目录可靠地起作用。 这是因为mkdir -p
与父目录存在较弱的竞争条件。 在您的情况下,您仅创建一个一级目录,所以可以。
下载远程文件时,没有必要依赖于远程文件,因为如果不先下载,就无法确定其时间戳。 因此,在这种情况下,进行此操作的一种好方法是仅在本地副本不存在的情况下下载。 如果要强制重新下载,则必须先删除本地副本。
任何不重要的配方都应取决于Makefile
因此,如果配方更改,则目标将重新生成。
我在这里使用了一些微妙的技巧,如果您没有经验,那么在阅读代码时,这些技巧不会立即显而易见。 但是,当您尝试更改代码时,它可能会“停止工作”,因为您没有意识到正在发生的事情。 那将是您学习的机会-GNU Make手册是您的朋友:)所以这就是为什么我没有特别注释代码的原因。
记住,在尝试我的代码之前,请记住在食谱中用开头的制表符替换空格-据我所知,无法在Stack Overflow中的代码中粘贴制表符-它会将制表符更改为空格。
干得好:
LIST_FILE_STEMS := \
L1 \
L2 \
LIST_FILES := $(patsubst %, conf/%.txt, $(LIST_FILE_STEMS))
MERGED_FILES := $(patsubst conf/%.txt, %.merged.bin, $(LIST_FILES))
GENERATED_MAKEFILES := $(addsuffix _Makefile, $(LIST_FILE_STEMS))
all: $(MERGED_FILES)
-include $(GENERATED_MAKEFILES)
$(GENERATED_MAKEFILES): %_Makefile: conf/%.txt Makefile
echo $*.merged.bin: $(patsubst %, data/$*/%.bin, $(shell sed 's/,//g' < $<)) > $@
%.merged.bin:
cat $^ > $@
$(LIST_FILES): Makefile
curl -sSL $(subst conf,some-list-url,$@) > $@
%/.:
mkdir -p $@
.SECONDEXPANSION:
%.bin: %.txt Makefile | $$(dir $$@).
my_process $< > $@
data/%.txt: Makefile | $$(dir $$@).
curl -sSL someurl/$(notdir $*).txt > $@
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.