【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)