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
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 将了解源路径中存在的任何内容,以防出现需要首先编译的任何内容,并且仅在需要时才这样做您为编译指定的任何实际文件。
与 javac
或 java
的任何 -xpath
选项一样,如果要指定超过 1 个条目,请使用冒号(windows 上的分号)作为分隔符,而不是 space。此外,想法是传递目录而不是实际文件。就像 -classpath
一样,传递无效(例如不存在的)路径是可以的。然后他们就被忽略了。
例子
javac -sourcepath deps:deps2 src/com/mypkg/Main.java src/com/mypkg/Extra.java
这将告诉 javac 编译 Main 和 Extra(不是 deps
或 deps2
或其中的任何文件)。但是,如果 Main.java
包含以下行:Object o = new bar.baz.Hello();
、 和 文件 deps/bar/baz/Hello.java
存在,则此命令最终也会编译 Hello.java
。如果 deps/bar/baz/Whatever.java
也存在,则不会被编译,除非 Whatever
在 Hello.java
、Main.java
或 Extra.java
中的某处被提及。并且既不在评论中也不在导入语句中(import
if java-ese for alias
,它实际上并没有导入任何东西)。
我有一个具有这种结构的项目(为简单起见缩短):
我正在尝试用终端编译它。
我在 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
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 将了解源路径中存在的任何内容,以防出现需要首先编译的任何内容,并且仅在需要时才这样做您为编译指定的任何实际文件。
与 javac
或 java
的任何 -xpath
选项一样,如果要指定超过 1 个条目,请使用冒号(windows 上的分号)作为分隔符,而不是 space。此外,想法是传递目录而不是实际文件。就像 -classpath
一样,传递无效(例如不存在的)路径是可以的。然后他们就被忽略了。
例子
javac -sourcepath deps:deps2 src/com/mypkg/Main.java src/com/mypkg/Extra.java
这将告诉 javac 编译 Main 和 Extra(不是 deps
或 deps2
或其中的任何文件)。但是,如果 Main.java
包含以下行:Object o = new bar.baz.Hello();
、 和 文件 deps/bar/baz/Hello.java
存在,则此命令最终也会编译 Hello.java
。如果 deps/bar/baz/Whatever.java
也存在,则不会被编译,除非 Whatever
在 Hello.java
、Main.java
或 Extra.java
中的某处被提及。并且既不在评论中也不在导入语句中(import
if java-ese for alias
,它实际上并没有导入任何东西)。