gogenerate

command
v0.0.0-...-5fef39c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2024 License: MIT, MIT Imports: 1 Imported by: 0

README

myitcv.io/cmd/gogenerate

gogenerate is a cache-based wrapper around go generate directives.

Usage:
        gogenerate [-p n] [-r n] [-trace] [-skipCache] [-tags 'tag list'] [packages]

gogenerate runs go generate directives found in packages according to the
reverse dependency graph implied by those packages' imports, and the
dependencies of the go generate directives. gogenerate repeatedly runs the
directives in a given package until a fixed point is reached.

gogenerate works in both GOPATH and modules modes.

gogenerate identifies generated artefacts by filename. Generated files have a
gen_ prefix and can have any extension. The directive command name is used as
the pre-extension suffix. For example, given the command name mygen, the
following are the names of generated artefacts:

  gen_mygen.go
  gen_something_mygen_test.go
  gen_another_mygen.json

The packages argument is similar to the packages argument for the go command;
see 'go help packages' for more information. In module mode, it is an error if
packages resolves to packages outside of the main module.

The -tags flag is similar to the build flag that can be passed to the go
command. It takes a space-separated list of build tags to consider satisfied as
gogenerate runs, and can appear multiple times.

The -p flag controls the concurrency level of gogenerate. By default will
assume a -p value of GOMAXPROCS. go generate directives only ever run in serial
and never concurrently with other work (this may be relaxed in the future to
allow concurrent execution of go generate directives). A -p value of 1 implies
serial execution of work in a well defined order.

The -trace flag outputs a log of work being executed by gogenerate. It is most
useful when specified along with -p 1 (else the order of execution of work is
not well defined).

The -skipCache flag causes gogenerate to skip checking for cache hits.
Consequently, all generators are run, regardless of cache state, until a fixed
point is reached. The cache is updated after each iteration in a package. As
such, this flag can be used to heal a broken cache, i.e. correct the delta for
a given cache key.

Note: at present, gogenerate does not understand the GOFLAGS environment
variable.  Neither does it pass the effective build tags via GOFLAGS to each go
generate directive. For more details see:

https://github.com/golang/go/issues/26849#issuecomment-460301061

go generate directives can take three forms:

  //go:generate command ...
  //go:generate gobin -run main_pkg[@version] ...
  //go:generate gobin -m -run main_pkg[@version] ...

The first form, a simple command-based directive, is a relative or absolute
PATH-resolved command.

The second form similar to the command-based directive, except that the path of
the resulting command is resolved via gobin's semantics (see gobin -help).

The third form uses the main module for resolution of the command and its
dependencies. Those dependencies take part in the reverse dependency graph. Use
of this form is, by definition, only possible in module mode.

For gobin-based directives, the command name, for the purposes of identifying
generated artefacts, is the base of the main package.

For all three forms, gogenerate understands how to parse two forms of flags.
Flags prefixed with -infiles: are interpreted as glob patterns of files the
directive will consume. The expansion of the glob must result in files
contained in directories that are dependencies of the package. For example:

  //go:generate mygen -infiles:all *.json

If the output of a generator is the function of any files other than those
understood by go list, it must use -infiles: prefixed flags to declare those
inputs, else gogenerate will not consider those files as part of its cache key.

Similarly, flags prefixed with -outdir: tell gogenerate that the directive will
generate files to the named directory in addition to the current package's
directory. For example:

  //go:generate anothergen -outdir:apples ./adir

If a generator places results in any directory other than the current directory
(i.e. the directory containing the package delcaring the directive) then it
must use -outdir: prefixed flags to declare those directories, else gogenerate
will miss artefacts generated by the directive.

gogenerate also understands a special form of directive:

  //go:generate:gogenerate [cond] break

This special directives include a [cond] prefix. At present, a single command
is understood: break. If the preceding conditions are satisfied, no further
go:generate directives are exectuted in this iteration. Note, if spaces are
required in [cond] it must be double-quoted.

The predefined conditions are:

  [exists:file] for whether the (relative) file path exists
  [exec:prog]   for whether prog is available for execution (found by
                exec.LookPath)

Where the third form of go generate directive is used, it may be necessary to
declare tool dependencies in your main module. For more information on how to
do this see:

https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module

By default, gogenerate uses the directory gogenerate-artefacts under your user
cache directory.  See the documentation for os.UserCacheDir for OS-specific
details on how to configure its location. Setting GOGENERATECACHE overrides the
default.

TODO

The following is a rough list of TODOs for gogenerate:

	* add support for parsing of GOFLAGS
	* add support for setting of GOFLAGS for go generate directives
	* consider supporting concurrent execution of go generate directives
	* define semantics for when generated files are removed by a generator
	* add full tests for cgo


Documentation

Overview

gogenerate is a cache-based wrapper around go generate directives.

Usage:

gogenerate [-p n] [-r n] [-trace] [-skipCache] [-tags 'tag list'] [packages]

gogenerate runs go generate directives found in packages according to the reverse dependency graph implied by those packages' imports, and the dependencies of the go generate directives. gogenerate repeatedly runs the directives in a given package until a fixed point is reached.

gogenerate works in both GOPATH and modules modes.

gogenerate identifies generated artefacts by filename. Generated files have a gen_ prefix and can have any extension. The directive command name is used as the pre-extension suffix. For example, given the command name mygen, the following are the names of generated artefacts:

gen_mygen.go
gen_something_mygen_test.go
gen_another_mygen.json

The packages argument is similar to the packages argument for the go command; see 'go help packages' for more information. In module mode, it is an error if packages resolves to packages outside of the main module.

The -tags flag is similar to the build flag that can be passed to the go command. It takes a space-separated list of build tags to consider satisfied as gogenerate runs, and can appear multiple times.

The -p flag controls the concurrency level of gogenerate. By default will assume a -p value of GOMAXPROCS. go generate directives only ever run in serial and never concurrently with other work (this may be relaxed in the future to allow concurrent execution of go generate directives). A -p value of 1 implies serial execution of work in a well defined order.

The -trace flag outputs a log of work being executed by gogenerate. It is most useful when specified along with -p 1 (else the order of execution of work is not well defined).

The -skipCache flag causes gogenerate to skip checking for cache hits. Consequently, all generators are run, regardless of cache state, until a fixed point is reached. The cache is updated after each iteration in a package. As such, this flag can be used to heal a broken cache, i.e. correct the delta for a given cache key.

Note: at present, gogenerate does not understand the GOFLAGS environment variable. Neither does it pass the effective build tags via GOFLAGS to each go generate directive. For more details see:

https://github.com/golang/go/issues/26849#issuecomment-460301061

go generate directives can take three forms:

//go:generate command ...
//go:generate gobin -run main_pkg[@version] ...
//go:generate gobin -m -run main_pkg[@version] ...

The first form, a simple command-based directive, is a relative or absolute PATH-resolved command.

The second form similar to the command-based directive, except that the path of the resulting command is resolved via gobin's semantics (see gobin -help).

The third form uses the main module for resolution of the command and its dependencies. Those dependencies take part in the reverse dependency graph. Use of this form is, by definition, only possible in module mode.

For gobin-based directives, the command name, for the purposes of identifying generated artefacts, is the base of the main package.

For all three forms, gogenerate understands how to parse two forms of flags. Flags prefixed with -infiles: are interpreted as glob patterns of files the directive will consume. The expansion of the glob must result in files contained in directories that are dependencies of the package. For example:

//go:generate mygen -infiles:all *.json

If the output of a generator is the function of any files other than those understood by go list, it must use -infiles: prefixed flags to declare those inputs, else gogenerate will not consider those files as part of its cache key.

Similarly, flags prefixed with -outdir: tell gogenerate that the directive will generate files to the named directory in addition to the current package's directory. For example:

//go:generate anothergen -outdir:apples ./adir

If a generator places results in any directory other than the current directory (i.e. the directory containing the package delcaring the directive) then it must use -outdir: prefixed flags to declare those directories, else gogenerate will miss artefacts generated by the directive.

gogenerate also understands a special form of directive:

//go:generate:gogenerate [cond] break

This special directives include a [cond] prefix. At present, a single command is understood: break. If the preceding conditions are satisfied, no further go:generate directives are exectuted in this iteration. Note, if spaces are required in [cond] it must be double-quoted.

The predefined conditions are:

[exists:file] for whether the (relative) file path exists
[exec:prog]   for whether prog is available for execution (found by
              exec.LookPath)

Where the third form of go generate directive is used, it may be necessary to declare tool dependencies in your main module. For more information on how to do this see:

https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module

By default, gogenerate uses the directory gogenerate-artefacts under your user cache directory. See the documentation for os.UserCacheDir for OS-specific details on how to configure its location. Setting GOGENERATECACHE overrides the default.

TODO

The following is a rough list of TODOs for gogenerate:

  • add support for parsing of GOFLAGS
  • add support for setting of GOFLAGS for go generate directives
  • consider supporting concurrent execution of go generate directives
  • define semantics for when generated files are removed by a generator
  • add full tests for cgo

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL