1

このメイクファイルが各 .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"

試行 3...:

#########################################################################
#                                   #
# 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"

試行 2...:

#########################################################################
#                                   #
# 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"

試行 1...:

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
4

2 に答える 2

2

a)ソースファイルとクラスファイルが異なるディレクトリにあり、b)これらのディレクトリがネストされており、c)ソースファイルとクラスファイルからの1対1のマッピングがないため、Java用に明確に定義されたmakefileを作成することは複雑な作業です。次に、makeユーティリティが各Javaファイルをコンパイルするための個別のプロセスを生成するため、適切に実行されたmakefileでさえ良好なパフォーマンスを達成できません。一方、Javaコンパイラ自体は高速に動作し、依存関係チェックが組み込まれており、1回のプロセス実行で数百のJavaファイルをコンパイルできます。その結果、makeユーティリティはJavaファイルのコンパイルには使用されません。中小規模のプロジェクトの場合は、Javaコンパイラを使用して、すべてのソースファイルを渡します。大規模なプロジェクトの場合は、Ant、Gradle、またはその他のJava対応のビルドツールを使用します。

編集:javac依存関係チェックを使用するには、次のように実行します。

  javac -d ${OUTDIR} -cp ${OUTDIR} -sourcepath ${SRCDIR} ${MAIN_JAVA_FILE_NAME}

つまり、メインのJavaファイルの名前、他のソースファイルが存在する場所、クラスファイルが2回存在する場所(保存する場所と存在を確認する場所)のみを渡します。$ {SRCDIR}は、パッケージ構造に従ってJavaファイルを連結する必要があります。

于 2012-12-04T06:48:44.140 に答える
0

問題は、「*。java」をターゲットとして使用するのではなく、関連する各「*.class」の依存関係として使用する必要があることです。それ以外の場合、「Attempt 2」のように、ターゲットが依存関係のないファイルである場合、再構築されず、常に「最新」と叫びます。

主なアイデアは、依存関係を明確に理解するようにメーカーに指示することです。以下は、クラスファイルの作成を簡単にするためのテストケースです。小さなプロジェクトでも問題ありません(クラスTestはRefのメソッドを使用するため、Ref.classに依存しているため、手動で追加する必要があります)。私はこの問題についてより良い答えを願っています!!! しかし、大規模なプロジェクトの場合は、うーん、代わりにantを試してみませんか?

Makefile:

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");
  }
}

ここで「より単純な」テンプレートを共有したいと思います(ファイル名と依存関係を追加するだけです):

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)
于 2012-12-04T12:30:49.103 に答える