如何避免每次运行Makefile时都运行所有目标?

时间:2019-04-12 19:02:32

标签: makefile

即使目标没有变化,如何仍能避免每次重建目标?我查看了以下答案:answer1answer2answer3,但是我仍然无法解决问题。我认为我从概念上理解了为什么会出现此问题。只是我无法将解决方案应用于我的案件。

这是我的makefile:

.PHONY: all dircreate dircreate_sub

# Create shortcuts to directories ##############################################
DAT4 = data/4-Year/
RES4 = data/results/4-Year/
FIG4 = figures/4-Year/
DAT2 = data/2-Year/
RES2 = data/results/2-Year/
FIG2 = figures/2-Year/
DEPVARS = \
    ret.1st.2nd.term.left \
    ret.1st.2nd.year.left \
    ret.1st.7th.year.grad \
    ret.1st.5th.year.grad

# Create directories ###########################################################
dircreate:
    mkdir -p \
    data/ \
    data/4-Year/ \
    data/2-Year/ \
    data/results/ \
    data/results/4-Year \
    data/results/2-Year \
    figures/ \
    figures/4-Year/ \
    figures/2-Year/

dircreate_sub:
    for d in $(DEPVARS); do \
        mkdir -p data/4-Year/$$d ; \
        mkdir -p data/2-Year/$$d ; \
        mkdir -p data/results/4-Year/$$d ; \
        mkdir -p data/results/2-Year/$$d ; \
        mkdir -p figures/4-Year/$$d ; \
        mkdir -p figures/2-Year/$$d ; \
    done;

#TARGETS_DATAPREP := \
#$(foreach dat, $(DAT4) $(DAT2), $\
#   $(foreach filename, \
#           train_index_outer.RDS \
#           train_outer.RDS \
#           train_inter_outer.RDS, $\
#               $(foreach depvar, $(DEPVARS),$(dat)$(depvar)/$(filename))))

# Data prep:####################################################################
TARGETS_DATAPREP := \
$(foreach filename, $\
    train_index_outer.RDS \
    train_outer.RDS \
    train_inter_outer.RDS \
    entire_data.RDS \
    entire_inter_data.RDS, $\
        $(foreach depvar, $(DEPVARS),$(DAT4)$(depvar)/$(filename)))

$(TARGETS_DATAPREP): \
    dataprep.R \
    funcs.R \
    ../core/data/analysis.data.RDS
    Rscript $<

# benchmark:####################################################################
DEPENDENCIES_BENCHMARK := \
$(foreach filename, $\
    train_index_outer.RDS \
    train_outer.RDS \
    train_inter_outer.RDS \
    entire_data.RDS \
  entire_inter_data.RDS, $\
        $(foreach depvar, $(DEPVARS),$(DAT4)$(depvar)/$(filename)))

TARGETS_BENCHMARK := \
$(foreach filename, $\
    logreg_inner.RDS \
    l1logreg_inner.RDS \
    l1logreg.int_inner.RDS \
    rf_inner.RDS \
    xgb_inner.RDS \
    logreg_outer.RDS \
    l1logreg_outer.RDS \
    l1logreg.int_outer.RDS \
    rf_outer.RDS \
    xgb_outer.RDS, $\
        $(foreach depvar, $(DEPVARS),$(RES4)$(depvar)/$(filename)))

$(TARGETS_BENCHMARK): \
    benchmark.R \
    funcs.R \
    $(DEPENDENCIES_BENCHMARK)
    Rscript $<

# Process:######################################################################
TARGETS_PROCESS := \
$(foreach filename, $\
    processed_inner.RDS \
    processed_inner_outer.RDS, $\
        $(foreach depvar, $(DEPVARS),$(RES4)$(depvar)/$(filename)))

$(TARGETS_PROCESS): \
    process.R \
    funcs.R \
    $(TARGETS_BENCHMARK)
    Rscript $<

# Graphs:#######################################################################
TARGETS_GRAPHS := \
$(foreach filename, $\
    ave_auc_inner.png \
    ave_ppv10_inner.png \
    dist_auc_inner.png \
    dist_ppv10_inner.png \
    roc_inner.png \
    ave_auc_outer.png \
    ave_ppv10_outer.png \
    dist_auc_outer.png \
    dist_ppv10_outer.png \
    roc_outer.png \
    ave_auc_ppv10_inner_outer.png \
    roc_inner_outer.png \
    thresh_inner_outer.png, $\
        $(foreach depvar, $(DEPVARS),$(FIG4)$(depvar)/$(filename)))

$(TARGETS_GRAPHS): \
    graphs.R \
    funcs.R \
    $(TARGETS_PROCESS)
    Rscript $<

# Make all
all: $(TARGETS_PROCESS)



因此,make -nd告诉我dircreate每次都需要重制。这就是为什么我还尝试添加一个名为OUTDIRS的变量并为其创建规则的原因。因此,我添加了以下内容而不是dircreate

OUTDIRS: $(DAT4) $(RES4) $(FIG4) $(DAT2) $(RES2) $(FIG2)
OUTDIRS := \
for d in $(DEPVARS); do \
    $(DAT4)$$d ; \
    $(DAT2)$$d ; \
    $(RES4)$$d ; \
    $(RES2)$$d ; \
    $(FIG4)$$d ; \
    $(FIG2)$$d ; \
done;

$(OUTDIRS):
  mkdir -p $@

但是,这次我在$(OUTDIRS): mkdir -p $@遇到了一个分隔符错误,我知道这与主要问题无关,但是我想知道我的前进方向是否至少在正确的轨道上?

1 个答案:

答案 0 :(得分:0)

假设你有

DIRS := 2-Year 4-Year
DEPVARS := term year

您要构造:

2-Year/term 2-Year/year 4-Year/term 4-Year/year

您可以这样做:

OUTDIRS := $(foreach d,$(DIRS),$(addprefix $(d)/,$(DEPVARS)))

工作完成后,您可以将其抽象为一个函数:

Multiply= $(foreach d,$(1),$(addprefix $(d)/,$(2)))

OUTDIRS:=$(call Multiply, $(DIRS), $(DEPVARS))

您有一个 可以使用它来构造您的那些树:

DIRS := data data/results figures
DIRS := $(DIRS) $(call Multiply, $(DIRS), 4-Year 2-Year)

DEPVARS := $(addprefix ret.1st., 2nd.term.left 2nd.year.left 7th.year.grad 5th.year.grad)

OUTDIRS:=$(call Multiply, $(DIRS), $(DEPVARS))

$(OUTDIRS):
    mkdir -p $@

请注意,如果要让Make创建其中不存在的目录,则必须在$(OUTDIRS)规则之前 添加另一个规则:

.PHONY: all-dirs
all-dirs: $(OUTDIRS)