简体   繁体   中英

Javac ignores first line of sourcepath file and doesn't compile class

I have a project with such structure (shortened for simplicity):

在此处输入图片说明

and I'm trying to compile it with terminal.

I'm in src directory and firstly doing this:

find * -name "*.java" > sources.txt

After the first command a sources.txt file is generated:

aircraft/Baloon.java
aircraft/Aircraft.java
aircraft/JetPlane.java
aircraft/AircraftFactory.java
aircraft/Coordinates.java
aircraft/Flyable.java
aircraft/Helicopter.java
exception/WrongNumberArgsException.java
simulator/Simulator.java

Further I'm doing:

javac -sourcepath @sources.txt

And it generates all .class files, EXCEPT the first one - Baloon.java is totally ignored by javac.

If I do:

javac -sourcepath @sources.txt src/aircraft/Baloon.java

a Baloon.class file is generated as well with other .class files.

If I manually change first row of sources.txt , for example switch first and second rows, then when I recompile again first .java file in sources.txt is ignored by javac and respective .class file is not created.

Alternatively if I compile with Intellij Idea - everything is fine, no problems occur.

It doesn't matter if I compile in the root directory of project, or in src directory, result is the same - first line of sources.txt is ignored.

So the question is - what I'm doing wrong with above 2 terminal commands? or maybe it's a bug of javac?

javac version - 1.8.0_221

project files themself: https://github.com/Dman-89/42_avaj_launcher

It sounds like your aim is to create a list of source files, and then pass them all to javac to compile. If that is your aim, -sourcepath is not what you want.

You want one of two things:

Do what all real java programmers do

'real' defined as: They do it for money and/or eyeballs, and not as an academic exercise.

Use a build system; gradle or maven are the common choices. They will take care of all this for you far better than a slapdash effort to hack some bash scripts together.

Just pass the java source files

Just remove the -sourcepath part. javac @sources.txt is what you want.

What is going on?

The first 'argument' (first line in your sources.txt file) is the 'value' for the -sourcepath argument, and javac doesn't compile this, because -sourcepath doesn't mean 'compile this stuff' (see later). The rest (lines 2 and further) are just arguments, which is actually what javac will compile.

So what is sourcepath?

To compile source files with javac, you'd write javac foo/A.java bar/B.java . However, what if, say, A.java contains: import lombok.Value; ? Javac is now not capable of compiling this file unless javac knows about lombok.Value . Usually such dependencies are already compiled (you have class files in a directory or a jar file), in which case you'd use the -classpath option of javac to tell javac about where to find this stuff.

-sourcepath is similar, except, it's for not-yet-compiled stuff. That means javac will gain awareness of the existence of anything in the sourcepath, in case it comes up that any of that needs to be compiled first, and will only do so if it is needed by any of the actual files you specified for compilation .

Like any -xpath option to javac or java , if you want to specify more than 1 entry, use colons (semicolons on windows) as a separator, not space. Furthermore, the idea is to pass directories and not actual files. And just like -classpath , passing invalid (eg non-existing) paths is fine. Then they are just ignored.

Example

javac -sourcepath deps:deps2 src/com/mypkg/Main.java src/com/mypkg/Extra.java

This will tell javac to compile Main and Extra (not deps or deps2 or any files inside). However, if, say, Main.java contains the line: Object o = new bar.baz.Hello(); , and the file deps/bar/baz/Hello.java exists, then this command will end up also compiling Hello.java . If deps/bar/baz/Whatever.java also exists, that won't be compiled, unless Whatever is mentioned somewhere in Hello.java , Main.java , or Extra.java . And not in either a comment or just an import statement ( import if java-ese for alias , it doesn't actually import anything).

javac will compile the source files specified, eg just Baloon.java in your case.

In addition, any classes referenced from those explicitly named source files will also be compiled, if the compiler can find the source files for them. It looks for them on the sourcepath , which defaults to the same as the classpath if not specified.

Assuming Simulator is the class with the main() method (as indicated by the green "play" triangle of the icon), it will directly or indirectly reference all the other source files, so that's the file to specify:

cd src
javac simulator/Simulator.java

Or:

javac -cp src src/simulator/Simulator.java

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM