I would like to create a runnable jar in the same manner in which eclipse does, but from CLI. I am using buildbot and I would like to be able to automatically create, for example, nightly builds automatically, but are also runnable.
My Makefile:
JFLAGS = -g
JC = javac
JAR = jar
JARFLAGS = cfe ./bin/java.jar alone.Gameloop -C resources . -C ./
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $(wildcard alone/*.java)
#$(JC) $(JFLAGS) $*.java
CLASSES = \
$(wildcard alone/*.java) \
# alone/Enter.java \
# alone/GameLoop.java \
# alone/ImageRender.java \
# Blah.java \
# Library.java \
# Main.java
all: classes
default: classes
packages: jars
jars:
#echo $(JAR) $(JARFLAGS) $(CLASSES:.java=.class)
#false
$(JAR) $(JARFLAGS) $(CLASSES:.java=.class)
classes: $(CLASSES:.java=.class)
clean:
$(RM) *.class
Thanks for the help! :)
Your stuff looks okay all you have to do is add $(CLASSES) to the jars target as a dependency:
jars: classes
$(JAR) $(JARFLAGS) $(CLASSES:.java=.class)
and then make jars will do the stuff nightly
Related
And also so that it puts the .class files in a ClassDir directory? So far, I've only been able to make it work when everything is in same directory.
JFLAGS = -g
JC = javac
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $*.java
# This uses the line continuation character (\) for readability
CLASSES = \
Context.java \
ClosedState.java \
OpenState.java \
Floor.java \
State.java \
Elevator.java
default: classes
classes: $(CLASSES:.java=.class)
clean:
$(RM) *.class
I'm building a java program in Windows envoirment, but i need to be able to compile it in Linux envoirment. I'm currently having problems with the makefile:
the project folders are organized in this way:
project_folder
library.jar
src
folder1
a.java
b.java
folder2
c.java
d.java
folder3
e.java
The e.java file into folder3 is in almost all the others .java files because it's the principal struct, and for every file i have the line
import folder3.e;
Wich Eclipse automatically generates when i use a structure from another class file. What the terminal tells me:
error: Package folder3 does not exist
this is the makefile
JFLAGS = -g -cp library.jar -sourcepath .
JC = javac
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $*.java
CLASSES = \
src/folder1/a.java \
src/folder1/b.java \
src/folder2/c.java \
src/folder2/d.java \
src/folder3/e.java
default: classes
classes: $(CLASSES:.java=.class)
clean:
find . -name "*.class" -type f -delete
It's my very first makefile for java and i think i'm wrongly including the references between classes, how i can solve this?
Thank you
UPDATE: #Karthikeyan Vaithilingam thank you for your detailed answer, now it's all clear and working!
Add -d . to JFLAGS so the class files will be created with proper folder structure.
So your JFLAGS should be as follows.
JFLAGS = -g -cp .:library.jar -sourcepath . -d .
-d is the flag is used for destination folder in the above example its the current folder. You can use any destination but don't forget to add it to the classpath using -cp. By using -d you can keep the source folders clean, also cleaning will be easy, just remove the destination folder.
Update
The problem is the order of the Java files in CLASSES section. Since folder3.e class is referred in other classes it has to be at the beginning. It should be like the below one.
CLASSES = \
src/folder3/e.java \
src/folder1/a.java \
src/folder1/b.java \
src/folder2/c.java \
src/folder2/d.java
Also you can keep the libraries in a separate folder then use -cp libs\* to add all the jars in the folder. It will be easy to maintain
So the folder structure will be
project_folder
libs
library.jar
src
folder1
a.java
b.java
folder2
c.java
d.java
folder3
e.java
And the final Makefile will be
JFLAGS = -g -cp ".:libs/*" -sourcepath . -d .
JC = javac
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $*.java
CLASSES = \
src/folder3/e.java \
src/folder1/a.java \
src/folder1/b.java \
src/folder2/c.java \
src/folder2/d.java
default: classes
classes: $(CLASSES:.java=.class)
clean:
rm -r folder*
Unrelated
Why don't you use build tools Gradle or Maven or Ant?
Any idea why this makefile would re-compile (unnessesarily so) each .class file? Also, I think it is relevant, the java files import the files above them. I've tried this 4 times and wasted hours to get this to work, instead of working on the actual code of my project so any help would be really appreciated.
most recent attempt:
#########################################################################
# #
# 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"
Attempt 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"
Attempt 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"
Attempt 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
Creating well defined makefile for java is a complex task because a) source and class files are in different directories, b) those directories are nested, and c) there is no one-to-one mapping from source and class files. Then, even well-done makefile would not achieve good performance because make utility spawns separate process to compile each java file. On the other hand, java compiler itself works fast, has embedded dependence checking, and is able to compile hundreds of java files in single process run. As a result, make utility is not used to compile java files. For small and medium projects, use java compiler and pass all source files to it. For large projects, use Ant, Gradle or other java-aware build tool.
EDIT: to employ javac dependency checking, run it this way:
javac -d ${OUTDIR} -cp ${OUTDIR} -sourcepath ${SRCDIR} ${MAIN_JAVA_FILE_NAME}
That is, pass only the name of the main java file, point where other source files reside, point where class files reside twice: where to store and where to check for existence. The ${SRCDIR} should contatin java files according to their package structure.
The problem is that you should not use "*.java" as a target, but should use it as a dependency for each related "*.class". Otherwise, like your "Attempt 2", when the target is a file with no dependency, it will not be rebuild, and will always shout "up to date".
The main idea is to tell your make to understand the dependencies clearly. Below is a test case to make it simpler to build class files, it will be ok for a small project (class Test will use method from Ref, therefore it relies on Ref.class and we should manually add this). I hope better answers on this issue!!! But for large project, hmm, why not try ant instead?
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");
}
}
and I would like to share my 'simpler' template here(you just need to add file name and dependency):
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)
My makefile is below
Also, I would appreciate it if you told me how to move my .class files to ../bin/
JFLAGS = -cp
JAR = "RSBot*.jar"
JC = javac
.SUFFIXES: .java .class
.java.class:
$(JC) $(JFLAGS) $(JAR) $*.java
CLASSES = \
src/Banker.java \
src/Eater.java \
src/Fighter.java \
src/grotgui.java \
src/InventTab.java \
src/Looter.java \
src/Potter.java \
src/W8babyGrotworm.java \
src/Walker.java
default: classes
classes: $(CLASSES:.java=.class)
clean:
$(RM) *.class
As you can see here, How to wildcard include JAR files when compiling?, you cannot use the wildcard '*' in the classpath to get several jar files unless you are using java 1.6 or above. Otherwise, you should write each concrete jar you need.
To put your .class files in the bin directory, you can use the -d <directory> option of javac to specify where to place generated class files.
just out of curiosity, why make? why not use a more modern tool like maven, ant or gradle?
They are designed for this sort of thing and usually give you what you want out of the box.
But to answer your question:
javac -d outputdir
I need to make a makefile that compiles and executes my classes with an external jar file..
I have 4 classes;sync.java, FileSynchroniser.java, DirectoryTracer.java and SyncFileTracer.java.
I also need to include gson-1.7.1.jar ..
Heres my make file
.SUFFIXES: .class .java
JAVAC= $(JAVAHOME)\bin\javac
PATH=$(JAVAHOME)\bin;$(PATH)
CLASSPATH=.;$(JAVAHOME)\lib\classes.zip;$(JSDKHOME)\lib\classes.zip
DEST=.
DOC=.
JAVA=$(JAVAHOME)\bin\java
JAVACFLAGS=-deprecation
.SUFFIXES: .java .class
.java.class:
$(JAVAC) -classpath $(CLASSPATH) $(JAVACFLAGS) $<
CLASSFILES = sync.class \
FileSynchroniser.class \
DirectoryTracer.class \
SyncFileTracer.class
SOURCEFILES = sync.java \
FileSynchroniser.java \
DirectoryTracer.java \
SyncFileTracer.java
# begin ---- JAR support ----------
JARFILE= gson-1.7.1.jar
$(JARFILE): $(CLASSFILES) $(SOURCEFILES)
jar cfm0 $(JARFILE) <<manifest.tmp $(CLASSFILES)>>
# end ---- JAR support ----------
all : $(JARFILE) $(CLASSFILES) doc
doc : $(CLASSFILES)
javadoc -version -author -d $(DOC) $(SOURCEFILES)
install :
copy $CLASSESFILE $(DEST)
clean:
del $(CLASSFILES)
Thank you
Are you referring to making the makefile in a Linux OS?
Check this - make makefile guide
http://www.cs.swarthmore.edu/~newhall/unixhelp/howto_makefiles.html
or this - example
http://www.cs.swarthmore.edu/~newhall/unixhelp/javamakefiles.html
hope it help.