This blog post is just another note to my future self. This time, it is about compiling (and running) a Java application (with multiple source files) from only the command line.
The Example Program
Let's say, our application is made up of two files: Main.java and Combination.java. In this example, their contents look like this …
// Main.java
package com.konstantintutsch.Example;
public class Main
{
private static Combination c;
public static void main(String[] args)
{
c = new Combination("Hello, World!", 42);
System.out.println(c.getText() + " (" + c.getNumber() + ")");
}
}
… and like this:
// Combination.java
package com.konstantintutsch.Example;
public class Combination
{
// Attributes
private String text;
private int number;
// Methods
public Combination(String text, int number) // Constructor
{
this.text = text;
this.number = number;
}
// text
public String getText()
{
return this.text;
}
public void setText(String text)
{
this.text = text;
}
// number
public int getNumber()
{
return this.number;
}
public void setNumber(int number)
{
this.number = number;
}
}
In this case, our entry point into the code of our program is the class Main from Main.java.
Compiling
If we want to compile and later execute this code, we need to create a JAR file.
Here's the procedure:
- Compile all
.javasource files to.classfiles - Bundle these
.classfiles into a.jarfile
Commands
The procedure, but translated into commands, looks like this:
mkdir ./build
javac -d ./build Main.java Combination.java
jar cfe ./build/Build.jar com.konstantintutsch.Example.Main -C ./build com
Explanation
javac-d ./build: write all.classfiles to./build/<PACKAGE>*.java: file(s) to be compiled
jarc: create a JARf: write the archive to a file (./build/Build.jar)e: use a class as the entry point (com.konstantintutsch.Example.Main)-C ./build com: bundle all.classfiles in the directory./buildfrom the namespacecom(alsocom.konstantintutsch.Example) into the archive
Makefile
If you don't want to retype these same commands every time you change something in your code, write a Makefile:
#
# Package
#
NAMESPACE := com
PACKAGE := $(NAMESPACE).konstantintutsch.Template
#
# Files
#
SOURCES := $(wildcard *.java)
BUILDDIR := build
EXECUTABLE := Build.jar
#
# Compilers
#
JC := javac
JCFLAGS := -d $(BUILDDIR)
JR := jar
#
# Build
#
$(BUILDDIR):
mkdir -p $(BUILDDIR)
$(BUILDDIR)/$(EXECUTABLE): $(BUILDDIR)
$(JC) $(JCFLAGS) $(SOURCES)
$(JR) cfe $(BUILDDIR)/$(EXECUTABLE) $(PACKAGE).Main -C $(BUILDDIR) $(NAMESPACE)
Compiling now looks like this:
make build/Build.jar
Much shorter!
Executing
The last thing to do now is to run the code:
$ java -jar ./build/Build.jar
Hello, World! (42)
Look at that! It worked!
At least on my end …