make file for Java/Linux - java

I have the following makefile after running it once I make some changes to the makefile and now when I run it I get a "make: Nothing to be done for `default'." How can I force it to rebuild? I execute "make" and also "make clean" and I still get the error message when I type "make".
Also, how do I get the log4.properties file which is in the src directory to be copied over to the target directory (in the make file and on the command line: javac -classpath src:lib/log4j-1.2.16.jar src/*.java -d bin)?
#
# define compiler and compiler flag variables
#
JFLAGS = -g -cp .:src:lib/log4j-1.2.16.jar
JC = javac
#
# Clear any default targets for building .class files from .java files; we
# will provide our own target entry to do this in this makefile.
# make has a set of default targets for different suffixes (like .c.o)
# Currently, clearing the default for .java.class is not necessary since
# make does not have a definition for this target, but later versions of
# make may, so it doesn't hurt to make sure that we clear any default
# definitions for these
#
.SUFFIXES: .java .class
#
# Here is our target entry for creating .class files from .java files
# This is a target entry that uses the suffix rule syntax:
# DSTS:
# rule
# 'TS' is the suffix of the target file, 'DS' is the suffix of the dependency
# file, and 'rule' is the rule for building a target
# '$*' is a built-in macro that gets the basename of the current target
# Remember that there must be a before the command line ('rule')
#
.java.class:
$(JC) $(JFLAGS) $*.java
#
# CLASSES is a macro consisting of 4 words (one for each java source file)
#
CLASSES = \
src/MatrixDriver.java \
src/ConcreteMatrix.java \
src/Matrix.java \
src/Submatrix.java
#
# the default make target entry
#
default: classes
#
# This target entry uses Suffix Replacement within a macro:
# $(name:string1=string2)
# In the words in the macro named 'name' replace 'string1' with 'string2'
# Below we are replacing the suffix .java of all words in the macro CLASSES
# with the .class suffix
#
classes: $(CLASSES:.java=.class)
#
# RM is a predefined macro in make (RM = rm -f)
#
clean: FORCE
$(RM) *.class
FORCE:

The problem is that this:
.java.class:
$(JC) $(JFLAGS) $*.java
doesn't do what you think it does. Perhaps you meant something like this?
%.class: %.java
$(JC) $(JFLAGS) $^

I did not read your Makefile carefully and I do not consider myself a make expert
but
there does not seem to be any dependency on the Makefile itself
all you changed is the Makefile
leads me to think that the correct behavior is exactly what you described. Perhaps you can add a dependency to the Makefile.

Make sure there is no file or directory called classes. Make could then assume nothing more to do.

Related

How to handle jars in a makefile for a java project

I need help incorporating jars(specifically mysql-connector-java.jar & javax.persistence_2.1.0.v201304241213.jar) into my makefile. I am aware that Make is not ideal for a java project, but due to requirements, using ant/Maven is not an option. So far my makefile looks like:
# Makefile brutally copypasta'd from previous CSC pracs.
LIB = ../lib
SRCDIR = src
BINDIR = bin
TESTDIR = test
DOCDIR = doc
JAVAC = javac
JFLAGS = -g -d $(BINDIR) -cp $(BINDIR)
vpath %.java $(SRCDIR)
vpath %.class $(BINDIR)
# define general build rule for java sources
.SUFFIXES: .java .class
.java.class:
$(JAVAC) $(JFLAGS) $<
all: client server
client: shared/NetMessage.class client/Command.class client/UploadConnectionThread.class client/DownloadConnectionThread.class client/MainConnectionThread.class client/ClientState.class client/Main.class
server: shared/NetMessage.class server/ConnectionInstance.class server/ServerState.class server/Main.class
# handling the cyclic dependency between ClientState and the connection thread classes:
client/ClientState.class: client/UploadConnectionThread.class client/DownloadConnectionThread.class client/MainConnectionThread.class
client/UploadConnectionThread.class client/DownloadConnectionThread.class client/MainConnectionThread.class: client/ClientState.java client/UploadConnectionThread.java client/DownloadConnectionThread.java client/MainConnectionThread.java
rm -f $(BINDIR)/client/ClientState.class $(BINDIR)/client/DownloadConnectionThread.class $(BINDIR)/client/UploadConnectionThread.class $(BINDIR)/client/MainConnectionThread.class
$(JAVAC) $(JFLAGS) $(SRCDIR)/client/ClientState.java $(SRCDIR)/client/UploadConnectionThread.java $(SRCDIR)/client/DownloadConnectionThread.java $(SRCDIR)/client/MainConnectionThread.java
# handling cyclic dependency between ServerState and ConnectionInstance
server/ServerState.class: server/ConnectionInstance.class
server/ConnectionInstance.class: server/ConnectionInstance.java server/ServerState.java
rm -f $(BINDIR)/server/ServerState.class $(BINDIR)/server/ConnectionInstance.class
$(JAVAC) $(JFLAGS) $(SRCDIR)/server/ServerState.java $(SRCDIR)/server/ConnectionInstance.java
# All the actual program classes
# compile/run commands
run_server: server
java -cp bin server.Main
run_client: client
java -cp bin client.Main 127.0.0.1
clean:
#rm -f $(BINDIR)/*.class
#rm -f $(BINDIR)/*/*.class
I have researched the Javadocs and other questions on SO, but the answers provided, are for simple project structures where the makefile produces classfiles in the same directory as the java files and no packages are used. In this case however the class files are created in bin/server (if they are server files) or the approriate bin/subdirectory. My project structure is as follows:
/bin
/server/
/client/
/shared/
/src
/server/
/client/
/shared/
/lib
/mysql-connector-java.jar
/javax.persistence_2.1.0.v201304241213.jar
/makefile
I have already tried adding the jars to the classpath as follows: CLASSPATH = /lib/mysql-connector-java.jar, but it does not work when I add the class path to the rule: .SUFFIXES: .java .class, as Make picks it up as multiple targets.

How to compile and run java files from sub-directory

I'm trying to compile .java files and store them in a sub-directory called bin. I then want to run the generated .class files from the main directory. How can I do this?
Here's my Makefile:
# java compiler
JCC = javac
# output directory
OUTDIR = bin/
# compilation flags
JFLAGS = -g -d $(OUTDIR)
# default target entry
default: A.class B.class C.class
A.class: A.java
$(JCC) $(JFLAGS) A.java
B.class: B.java
$(JCC) $(JFLAGS) B.java
C.class: C.java
$(JCC) $(JFLAGS) C.java
# To start over from scratch, type 'make clean'.
# Removes all .class files, so that the next make rebuilds them
clean:
$(RM) $(OUTDIR)*.class
What I want to do:
make
java bin/A
You must specify the bin directory as the classpath of the JVM, using the -cp option
java -cp bin A
A being the fully qualified name of the class to run.

make file Java "missing operator" "none to do with default"

I am trying to build a make file for my program and Im getting the error missing operator at line 4 (javac $(JFLAGS)). I am also getting the error "none to do with default". Can someone help me with this error please? i have been stuck for quite a bit. Thank you much
JFLAGS = -g -d
JC = javac
%.class : %.java
javac $(JFLAGS)
CLASSES = \
Hello.java
default: $(CLASSES:.java=.class)
clean:
$(RM) *.class
You mention you are getting the error
make: Nothing to be done for 'default'.
This is not an error. It is make telling you that the target default is up to date and none of its prerequisites are older than it or need to be remade. For your particular case this will occur when the file Hello.class already exists in the same directory as your makefile. It is not an error but a simple message from make.
With regards to your other error
Java: missing operator at line 4
might this possibly say
makefile:4: *** missing separator. Stop.
instead? If that is the case then it means that you have not correctly indented the line
javac $(JFLAGS)
with a tab character.
Note: I mention this because it appears to be the closest error message to what you have described that I can replicate.
Another more pressing issue than the above is in particular your use of javac $(JFLAGS) and JFLAGS. In JFLAGS you have specified the -d option. When you execute javac $(JFLAGS) the error you get should look similar to
$ javac -g -d
javac: -d requires an argument
This is because the -d option when passed to javac is used to tell javac where the output directory that it should place .class files is. If you want your .class files to be output in the same directory as your makefile relative to their package name (see below) then you need to delete the -d option and declare JFLAGS as
JFLAGS = -g
If however, you dont want your .class files to be output in the same directory as your makefile then you need to declare a directory after the -d option in JFLAGS as
JFLAGS = -g -d /path/to/my/output/directory
Now that we've covered the -d option let's move on to actually compiling your .java files. The current rule you have is
%.class : %.java
javac $(JFLAGS)
this should to be altered to
%.class : %.java
$(JC) $(JFLAGS) $<
The automatic variable $< stands for the first prerequisite and will create a command like
$ javac -g Hello.java
for your particular example, which will create a Hello.class file in the same directory as the makefile and your Hello.java file.

How can I compile and run a Java class in a different directory?

I'm writing a makefile that compiles a .java file in a different directory, and then I want to run it, without changing directories. I want to do something along the lines of:
$(SQM_JAVA_TOOL_DONE) : $(SQM_JAVA_TOOL)
$(shell cd /home_dir)
javac myjavafile.java
java myjavafile
where the Java file is /home/myjavafile.java, and the makefile isn't running from /home.
How can I do this?
I might be misunderstanding the question, but you can compile with
javac /home/MyJavaFile.java
This will create MyJavaFile.class in /home
You can then run it by including /home on the classpath. e.g.
java -cp /home MyJavaFile
If you want to generate the class file in a different directory then you can use the -d option to javac.
Use the -d command line parameter with javac to tell it what directory you'd like to store the compiled class files in. Then, to run the program, simply include this directory in the classpath:
javac -d some/directory myjavafile.java
java -cp some/directory myjavafile
Just to add to the existing answers, you may want the --source-path flag:
--source-path <path>, -sourcepath <path>
Specify where to find input source files
I believe this effectively sets the package root javac will compile from (i.e. <path> will be stripped from the expected package name of the files). It's still necessary to enumerate the files to compile, and this should still be relative to the current working directory, not the path passed to --source-path.
For example, to compile and run from a project's root where source is stored in src/ and you want it build in bin/:
$ javac --source-path src -d bin src/mypackage/*.java
$ java -cp bin mypackage.Main
This works even from directories elsewhere in the filesystem, e.g.:
$ javac --source-path /some/absolute/path/src -d /some/absolute/path/bin /some/absolute/path/
$ java -cp /some/absolute/path/bin mypackage.Main
I am using VS Code and installed java and code runner extensions. When I created new java project using the extension, it was creating the .class file in src instead of bin. To solve the issue I opened settings.json file from File > Preferences > Settings and searched for "settings" (or "code-runner"). Then I added following lines in that file.
"code-runner.executorMap": {
"java": "cd \"$workspaceRoot\\\" && javac --source-path src -d bin src\\$fileName && java -cp bin $fileNameWithoutExt",
}
If you don`t want to see the command that runs before code file then add these lines instead:
"code-runner.clearPreviousOutput": true,
"code-runner.showExecutionMessage": false,
"code-runner.executorMap": {
"java": "there is && clear added in the execution paramater"
"java": "cd \"$workspaceRoot\\\" && javac --source-path src -d bin src\\$fileName && clear && java -cp bin $fileNameWithoutExt",
}
I hope this finds someone with similar issue.

How to launch a java CLI program, developed in Eclipse, from Cygwin bash shell?

I wanted to share here a useful script of mine.
I am developing some java CLI software under Eclipse.
For time to time, I find it useful to run it from the command line with custom arguments (with Cygwin in my case), instead of creating a new "Run configuration" in eclipse.
My eclipse project depends on some other "core" projects and a bunch of libs.
So I needed a bash launcher ...
So here is my solution :
I used to hardcode this whole CLASSPATH in a launcher script, but it was a pain to maintain.
So recently, I wrote a bash script that automatically parses the ".classpath" files recursively and generates CLASSPATH dynamically. This way, my launcher is always up to date. I have also added a "debug" option, that launches Java in remote debug mode.
Hope this helps someone.
#! /usr/bin/bash
# Eclipse CLI program launcher.
# ----------------------------------------------------------
# Constants
# ----------------------------------------------------------
# Main class
CLASS=your.main.class.Here
# ----------------------------------------------------------
# Parse arguments
# ----------------------------------------------------------
# Debugger mode ?
if [ "$1" = "debug" ]
then
shift
DEBUG_OPTIONS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3409,suspend=y"
fi
# -------------------------------------------------------
# Setup the classpath from eclipse .classpath files
# -------------------------------------------------------
# Init classpath
CLASSPATH=""
# Process a single .classpath file
# This is a recursive function
# Arguments:
# $1 : Dir path where to search for a ".classpath" file
function build_classpath() {
# Aliases to arguments
local folder="$1"
local file="$folder/.classpath"
# ".classpath" file does not exists ? => exit
if [ ! -f "$file" ]
then
return
fi
# Parse the file with sed
# return a list of <type>:<path> pairs
local lines=`sed -ne 's/^.*kind="\(.*\)"\s\s*path="\(.*\)".*$/\1:\2/gp' $file`
# Loop on lines
for line in $lines
do
# Split the type and path values
local type=${line%:*}
local path=${line#*:}
# Switch on type
case $type in
"lib" )
CLASSPATH=$CLASSPATH:$folder/$path
;;
"output" )
CLASSPATH=$CLASSPATH:$folder/$path
;;
"src" )
# Recursive call for other projects, relative to the workspace (the parent dir)
build_classpath "..$path"
;;
esac
done
}
# Start building the classpath from the current project dir
build_classpath .
# Call java
java $DEBUG_OPTIONS -Xmx1024m -cp `cygpath -wp $CLASSPATH` $CLASS $#

Categories

Resources