protojure / protoc-plugin

A protoc compiler plugin for Clojure applications
https://protojure.github.io
Apache License 2.0
36 stars 9 forks source link

Why does the namespace require itself? #67

Open reify-tanner-stirrat opened 2 years ago

reify-tanner-stirrat commented 2 years ago

We're trying to use a protoc-gen-clojure-gen'd lib in our application, and the top-level namespace require includes the namespace itself. This doesn't cause problems on first load, but does cause problems when we try to reload the namespaces as a part of hot-reloading functionality.

Should the namespace be requiring itself? If so, why is it necessary (for my own edification)? If not, is that something that can safely be removed?

I can provide an example if desired.

ghaskins commented 2 years ago

It sounds like a bug. An example would help determine this for sure.

reify-tanner-stirrat commented 2 years ago

Hmm... it seems to be specific to the repository that I'm working with, which makes me think that it's something about the references between the proto files that's causing the problem.

This simple repository doesn't have the circular requirement in its built output: https://buf.build/authzed/api/tree/main:authzed/api/v1

But this repository (which is the one in question) does: https://buf.build/authzed/api/tree/main:authzed/api/v1

I don't see anything that looks obviously circular in those protofiles. Two things stick out to me that might be related, though - one is that all of the files in that repo have a java_package declaration at the top of them, and the other is that the permission service and the watch service both reference the core service.

There's also a chance that this is something related to buf interpretation of the proto files, but I'm having trouble getting a protoc reproduction because of the external references in the authzed proto files.

Let me know if there's anything else I can test or any other context I can provide.

ghaskins commented 2 years ago

I'll try to take a look at your reproductions later. In the meantime, my thought is it is unlikely to be a problem with buf: There is a protobuf based protocol between protoc and a plugin like protoc-gen-clojure, so the data really has to be fairly normalized or it wouldn't work at all. I suspect your theory about the java pragmas is what's causing the issue.

ghaskins commented 2 years ago

BTW: you could play around with https://github.com/protojure/protoc-plugin/blob/master/tools/protoc-gen-reqcapture to capture the output from buf. We use that tool to capture protoc output so that we may play it back in the UTs without requiring the protoc binary be present. Perhaps we may spy something odd in the buf generated output...

reify-tanner-stirrat commented 2 years ago

I was able to get the capture, but it's 10kloc with some funky encoding. Is there a best way for me to share that?

ghaskins commented 2 years ago

You can use 'protoc --decode' to make sense of it. For example

$ cat resources/testdata/protoc.request | protoc --decode=google.protobuf.compiler.CodeGeneratorRequest --proto_path ../protojure-google-protobuf/protos/google/protobuf compiler/plugin.proto | less
reify-tanner-stirrat commented 2 years ago

I'm running into the same problem, where the external dependencies that are typically managed by buf aren't present, so the decode fails.

My coworker noticed something else, though: in the compiled output there are requires corresponding to other imports, despite those requires not actually being referenced anywhere in the output. [io.envoyproxy.pgv.validate :as io.envoyproxy.pgv.validate] is an example. It makes me wonder if there's something in how you write .proto files for buf, and how the imports get interpreted by buf vs the plugin.