So there's a bunch of stuff on the group that suggests you can do this in go (although not on the cgo documentation):
package bridge import "fmt" // #cgo CFLAGS: -I/Users/doug/projects/c/go-bridge/include // #cgo LDFLAGS: /Users/doug/projects/c/go-bridge/build/libgb.a // #include <junk.h> import "C" func Run() { fmt.Printf("Invoking c library...\n") C.x(10) fmt.Printf("Done\n") }
However, it doesn't seem to work:
/var/folders/.../bridge.a(bridge.cgo2.o)(__TEXT/__text): x: not defined
This seems to work fine using a dynamic library, and inspecting the generated files, it actually has the symbol 'x' in there:
/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build442792776/bridge/_obj/_cgo_.o: 0000000100001048 S _NXArgc 0000000100001050 S _NXArgv 0000000100001060 S ___progname 0000000100000dc0 T __cgo_2d7eefe3d6d4_Cfunc_x 0000000100000da0 T __cgo_allocate 0000000100000db0 T __cgo_panic 0000000100000000 T __mh_execute_header 0000000100000d90 T _crosscall2 0000000100001058 S _environ U _exit 0000000100000d80 T _main U _puts 0000000100001000 s _pvars 0000000100000de0 T _x <------- Exists U dyld_stub_binder 0000000100000d40 T start
but obviously is just a marker in bridge.cgo2.o:
/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build442792776/bridge.a(bridge.cgo2.o): 0000000000000368 s EH_frame0 0000000000000000 T __cgo_2d7eefe3d6d4_Cfunc_x 0000000000000380 S __cgo_2d7eefe3d6d4_Cfunc_x.eh U _x
What am I doing wrong?
For ref, the c header:
int x(int y);
And code:
#include <junk.h> #include <stdio.h> int x(int y) { printf("Hello World\n"); return y; }
--
Edit:
No, -L and -l don't work either; there's actually some specific discussion on the google group that this (-l/blah/blah.a) does not work for cgo, and the correct syntax is in fact to omit the -l and just list the .a file... but hey, if it'd worked, I'd totally just use it. But it doesn't:
dougs-mini:go doug$ go run test.go # bridge ld: library not found for -l/Users/doug/projects/c/go-bridge/build/libgb.a collect2: ld returned 1 exit status dougs-mini:go doug$ ls -l /Users/doug/projects/c/go-bridge/build/libgb.a -rw-r--r-- 1 doug staff 872 25 May 14:02 /Users/doug/projects/c/go-bridge/build/libgb.a
verbose version:
dougs-mini:go doug$ go build -work -x test.go WORK=/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build354497708 mkdir -p $WORK/bridge/_obj/ cd /Users/doug/projects/c/go-bridge/go/src/bridge /Users/doug/projects/go/go/pkg/tool/darwin_amd64/cgo -objdir $WORK/bridge/_obj/ -- -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ bridge.go /Users/doug/projects/go/go/pkg/tool/darwin_amd64/6c -FVw -I $WORK/bridge/_obj/ -I /Users/doug/projects/go/go/pkg/darwin_amd64 -o $WORK/bridge/_obj/_cgo_defun.6 -DGOOS_darwin -DGOARCH_amd64 $WORK/bridge/_obj/_cgo_defun.c gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/_cgo_main.o -c $WORK/bridge/_obj/_cgo_main.c gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/_cgo_export.o -c $WORK/bridge/_obj/_cgo_export.c gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/bridge.cgo2.o -c $WORK/bridge/_obj/bridge.cgo2.c gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o $WORK/bridge/_obj/_cgo_.o $WORK/bridge/_obj/_cgo_main.o $WORK/bridge/_obj/_cgo_export.o $WORK/bridge/_obj/bridge.cgo2.o -l/Users/doug/projects/c/go-bridge/build/libgb.a # bridge ld: library not found for -l/Users/doug/projects/c/go-bridge/build/libgb.a collect2: ld returned 1 exit status
It's worth noting that the failure when you try to link like this (using -l) is typical of gcc failing to link because you're attempting to combine a set of object files.
ie. This:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l/path/libgb.a
Will never compile under gcc; you must link a static library like this:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a
ie. It is absolutely not that I'm missing a -l or -L.
Go allows linking against C libraries or pasting in in-line code.
Well, Go code is statically linked, but the runtime may try to dynamically load libc for DNS resolving. Use of cgo of course drastically change everything. By default, nowadays the toolchain also supports generating dynamic libraries.
Most of the sources online state that you can statically link glibc, but discourage from doing so; e.g. centos package repo: The glibc-static package contains the C library static libraries for -static linking. You don't need these, unless you link statically, which is highly discouraged.
You can't statically link a shared library (or dynamically link a static one).
Turns out my code is 100% fine; it was a copy of Go 1.0; under go 1.1 this works. Under go 1.0, it doesn't.
(it's a bit lame answering my own question, I know; but the 'use -L -l answers below aren't right either; it had nothing to do with that).
A working solution example is up on github here for anyone who find's this question later:
https://github.com/shadowmint/go-static-linking
in short that looks like:
CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go
see also: https://github.com/golang/go/issues/9344
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With