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: undefined reference for C function with -buildmode=c-archive #25832

Open
Andari85 opened this Issue Jun 11, 2018 · 13 comments

Comments

Projects
None yet
4 participants
@Andari85

Andari85 commented Jun 11, 2018

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

go version go1.10.3 darwin/amd64

Does this issue reproduce with the latest release?

Yes

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

GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/Andari/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/Andari/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.10.3/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.10.3/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/lw/5pzww_8n38g1lv_kqqmqfvqr0000gn/T/go-build228325343=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I was experimenting with C interfacing:

// int cadd(int a, int b);
import "C"
...
// using the function somewhere

I built it with go build -buildmode=c-archive GoAdd.go

What did you expect to see?

The build to be successful.

What did you see instead?

Undefined symbols for architecture x86_64:
"_cadd", referenced from:
__cgo_ece3f0761be9_Cfunc_cadd in _x002.o

Why would linking be neccessary, if I am generating an archive which I link together with the cadd implementing object file later?

@Andari85 Andari85 changed the title from There should be no need to add cgo ladflags for linking when using -buildmode=c-archive to There should be no need to add cgo ldflags for linking when using -buildmode=c-archive Jun 11, 2018

@bcmills

This comment has been minimized.

Member

bcmills commented Jun 11, 2018

@bcmills bcmills changed the title from There should be no need to add cgo ldflags for linking when using -buildmode=c-archive to cmd/cgo: undefined reference for forward-declared function with -buildmode=c-archive Jun 11, 2018

@bcmills bcmills added this to the Go1.12 milestone Jun 11, 2018

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Jun 12, 2018

The cgo tool works this way because it needs to know the type of the C function cadd. It currently determines it by linking the program against the C libraries and examining the debug info. It would be nice if it could simply parse the declaration in the "C" comment, but, well, that requires a C parser. Examining the debug info seems to work reliably enough.

You are doing something rather complicated: you are building a C archive, which is Go code callable from C. And you want that code, written in Go, to itself call a C function. So you have C calling Go calling C. I agree that in principle this ought to work. But in practice it's kind of complicated.

Which is to say: yes, let's fix this if we can. But no promises on when or if anybody will look into it.

@ianlancetaylor ianlancetaylor modified the milestones: Go1.12, Unplanned Jun 12, 2018

@ianlancetaylor ianlancetaylor changed the title from cmd/cgo: undefined reference for forward-declared function with -buildmode=c-archive to cmd/cgo: undefined reference for C function with -buildmode=c-archive Jun 12, 2018

@Andari85

This comment has been minimized.

Andari85 commented Jun 13, 2018

Ok, I understand – I thought, it already parsed the comment abowe the import "C". Note, that I can get it working by compiling-only (clang -c) the C code first and using #cgo LDFLAGS: CAdd.o. The resulted CAdd.o and GoAdd.a can be linked or archived together either with each other or for example a C++ code using extern "C", or an Objective C / Swift code, and possible many other languages. (Actually, my final goal is to write a rendering engine in Go by calling its exported functions from native languages of each platform.)

@Andari85

This comment has been minimized.

Andari85 commented Jun 13, 2018

Alternative possibility to allow declaring only C function would be something like this:

import "C"

//import cadd
func cadd(a C.int, b C.int) C.int

Like extern "C" in C++ or extern(C) in D.
This way a C parser would be not required.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Jun 13, 2018

You might be able to do that today using go:linkname. I haven't tried, though.

@Andari85

This comment has been minimized.

Andari85 commented Jun 20, 2018

I had no success with go:linkname to get the C function imported.

@NickNaso

This comment has been minimized.

NickNaso commented Aug 13, 2018

Hi everyone,
I have the same problem. I have C calling Go calling C and it should be great have a chance to do that without the linker error.

@Andari85

This comment has been minimized.

Andari85 commented Aug 14, 2018

Until there is a better option, you can get it working by compiling the C code with -c and use that to compile the Go code and than link together those. For that, you have to have the declarations of the functions exported from the Go source. I did that by hand. I was even lazy enough to simply use int on both sides, which works on most architectures.

I would suggest to create a feature request to be able to use this:

import "C"

//import cadd
func cadd(a C.int, b C.int) C.int

// for use in other packages with Go types
func Cadd(a int, b int) int {
  return int(cadd(C.int(a), C.int(b)))
}
@NickNaso

This comment has been minimized.

NickNaso commented Aug 14, 2018

Hi @Andari85 ,
I did as you proposed and all worked fine. Thanks for the advice. It could be good have a better option because in my case compiling with the -c option requested a lot of work. Thanks again.

@Andari85

This comment has been minimized.

Andari85 commented Sep 6, 2018

So, is there a specific way to create a feature request, or will this be picked up by someone?

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 6, 2018

@Andari85 This issue is still open, so it is in effect a feature request. However, as I said above, it's kind of complicated, let's fix it if we can, but no promises on when or if anybody will look into it.

Go is an open source project, so: volunteers welcome. I've already marked the issue as "help wanted".

@Andari85

This comment has been minimized.

Andari85 commented Sep 7, 2018

Okay, thanks. Well, I'm not much of a compiler guru, one day I might try to learn into the Go compiler.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 7, 2018

For what it's worth, I don't think that any fix to this will involve the compiler itself at all. I think all the work will be in the go tool and/or the cgo tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment