4

I'm having this error when trying to compile my Java project with a Makefile I created.

Error:

make: No rule to make target src/edu/osu/lispinterpreter/output/*.class', needed byclasses'. Stop.*

Makefile content:

JFLAGS = -g
JC = javac
.SUFFIXES: .java .class
.java.class:
    $(JC) $(JFLAGS) $*.java

CLASSES = \
        src/edu/osu/lispinterpreter/tokenizer/*.java \
        src/edu/osu/lispinterpreter/core/*.java \
        src/edu/osu/lispinterpreter/output/*.java \
        src/edu/osu/lispinterpreter/exceptions/*.java \
        src/edu/osu/lispinterpreter/input/InputParser.java \
        src/edu/osu/lispinterpreter/input/ReadInputString.java 

default: classes

classes: $(CLASSES:.java=.class)

clean:
    $(RM) *.class

Can someone give me a hand with the Makefile please?

I'm using Eclipse btw.

Cacho Santa
  • 6,846
  • 6
  • 41
  • 73
  • the folder src/edu/osu/lispinterpreter/output has no java files, it seems? – uba Mar 09 '13 at 02:51
  • 1
    Since you are using Eclipse, you should be able to **automatically** generate an Ant "build.xml". Ant is vastly superior to Make for building Java code. – Stephen C Mar 09 '13 at 02:52
  • but I need to create a Makefile, build.xml is not an option..... @StephenC – Cacho Santa Mar 09 '13 at 02:56
  • all the files are the @uba.... thank you both! – Cacho Santa Mar 09 '13 at 02:57
  • Ummm ... that is not true. If you can run Java on the build platform then you can also install and run Ant. And you can always write your Makefile to run `ant` to build the Java code. – Stephen C Mar 09 '13 at 03:00
  • 3
    @StephenC In fairness, not all requirements are (a) technical or (b) reasonable. – Dave Newton Mar 09 '13 at 03:21
  • @DaveNewton - But the flipside is that you (e.g. the OP) need to be prepared to "push back" on requirements that are not reasonable ... if there is a chance that it will work. In this case, a technically unsound / unreasonable requirement is going to create a lot of unnecessary work and lead to a slow and/or fragile builds ... 'cos "someone" doesn't understand how bad an idea it is. – Stephen C Mar 09 '13 at 03:34
  • @DaveNewton - The worst thing that *we* can do is to fail to advise people like the OP of the consequences of their poor choices ... whether or not they were the people responsible for the choices. – Stephen C Mar 09 '13 at 03:37
  • @StephenC I'm pretty sure that's not the worst thing we can do. That aside, OP stated the reqs after you suggested Ant; the responsibility was fulfilled. – Dave Newton Mar 09 '13 at 15:04

3 Answers3

2

From http://www.gnu.org/software/make/manual/html_node/Wildcard-Pitfall.html#Wildcard-Pitfall

When a wildcard matches no files, it is left as it is

It seems src/edu/osu/lispinterpreter/output is empty, so src/edu/osu/lispinterpreter/output/*.java does not match any file and is left as it is, which is not what is intended. Using the wildcard function, this can be avoided.

The solution would be to replace

src/edu/osu/lispinterpreter/output/*.java

by

$(wildcard src/edu/osu/lispinterpreter/output/*.java)

and so on for all the other lines, I think

uba
  • 2,012
  • 18
  • 21
1

I think that the problem is that your use of * in the CLASSES variable. The way you have written that variable, it is being populated with a list of "file names" that have * characters in them ... which will propagate through the rest of the processing.

You either need to list the classes individually, or do something to tell Make to "glob" the list. If you are using GNU Make then the wildcard function should do the trick.

But note that won't work on other versions of Make, so you've got a Makefile portability problem. (Which brings me back to my comment that Ant is better.)


And once you've gotten past that, you have the problem that if you are compile Java classes one at a time:

  • your build will be really slow ... 'cos each javac command incurs a JVM startup (assuming you are using the Hotspot or OpenJDK tool chains),
  • you have to build the classes in the right order ... according to the dependencies inherent in the source code,
  • you have to add those dependencies to the Makefile (!!!), and
  • if you have dependency cycles, you've got problems!

With enough patience, you could build a Makefile that coped with this, but it is really tricky, and the resulting Makefile will be fragile. Realistic alternatives are:

  • just build all of the /.java files in one javac command, irrespective of dependencies,
  • add a "make depend" rule that uses something to analyse the source code or bytecode files and generate the dependencies in the Makefile.

Or just use Ant.

References:

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

You either list all the source files individually or use the wildcard directive in Makefile to automatically match the files instead.

Also from your comments it looks like the package names for the java files are edu.osu.lispinterpreter.*.

So I would suggest to move the Makefile to the src directory and make these changes in the Makefile.

CLASSES := $(wildcard edu/osu/lispinterpreter/tokenizer/*.java)
CLASSES += $(wildcard edu/osu/lispinterpreter/core/*.java)
CLASSES += $(wildcard edu/osu/lispinterpreter/output/*.java)
CLASSES += $(wildcard edu/osu/lispinterpreter/exceptions/*.java)
CLASSES += edu/osu/lispinterpreter/input/InputParser.java
CLASSES += edu/osu/lispinterpreter/input/ReadInputString.java

The java compiler should be able to pick up definitions of classes from other packages as long as the package name corresponds to the directory structure without writing any explicit dependencies in the Makefile.

Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • I tried that, but now it throws this error: src/edu/osu/lispinterpreter/tokenizer/Tokenizer.java:4: package edu.osu.lispinterpreter.exceptions does not exist – Cacho Santa Mar 09 '13 at 03:08
  • should I put them in a specific order? – Cacho Santa Mar 09 '13 at 03:09
  • 1
    You should define dependencies in your Makefile, that is what a `Makefile` is for. :) – Tuxdude Mar 09 '13 at 03:09
  • great! in which section of the file should I put that? – Cacho Santa Mar 09 '13 at 03:16
  • 1
    You can define it after this line: `classes: $(CLASSES:.java=.class)`. Since that by itself is another dependency rule, make sure to add a new line. – Tuxdude Mar 09 '13 at 03:18
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/25867/discussion-between-tuxdude-and-cacho) – Tuxdude Mar 09 '13 at 03:18
  • Thats the exact answer! The problem was that the Makefile should be located inside the "src" folder..... The wildcard saved me also! Thanks @Tuxdude! Amazing help! :O) – Cacho Santa Mar 09 '13 at 04:44