首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >奇怪的Makefile行为,需要先生成文件,然后编译文件

奇怪的Makefile行为,需要先生成文件,然后编译文件
EN

Stack Overflow用户
提问于 2021-04-05 16:52:11
回答 1查看 25关注 0票数 0

我在Makefile有奇怪的行为。基本上,对于grammar.aps,它需要先运行grammar.generate来创建文件,然后运行grammar.class来编译生成的文件。如果我单独运行依赖项,所有这些都可以工作。但是如果我运行grammar.aps,它就不工作了。

代码语言:javascript
复制
// Running everything
➜  tests git:(first-follow-tests) ✗ make
scalac -cp .:../../../lib/aps-library-2.12.jar Spec.scala
make: *** No rule to make target 'grammar.class', needed by 'grammar.aps'.  Stop.

// Now running first depdency of `grammar.aps` which is `grammar.generate`
➜  tests git:(first-follow-tests) ✗ make grammar.generate
../../../bin/aps2scala -DCOT -p ../..:../../../base grammar

// Now running second depdency of `grammar.aps` which is `grammar.generate`
➜  tests git:(first-follow-tests) ✗ make grammar.class
scalac -cp .:../../../lib/aps-library-2.12.jar grammar.scala

// Okay but why grammar.aps didn't work? ... Makefile continues further now
➜  tests git:(first-follow-tests) ✗ make                 
scalac -cp .:../../../lib/aps-library-2.12.jar grammar.scala
../../../bin/aps2scala -DCOT -p ../..:../../../base grammar
echo "Building aps"
Building aps
scalac -cp .:../../../lib/aps-library-2.12.jar GrammarUtil.scala
echo "Building GrammarUtil.scala"
Building GrammarUtil.scala

// Same problem with `first.aps`
make: *** No rule to make target 'first.aps', needed by 'FirstSpec.compile'.  Stop.

Makefile:

代码语言:javascript
复制
SPECS=First Follow
EXAMPLES_PATH=../..
ROOT_PATH=../${EXAMPLES_PATH}
SCALAV=2.12
APSLIB=${ROOT_PATH}/lib/aps-library-${SCALAV}.jar
SCALA_FLAGS=.:${APSLIB}
APS2SCALA=${ROOT_PATH}/bin/aps2scala

.PHONY:
all: $(addsuffix Spec.compile, $(SPECS))

%.class: %.scala
    scalac -cp ${SCALA_FLAGS} $<

%.generate:
    ${APS2SCALA} -DCOT -p ${EXAMPLES_PATH}:${ROOT_PATH}/base $*

%.aps: %.generate %.class
    echo "Building aps"

%.run: %.class
    @scala -cp ${SCALA_FLAGS} $<

FirstSpec.compile: Spec.class GrammarUtil.compile first.aps FirstSpec.class 
    echo "Building FirstSpec.scala"

FollowSpec.compile: Spec.class GrammarUtil.compile follow.aps FollowSpec.class
    echo "Building FollowSpec.scala"

GrammarUtil.compile: grammar.aps grammar.class GrammarUtil.class
    echo "Building GrammarUtil.scala"

.PHONY:
clean:
    rm -f *.class grammar.scala first.scala follow.scala
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-05 17:37:03

,我在Makefile上有奇怪的行为。基本上,对于grammar.aps,它需要先运行grammar.generate来创建文件,然后运行grammar.class来编译生成的文件。如果我单独运行依赖项,所有这些都可以工作。但是如果我运行grammar.aps,它就不工作了。

您正在尝试将makefile当作脚本对待。在最基本的层次上,它是对您的项目的声明性描述,它告诉make如何构造一个或多个目标,并给出每个目标的特定先决条件列表。每个先决条件列表都是偶然排序的。一个先决条件出现在词汇上高于另一个先决条件,这一点没有任何意义。由make根据makefile中的信息和可用文件选择和执行构建计划。

特别是,make根据声明的构建规则,根据运行开始时可用的先决条件对要构建的中间目标进行分析。此外,先决条件构建顺序仅受先决条件本身的前提条件的限制,并不一定是可预测的。

但是,make确实为您提供了信息丰富的错误消息。例如,这个..。

make:*没有规则可以使目标“gramar.class”成为“gramar.aps”所需要的。停止播放。

..。非常清楚:需要构建目标grammar.aps,并且它以grammar.class为先决条件,但是没有构建grammar.class的规则。也就是说,没有以grammar.class为目标的规则。实际上,构建grammar.generate将创建grammar.class是不相关的,因为您还没有将其表达给make

您可以通过将%.generate的规则转换为%.class的规则来解决这个特殊问题。

代码语言:javascript
复制
%.class:
    ${APS2SCALA} -DCOT -p ${EXAMPLES_PATH}:${ROOT_PATH}/base $*

%.aps: %.class
    echo "Building aps"

更广泛地说,你应该更喜欢用真正的目标写规则,而不是用假的规则。虚假的目标不一定是坏的,但它们并不是真正的目标的可行替代品。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66956620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档