If you want to check your IDE whether it handles Java modules accurately, then you need to do a command line compilation and see what the JDK's javac compiler says. But how to do this?
Since Java 9, the javac compiler supports two kinds of module compilations: single- and multi-module.
Assume following source directories and files:
When your terminal window stands above the module's root directory fri.i18n.messages
, following command-line would compile the module's classes into the target directory given by the -d
option, in this case I named it module-classes
:
javac --module-path module-classes \
-d module-classes/fri.i18n.messages \
`find fri.i18n.messages -name '*.java'`
The --module-path option (also -p) is necessary only when the module depends on other modules that were already compiled into module-classes
. It tells the compiler where to search for referenced modules, being the future replacement for CLASSPATH.
The -d option gives the output directory where to write compiled classes into. In this case the name of the module (fri.i18n.messages
) must be appended to achieve a correct output path.
The find command is available on UNIX systems only, on WINDOWS you have to download and install it. It searches all .java files inside the fri.i18n.messages
directory. The `backquotes` are a UNIX-shell mechanism that puts the output of the find
command into the javac
command line. (Not a good solution, because the list of sources could get huge. See below for a better way to pass sources to the compiler. The new --module-source-path
option was not made for this!)
This single-module compilation command would result in following:
A certain directory structure is required to compile several modules in one run. All modules must be located below a directory that is given as --module-source-path
, in this case I named it module-sources
. Each module's sources are in a directory below that is named like the module. Mind that this name is duplicated in module-info.java
!
You can compile all modules contained in module-sources
by following command line:
javac --module-path module-classes \
-d module-classes \
--module-source-path module-sources \
`find module-sources -name '*.java'`
Again the --module-path option could be left out when the modules do not depend on precompiled modules.
The --module-source-path option points to the directory where the module directories are below, in this case it is module-sources
.
Result of this compilation command would be:
Mind that I didn't have to put any module name into the command line, like I had to do for a single module compilation.
Putting the find
command as substitution into the javac
command line is not a real-world solution. Most projects have tons of source files, and the shell command buffer may get out of bounds. There is an option to replace the list of sources by a file name tagged with '@'. You would let the find
command write into a file, and then pass the file to javac
. Here is an example for single module compilation:
find fri.i18n.messages -name '*.java' >sources.list
javac --module-path module-classes -d module-classes/fri.i18n.messages @sources.list
rm -f sources.list
The according multi-module commands would be:
find module-sources -name '*.java' >sources.list
javac --module-path module-classes -d module-classes --module-source-path module-sources @sources.list
rm -f sources.list
The '@' (ampersand) before the file name sources.list
does the magic.
Here is a UNIX shell script, named modules-compile.sh
, that can do both single and multi module compilations. Put this into the directory above your module source directory like the following:
Put the list of your module directories into modules.list (no comments allowed here!):
fri.i18n.messages
module-sources
These can be single modules (fri.i18n.messages
) or directories containing multiple modules (module-sources
).
IMPORTANT: keep the list in dependency order, so that basic modules are already compiled when the modules that depend on them get compiled!
Then put following into modules-compile.sh:
1 | # compiled classes target directory |
Most likely you'll have to make the script executable then:
chmod 754 modules-compile.sh
Mind that this script requires the name of the module written in same line as the module
keyword in a module-info.java
of a single module (script line 23). For multi-module compilation this is not needed.
This script works with both Maven and Eclipse projects. Eclipse projects have all sources inside a src/
directory, Maven has them in src/main/java/
and src/test/java/
.
It would take too much space to explain the script. Shell scripts are not well readable, they are quick & dirty, you need an expert to maintain them. But they are quite useful sometimes, so try it out !-)
ɔ⃝ Fritz Ritzberger, 2020-05-31