Javac 忽略源路径文件的第一行并且不编译 class

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

我有一个具有这种结构的项目(为简单起见缩短):

我正在尝试用终端编译它。

我在 src 目录中,首先执行此操作:

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

在第一个命令之后生成一个 sources.txt 文件:

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

我还在做:

javac -sourcepath @sources.txt

它生成所有 .class 文件,除了第一个 - Baloon.java 被 javac 完全忽略。

如果我这样做:

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

一个 Baloon.class 文件与其他 .class 文件一起生成。

如果我手动更改 sources.txt 的第一行,例如切换第一行和第二行,那么当我再次重新编译时,sources.txt 中的 .java 文件将被 javac 和相应的忽略.class 文件未创建。

或者,如果我使用 Intellij Idea 进行编译 - 一切正常,不会出现任何问题。

无论是在项目根目录编译,还是在src目录编译,结果都是一样的——sources.txt第一行被忽略。

所以问题是 - 我对以上 2 个终端命令做错了什么?还是 javac 的 bug?

javac 版本 - 1.8.0_221

项目文件本身:https://github.com/Dman-89/42_avaj_launcher

javac 将编译指定的源文件,例如你的情况只是 Baloon.java

此外,如果编译器可以找到它们的源文件,那么从那些明确命名的源文件中引用的任何 classes 也将被编译。它在 sourcepath 上查找它们,如果未指定,则默认与 classpath 相同。

假设Simulator是带有main()方法的class(如图标的绿色“播放”三角形所示),它将直接或间接引用所有其他源文件,所以这是要指定的文件:

cd src
javac simulator/Simulator.java

或:

javac -cp src src/simulator/Simulator.java

听起来你的目标是创建一个源文件列表,然后将它们全部传递给 javac 进行编译。如果那是你的目标,-sourcepath 不是你想要的。

您想要以下两件事之一:

做所有真正的 java 程序员所做的事情

'real' 定义为:他们这样做是为了赚钱 and/or 眼球,而不是作为学术活动。

使用构建系统; gradle 或 maven 是常见的选择。他们会为您处理所有这一切,远比草率地破解一些 bash 脚本要好得多。

只需传递 java 个源文件

只需删除 -sourcepath 部分。 javac @sources.txt就是你想要的。

这是怎么回事?

第一个 'argument'(sources.txt 文件中的第一行)是 -sourcepath 参数的 'value',而 javac 不是编译这个,因为 -sourcepath 并不意味着 'compile this stuff'(见后面)。其余部分(第 2 行及以后)只是参数,实际上 javac 将编译的内容。

那么sourcepath是什么?

要使用 javac 编译源文件,您需要编写 javac foo/A.java bar/B.java。但是,如果 A.java 包含:import lombok.Value; 怎么办?除非 javac 知道 lombok.Value,否则 Javac 现在无法编译此文件。通常这样的依赖已经被编译(你在目录或 jar 文件中有 class 文件),在这种情况下你会使用 javac-classpath 选项来告诉 javac 关于在哪里可以找到这些东西。

-sourcepath 类似,只是它用于尚未编译的内容。这意味着 javac 将了解源路径中存在的任何内容,以防出现需要首先编译的任何内容,并且仅在需要时才这样做您为编译指定的任何实际文件

javacjava 的任何 -xpath 选项一样,如果要指定超过 1 个条目,请使用冒号(windows 上的分号)作为分隔符,而不是 space。此外,想法是传递目录而不是实际文件。就像 -classpath 一样,传递无效(例如不存在的)路径是可以的。然后他们就被忽略了。

例子

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

这将告诉 javac 编译 Main 和 Extra(不是 depsdeps2 或其中的任何文件)。但是,如果 Main.java 包含以下行:Object o = new bar.baz.Hello(); 文件 deps/bar/baz/Hello.java 存在,则此命令最终也会编译 Hello.java。如果 deps/bar/baz/Whatever.java 也存在,则不会被编译,除非 WhateverHello.javaMain.javaExtra.java 中的某处被提及。并且既不在评论中也不在导入语句中(import if java-ese for alias,它实际上并没有导入任何东西)。