Great, thanks for that.  I fully appreciate "a lot going on" :)

I want to solve this, but it's beyond my limited understanding of Go's 
impls and beyond my limited free-time to overcome that lack of 
understanding.

Please consider me a willing partner when the time comes to poke at this 
beehive again.

On Wednesday, August 11, 2021 at 1:11:58 PM UTC-7 jayc...@google.com wrote:

> Despite what the blog post says, Go 1.17 won't drop support for 
> GO111MODULE or GOPATH mode. It will be more or less the same as GOPATH mode.
>
> We'll continue to work on these issues and others that are blocking people 
> from migrating. I apologize for the slow progress–we have a lot going on.
>
> On Wed, Aug 11, 2021 at 12:34 PM Tim Hockin <tho...@google.com> wrote:
>
>> Hi all.  I realized that https://blog.golang.org/go116-module-changes 
>> says "We plan to drop support for GOPATH mode in Go 1.17. In other words, 
>> Go 1.17 will ignore GO111MODULE".  This will  break Kubernetes - our builds 
>> will be orders of magnitude slower.
>>
>> AFAICT, https://github.com/golang/go/issues/43806 has had no progress 
>> and https://github.com/golang/go/issues/43733 is still open, too.  I 
>> have zero confidence that these are the ONLY issues, and until I can get 
>> past them, I can't really find out.
>>
>> Please advise - how should I proceed?
>>
>> Tim
>>
>>
>> On Wed, Jan 20, 2021 at 12:57 PM Tim Hockin <tho...@google.com> wrote:
>>
>>> As long as these things are bugs and not "that's not how it works or 
>>> will ever work", I have some hope.  This is a back-burner exploration for 
>>> me, so I am not in a panic.  Every now and again I will circle back and see 
>>> if anything new happens :)
>>>
>>> On Wed, Jan 20, 2021 at 10:50 AM Jay Conrod <jayc...@google.com> wrote:
>>>
>>>> You appear to have discovered another new bug. Sorry for that. I've 
>>>> opened #43806 <https://github.com/golang/go/issues/43806> to track it.
>>>>
>>>> With that bug, it doesn't look like `go list` with local paths 
>>>> (relative or absolute) in a repository with nested replacement directories 
>>>> will work (at least not yet).
>>>>
>>>> `go list` should still work on full packages paths, but I'm not sure 
>>>> there's an easy way to resolve directory paths to package paths, other 
>>>> than 
>>>> by walking up the directory tree to the nearest go.mod and reading the 
>>>> module path from there.
>>>>
>>>> On Tue, Jan 19, 2021 at 8:06 PM Tim Hockin <tho...@google.com> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tue, Jan 19, 2021 at 7:54 AM Jay Conrod <jayc...@google.com> wrote:
>>>>>
>>>>>> By the way, I'm not sure if you're already doing this, but if you can 
>>>>>> batch all of the `go list` runs (or go/packages 
>>>>>> <https://goto.google.com/packages>.Load) together per module 
>>>>>> (passing an argument per package), that will be much faster than loading 
>>>>>> individual packages with separate `go list` calls. It will save `go 
>>>>>> list` 
>>>>>> from having to load the module graph and common sets of dependencies 
>>>>>> multiple times.
>>>>>>
>>>>>> If you need to load all the packages in a module, you can also use an 
>>>>>> argument like ./... from the root directory of the module to load 
>>>>>> everything there (excluding modules in subdirectories).
>>>>>>
>>>>>
>>>>> Yeah, I am trying that but tripping on the "does not contain package" 
>>>>> error.
>>>>>  
>>>>>
>>>>>>
>>>>>> On Tue, Jan 19, 2021 at 10:02 AM Jay Conrod <jayc...@google.com> 
>>>>>> wrote:
>>>>>>
>>>>>>> > Interesting - is the difference the absolute paths vs relative?
>>>>>>>
>>>>>>> It looks like the bug has to do with whether the directory is below 
>>>>>>> the main module root directory or not. If it is, the go command takes a 
>>>>>>> path that assumes it's part of the main module, which it's not.
>>>>>>>
>>>>>>> > I hoped maybe `-modfile` would do the same trick, but alas not:
>>>>>>>
>>>>>>> -modfile lets you change the effective content of go.mod but not the 
>>>>>>> module root directory. Unfortunately it doesn't look like that can be 
>>>>>>> used 
>>>>>>> to work around the issue.
>>>>>>>
>>>>>>> > It seems that is because the "main" (top-level dir) go.mod has
>>>>>>> > `replace` directives with relative paths, which kubernetes really
>>>>>>> > does.
>>>>>>>
>>>>>>> You may need to copy those over to the tmp go.mod and adjust the 
>>>>>>> paths. Sorry this has gotten pretty involved.
>>>>>>>
>>>>>>> > Yeah, I noticed.  When GO111MODULE=off, everything I am doing is 
>>>>>>> much
>>>>>>> > faster.  I'm wary of depending on that forever, though.
>>>>>>>
>>>>>>> Module-aware mode is quite a bit more complicated than GOPATH mode, 
>>>>>>> so to some degree it's not surprising it's slower... it's surprising 
>>>>>>> that 
>>>>>>> it's a LOT slower though. I expect there's some optimization work for 
>>>>>>> us to 
>>>>>>> do in the next development cycle.
>>>>>>>
>>>>>>> We would eventually like to deprecate GOPATH mode though, so it's a 
>>>>>>> good idea not to depend on it in new tooling today. 'go list' should be 
>>>>>>> fine to get package dependency info in either module mode or GOPATH 
>>>>>>> mode. 
>>>>>>> go/packages <https://goto.google.com/packages> is useful if you 
>>>>>>> need additional information on top of that (parsed syntax trees, type 
>>>>>>> info).
>>>>>>>
>>>>>>> > I want to run a slow codegen process only if the packages it 
>>>>>>> depends
>>>>>>> > on have ACTUALLY changed (mtime is a good enough proxy) and I don't
>>>>>>> > know a priori which packages need codegen.  I want to scan the file
>>>>>>> > tree, find the files that need codegen, check their deps, and only
>>>>>>> > then run the codegen.
>>>>>>>
>>>>>>> How much dependency info do you need? If the codegen is only within 
>>>>>>> packages with files that have changed, 'go list' might be overkill (it 
>>>>>>> always loads dependencies, even if they aren't printed). If you need 
>>>>>>> dependencies or reverse dependencies, 'go list' or go/packages 
>>>>>>> <https://goto.google.com/packages> are probably the right tools.
>>>>>>>
>>>>>>> On Fri, Jan 15, 2021 at 6:43 PM Tim Hockin <tho...@google.com> 
>>>>>>> wrote:
>>>>>>>
>>>>>>>> On Fri, Jan 15, 2021 at 2:17 PM Jay Conrod <jayc...@google.com> 
>>>>>>>> wrote:
>>>>>>>> >
>>>>>>>> > I was initially going to suggest adding the module subdirectories 
>>>>>>>> as requirements to the main go.mod, then replacing those with the 
>>>>>>>> subdirectories.
>>>>>>>> >
>>>>>>>> > module example.com/m
>>>>>>>> >
>>>>>>>> > go 1.15
>>>>>>>> >
>>>>>>>> > require (
>>>>>>>> >   example.com/other1 v0.0.0
>>>>>>>> >   example.com/other2 v0.0.0
>>>>>>>> >   example.com/m/submod v0.0.0
>>>>>>>> > )
>>>>>>>> >
>>>>>>>> > replace (
>>>>>>>> >   example.com/other1 => ./staging/src/example.com/other1
>>>>>>>> >   example.com/other2 => ./staging/src/example.com/other2
>>>>>>>> >   example.com/m/submod v0.0.0 => ./submod
>>>>>>>> > )
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > I think you might have tried this already. It gives the same 
>>>>>>>> "main module ... does not contain package" error. I believe that's a 
>>>>>>>> bug. 
>>>>>>>> I've opened #43733 to track it.
>>>>>>>>
>>>>>>>> Interesting.  If that's a bug, then maybe I'll be able to do what I
>>>>>>>> need once fixed.
>>>>>>>>
>>>>>>>> > In general, it should be possible to give 'go list' an absolute 
>>>>>>>> or relative path (starting with ./ or ../) to any directory containing 
>>>>>>>> a 
>>>>>>>> package which is part of any module in the build list. For example, 
>>>>>>>> some 
>>>>>>>> tools list directories in the module cache to find out what package a 
>>>>>>>> .go 
>>>>>>>> file belongs to.
>>>>>>>> >
>>>>>>>> > As a workaround, you could put a go.mod in an otherwise empty 
>>>>>>>> directory (in /tmp or something), then require the relevant modules 
>>>>>>>> from 
>>>>>>>> the repo and replace them with absolute paths. Then you can run 'go 
>>>>>>>> list' 
>>>>>>>> in that directory with absolute paths of package directories.
>>>>>>>>
>>>>>>>> Interesting - is the difference the absolute paths vs relative?
>>>>>>>>
>>>>>>>> I hoped maybe `-modfile` would do the same trick, but alas not:
>>>>>>>>
>>>>>>>> ```
>>>>>>>> $ (cd /tmp/gomodhack/; go list /tmp/go-list-modules/submod/used/)
>>>>>>>> example.com/m/submod/used
>>>>>>>>
>>>>>>>> $ go list --modfile /tmp/gomodhack/go.mod 
>>>>>>>> /tmp/go-list-modules/submod/used/
>>>>>>>> main module (tmp) does not contain package tmp/submod/used
>>>>>>>> ```
>>>>>>>>
>>>>>>>> It also fails some cases:
>>>>>>>>
>>>>>>>> ```
>>>>>>>>  (cd /tmp/gomodhack/; go list /tmp/go-list-modules/submod/used/)
>>>>>>>> example.com/m/submod/used
>>>>>>>> thockin@thockin-glaptop4 go-list-modules main /$ (cd 
>>>>>>>> /tmp/gomodhack/;
>>>>>>>> go list /tmp/go-list-modules/staging/src/example.com/other1/used/)
>>>>>>>> go: finding module for package 
>>>>>>>> example.com/m/staging/src/example.com/other1/used
>>>>>>>> cannot find module providing package
>>>>>>>> example.com/m/staging/src/example.com/other1/used: unrecognized 
>>>>>>>> import
>>>>>>>> path "example.com/m/staging/src/example.com/other1/used": reading
>>>>>>>> https://example.com/m/staging/src/example.com/other1/used?go-get=1:
>>>>>>>> 404 Not Found
>>>>>>>> ```
>>>>>>>>
>>>>>>>> It seems that is because the "main" (top-level dir) go.mod has
>>>>>>>> `replace` directives with relative paths, which kubernetes really
>>>>>>>> does.
>>>>>>>>
>>>>>>>> > Incidentally, golang.org/x/tools/go/packages will call 'go list' 
>>>>>>>> under the hood in module mode. go/build 
>>>>>>>> <https://goto.google.com/build> might do the same, depending on 
>>>>>>>> how it's invoked. 'go list' may be the best thing to use if it gives 
>>>>>>>> the 
>>>>>>>> information you need.
>>>>>>>>
>>>>>>>> Yeah, I noticed.  When GO111MODULE=off, everything I am doing is 
>>>>>>>> much
>>>>>>>> faster.  I'm wary of depending on that forever, though.
>>>>>>>>
>>>>>>>> Stepping back, I fear I am pushing the square peg into a round hole.
>>>>>>>> Let me restate what I am trying to do.
>>>>>>>>
>>>>>>>> I want to run a slow codegen process only if the packages it depends
>>>>>>>> on have ACTUALLY changed (mtime is a good enough proxy) and I don't
>>>>>>>> know a priori which packages need codegen.  I want to scan the file
>>>>>>>> tree, find the files that need codegen, check their deps, and only
>>>>>>>> then run the codegen.
>>>>>>>>
>>>>>>>> We do this today with `go list` and GO111MODULE=off, but I was 
>>>>>>>> advised
>>>>>>>> at some point that x/tools/go/packages was the future-safe approach.
>>>>>>>>
>>>>>>>> If there's a better way, I am all ears.
>>>>>>>>
>>>>>>>> Tim
>>>>>>>> GO111MODULE=off
>>>>>>>> > On Fri, Jan 15, 2021 at 11:59 AM 'Tim Hockin' via golang-nuts <
>>>>>>>> golan...@googlegroups.com> wrote:
>>>>>>>> >>
>>>>>>>> >> Hi.  This isn't exactly burning urgent, but it is a long-term 
>>>>>>>> issue
>>>>>>>> >> for Kubernetes.  If there's anything I can do to catalyze the
>>>>>>>> >> discussion - tests to run, info to dig up, etc - please let me 
>>>>>>>> know.
>>>>>>>> >>
>>>>>>>> >> On Wed, Dec 23, 2020 at 10:48 AM Tim Hockin <tho...@google.com> 
>>>>>>>> wrote:
>>>>>>>> >> >
>>>>>>>> >> > Hi Paul!
>>>>>>>> >> >
>>>>>>>> >> > On Wed, Dec 23, 2020 at 4:23 AM Paul Jolly <pa...@myitcv.io> 
>>>>>>>> wrote:
>>>>>>>> >> > >
>>>>>>>> >> > > > I just can't figure out how to do this.  Maybe it can't be 
>>>>>>>> done in `go
>>>>>>>> >> > > > list` ?  Or maybe we're just missing some detail of go 
>>>>>>>> modules..
>>>>>>>> >> > >
>>>>>>>> >> > > go list operates in the context of a single module (in the 
>>>>>>>> mode you
>>>>>>>> >> > > are interested in), so you cannot do this with a single 
>>>>>>>> command across
>>>>>>>> >> > > multiple modules.
>>>>>>>> >> >
>>>>>>>> >> > This might be a real problem for us.  For this post I am 
>>>>>>>> reducing it
>>>>>>>> >> > to `go list`, but in actuality we have a small program that we 
>>>>>>>> wrote
>>>>>>>> >> > which does what we need in terms of `go/build`.  It works 
>>>>>>>> great when
>>>>>>>> >> > `GO111MODULE=off` but is more than 100x slower normally.  I 
>>>>>>>> thought it
>>>>>>>> >> > was finally time to rewrite it in terms of `go/packages` and 
>>>>>>>> get rid
>>>>>>>> >> > of GO111MODULE=off.  That didn't pan out, hence this post.
>>>>>>>> >> >
>>>>>>>> >> > More inline and below
>>>>>>>> >> >
>>>>>>>> >> > > > First I do a `find` for any file that has a specific 
>>>>>>>> comment tag,
>>>>>>>> >> > > > indicating that the package needs codegen.  The results 
>>>>>>>> span several
>>>>>>>> >> > > > of the in-repo submodules.
>>>>>>>> >> > >
>>>>>>>> >> > > Just to check, I'm assuming the results of this find command 
>>>>>>>> are being
>>>>>>>> >> > > translated to a list of packages? Because the transitive 
>>>>>>>> dependencies
>>>>>>>> >> > > of a list of packages within a module can be done via a 
>>>>>>>> single go list
>>>>>>>> >> > > command.
>>>>>>>> >> >
>>>>>>>> >> > The trick is "within a module".  I'll update
>>>>>>>> >> > https://github.com/thockin/go-list-modules to reflect the 
>>>>>>>> process
>>>>>>>> >> > more.   I've added a
>>>>>>>> >> > get_codegen_deps.sh that models the behavior.  Note that I 
>>>>>>>> really want
>>>>>>>> >> > files, not packages, so I can express the dep-graph.
>>>>>>>> >> >
>>>>>>>> >> > What do you mean by "translated to a list of packages" - which 
>>>>>>>> specific syntax?
>>>>>>>> >> >
>>>>>>>> >> > What I end up with is something like `go list ./path/to/dir1
>>>>>>>> >> > ./path/to/dir2 ./path/to/dir3`.  Any of those dirs might be in
>>>>>>>> >> > different modules.  So `go list` tells me "main module (
>>>>>>>> example.com/m)
>>>>>>>> >> > does not contain package example.com/m/path/to/dir1" and so 
>>>>>>>> on.
>>>>>>>> >> > Setting `GO111MODULE=off` does work, but I fear the future of 
>>>>>>>> that.
>>>>>>>> >> >
>>>>>>>> >> > > > For each target package, I want to get the list of all 
>>>>>>>> deps and
>>>>>>>> >> > > > extract the GoFiles.  Then I can use that to determine if 
>>>>>>>> the codegen
>>>>>>>> >> > > > needs to run.
>>>>>>>> >> > >
>>>>>>>> >> > > FWIW I wrote a tool to do just this:
>>>>>>>> >> > > 
>>>>>>>> https://pkg.go.dev/myit...@v0.0.0-20201125173645-a7167afc9e13/cmd/gogenerate
>>>>>>>>  
>>>>>>>> <https://pkg.go.dev/myitcv.io@v0.0.0-20201125173645-a7167afc9e13/cmd/gogenerate>
>>>>>>>> >> > > which might work in your situation.
>>>>>>>> >> >
>>>>>>>> >> > I will take a look - it seems I will need to restructure a 
>>>>>>>> bunch of
>>>>>>>> >> > tooling to prove it works for us or doesn't :)
>>>>>>>> >> >
>>>>>>>> >> > > > Where it breaks down is that I can't seem to `go list` all 
>>>>>>>> at once:
>>>>>>>> >> > > >
>>>>>>>> >> > > > ```
>>>>>>>> >> > > > # This works within the "root" module
>>>>>>>> >> > > > $ go list -f '{{.GoFiles}}' ./subdir
>>>>>>>> >> > > > [file.go]
>>>>>>>> >> > >
>>>>>>>> >> > > This will work.
>>>>>>>> >> > >
>>>>>>>> >> > > > # This does not work across modules
>>>>>>>> >> > > > $ go list -f '{{.GoFiles}}' ./submod/used ./submod/unused
>>>>>>>> >> > > > main module (example.com/m) does not contain package 
>>>>>>>> example.com/m/submod/used
>>>>>>>> >> > > > main module (example.com/m) does not contain package 
>>>>>>>> example.com/m/submod/unused
>>>>>>>> >> > >
>>>>>>>> >> > > Per above, this will not work across module boundaries.
>>>>>>>> >> >
>>>>>>>> >> > It works with `GO111MODULE=off` which means that introducing 
>>>>>>>> modules
>>>>>>>> >> > is a breaking change.  Can I depend on GO111MODULE=off to work 
>>>>>>>> the
>>>>>>>> >> > same way forever?
>>>>>>>> >> >
>>>>>>>> >> > > > # Nor does this work, even with module replacements
>>>>>>>> >> > > > $ go list -f '{{.GoFiles}}' ./staging/src/
>>>>>>>> example.com/other1/used
>>>>>>>> >> > > > ./staging/src/example.com/other1/unused
>>>>>>>> >> > > > main module (example.com/m) does not contain package
>>>>>>>> >> > > > example.com/m/staging/src/example.com/other1/used
>>>>>>>> >> > > > main module (example.com/m) does not contain package
>>>>>>>> >> > > > example.com/m/staging/src/example.com/other1/unused
>>>>>>>> >> > > > ```
>>>>>>>> >> > >
>>>>>>>> >> > > With replace directives in place this should work, but you 
>>>>>>>> won't be
>>>>>>>> >> > > able to use the relative path to the modules (which is in 
>>>>>>>> fact
>>>>>>>> >> > > interpreted as a directory): it will need to be the full
>>>>>>>> >> > > module/package path.
>>>>>>>> >> >
>>>>>>>> >> > Given a "./path/to/pkg" - how do I convert that to a 
>>>>>>>> module/package
>>>>>>>> >> > path?  I can run `(cd $dir && go list -m)` but that is super 
>>>>>>>> slow.
>>>>>>>> >> > Running JUST that for each directory that needs codegen in 
>>>>>>>> kubernetes
>>>>>>>> >> > takes 20+ seconds.  Is there a better way, short of writing my 
>>>>>>>> own
>>>>>>>> >> > directory-climb and parsing go.mod?
>>>>>>>> >> >
>>>>>>>> >> > > > I can run `go list` multiple times, but that's INCREDIBLY 
>>>>>>>> slow - most
>>>>>>>> >> > > > of these submodules have common deps that are large.  This 
>>>>>>>> re-parses
>>>>>>>> >> > > > everything over and over.  It takes almost 60 seconds just 
>>>>>>>> to do `cd
>>>>>>>> >> > > > $dir; go list` (on the real kubernetes repo).
>>>>>>>> >> > >
>>>>>>>> >> > > Do you have a repro of this taking 60 seconds? Because that 
>>>>>>>> really
>>>>>>>> >> > > shouldn't be the case with a populated local module cache.
>>>>>>>> >> >
>>>>>>>> >> > github.com/kubernetes/kubernetes
>>>>>>>> >> >
>>>>>>>> >> > ```
>>>>>>>> >> > $ time \
>>>>>>>> >> >     find . -type f -name \*.go \
>>>>>>>> >> >         | xargs grep -l "^// *+k8s:" \
>>>>>>>> >> >         | xargs -n 1 dirname \
>>>>>>>> >> >         | sort \
>>>>>>>> >> >         | uniq \
>>>>>>>> >> >         | while read X; do \
>>>>>>>> >> >             (cd $X; go list -f '{{.Deps}}'); \
>>>>>>>> >> >         done \
>>>>>>>> >> >         > /dev/null
>>>>>>>> >> >
>>>>>>>> >> > real 0m50.488s
>>>>>>>> >> > user 0m46.686s
>>>>>>>> >> > sys 0m18.416s
>>>>>>>> >> > ```
>>>>>>>> >> >
>>>>>>>> >> > Just running that inner `go list` with GO111MODULE=off cuts 
>>>>>>>> the run
>>>>>>>> >> > time in half.
>>>>>>>> >> >
>>>>>>>> >> > Compare to:
>>>>>>>> >> >
>>>>>>>> >> > ```
>>>>>>>> >> > time \
>>>>>>>> >> >     ( \
>>>>>>>> >> >         export GO111MODULE=off; \
>>>>>>>> >> >         find . -type f -name \*.go \
>>>>>>>> >> >             | xargs grep -l "^// *+k8s:" \
>>>>>>>> >> >             | xargs -n 1 dirname \
>>>>>>>> >> >             | sort \
>>>>>>>> >> >             | uniq \
>>>>>>>> >> >             | xargs go list -e -f '{{.Deps}}' \
>>>>>>>> >> >     ) \
>>>>>>>> >> >     > /dev/null
>>>>>>>> >> >
>>>>>>>> >> > real 0m1.323s
>>>>>>>> >> > user 0m1.174s
>>>>>>>> >> > sys 0m0.567s
>>>>>>>> >> > ```
>>>>>>>> >> >
>>>>>>>> >> > The model repo doesn't show so significantly because it is 
>>>>>>>> small.
>>>>>>>> >> > Kubernetes is not small.
>>>>>>>> >> >
>>>>>>>> >> > I'm happy to hear better approaches - I really don't like 
>>>>>>>> relying on
>>>>>>>> >> > GO111MODULE=off forever - it seems like the sort of thing that 
>>>>>>>> will
>>>>>>>> >> > eventually get removed.
>>>>>>>> >>
>>>>>>>> >> --
>>>>>>>> >> You received this message because you are subscribed to the 
>>>>>>>> Google Groups "golang-nuts" group.
>>>>>>>> >> To unsubscribe from this group and stop receiving emails from 
>>>>>>>> it, send an email to golang-nuts...@googlegroups.com.
>>>>>>>> >> To view this discussion on the web visit 
>>>>>>>> https://groups.google.com/d/msgid/golang-nuts/CAO_Rewa6rMW79iBHj2Jz6HfJ-tCFLFhNAhYiwDh%3DNy6M35Y91Q%40mail.gmail.com
>>>>>>>> .
>>>>>>>>
>>>>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/a6616d03-49ff-4899-9e48-9f498f8c2359n%40googlegroups.com.

Reply via email to