I'm trying to compile a Java module that is located in a separate directory from my project's source root. Here's my project structure:
Foundation-Test-1:
│ .gitignore
│ Foundation-Test-1.iml
│
├───MyFirstModule
│ │ MyFirstModule.iml
│ │
│ └───src
│ │ module-info.java
│ │
│ └───modular
│ HelloWorld.java
│
├───out
│ └───production
│ └───MyFirstModule
│ │ module-info.class
│ │
│ └───modular
│ HelloWorld.class
│
└───src
My module-info.java content:
module MyFirstModule {
exports modular;
}
When I try to compile using:
I get the error:
error: module MyFirstModule not found in module source path
I have read similar module-related issues on StackOverflow but still cannot resolve my specific problem.
Note all commands below assume Foundation-Test-1
is the working directory.
To understand how javac
works, I recommend reading its tool specification. In particular, reading the Directory Hierarchy and The Module Source Path Option sections will help with understanding how to compile modules.
In your case, the following command should work:
javac -d out/production --module-source-path MyFirstModule=MyFirstModule/src --module MyFirstModule
The above uses the so-called "module-specific form" when specifying the --module-source-path
option, which directly tells the compiler which directory contains the MyFirstModule
module. See the Module Source Path Option section of the tool specification linked earlier for more information.
Note this only seems to be possible on Java 12+. See JDK-8208609.
Another option you have is to move the module-info.java
file up a level so that you have:
Foundation-Test-1
|
\---MyFirstModule
| module-info.java
|
\---src
\---modular
HelloWorld.java
Note how module-info.java
is directly under the MyFirstModule/
directory instead of under the src/
directory.
With that change, you should be able to execute:
javac -d out/production --module-source-path . --module MyFirstModule
This works because now the module-info
descriptor for the module named MyFirstModule
is directly under a directory with the same name. See the Module Source Hierarchy subsection of the Directory Hierarchy section of the tool specification linked earlier for more information.
A third option is to get rid of the src
directory entirely and use MyFirstModule
as the "source root". This would give you:
Foundation-Test-1
|
\---MyFirstModule
| module-info.java
|
\---modular
HelloWorld.java
Then the same command as before should work:
javac -d out/production --module-source-path . --module MyFirstModule
This works for similar reasons as option 2.
An alternative approach you could use is to compile the code the "old way":
javac -d out/productions --source-path MyFirstModule/src <sources>
Where <sources>
is replaced by a list of source files you wish to compile. This is how you compile non-modular source code, but if you include the module-info.java
file in the sources list then it will also be compiled (and validated). Note if you have a lot of source files to compile then you may wish to use an arguments file to list them. And you may wish to use command line tools to find all *.java
files for you instead of listing them manually.
Note you rarely if ever interact with javac
directly when compiling Java projects in the "real world". Instead, you would rely on a build tool such as Maven, Gradle, or even just your IDE to compile your project. It can be good to understand how javac
works and how your build tool or IDE interacts with it, but for any non-trivial project I recommend using a build tool instead of invoking javac
(and other tools) manually.