如何在Gradle任务中调用项目源码生成文件并打包进同一JAR
问题描述
我在项目根目录的buildSrc下编写了如下Gradle任务代码:
package myapp.gradle; import myapp.Utils; import myapp.GoodRecord; import myapp.GoodRecordFactory; import org.apache.commons.io.FileUtils; import org.gradle.api.DefaultTask; import org.gradle.api.tasks.TaskAction; import java.io.File; import java.io.IOException; public class SoqTask extends DefaultTask { private File saveToDir; public void setSaveToDir(File saveToDir) { this.saveToDir = saveToDir; } @TaskAction public void run() { try { GoodRecord instance = GoodRecordFactory.instance(); byte[] serialize = Utils.serialize(instance); FileUtils.writeByteArrayToFile(new File(saveToDir, "goodrecord.bin"), serialize); } catch (IOException e) { throw new RuntimeException(e); } } }
但SoqTask无法访问所需的导入类(myapp.Utils、myapp.GoodRecord等项目代码),请问如何实现调用项目代码生成文件,并将生成的文件与项目一起打包进同一个JAR文件?
解决方案
1. 推荐方案:调整任务实现逻辑,避免buildSrc依赖项目代码
buildSrc下的代码会在项目构建脚本执行前完成编译,无法直接依赖主项目的源码。正确的做法是把生成文件的逻辑放到主项目源码中,再通过Gradle任务调用。
步骤1:在主项目中编写生成工具类
在myapp包下创建生成逻辑的工具类,把原来SoqTask里的核心逻辑迁移过来:
package myapp; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; public class GoodRecordGenerator { public static void generate(File saveToDir) throws IOException { GoodRecord instance = GoodRecordFactory.instance(); byte[] serialize = Utils.serialize(instance); FileUtils.writeByteArrayToFile(new File(saveToDir, "goodrecord.bin"), serialize); } }
步骤2:在Gradle脚本中定义任务并关联打包流程
在项目根目录的build.gradle(或build.gradle.kts)中注册任务,确保依赖主项目编译任务,同时将生成的文件纳入打包资源:
// 注册生成文件的任务 tasks.register('generateGoodRecord', JavaExec) { // 先编译主项目代码,再执行生成逻辑 dependsOn tasks.compileJava // 指定要执行的主类 mainClass = 'myapp.GoodRecordGenerator' // 传入文件保存目录,这里指定到构建目录下的资源生成目录 args = [project.layout.buildDirectory.dir('generated/resources/main').get().asFile.absolutePath] // 使用主项目的运行时类路径 classpath = sourceSets.main.runtimeClasspath } // 让jar打包任务依赖生成任务,确保文件生成后再打包 tasks.jar.dependsOn tasks.generateGoodRecord // 将生成目录添加到主项目资源目录,打包时自动包含生成的文件 sourceSets.main.resources.srcDir project.layout.buildDirectory.dir('generated/resources/main')
2. 不推荐方案:buildSrc直接依赖主项目JAR
如果一定要在buildSrc中实现任务,需要先将主项目代码打包成JAR,再在buildSrc的依赖中引入。但这种方式会产生循环依赖,每次主项目代码变更都需要手动重新打包,维护成本极高。
操作步骤:
- 先执行主项目打包:
./gradlew jar - 在
buildSrc/build.gradle中添加依赖:
dependencies { // 引入主项目打包后的JAR implementation files('../build/libs/your-project-name.jar') implementation 'org.apache.commons:commons-io:2.15.0' implementation gradleApi() }
内容的提问来源于stack exchange,提问作者Micah
相关产品推荐
相关产品推荐

