我尝试编写自己的makefile,但它不起作用

时间:2016-04-24 03:34:31

标签: java makefile

#define the suffixes
.SUFFIXES: .java .class

#compile all java files to .class
.java.class:
        javac -g *.java

#CounterStatTester is a tester class for CounterStat
CounterStatTester.class: CounterStat.class

test: CounterStatTester.class CounterStat.class
        java CounterStatTester

当我尝试"进行测试"时,shell说" make:***没有规则来制作目标`test'。停止&#34。 但是我确实写过" java CounterStatTester",为什么它仍然无法找到规则?

1 个答案:

答案 0 :(得分:1)

这里有很多不良风格的例子。我将尝试按照外观顺序列出所有问题,而不仅仅是回答问题。如果你做了我建议的所有事情,你原来的问题肯定会消失。

如果你知道自己在做什么并且有充分的理由这样做就可以使用“穷人风格”,并且已经学会了很好的风格。在你的情况下,这些都不是。

  1. .SUFFIXES已过时,不应用于新代码

  2. 同样,.java.class:之类的“后缀规则”已过时,不应使用。

  3. 在任何情况下,您的.java.class:规则都应该生成一个.java文件并生成一个.class文件。 makefile中的好样式,是每个规则配方​​一次生成一个目标,而不是多个目标。

  4. 所以,你应该有这样的东西:

    %.class: %.java Makefile
            javac -g $<
    
    1. CounterStatTester.class没有理由“依赖”CounterStat.class,所以你不应该有这个规则。在这种情况下,“依赖性”意味着CounterStatTester.class的方法读取CounterStat.classCounterStatTester.class实际上取决于CounterStatTester.java(和Makefile,这不太明显),这已经被我向你展示的规则捕获了。

    2. 如上所述,每个规则配方​​都应该写一个目标。由于test不是文件,而是抽象概念,因此无法编写,因此,它不应具有带有配方的规则。

    3. 编写makefile的重点是,除非必要,否则不必执行配方,从而节省时间。在您的情况下,test根本不存在,因此将始终执行配方,这对于makefile来说毫无意义。

      相反,您应该拥有一个名称为CounterStat_tested的文件和一个如下规则:

      CounterStat_tested: CounterStatTester.class CounterStat.class Makefile
              java CounterStatTester && touch $@
      
      1. 最后,makefile的顶部应该有一个all目标:

        .PHONY: all
        all: CounterStatTester.class CounterStat.class CounterStat_tested