From 6b80dc972ba3d020ac885811464a4d0267935ae8 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Mon, 21 Oct 2024 15:24:14 +0200 Subject: [PATCH] Document how to avoid `protoc` artifact download Update the gRPC codegen to avoid having to use a downloaded protoc and document how the user can avoid using a downloaded protoc and use a local one instead. Unfortunately, due to the packaging of `protoc` and Java plugin (using classifier), it is not possible to exclude platforms individually. --- .../asciidoc/grpc-generation-reference.adoc | 53 +++++++++++++++++++ extensions/grpc/codegen/pom.xml | 10 +++- .../quarkus/grpc/deployment/GrpcCodeGen.java | 6 ++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/docs/src/main/asciidoc/grpc-generation-reference.adoc b/docs/src/main/asciidoc/grpc-generation-reference.adoc index 4393014a18c8c..70c0a4cde0fb6 100644 --- a/docs/src/main/asciidoc/grpc-generation-reference.adoc +++ b/docs/src/main/asciidoc/grpc-generation-reference.adoc @@ -297,3 +297,56 @@ To enable this feature, set the `quarkus.generate-code.grpc.use-arg-file` proper If you are on Windows, and the command line exceeds 8190 characters, Quarkus automatically uses an argument file to pass the arguments to the `protoc` command. +== Local vs. Downloaded `protoc` + +To generate gRPC classes, Quarkus uses the `protoc` artifact from the `com.google.protobuf` group id. +However, to ensure the support of various platforms, Quarkus automatically downloads _all_ the possible variants of the `protoc` artifact. +In addition, Quarkus downloads both `protoc` and the plugin used to generate gRPC classes in Java. +For example, even if you are using Linux, Quarkus downloads the `protoc` and the Java plugin artifacts for Windows and MacOS. + +The next table lists the different variants of the `protoc` and plugin artifacts: + +[col="1,1, 1"] +|=== +| *Platform* | *Classifier* | *Dependencies* + +| Linux/ARM64 | `linux-aarch_64` | `com.google.protobuf:protoc:VERSION:exe:linux-aarch_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:linux-aarch_64` +| Linux/Power PC 64 bits | `linux-ppcle_64` | `com.google.protobuf:protoc:VERSION:exe:linux-ppcle_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:linux-ppcle_64` +| Linux/S390 64 bits | `linux-s390_64` | `com.google.protobuf:protoc:VERSION:exe:linux-s390_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:linux-s390_64` +| Linux/x86 32bits | `linux-x86_32` | `com.google.protobuf:protoc:VERSION:exe:linux-x86_32` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:linux-x86_32` +| Linux/x86 64bits | `linux-x86_64` | `com.google.protobuf:protoc:VERSION:exe:linux-x86_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:linux-x86_64` +| Mac osx/ARM64 | `osx-aarch_64` | `com.google.protobuf:protoc:VERSION:exe:osx-aarch_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:osx-aarch_64` +| Mac osx/x86 64bits | `osx-x86_64` | `com.google.protobuf:protoc:VERSION:exe:osx-x86_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:osx-x86_64` +| Windows x86 32 bits | `windows-x86_32` | `com.google.protobuf:protoc:VERSION:exe:windows-x86_32` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:windows-x86_32` +| Windows x86 64 bits | `windows-x86_64` | `com.google.protobuf:protoc:VERSION:exe:windows-x86_64` and `io.grpc:protoc-gen-grpc-java:VERSION:exe:windows-x86_64` +|=== + +Because of the packaging of `protoc` and the plugin (using classifier), it's not possible to exclude undesired platforms individually. + +You can, however, exclude the `protoc` dependency altogether and use the `quarkus.grpc.protoc-path` system property to configure the path to the `protoc` executable installed on your machine. +Thus, you don't need to download any `protoc` variants: + +.Step 1: Exclusion of `protoc` +[source, xml] +---- + + io.quarkus + quarkus-grpc + + + com.google.protobuf + protoc + + + +---- + +.Step 2: Passing the `quarkus.grpc.protoc-path` property: +[source, shell] +---- +mvn clean quarkus:dev -Dquarkus.grpc.protoc-path=/path/to/protoc +---- + +IMPORTANT: Using this approach requires to have `protoc` installed locally. It will not download any `protoc` artifact. + +WARNING: Unfortunately, this only works for `protoc` and not for the Java plugin. The Java plugin is always downloaded. diff --git a/extensions/grpc/codegen/pom.xml b/extensions/grpc/codegen/pom.xml index dd111e65d39ea..995f85aa3e6c3 100644 --- a/extensions/grpc/codegen/pom.xml +++ b/extensions/grpc/codegen/pom.xml @@ -25,6 +25,11 @@ com.google.protobuf protobuf-java-util + + com.google.protobuf + protobuf-java + + com.google.protobuf protoc @@ -58,13 +63,13 @@ com.google.protobuf protoc - osx-x86_64 + osx-aarch_64 exe com.google.protobuf protoc - osx-aarch_64 + osx-x86_64 exe @@ -79,6 +84,7 @@ windows-x86_64 exe + io.grpc protoc-gen-grpc-java diff --git a/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java b/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java index 4ba5e69b6b5ad..d4e67796e2420 100644 --- a/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java +++ b/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java @@ -183,6 +183,7 @@ public boolean trigger(CodeGenContext context) throws CodeGenException { command = new ArrayList<>(Arrays.asList(command.get(0), "@" + argFile.getAbsolutePath())); } + log.debugf("Executing command: %s", String.join(" ", command)); ProcessBuilder processBuilder = new ProcessBuilder(command); final Process process = ProcessUtil.launchProcess(processBuilder, context.shouldRedirectIO()); @@ -409,12 +410,15 @@ private void initExecutables(Path workDir, ApplicationModel model) throws CodeGe Path protocPath; String protocPathProperty = System.getProperty("quarkus.grpc.protoc-path"); String classifier = System.getProperty("quarkus.grpc.protoc-os-classifier", osClassifier()); + Path protocExe; if (protocPathProperty == null) { protocPath = findArtifactPath(model, PROTOC_GROUPID, PROTOC, classifier, EXE); + protocExe = makeExecutableFromPath(workDir, PROTOC_GROUPID, PROTOC, classifier, "exe", protocPath); } else { + log.debugf("Using protoc from %s", protocPathProperty); protocPath = Paths.get(protocPathProperty); + protocExe = protocPath; } - Path protocExe = makeExecutableFromPath(workDir, PROTOC_GROUPID, PROTOC, classifier, "exe", protocPath); Path protocGrpcPluginExe = prepareExecutable(workDir, model, "io.grpc", "protoc-gen-grpc-java", classifier, "exe");