pais - ¿Cómo se conecta estáticamente la biblioteca de CA en go usando cgo?
cgo markets (4)
Así que hay un montón de cosas en el grupo que sugieren que puede hacer esto de una vez (aunque no en la documentación de cgo):
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")
}
Sin embargo, parece que no funciona:
/var/folders/.../bridge.a(bridge.cgo2.o)(__TEXT/__text): x: not defined
Esto parece funcionar bien usando una biblioteca dinámica, e inspeccionando los archivos generados, en realidad tiene el símbolo ''x'' allí:
/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
pero obviamente es solo un marcador en 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
¿Qué estoy haciendo mal?
Para ref, el encabezado c:
int x(int y);
Y código:
#include <junk.h>
#include <stdio.h>
int x(int y) {
printf("Hello World/n");
return y;
}
-
Editar:
No, -L y -l tampoco funcionan; en realidad hay una discusión específica en el grupo de google que esto (-l / blah / blah.a) no funciona para cgo, y la sintaxis correcta es, de hecho, omitir el -l y simplemente listar el archivo .a ... pero hey, si hubiera funcionado, simplemente lo usaría. Pero no:
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
versión detallada
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
Vale la pena señalar que el error cuando intentas vincular de esta manera (usando -l) es típico de que gcc no pueda establecer un enlace porque estás intentando combinar un conjunto de archivos de objeto.
es decir. Esta:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l/path/libgb.a
Nunca compilará bajo gcc; debe vincular una biblioteca estática como esta:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a
es decir. No es absolutamente que me falta un -l o -L.
Resulta que mi código es 100% bueno; era una copia de Go 1.0; bajo ir 1.1 esto funciona. Debajo de 1.0, no es así.
(Es un poco tonto responder a mi propia pregunta, lo sé, pero las respuestas ''use -L-l a continuación tampoco están bien, no tiene nada que ver con eso).
Un ejemplo de solución de trabajo está en github aquí para cualquiera que encuentre esta pregunta más adelante:
https://github.com/shadowmint/go-static-linking
en resumen que se ve así:
CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags ''-s'' src/myapp/myapp.go
ver también: https://github.com/golang/go/issues/9344
Solo tiene que enlazar con -Ldirectory -lgb.
$ cat >toto.c
int x( int y ) { return y+1; }
$ cat >toto.h
int x(int);
$ gcc -O2 -c toto.c
$ ar q libgb.a toto.o
$ cat >test.go
package main
import "fmt"
// #cgo CFLAGS: -I.
// #cgo LDFLAGS: -L. -lgb
// #include <toto.h>
import "C"
func main() {
fmt.Printf("Invoking c library.../n")
fmt.Println("Done ", C.x(10) )
}
$ go build test.go
$ ./test
Invoking c library...
Done 11
Tratar:
// #cgo LDFLAGS: -l/Users/doug/projects/c/go-bridge/build/libgb.a
Te perdiste el -l
en la directiva LDFLAGS.
Un Makefile directo para vincular el código Go con una biblioteca dinámica o estática:
static:
gcc -c gb.c
ar -rcs libgb.a gb.o
go build -ldflags "-linkmode external -extldflags -static" bridge.go
dynamic:
gcc -shared -o libgb.so gb.c
go build bridge.go
Directivas en bridge.go:
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lgb
#include "gb.h"
*/
import "C"
...