【问题标题】:Java: How can I compile an entire directory structure of code ?Java:如何编译代码的整个目录结构?
【发布时间】:2011-06-13 11:32:05
【问题描述】:

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

如何使用 javac 从终端编译整个内容?

【问题讨论】:

  • 出于好奇,您使用的是哪个操作系统——Windows、Linux、Mac 等?这可能有助于回答问题
  • 我已经有几年没有在命令行上编译过 java 了,但我认为如果你只是将包含 main() 的文件传递给 javac,它会搜索出它需要的所有其他文件编译,因为可以从包含 main() 的文件开始发现所有依赖项。

标签: java compilation javac directory-structure


【解决方案1】:

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

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

【讨论】:

  • 我想通了:只需使用名称或通配符列出 javac 之后的所有 .java 文件。
  • 或者直接使用javac $(find . -name "*.java")
  • 如果不能指定中间目录,** 也能正常工作吗?
【解决方案2】:

使用 Bash 4+,您只需启用 globstar

shopt -s globstar

然后做

javac **/*.java

【讨论】:

  • 或者使用 zsh 和 oh-my-zsh :)
【解决方案3】:

如果您只想运行主类(不编译主类不依赖的.java 文件),那么您可以执行以下操作:

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

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

javac 会自动解析所有的依赖并编译所有的依赖。

【讨论】:

  • 这是迄今为止最简单的工作解决方案。为什么人们不喜欢它?
  • 可能是因为它的简单性忽略了这样一个事实,即许多库或支持代码的编译作业将没有链接到所有必需依赖项的主方法。这是一个很好的答案,但我不会在任何框架/公共代码库中使用它。
  • 恕我直言,框架或任何其他公共项目都应该使用某种构建管理。这种编译,只对小型私人项目有意义。
  • @Ajax 但如果是这种情况,您也可以使用-sourcepath . 选项,然后为相同的效果命名主文件
  • 谁说有主线?谁说没有四线?你想要的输出中的每个类是否都被 main 引用(而不是使用 META-INF/services 或其他服务加载技术)。如果您所做的只是测试一个 main,则此方法很好,但是,它无法解决“编译给定目录中的所有 java 文件”的完整任务。一个合适的构建系统是#1,像find . -type f -name "*.java" | xargs javac 这样的cli 工具是2,只有当有一个包含整个应用程序的主方法入口点时才使用此方法。
【解决方案4】:

我会接受Jon 的建议并使用 Ant,因为这是一项相当复杂的任务。

但是,如果您决定在终端的一行中完成所有操作,则在 Linux 上您可以使用 find 命令。但我根本不推荐这样做,因为不能保证 Foo.java 将在 Bar.java 之后编译,即使 Foo 使用 Bar。一个例子是:

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

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

【讨论】:

  • 在 Windows 上,一旦 find.exe 的 gnu 版本重命名为 find_gnu.exe,就可以使用 find_gnu . -type f -name "*.java" | xargs javac。我从 msysgit 得到了我的 gnu find.exe。
  • 或在纯 Windows 批处理上:for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f(在 dir /s /b 中使用单反引号,但我找不到正确格式化它的方法)。
  • 我认为find的方案是有问题的,因为它单独编译每个java类,速度很慢。
【解决方案5】:

以下是我找到的方法:

1) 在文件(比如 FilesList.txt)中列出具有相对路径的文件,如下所示(空格分隔或行分隔):

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

2) 使用命令:

javac @FilesList.txt -d classes

这将编译所有文件并将类文件放在类目录中。

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

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

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

【讨论】:

  • 这是更“原生”的方式,因为 javac 支持“批处理”文件
  • 如果路径包含空格,"dir *.java /s /b > FilesList.txt" 方法将不起作用。 javac 会抱怨 FilesList.txt
【解决方案6】:

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

递归获取所有 *.java 文件并包含构建所需的 *.jar 文件的一个很好的单行情况是:

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

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

【讨论】:

  • 我在编译 swagger 生成的客户端源代码时遇到问题
【解决方案7】:

您必须使用 Ant 之类的东西来分层执行此操作:

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

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

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

然后你就可以通过运行编译所有文件了:

 ant compile

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

【讨论】:

  • 很遗憾,这是在不支持 ant 的服务器上完成的。
【解决方案8】:

有一种方法可以在不使用管道字符的情况下执行此操作,如果您要从另一种编程语言分叉一个进程来执行此操作,这会很方便:

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

虽然如果你在 Bash 中和/或不介意使用管道,那么你可以这样做:

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

【讨论】:

    【解决方案9】:

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

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

    如果 src 在其下方包含一个 .java 文件,那么这会更快

    javac src\\*.java -d bin
    

    【讨论】:

    • 工作,但超慢 - javac 每次调用只调用一个文件,所以如果你有很多......
    猜你喜欢
    • 1970-01-01
    • 2018-01-28
    • 2017-02-07
    • 2015-07-24
    • 2020-02-29
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    相关资源
    最近更新 更多