如何静态链接一个c库去使用cgo? [英] How do you statically link a c library in go using cgo?

查看:374
本文介绍了如何静态链接一个c库去使用cgo?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,团队中有很多东西表明你可以这样做(尽管不在cgo文档中):

  package bridge 

importfmt

// #cgo CFLAGS:-I / Users / doug / projects / c / go-bridge / include
// #cgo LDFLAGS:/Users/doug/projects/c/go-bridge/build/libgb.a
// #include< junk.h>
导入C

func Run(){
fmt.Printf(调用c库... \\\

Cx(10)
fmt.Printf(Done \\\

}

然而,它似乎不工作:

  / var / folders /.../ bridge.a(bridge.cgo2.o )(__ TEXT / __ text):x:未定义

这似乎很好地使用动态库,并检查生成的文件,它实际上有符号'x'在那里:

  / 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< -------存在
U dyld_stub_binder
0000000100000d40 T开始

但显然只是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

我做错了什么?



对于ref,c头文件:

  int x(int y); 

和代码:

  #include< junk.h> 
#include< stdio.h>

int x(int y){
printf(Hello World\\\
);
return y;
}

-



编辑:



不,-L和-l也不起作用;实际上有一些关于谷歌组的具体讨论,这个(-l / blah / blah.a)不适用于cgo,正确的语法实际上是省略了-l,并且仅仅列出了.a文件...但是,嘿,如果它能工作,我完全可以使用它。但它没有:

  dougs-mini:go doug $ go run test.go 
#bridge
ld:库找不到-l / Users / doug / projects / c / go-bridge / build / libgb.a
collect2:ld返回1退出状态
dougs-mini:go doug $ ls -l /Users/doug/projects/c/go-bridge/build/libgb.a
-rw-r - r-- 1个工作人员872 25 5月14:02 / Users / doug / projects / c / go-bridge / build / libgb.a

详细版本:

  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_de fun.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:找不到-l / Users / doug的库/projects/c/go-bridge/build/libgb.a
collect2:ld返回1退出状态

值得注意的是,当你尝试像这样链接(使用-l)时出现故障是gcc无法链接的典型情况,因为你试图组合一组目标文件。



即。这:

  gcc -I。 -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l / path / libgb.a 

不会在gcc下编译;你必须链接这样一个静态库:

  gcc -I。 -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a 

即这绝对不是我缺少-l或-L。

解决方案

我发现我的代码是100%它是Go 1.0的副本;在1.1下工作。
在go 1.0下,它没有。



(我知道,回答我自己的问题有点蹩脚;但'使用-L -l回答下面是不正确的;它与此无关)。



一个工作解决方案的例子在github上适用于任何后来发现这个问题的人: p>

https://github.com/shadowmint/ go-static-linking



总之,看起来像:

  CGO_ENABLED = 0 go build -a -installsuffix cgo -ldflags'-s'src / myapp / myapp.go 

另请参阅:
https://github.com/golang/ go / issues / 9344


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.

解决方案

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

这篇关于如何静态链接一个c库去使用cgo?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆