且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-15 14:18:57

感谢在@PeterNiederwieser关于评论中的原始帖子的讨论,我将在此提供答案以确保完整性。


$ b 为了使Gradle JavaCompile的功能与ant javac非常相似,你需要提供 sourcepath 编译器选项通过 options.compilerArgs 属性。因此,现在运行的gradle脚本如下所示:
  apply plugin:'java'

任务compileOne(类型:JavaCompile){
source = sourceSets.main.java.srcDirs
包含'some / pkg / ClassTwo.java'
classpath = sourceSets.main.compileClasspath
destinationDir = sourceSets.main.output.classesDir
}

compileOne.options.compilerArgs = [-sourcepath,$ projectDir / src / main / java]

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



感谢Peter!


(UPDATED: Thanks to comments from Peter N below.)

I have a java package with several classes and therefore files within it. However I only want to compile one of those files initially so that I can then use it to update the other classes in the package. It's a factory for the other classes and as a result is dependent on them - ie. it has references to them.

I've been attempting to use a JavaCompile gradle task to do this. As a result I've read the documentation for JavaCompile and attempted to search for examples but seems there is very little out there. I've even posted on the gradle forums, but slow going so far.

I'm able to do what is required readily with an ant script using the ant javac task. But I'd like to do it in gradle (and without using the ant.javac method - if I have to do that I'll just use ant).

I've created an example case with just two source files for two classes in the one package.

Both files are in a package called some.pkg and we therefore have the following directory structure:

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

ClassOne:

package some.pkg;

import some.pkg.*;

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

ClassTwo:

package some.pkg;

import some.pkg.*;

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

As you can see, ClassTwo (our class we want to compile standalone) depends on ClassOne.

The ant script is a simple case of:

<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>

But in gradle, I keep having an issue where javac (or JavaCompile task) can not find ClassOne. It's as though the sourcedir is not pointing where it should - and indeed as though I was just running javac on the command line. I was thinking the gradle 'JavaCompile' task's 'source' property was working like the ant 'srcdir' property, but that appears to not be the case. So here is the gradle script I'm currently trying:

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
}

But it results in:

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

So how do I achieve an ant javac equivalent in gradle?

ant javac seems to have the smarts to go and compile all the other related classes, but I guess for gradle JavaCompile I will need to set up a sourceSet to do that.. not sure..

Thanks!

Thanks to the discussion with @PeterNiederwieser on the original post in the comments, I'll provide the answer here for completeness.

To have gradle JavaCompile function in a manner very similar to the ant javac, you need to provide the sourcepath compiler option via the options.compilerArgs property. Therefore, the gradle script that now works is as follows:

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"]

Note specifically the last line (the only difference) which allows all to work. The result of which is that it will actually compile both ClassOne and ClassTwo at build time - rather than only attempting the single explicit file you specified. Any other classes (that are not required) remain uncompiled - as confirmed by looking in the build directory.

Thanks Peter!