如何使用gradle编译单个java文件?

2022-09-02 12:33:17

(更新:感谢下面彼得N的评论。

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

我一直在尝试使用JavaCompile gradle任务来做到这一点。因此,我阅读了JavaCompile的文档,并试图搜索示例,但似乎很少。我甚至在gradle论坛上发帖,但到目前为止进展缓慢。

我能够使用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。

蚂蚁脚本是以下简单情况:

<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 等效项呢?

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

谢谢!


答案 1

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

要以与 ant javac 非常相似的方式使用 gradle JavaCompile 函数,您需要通过该属性提供编译器选项。因此,现在有效的 gradle 脚本如下所示:sourcepathoptions.compilerArgs

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 ,而不仅仅是尝试您指定的单个显式文件。任何其他类(不是必需的)保持未编译状态 - 通过查找生成目录进行确认。

谢谢彼得!


答案 2

我试图使用@I史蒂文森答案与gradle版本6.4.1。有一些变化让我感到惊讶,所以希望这对其他人有所帮助。此任务中的更改包括:

目的地目录>目的地目录(孵化)(我也有类型问题)

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

我还需要在编译中添加注释处理,因为我使用的是项目龙目岛。我知道您的问题没有要求进行注释处理,因此我将在任务中发表评论,指出这是额外的。

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
}

推荐