我正在尝试在一个小型 Java 应用程序中将 Protobuf 与 Google 官方 Gradle 插件、Gradle 一起使用,在 VS Code 中测试工作流程。
我无法让 VS Code 识别生成的 Java 源代码,并且在终端中,当我尝试使用 Gradle 构建应用程序时,我也无法让 Gradle 识别代码。
当我尝试引用生成的代码时,VS Code 显示此信息:
当我尝试构建时,Gradle 显示以下错误:
> Task :app:compileJava FAILED
/home/mattgbi/vscode-gradle-protobuf-repro/app/src/main/java/vscode/gradle/protobuf/repro/App.java:14: error: cannot find symbol
System.out.println(Person.class);
^
symbol: class Person
location: class App
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileJava'.
> Compilation failed; see the compiler error output for details.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 405ms
4 actionable tasks: 1 executed, 3 up-to-date
我知道我需要在
App.java
中添加导入才能使用 Person
类。但是,当我尝试调用 VS Code 代码补全工具来执行此操作时,如上所述,代码补全无法帮助我执行此操作。
但是,如果我手动输入 import 语句,VS Code 会说找不到它。:
但是,此时,Gradle 能够使用 import 语句(即使 VS Code 渲染错误)并且能够完成构建:
> ./gradlew build
> Task :app:compileJava
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
BUILD SUCCESSFUL in 1s
13 actionable tasks: 10 executed, 3 up-to-date
这里是一个 GitHub 存储库,完整重现了该问题:https://github.com/mattwelke/repros/tree/main/vscode-gradle-protobuf-repro
以下是我遇到此问题时完成的步骤:
gradle init
创建项目。选择“应用程序”并将所有设置保留为默认值。build.gradle
文件的顶部,位于文件的 plugins
部分之上。在 plugins
部分内添加带有 id "com.google.protobuf" version "0.8.18"
的线,位于该部分中 id 'application'
线下方。将以 protobuf {
开头的块添加到文件底部,以便我可以让 Gradle 下载并使用它自己的 protoc
二进制文件。message Person {
的代码添加到我的新文件中的应用程序 app/src/main/proto/message.proto
。./gradlew build
进行构建。app/build/generated/source
中的源代码,即使控制台中出现错误,提示 package com.google.protobuf does not exist
。protobuf-java
(来自https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java)添加到文件的build.gradle
部分下的dependencies
文件,以便我的应用程序生成Java源代码将能够引用 Protobuf 库。选择版本 3.21.1,因为它是目前的最新版本。使用 implementation
语法添加。./gradlew build
再次构建应用程序。这次在终端中没有观察到错误。App.java
(在src
下)中编写引用生成的Person
类的源代码。 VS Code 找不到它。./gradlew build
再次构建应用程序。 Gradle也找不到源代码。App.java
。观察 VS Code 显示有关仍然无法找到包的错误。./gradlew build
再次构建应用程序。 Gradle也找不到源代码。这次 Gradle 成功了。剩下的唯一问题是 IDE 如何识别所有代码(期望的是所有代码,包括生成的代码,都能被识别)。我的问题是我没有配置 Gradle(通过
build.gradle
)来包含生成代码所在位置的新源集。 VS Code 在检测到 Gradle 时读取 Gradle 配置以设置类路径,并在检测到它时禁用手动调整类路径,因此配置 Gradle 是唯一的选择。
将源集添加到 Gradle 配置之前:
将其添加到底部的
build.gradle
后:
sourceSets {
main {
java {
srcDir 'build/generated/source/proto/main/java'
}
}
}
此外,删除
app/build
目录并再次运行 ./gradlew build
后,我发现我必须从 Java 扩展运行“删除工作区”命令才能使我的工作区恢复到健康状态,其中生成的代码已被 VS Code 识别。
在阅读插件的自述文件(https://github.com/google/protobuf-gradle-plugin)并阅读他们关于覆盖源集的说明后,我意识到这是问题所在。由于对 Gradle 有点陌生,我忘记了源集的重要性。自述文件描述了插件如何动态地为生成的代码目录设置源集。
我想,因为 VS Code 没有调用任何 Gradle 任务来完成 Java 代码完成等(我认为它使用 Eclipse 工具),但因为它显然使用 Gradle 配置来配置它与 Java 的行为方式,所以解决我的问题的关键问题是通过在我的
build.gradle
文件中显式指定来手动告诉 VS Code 有关新源集的信息。