【问题标题】:How to compile a single java file with gradle?如何使用 gradle 编译单个 java 文件?
【发布时间】:2013-10-23 21:15:55
【问题描述】:

已更新:感谢下方 Peter N 的 cmets。)

我有一个包含多个类的 java 包,因此其中包含文件。但是,我最初只想编译其中一个文件,以便我可以使用它来更新包中的其他类。它是其他类的工厂,因此依赖于它们 - 即。它有对它们的引用。

我一直在尝试使用JavaCompile gradle task 来执行此操作。结果,我阅读了 JavaCompile 的文档并尝试搜索示例,但似乎那里几乎没有。我什至在gradle forums 上发过帖子,但进展缓慢。

我可以使用 ant javac 任务通过 ant 脚本轻松完成所需的操作。但我想在 gradle 中完成(并且不使用 ant.javac 方法 - 如果必须这样做,我将只使用 ant)。

我创建了一个示例案例,其中只有一个包中的两个类的两个源文件。

这两个文件都在一个名为 some.pkg 的包中,因此我们有以下目录结构:

  • .\build.gradle
  • .\src\main\java\some\pkg\ClassOne.java
  • .\src\main\java\some\pkg\ClassTwo.java

类一:

package some.pkg;

import some.pkg.*;

public class ClassOne {
    public void doStuff() {
    }
}

第二类:

package some.pkg;

import some.pkg.*;

public class ClassTwo {
    public void ClassTwo() {
        ClassOne cone = new ClassOne();
        cone.doStuff();
    }
}

如您所见,ClassTwo(我们要独立编译的类)依赖于 ClassOne。

ant 脚本是一个简单的例子:

<project>
    <property name="build.dir"     value="build"/>
    <property name="lib.dir"     value="lib"/>
    <property name="src.dir"     value="src/main/java"/>
    <target name="generate" >
        <mkdir dir="${build.dir}"/>
        <javac source="1.6" target="1.6" srcdir="${src.dir}" destdir="${build.dir}" 
               debug="true" includeantruntime="false"
               includes="some/pkg/ClassTwo.java">
        </javac>
    </target>
</project>

但在 gradle 中,我一直遇到 javac(或 JavaCompile 任务)找不到 ClassOne 的问题。就好像 sourcedir 没有指向它应该指向的位置——实际上就好像我只是在命令行上运行 javac 一样。我在想 gradle 'JavaCompile' 任务的 'source' 属性就像 ant 'srcdir' 属性一样工作,但情况似乎并非如此。所以这是我目前正在尝试的 gradle 脚本:

apply plugin: 'java'

task compileOne (type: JavaCompile) {
    source = sourceSets.main.java.srcDirs
    include 'some/pkg/ClassTwo.java'
    classpath = sourceSets.main.compileClasspath
    destinationDir = sourceSets.main.output.classesDir
}

但结果是:

C:\test\>gradle generate
:generate
C:\test\src\main\java\some\pkg\ClassTwo.java:7: cannot find symbol
symbol  : class ClassOne
location: class some.pkg.ClassTwo
                ClassOne cone = new ClassOne();
                ^
C:\test\src\main\java\some\pkg\ClassTwo.java:7: cannot find symbol
symbol  : class ClassOne
location: class some.pkg.ClassTwo
                ClassOne cone = new ClassOne();
                                    ^
2 errors
:generate FAILED

那么如何在 gradle 中实现 ant javac 等价物呢?

ant javac 似乎很聪明,可以编译所有其他相关的类,但我想对于 gradle JavaCompile,我需要设置一个 sourceSet 来做到这一点.. 不确定..

谢谢!

【问题讨论】:

  • 不管使用哪种构建系统,这都行不通。要么你必须一起编译ClassOneClassTwo,或者先编译ClassOne 然后ClassTwo(在类路径上使用ClassOne)。另外,我不明白你单独编译它们的动机。
  • 嗨@PeterNiederwieser,无论使用哪种构建系统,它都不起作用是什么意思?我可以向您保证,上面的示例在命令行上使用 javac 和提供的 ant 构建脚本 DO 都可以工作。随意将文件复制到上述文件夹结构中并尝试使用 ant 和 javac 命令行 - 您将很容易看到它们确实有效。 (我还刚刚更新了 javac 命令行 - 请注意,当我打算指定 ClassTwo.java 时,我指定了 ClassOne.java,这是我一直在做的。)
  • 好吧,我刚刚又玩了一场。我怕我把自己弄糊涂了。似乎 ant 正在编译整个源依赖树,除非我先执行 ClassOne.java,否则 ClassTwo.java 命令行上的 javac 不起作用。是的,我想我自己都搞糊涂了。我会先确认我的测试。谢谢。
  • 为了编译ClassTwo,你要么必须同时编译ClassOne,要么将ClassOne的类文件放在编译器的类路径中,或者把@的源文件987654337@ 在编译器的源路径上。无论使用哪种构建系统都是如此。
  • 您可以使用compileOne.options.compilerArgs = ["-sourcepath", "$projectDir/src/main/java"] 之类的内容设置源路径。将源目录放在类路径上也应该可以,因为 javac 使用它作为默认源路径。

标签: java gradle


【解决方案1】:

我尝试在 gradle 版本 6.4.1 中使用@I Stevenson 回答。有一些变化让我感到惊讶,所以希望这对其他人有所帮助。此任务的变化是:

destinationDir-> destinationDirectory(孵化中)(我也遇到了类型问题)

compileOne.options.compilerArgs -> options.sourcepath 这也在任务中定义

我还需要在编译中添加注释处理,因为我使用的是项目 lombok。我了解您的问题并未要求进行注释处理,因此我将在任务中发表评论,指出这是额外的。

apply plugin: 'java'
task compileOne (type: JavaCompile) {
    source = sourceSets.main.java.srcDirs
    include 'some/pkg/ClassTwo.java'
    classpath = sourceSets.main.compileClasspath
    destinationDirectory = new File("${buildDir}/classes/java/main") 
    options.sourcepath = sourceSets.main.java.getSourceDirectories()
    options.annotationProcessorPath = sourcesSet.main.compileClasspath//extra for lombok
}

【讨论】:

    【解决方案2】:

    感谢与 @PeterNiederwieser 就 cmets 中的原始帖子进行的讨论,为了完整起见,我将在此处提供答案。

    要以非常类似于 ant javac 的方式使用 gradle JavaCompile 函数,您需要通过 options.compilerArgs 属性提供 sourcepath 编译器选项。因此,现在可以运行的 gradle 脚本如下:

    apply plugin: 'java'
    
    task compileOne (type: JavaCompile) {
        source = sourceSets.main.java.srcDirs
        include 'some/pkg/ClassTwo.java'
        classpath = sourceSets.main.compileClasspath
        destinationDir = sourceSets.main.output.classesDir
    }
    
    compileOne.options.compilerArgs = ["-sourcepath", "$projectDir/src/main/java"]
    

    特别注意允许所有工作的最后一行(唯一的区别)。结果是它实际上会在构建时同时编译 ClassOne 和 ClassTwo - 而不是只尝试您指定的单个显式文件。任何其他类(不是必需的)保持未编译 - 通过查看构建目录确认。

    谢谢彼得!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 2014-04-15
      相关资源
      最近更新 更多