英文:
Stringer can't generate constants with values from C enum
问题
我正在尝试在本地运行CGO项目https://github.com/libgit2/git2go上的generate
命令。我已经成功安装了libgit2
系统库,并且可以使用go build -tags static,system_libgit2
和go test -tags static,system_libgit2
构建和测试该项目。
问题出现在我尝试使用stringer
生成额外文件时。我展示的代码位于主分支中,所以我认为它应该能正常工作,问题可能出在我这边。
文件diff.go中有stringer注释(删除了不重要的部分):
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
...
这个类型引用了libgit2
的C枚举,位于/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;
当我运行go generate
命令时,我得到以下错误:
stringer: can't happen: constant is not an integer DeltaUnmodified
diff.go:43: running "stringer": exit status 1
我尝试运行以下命令:
go generate ./diff.go
go generate -tags static,system_libgit2
go generate -tags static,system_libgit2 ./diff.go
但始终显示相同的错误。
如何正确使用stringer为具有来自C枚举的值的Go常量生成文件?
英文:
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?
答案1
得分: 1
stringer
通过使用go.ast
解析Go源代码来提取所需的常量值。这些值必须是在定义处指定的整数字面量(参见源代码)。
CGo通过为C代码生成Go的包装代码来工作。例如,C常量会作为const _Ciconst_... = ...
的包装代码放入_cgo_gotypes.go
文件中。
通常情况下,CGo在完成后会删除生成的文件,但你可以通过显式调用来保留它们,例如go tool cgo main.go
。
因此,你可以像这样操作:
<!-- language: lang-none -->
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 .
英文:
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:
<!-- language: lang-none -->
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 .
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论