I'm trying run generate
on CGO project https://github.com/libgit2/git2go locally. I have successfully installed libgit2
system library and can build and test the project with go build -tags static,system_libgit2
and go test -tags static,system_libgit2
.
The problem occurs when I try to generate additional files with stringer
. The code I'm showing is located in master branch, so I suppose it should work correctly and the problem is on my side.
The file diff.go has stringer annotation (removed unimportant parts):
package git
/*
#include <git2.h>
...
*/
import "C"
import (
"errors"
"runtime"
"unsafe"
)
...
type Delta int
const (
DeltaUnmodified Delta = C.GIT_DELTA_UNMODIFIED
DeltaAdded Delta = C.GIT_DELTA_ADDED
DeltaDeleted Delta = C.GIT_DELTA_DELETED
DeltaModified Delta = C.GIT_DELTA_MODIFIED
DeltaRenamed Delta = C.GIT_DELTA_RENAMED
DeltaCopied Delta = C.GIT_DELTA_COPIED
DeltaIgnored Delta = C.GIT_DELTA_IGNORED
DeltaUntracked Delta = C.GIT_DELTA_UNTRACKED
DeltaTypeChange Delta = C.GIT_DELTA_TYPECHANGE
DeltaUnreadable Delta = C.GIT_DELTA_UNREADABLE
DeltaConflicted Delta = C.GIT_DELTA_CONFLICTED
)
//go:generate stringer -type Delta -trimprefix Delta -tags static
...
This type is referencing to libgit2
C enum, the part of /usr/include/git2/diff.h
:
/**
* What type of change is described by a git_diff_delta?
*
* `GIT_DELTA_RENAMED` and `GIT_DELTA_COPIED` will only show up if you run
* `git_diff_find_similar()` on the diff object.
*
* `GIT_DELTA_TYPECHANGE` only shows up given `GIT_DIFF_INCLUDE_TYPECHANGE`
* in the option flags (otherwise type changes will be split into ADDED /
* DELETED pairs).
*/
typedef enum {
GIT_DELTA_UNMODIFIED = 0, /**< no changes */
GIT_DELTA_ADDED = 1, /**< entry does not exist in old version */
GIT_DELTA_DELETED = 2, /**< entry does not exist in new version */
GIT_DELTA_MODIFIED = 3, /**< entry content changed between old and new */
GIT_DELTA_RENAMED = 4, /**< entry was renamed between old and new */
GIT_DELTA_COPIED = 5, /**< entry was copied from another old entry */
GIT_DELTA_IGNORED = 6, /**< entry is ignored item in workdir */
GIT_DELTA_UNTRACKED = 7, /**< entry is untracked item in workdir */
GIT_DELTA_TYPECHANGE = 8, /**< type of entry changed between old and new */
GIT_DELTA_UNREADABLE = 9, /**< entry is unreadable */
GIT_DELTA_CONFLICTED = 10, /**< entry in the index is conflicted */
} git_delta_t;
When I run command go generate
I'm getting error:
stringer: can't happen: constant is not an integer DeltaUnmodified
diff.go:43: running "stringer": exit status 1
I tried to run these commands:
go generate ./diff.go
go generate -tags static,system_libgit2
go generate -tags static,system_libgit2 ./diff.go
But it always shows the same error.
How to correctly generate file with stringer for Go constants with values from C enum?
CodePudding user response:
stringer
works by simply parsing Go source with go.ast
to extract the needed constant values. The values must be integer literals specified at the definition site (see source).
CGo works by generating Go shims for C code. For example, C constants go into the _cgo_gotypes.go
file as const _Ciconst_... = ...
shims.
Normally CGo deletes generated files when done, but you can keep them by invoking it explicitly, e.g. go tool cgo main.go
.
So you should be able to do something like this:
go tool cgo main.go
mv _obj/_cgo_gotypes.go _obj/cgo_gotypes.go
stringer -type Delta -trimprefix Delta ./_obj
cp _obj/delta_strings.go .