不一致的行为在Make/Makefile中分组目标,有/没有依赖关系



编辑文章澄清我的问题。

简短说明:在data/raw目录下有15个。csv文件。您可以在RAW_NAMES中看到它们的名称。

print-% :
@echo "$*=$($*)"
RAW = data/raw
PROCESS = data/process
RAW_NAMES = circuits constructor_results constructor_standings constructors driver_standings
drivers lap_times pit_stops qualifying races results seasons sprint_results status
RAW_FILES = $(addsuffix .csv, $(addprefix $(RAW)/,$(RAW_NAMES)))
$(RAW_FILES) :  
wget -nc --no-check-certificate -P $(RAW) http://ergast.com/downloads/f1db_csv.zip
unzip -d $(RAW) $(RAW)/f1db_csv.zip
data/process/roundtimes.csv : code/create_roundtimes.R $(RAW_FILES)
R -e "source('code/create_roundtimes.R')"
data/process/fastest_rounds.csv : code/fastest_rounds.R data/process/roundtimes.csv
R -e "source('code/fastest_rounds.R')"

假设我删除了3个文件(constructor_results.csv, constructor_standing .csv, constructors.csv),然后运行命令:

make -n data/process/fastst_rounds .csv

wget -nc --no-check-certificate -P data/raw http://ergast.com/downloads/f1db_csv.zip
unzip -d data/raw data/raw/f1db_csv.zip "constructor_results.csv"
wget -nc --no-check-certificate -P data/raw http://ergast.com/downloads/f1db_csv.zip
unzip -d data/raw data/raw/f1db_csv.zip "constructor_standings.csv"
wget -nc --no-check-certificate -P data/raw http://ergast.com/downloads/f1db_csv.zip
unzip -d data/raw data/raw/f1db_csv.zip "constructors.csv"
R -e "source('code/create_roundtimes.R')"
R -e "source('code/fastest_rounds.R')"

现在,我试着让下面的代码工作:

$(RAW)/f1db_csv.zip :
wget -nc --no-check-certificate -P $(RAW) http://ergast.com/downloads/f1db_csv.zip
$(RAW_FILES) : $(RAW)/f1db_csv.zip
unzip -d $(RAW) $(RAW)/f1db_csv.zip "$(@F)"

但是现在输出是这样的:

make -n data/process/fastst_rounds .csv

unzip -j data/raw/f1db_csv.zip -d data/raw "circuits.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "constructor_results.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "constructor_standings.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "constructors.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "driver_standings.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "drivers.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "lap_times.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "pit_stops.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "qualifying.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "races.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "results.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "seasons.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "sprint_results.csv"
unzip -j data/raw/f1db_csv.zip -d data/raw "status.csv"
R -e "source('code/create_roundtimes.R')"
R -e "source('code/fastest_rounds.R')"

或者当我使用:

$(RAW)/f1db_csv.zip :
wget -nc --no-check-certificate -P $(RAW) http://ergast.com/downloads/f1db_csv.zip
$(RAW_FILES) &: $(RAW)/f1db_csv.zip
unzip -j $(RAW)/f1db_csv.zip -d $(RAW) "$(@F)"

输出为:make -n data/process/fastst_rounds .csv

unzip -j data/raw/f1db_csv.zip -d data/raw "circuits.csv"
R -e "source('code/create_roundtimes.R')"
R -e "source('code/fastest_rounds.R')"

所以,你明白我的意思了吗?每当由于依赖项更改而调用规则时,我都希望从组中提取触发该规则的特定依赖项。因此,如果这3个构造函数文件被删除,我希望能够单独列出它们并对它们进行处理。

您使用分组目标的最后一个选项是正确的,但是您不能使用$@,因为它只扩展到make试图构建的特定文件。

如果您想将所有目标传递给命令,则应该使用$(RAWFILES):

$(RAW)/f1db_csv.zip :
wget -nc --no-check-certificate -P $(@D) http://ergast.com/downloads/$(@F)
$(RAW_FILES) &: $(RAW)/f1db_csv.zip
unzip -o -d $(<D) -j $< $(RAWFILES)

埃塔

问题是当unzip提取文件时,它也提取了文件的时间戳。因此,如果该文件在压缩时具有2020年6月的时间戳,那么在提取它时,它也具有2020年6月的时间戳。当你提取它时,它没有2022年6月的时间戳。

因为make完全在时间戳上工作,所以它知道提取的文件是否需要更新的唯一方法是将其与zip文件的时间戳进行比较:如果时间戳较新,则我们知道在zip文件更新后提取了该文件。如果不是,我们假设zip文件是新的,我们需要重新解压缩文件。

您想要将-D选项添加到您的unzip命令中(参见手册页),或者使用穷人的方法,例如:

$(RAW_FILES) : $(RAW)/f1db_csv.zip
unzip -d $(RAW) $(RAW)/f1db_csv.zip "$(@F)"
touch $@

来更新刚刚提取的文件的时间戳。

解决这个问题的方法是:你可以检查文件上的时间戳,因为这是make使用的。您可以使用make -d查看make决定重新构建文件的原因。

最新更新