2

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:

  • javac -d out/production --module-source-path MyFirstModule/src --module MyFirstModule
  • javac -d out/production --module-source-path . --module MyFirstModule

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.

1
  • Hi, I don't know what is "old way"? Can you guideline step-by-step to fix this using --module-source-path. I have tried to create MyFirstModule under MyFirstModule/src and run command above again, it not still working. Commented Oct 26, 2024 at 11:09

1 Answer 1

3

Note all commands below assume Foundation-Test-1 is the working directory.


Compiling Modules

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.

Option 1

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.

Option 2

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.

Option 3

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.


The "Old Way"

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.


In the Real World

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.

Sign up to request clarification or add additional context in comments.

9 Comments

after I remove module-info.java to MyFirstModule/. it raise a warning: java file is located outside of the module source root, so it won't be compiled. if left unchange, after run javac -d out/production --module-source-path MyFirstModule=MyFirstModule/src --module MyFirstModule at Foundation-Test-1 folder, it still report an error error: module MyFirstModule not found in module source path
I'm not sure why your commands are failing. I tested all three of the approaches I mentioned (using a setup similar to what you described in your question) on Java 11.0.25, 17.0.13, 21.0.5, and 23.0.1. Each test compiled the code as expected without any warnings, except for the "module-specific form" approach which failed on Java 11.0.25 (and only on that version). I tested on Windows, though the operating system should be irrelevant.
this is all my code, please fix it for me: github.com/manhcntt21/Foundation-Test-1 (approach 1)
I cloned your repo and ran the command in your readme without modification and the code compiled successfully--no warnings or errors--using Java 23.0.1. I could even successfully execute the application as a module (i.e., java -p out/production -m MyFirstModule/MyFirstModule.HelloWorld), meaning the module was compiled as expected.
Olá, estou estudando sobre javac agora, pois estou com dificuldades em compilar os packages com o Geany, no Linux Mint 22. Baixei, também seu repositório e executei os comando javac e java e ambos responderam corretamente. Estou usando o JDK25.
Well, "option 2" (I've labeled the options in the answer) still works for me in Java 11.0.25 without any warnings (I don't have Java 11.0.9 available for testing). But another option you have is to get rid of the src directory entirely and move its contents directly under MyFirstModule. I've added that option as "option 3" to the answer. I also created a pull request in your repo showing this solution.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.