【问题标题】:Why does this makefile build every dependency, every time?为什么这个 makefile 每次都构建每个依赖项?
【发布时间】:2013-03-03 17:42:24
【问题描述】:

我正在使用一个 makefile 来运行几个与文本文件、其他数据集等一起使用的 Stata 文件。每次我运行 make 时,它​​都会运行 analysis.do,即使我没有对任何依赖关系。 这是生成文件:

.PHONY: clean spotless

STATACOMMAND=/opt/stata/stata-mp -b

analysis.txt: analysis.do uniform.dta normal.dta
    $(STATACOMMAND) analysis.do

uniform.dta: uniform.do
    $(STATACOMMAND) uniform.do

normal.dta: normal.do noise.txt
    $(STATACOMMAND) normal.do

clean:
    -rm *.log

spotless: clean
    -rm analysis.txt
    -rm *.dta

分析.做

use normal.dta, clear
merge t using uniform.dta
log using analysis.txt, text
regress norm unif
log close

正常的.do

clear
insheet using "noise.txt", clear
gen t = _n
gen norm = rnormal()
sort t
save normal.dta, replace

制服.do

clear
set obs 10
gen t = _n
gen unif = runiform()
sort t
save uniform.dta, replace

噪音.txt

noise
14
49
59
63
55
13
60
54
26
39

我的实际代码中有更多文件显示此问题,但我希望这个简单的示例至少可以帮助我缩小范围。

更新:文件修改时间是否以某种方式没有更新?每次运行 makefile 时,我都会在 make -d 的末尾看到这些消息:

Finished prerequisites of target file `analysis.txt'.
 Prerequisite `analysis.do' is older than target `analysis.txt'.
 Prerequisite `uniform.dta' is newer than target `analysis.txt'.
 Prerequisite `normal.dta' is newer than target `analysis.txt'.
Must remake target `analysis.txt'.

这是另一个例子。假设我已经运行了几次make。以下是文件修改时间:

-rw-r--r-- 1 ricardo ricardo  105 Mar  1 19:25 analysis.do
-rw-r--r-- 1 ricardo ricardo 1.1K Mar  2 13:26 analysis.log
-rw-r--r-- 1 ricardo ricardo 1.5K Mar  1 19:25 analysis.txt
-rw-r--r-- 1 ricardo ricardo  317 Mar  1 19:41 makefile
-rw-r--r-- 1 ricardo ricardo   36 Mar  1 19:34 noise.txt
-rw-r--r-- 1 ricardo ricardo  103 Mar  1 19:33 normal.do
-rw-r--r-- 1 ricardo ricardo  803 Mar  1 19:38 normal.dta
-rw-r--r-- 1 ricardo ricardo 1007 Mar  1 19:38 normal.log
-rw-r--r-- 1 ricardo ricardo   83 Mar  1 19:28 uniform.do
-rw-r--r-- 1 ricardo ricardo  594 Mar  1 19:38 uniform.dta
-rw-r--r-- 1 ricardo ricardo  991 Mar  1 19:38 uniform.log

再次运行make 后,时间到了。 除了由 Stata 自动生成的 .log 文件之外,没有时间变化。

-rw-r--r-- 1 ricardo ricardo  105 Mar  1 19:25 analysis.do
-rw-r--r-- 1 ricardo ricardo 1.1K Mar  2 13:29 analysis.log
-rw-r--r-- 1 ricardo ricardo 1.5K Mar  1 19:25 analysis.txt
-rw-r--r-- 1 ricardo ricardo  317 Mar  1 19:41 makefile
-rw-r--r-- 1 ricardo ricardo   36 Mar  1 19:34 noise.txt
-rw-r--r-- 1 ricardo ricardo  103 Mar  1 19:33 normal.do
-rw-r--r-- 1 ricardo ricardo  803 Mar  1 19:38 normal.dta
-rw-r--r-- 1 ricardo ricardo 1007 Mar  1 19:38 normal.log
-rw-r--r-- 1 ricardo ricardo   83 Mar  1 19:28 uniform.do
-rw-r--r-- 1 ricardo ricardo  594 Mar  1 19:38 uniform.dta
-rw-r--r-- 1 ricardo ricardo  991 Mar  1 19:38 uniform.log

这可能是问题吗?

【问题讨论】:

  • 你说它通过raw12.do 构建raw4.do,但我认为没有规则可以重建这些目标中的任何(可能除了raw9.do,但这看起来像错字)。而且其中一些规则几乎肯定不会像你认为的那样做。当你make raw4.do 时会发生什么?
  • 如何创建dta/raw10b.dta 所需的dta/finaldata.dta
  • @Beta 抱歉,我最初的陈述是错误的。它不构建 do 文件,而是运行它们。它重建与这些关联的 dta 文件。如果我运行make raw4.do,它会告诉我无事可做。
  • @AlexCohn @AlexCohn 我的理解是,当 make 寻找构建 dta/finaldata 时,它会将 dta/raw10b.dta 视为依赖项,因此它会跳转到该规则。它将dta/raw10a.dta 视为依赖项,因此查看其规则。看到这条规则,它运行raw10.do,它同时构建dta/raw10a.dtadta/raw10b.dta。让规则与我编辑中的版本一样更有意义吗?
  • 为什么需要dta/raw10a.dta 作为目标?无论如何,编辑确实有意义:如果$(STATA) raw10.do 构建(以及其他输出)dta/raw10a.dtb,它应该是dta/raw10a.dtb 的规则。

标签: makefile stata


【解决方案1】:

这是你的问题:

dta/raw4a.dta dta/raw4b.dta: raw4.do raw4datasource/ftp/%.csv
    $(STATA) raw4.do

raw4datasource/ftp/%.csv: ;

第一条规则并不像你想的那样。先决条件列表中有一个“%”,但目标中没有。 这不是一个模式规则。这些目标不依赖于raw4datasource/ftp/{something}.csv形式的所有现有文件(或可构建文件),它们依赖于目标raw4datasource/ftp/%.csv .没错,一个名称中有% 的文件。该文件不存在。而且它不会被构建,因为第二条规则什么都不做。

我看到了四个这样的规则,其他的事情都依赖于它们。

您必须重新考虑这些规则的设计;决定你想让它们做什么,弄清楚如何让它们工作,并在尝试将它们连接到 makefile 的其余部分之前单独测试它们

【讨论】:

  • 我的目标是有一个目标规则,它依赖于raw4datasource/ftp/{something}.csv 形式的所有文件。这是不可能的,还是我应该使用不同的通配符?
  • 根据documentation 我正在阅读,* 是正确的通配符,所以我将更新makefile 以考虑到这一点,单独测试规则,然后再次发布。
  • 我将我的问题更新为一个更简单的示例,该示例也演示了该问题,因此我希望这有助于缩小问题范围。
  • 你想要一个依赖于某种形式的所有文件的规则,或者解释为什么 Make 运行 stata,即使你没有修改任何东西?
  • 我意识到在我最初的示例中,我的依赖项在 makefile 中不正确,这导致我感到困惑。目前似乎一切正常。
【解决方案2】:

您的 stata 似乎有问题。我从来没有用过这个工具,但是看看他们的documentation,你应该试试analysis.log而不是analysis.txt,以及下面的脚本:

use normal.dta, clear
merge t using uniform.dta
log using analysis, replace text
regress norm unif
log close

【讨论】:

  • replace 关键字是此版本问题中的问题。我在上一个问题中发现了错误(在我最后一次重大编辑之前),发现它与此无关。不知道在这种情况下如何进行,但我会给你功劳。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 2022-07-23
相关资源
最近更新 更多