Sep 5, 2024

Home

How To Compile a Java Program with Multiple Source Files

This post is older than one year. It may contain outdated information or opinions I no longer hold and may not be an adequate guide anymore.

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:

  1. Compile all .java source files to .class files
  2. Bundle these .class files into a .jar file

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

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 …