【Free Style】如何使用Go的so发布库
Go默认使用的源码发布的模式,但是使用源码发布可能会遇到这样那样的问题和限制。Go同样是提供了一种使用so发布的方式。下面会关于,开发者如何发布so,以及使用者如何使用so进行详细说明。
工程树
. ├── common │ ├── makefile │ └── src │ └── sum │ └── pack.go ├── developer1 │ ├── makefile │ └── src │ ├── pack1 │ │ └── pack1.go │ └── sum │ └── sum.go ├── developer2 │ ├── makefile │ └── src │ ├── pack2 │ │ └── pack2.go │ └── sum │ └── sum.go └── manager ├── makefile └── src ├── main │ └── main.go ├── pack1 │ └── pack1.go └── pack2 └── pack2.go
其中common中的sum为developer1开发的pack1和developer2开发的pack2共同使用的包,manager中main使用pack1和pack2两个包。所以,根据这样的逻辑关系,需要common发布一个sum包的libsum.so,pack1和pack2需要各自拿到这个libsum.so,并发布libpack1.so和libpack2.so。最后main需要拿到libsum.so、libpack1.so和libpack2.so。
sum的编译
该工程的目录树为
. └── common ├── makefile └── src └── sum └── pack.go
package sum
func Sum(x, y int) int {
return x + y
}sum包的编写如上面代码所示,定义一个package sum,并在里面定义了一个函数Sum。该包的编译如下:
GOPATH=$(shell pwd) go install -buildmode=shared -linkshared std GOPATH=$(shell pwd) go install -buildmode=shared -linkshared sum
第一行为编译准备一些标准包设置,第二行为编译sum包。注意,第一行一定不能缺少。此时,会在工程下增加pkg节点,此时目录树为:
. ├── makefile ├── pkg │ └── linux_amd64_dynlink │ ├── libsum.so │ ├── sum.a │ └── sum.shlibname └── src └── sum └── pack.go
生成的libsum.so、sum.a以及sum.shlibname都需要发布出去。sum.shlibname的内容很简单。
libsum.so
pack1/pack2的编译
pack1与pack2的编译类似,以pack1为例,在拿到sum的相关包之后,目录树如下:
. ├── makefile ├── pkg │ └── linux_amd64_dynlink │ ├── libsum.so │ ├── sum.a │ └── sum.shlibname └── src ├── pack1 │ └── pack1.go └── sum └── sum.go
此时目录树中的pkg是直接从common中拷贝过来的,不再赘述。src下的pack1为实际开发的pack1包主体,其实现如下:
package pack1
import "sum"
func Sum(x, y int) int {
return sum.Sum(x, y) + 1
}对于sum的使用,直接使用import即可。和正常编写的Go程序并没有太大区别。此处,使用so文件与C中不同的是,需要在于pack1平行的位置建立一个sum文件夹,并新建sum.go文件,其中里面需要填入如下代码:
//go:binary-only-package package sum
这两行会告诉编译器,此处为sum包,并只提供binary编译。至此,pack1的编译准备完成,编译命令如下所示:
GOPATH=$(shell pwd) go install -buildmode=shared -linkshared std GOPATH=$(shell pwd) go install -buildmode=shared -linkshared pack1
编译命令与sum包的类似,在此不作赘述。此时,pack1的目录树为:
. ├── makefile ├── pkg │ └── linux_amd64_dynlink │ ├── libpack1.so │ ├── libsum.so │ ├── pack1.a │ ├── pack1.shlibname │ ├── sum.a │ └── sum.shlibname └── src ├── pack1 │ └── pack1.go └── sum └── sum.go
在pkg目录中,多了pack1的相关信息。
main的编译
main为pack1和pack2的使用者。分别把sum、pack1和pack2里面pkg下面的相关文件迁移过来,此时目录树为:
. ├── makefile ├── pkg │ └── linux_amd64_dynlink │ ├── libpack1.so │ ├── libpack2.so │ ├── libsum.so │ ├── pack1.a │ ├── pack1.shlibname │ ├── pack2.a │ ├── pack2.shlibname │ ├── sum.a │ └── sum.shlibname └── src ├── main │ └── main.go ├── pack1 │ └── pack1.go └── pack2 └── pack2.go
其中main/main.go的代码为:
package main
import "pack1"
import "pack2"
func main() {
println(pack1.Sum(1,2))
println(pack2.Sum(1,2))
}与pack1使用sum类似,同样需要建立于main平级的两个目录pack1和pack2。以pack1为例,其代码为:
//go:binary-only-package package pack1
编译命令为:
GOPATH=$(shell pwd) go build -linkshared -o main main
运行结果为:
./main 4 5
说明
另外,使用这种shared模式,默认是打开cgo标记的,所以可以在这种模式下使用cgo相关的操作。:)
有问题请espace我, From 编译器与编程语言实验室。
- 点赞
- 收藏
- 关注作者
评论(0)