知道为什么这个makefile会重新编译(通常是这样)每个.class文件?另外,我认为这是相关的,java文件导入它们上面的文件。我已经尝试了4次并浪费了几个小时才能使用它,而不是处理我项目的实际代码,所以任何帮助都会非常感激。
#########################################################################
# #
# http://ieng6.ucsd.edu/~cs131f/makenotes.html #
# #
#########################################################################
JFLAGS = -g -d
JC = javac
.SUFFIXES : .java .class
SRCDIR = simpella
OUTDIR = simpella/out
.java.class:
$(JC) $(JFLAGS) $(OUTDIR) $*.java
#########################################################################
#
# example run: javac -g -d simpella/out simpella/simpella.java
#
#########################################################################
CLASSES = \
$(SRCDIR)/Util.java \
$(SRCDIR)/Converters.java \
$(SRCDIR)/Connection.java \
$(SRCDIR)/Simpella.java
default: classes
classes: $(CLASSES:.java=.class)
#########################################################################
clean:
$(RM) -v simpella/out/simpella/*.class
@- echo "Cleaned"
#########################################################################
# #
# http://ieng6.ucsd.edu/~cs131f/makenotes.html #
# #
#########################################################################
JFLAGS = -g -d
JC = javac
.SUFFIXES : .java .class
SRCDIR = simpella
OUTDIR = simpella/out
.java.class:
$(JC) $(JFLAGS) $(OUTDIR) $*.java
#########################################################################
#
# example run: javac -g -d simpella/out simpella/simpella.java
#
#########################################################################
all: Simpella.java
Util.java:
Util.java=Util.java
Converters.java:
Converters.java=Converters.class
Connection.java: Converters.java Util.java
Connection.java=Connection.class
Simpella.java: Connection.java Converters.java Util.java
Simpella.java=Simpella.class
@- echo "Done Compiling!!"
#########################################################################
clean:
$(RM) -v simpella/out/simpella/*.class
@- echo "Cleaned"
#########################################################################
# #
# http://ieng6.ucsd.edu/~cs131f/makenotes.html #
# #
#########################################################################
JFLAGS = -g -d
JC = javac
.SUFFIXES : .java .class
SRCDIR = simpella
OUTDIR = simpella/out
.java.class:
$(JC) $(JFLAGS) $*.java
#########################################################################
#CLASSES = Simpella.java Connection.java Converters.java Util.java
all: Simpella.java
#example run: javac -g -d simpella/out simpella/simpella.java
Util.java:
$(JC) $(JFLAGS) $(OUTDIR) $(SRCDIR)/Util.java
Converters.java:
$(JC) $(JFLAGS) $(OUTDIR) $(SRCDIR)/Converters.java
Connection.java:
$(JC) $(JFLAGS) $(OUTDIR) $(SRCDIR)/Connection.java
Simpella.java: Util.java Connection.java Converters.java
$(JC) $(JFLAGS) $(OUTDIR) $(SRCDIR)/Simpella.java
@- echo "Done Compiling!!"
#########################################################################
clean:
$(RM) -v simpella/out/simpella/*.class
@- echo "Cleaned"
JFLAGS = -g -d
JC = javac
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $*.java
CLASSES = \
simpella\Util.java \
simpella\Converters.java \
simpella\Connection.java \
simpella\simpella.java
default: classes
classes: $(CLASSES:.java=.class)
@- echo "Done Compiling!!"
clean:
$(RM) *.class
答案 0 :(得分:2)
为java创建定义良好的makefile是一项复杂的任务,因为a)源文件和类文件位于不同的目录中,b)这些目录是嵌套的,c)源文件和类文件没有一对一的映射。然后,即使做得好的makefile也无法实现良好的性能,因为make实用程序会生成单独的进程来编译每个java文件。另一方面,java编译器本身工作速度快,具有嵌入式依赖性检查,并且能够在单个进程运行中编译数百个java文件。因此,make实用程序不用于编译java文件。对于中小型项目,使用java编译器并将所有源文件传递给它。对于大型项目,请使用Ant,Gradle或其他支持java的构建工具。
编辑:使用javac依赖性检查,以这种方式运行:
javac -d ${OUTDIR} -cp ${OUTDIR} -sourcepath ${SRCDIR} ${MAIN_JAVA_FILE_NAME}
也就是说,只传递主java文件的名称,指向其他源文件所在的位置,指向类文件所在的位置两次:存储位置以及检查存在位置。 $ {SRCDIR}应该根据包的结构来控制java文件。
答案 1 :(得分:0)
问题是你不应该使用" * .java"作为目标,但应将其用作每个相关的" * .class"的依赖项。否则,就像你的"尝试2",当目标是一个没有依赖关系的文件时,它将不会重建,并且总是大喊“#34;最新的"。
主要思想是告诉你的make清楚地理解依赖关系。下面是一个测试用例,它使构建类文件更简单,对于一个小项目来说是可以的(类Test将使用Ref中的方法,因此它依赖于Ref.class,我们应该手动添加它)。我希望在这个问题上有更好的答案!但对于大型项目,嗯,为什么不尝试ant呢?
生成文件:
OBJ = ./obj/
SRC = ./src/
JARS = $(wildcard lib/*.jar)
LIB = .:$(OBJ):$(shell echo '$(JARS)' | sed 's/jar /jar:/g')
define make-target
@echo + cc $<
@javac -classpath $(LIB) $< -d $(OBJ) $*
endef
all: always ./obj/Ref.class ./obj/Test.class
./obj/Ref.class: ./src/Ref.java
$(make-target)
./obj/Test.class:./src/Test.java ./obj/Ref.class
$(make-target)
run:
@java -classpath $(LIB) Test
always:
@mkdir -p $(OBJ)
Test.java:
public class Test {
public static void main(String argv[]) {
Ref ref = new Ref();
ref.run();
}
}
Ref.java:
public class Ref {
public void run() {
System.out.println("hhhh");
}
}
我想和我分享更简单的&#39;这里的模板(你只需要添加文件名和依赖项):
OBJ = obj
SRC = src
JARS = $(wildcard lib/*.jar)
LIB = .:$(OBJ):$(shell echo '$(JARS)' | sed 's/jar /jar:/g')
targets := $(wildcard */*.java)
targets := $(patsubst %.java,%.class,$(targets))
targets := $(notdir $(targets))
targets := $(addprefix $(OBJ)/,$(targets))
define build
@echo + cc $<
@javac -classpath $(LIB) $< -d $(OBJ) $*
endef
define extend
$(shell echo $1|sed 's/.class/.java/'|sed 's/$(OBJ)/$(SRC)/')
endef
all: always $(targets)
.SECONDEXPANSION:
$(OBJ)/Ref.class: $$(call extend, $$@)
$(call build)
$(OBJ)/Test.class:$$(call extend, $$@) $(OBJ)/Ref.class
$(call build)
run:
@java -classpath $(LIB) Test
.PHONY: clean always
clean:
@rm -rf $(OBJ)
always:
@mkdir -p $(OBJ)