Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: "inconsistent definitions for C.CString" errors #17723

Closed
dtromb opened this issue Nov 1, 2016 · 7 comments

Comments

@dtromb
Copy link

commented Nov 1, 2016

Something severely funky is happening with cgo as I try to create bindings for the X Windows library.

I know there is a bug relating to struct definitions where you get "inconsistent definitions", but this is a conflict for an object in the default C package which I am certainly not defining (and that text does not appear in the cgo include headers, nor does it appear as a symbol in the target library!)

What is really quite strange about this, is that it will randomly appear and disappear as I add functions to the library - it seems to be pretty dependent on some state which we might call "random" (possibly position of defs in the cgo generated sources?), but is reproducible on a single codebase state. I cannot seem to create a MCVE because of this, but I have uploaded the source of the project so far to https://github.com/dtromb/x11-cgo-bug - attempting to compile this should reproduce the issue.

I have really no idea how to debug this. First, I grepped through the generated cgo source, expecting to find a duplicate definition of CString() (or rather the C-mangled-name function implementing it). I did not - there was only one. I then noticed that the error is emitted from the cgo binary after a reflect.DeepEqual() comparison of the conflicting *main.Name types. I tried rewriting DeepEqual() to provide some debugging information - and that was not helpful (package access rules thwarted the implementation). Next, I wrote a function to dump the Name structure to a string, and all of the ast.Expr and friends so that we can see the exact differences. I've attached those dumps as files here.

fail.txt

fail2.txt

As you can see, there is a Typedef field in the FuncType record being set to "XPointer"; this corresponds, I believe, to the return type of the CString() implementation.

This is something of a clue, as Xlib does define an XPointer type, as follows:

   Xlib.h:typedef char *XPointer;

, so it is at least /plausible/ that something somewhere is mistaking this for the actual return type of CString(). I'm sorry to say my trail ended here though, as I really don't know enough about the Go parser or these specific structures to progress easily further...

What version of Go are you using (go version)?

go version go1.7.3 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/dtrombley/go/path"
GORACE=""
GOROOT="/home/dtrombley/go/root"
GOTOOLDIR="/home/dtrombley/go/root/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build434390939=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"

What did you do?

I am attempting to compile a valid Go program with cgo interfaces to the X library.

What did you expect to see?

Completed Proper compilation.

What did you see instead?

cgo emits: "inconsistent definitions for C.CString"

@ianlancetaylor ianlancetaylor added this to the Go1.8 milestone Nov 1, 2016

@ianlancetaylor ianlancetaylor changed the title cgo: "inconsistent definitions for C.CString" errors cmd/cgo: "inconsistent definitions for C.CString" errors Nov 1, 2016

@ainar-g

This comment has been minimized.

Copy link
Contributor

commented Nov 1, 2016

Interestingly enough, it goes away if you put the contents of color.go into x11.go. Might be similar to #8133?

@ainar-g

This comment has been minimized.

Copy link
Contributor

commented Nov 1, 2016

I've found a workaround:

func CString(s string) *C.char { return C.CString(s) }

If I replace all C.CString calls with this CString call, it compiles.

@dtromb

This comment has been minimized.

Copy link
Author

commented Nov 1, 2016

@ainar-g - That "one file" behavior seems to make some sense as it appears the parser caches types per file. Thanks for the workaround! I'm leaning toward wanting to investigate this further, as my previous random workaround worked at first, then stopped working! That will be good to let me continue along, at any rate...

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Nov 1, 2016

The problem occurs when two files refer to C.CString, and one of the files also refers to a function that takes an argument, where the type of the argument is a typedef for char *. In that case cgo sees the typedef and installs it on char * (see typeConv.FuncArg), and that later leads cgo to believe that the call to C.CString in one file has a different type than the call in a different file.

Testing a fix now.

@gopherbot

This comment has been minimized.

Copy link

commented Nov 1, 2016

CL https://golang.org/cl/32536 mentions this issue.

@gopherbot gopherbot closed this in 689947d Nov 1, 2016

@dtromb

This comment has been minimized.

Copy link
Author

commented Nov 2, 2016

Might it be good, in addition, to do some more tailored comparison of Name in cmd/cgo/main.go than reflect.DeepEqual()? It seems like there may be other circumstances where the types should be considered the same, even if the entire parse tree doesn't match exactly. (Or then again, maybe there aren't - and there is only ever One Way To Say It. There are of course other "transient" or rather, non-lexical fields like that Typedef lurking in that object graph, however!) I will try to construct some pathological examples and open another issue if successful.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Nov 2, 2016

Thanks, yes, we would need examples to make any changes here. The complexities of merging the type systems of the two different languages are difficult to reason about in the abstract.

@golang golang locked and limited conversation to collaborators Nov 2, 2017

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants
You can’t perform that action at this time.