gg is a cache-based wrapper around go generate directives.
gg [-p n] [-r n] [-trace] [-skipCache] [-tags 'tag list'] [packages]
gg 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. gg repeatedly runs the directives in a given package until a fixed point is reached.
gg works in both GOPATH and modules modes.
gg 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 gg runs, and can appear multiple times.
The -p flag controls the concurrency level of gg. 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 gg. 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 gg 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, gg 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:
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, gg 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 gg will not consider those files as part of its cache key.
Similarly, flags prefixed with -outdir: tell gg 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 gg will miss artefacts generated by the directive.
gg also understands a special form of directive:
//go:generate:gg [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:
By default, gg uses the directory gg-artefacts under your user cache directory. See the documentation for os.UserCacheDir for OS-specific details on how to configure its location. Setting GGCACHE overrides the default.
The following is a rough list of TODOs for gg:
* 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