Java:如何编译代码的整个目录结构?


84

用例很简单。我得到了使用Eclipse创建的源文件。因此,有一个深层的目录结构,其中任何Java类都可以引用同一,子,兄弟或父文件夹中的另一个Java类。

我如何使用javac从终端编译整个程序?


出于好奇,您使用的是Windows,Linux,Mac等操作系统?这可能有助于回答这个问题
扎克大号

1
我已经有两年没有在命令行上编译Java了,但是我认为,如果仅将包含main()的文件传递给javac,它将搜索出所有需要编译的其他文件,因为所有依赖项都可以从包含main()的文件开始发现。
Endophage 2011年

Answers:


59

您必须知道所有目录,或者能够使用通配符..

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java

2
我想通了:只需使用名称或通配符在javac之后列出所有.java文件即可。
euphoria83'1

52
或只是使用javac $(find . -name "*.java")
GeorgSchölly16年


40

如果您要做的只是运行主类(而不编译.java不依赖主类的文件),则可以执行以下操作:

cd <root-package-directory>
javac <complete-path-to-main-class>

要么

javac -cp <root-package-directory> <complete-path-to-main-class>

javac 会自动解决所有依赖关系,并编译所有依赖关系。


4
到目前为止,这是最简单的工作解决方案。为什么人们不喜欢它?
Alphaaa

11
可能是因为其简单性忽略了以下事实:许多库或支持代码的编译作业将没有链接到所有必需依赖项的main方法。这是一个很好的答案,但是我不会在任何框架/公共代码库中使用。
阿贾克斯

4
恕我直言,框架或任何其他公共项目应使用某种形式的构建管理。这种编译仅对小型私人项目有意义。
svenwltr

@Ajax,但如果是这种情况,您也可以使用该-sourcepath .选项,然后以相同的效果命名主文件
coderatchet16年

1
谁说有主线?谁说没有四个电源?是您希望输出中的每个类甚至被main引用(并且不使用META-INF / services或其他服务加载技术)。如果您正在做的只是测试主数据库,则此方法很好,但是,它无法解决“编译给定目录中的所有Java文件”这一完整任务。一个合适的构建系统是#1,cli工具find . -type f -name "*.java" | xargs javac 是2,并且只有在包含整个应用程序的单个main方法入口点时,才使用此方法。
阿贾克斯

12

我会接受Jon的建议并使用Ant,因为这是一个非常复杂的任务。

但是,如果确定要在终端中将所有内容全部放入一行,则在Linux上,可以使用find命令。但是我完全不建议这样做,因为不能保证Foo.java即使在Foo使用Bar.java之后也可以编译Bar。一个例子是:

find . -type f -name "*.java" -exec javac {} \;

如果尚未编译所有类,如果有一个主线束或驱动程序类(基本上是一个包含main方法的类),则单独编译该主类应编译大部分项目,即使它们位于不同的文件夹中,因为Javac将尽力解决依赖性问题。


1
在Windows上,find_gnu . -type f -name "*.java" | xargs javac一旦将find.exe的gnu版本重命名为find_gnu.exe,就可以使用。我从msysgit获得了gnu find.exe。
n611x007 2012年

或在纯Windows批处理中:(for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f使用单反引号,dir /s /b但我找不到正确格式化它的方法)。
Matthieu 2014年

我认为该find解决方案是有问题的,因为它会分别编译每个java类,因此速度很慢。
AlikElzin-kilaka的

12

以下是我发现的方法:

1)如下创建文件的列表,并在文件中添加相对路径(例如FilesList.txt)(以空格分隔或以行分隔):

foo/AccessTestInterface.java
foo/goo/AccessTestInterfaceImpl.java

2)使用命令:

javac @FilesList.txt -d classes

这将编译所有文件,并将类文件放入classes目录中。

现在,创建FilesList.txt的简单方法是:转到源根目录。

dir *.java /s /b > FilesList.txt

但是,这将填充绝对路径。使用文本编辑器“全部替换”使用“”(即空字符串)并保存到源目录(最后包括\)的路径。


这是更“原生”的方式,因为javac支持“批处理”文件
lovespring

如果路径包含空格,则“ dir * .java / s / b> FilesList.txt”方法将不起作用。javac将抱怨FilesList.txt
aderesh '17

10

已经存在的答案似乎只与* .java文件本身有关,而与如何轻松构建可能需要的库文件有关。

递归获取所有* .java文件以及包括构建所需的* .jar文件的一种单行情况是:

javac -cp ".:lib/*" -d bin $(find ./src/* | grep .java)

这里的bin文件是类文件的目标,lib(可能还有当前的工作目录)包含库文件,并且src目录及其下面的所有java文件都已编译。


我在编译swagger生成的客户端源代码时遇到问题
Eenvincible

9

您必须使用类似Ant之类的方法来分层执行此操作:

http://ant.apache.org/manual/Tasks/javac.html

您将需要使用一个名为compile的目标来创建一个构建脚本,其中包含以下内容:

<javac sourcepath="" srcdir="${src}"
         destdir="${build}" >
    <include name="**/*.java"/>
</javac>

然后,您将可以通过运行以下命令来编译所有文件:

 ant compile

或者,将您的项目导入Eclipse,它将自动编译该项目的所有源文件。


不幸的是,这是在不支持ant的服务器上完成的。
euphoria83

2

有一种无需使用管道字符即可执行此操作的方法,如果您要从另一种编程语言派生一个进程来执行此操作,这将很方便:

find $JAVA_SRC_DIR -name '*.java' -exec javac -d $OUTPUT_DIR {} +

尽管如果您在Bash中和/或不介意使用管道,则可以执行以下操作:

find $JAVA_SRC_DIR -name '*.java' | xargs javac -d $OUTPUT_DIR

2

Windows解决方案:假设所有文件都包含在子目录“ src”中,并且您要将其编译为“ bin”。

for /r src %i in (*.java) do javac %i -sourcepath src -d bin

如果src在其下面立即包含一个.java文件,则速度会更快

javac src\\*.java -d bin

1
可以,但是超慢-每次调用仅用一个文件来调用javac,因此,如果其中有很多...
St.Shadow
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.