如何分发go binary only包

时间:2018-05-20 02:52:11

标签: go

我想以二进制形式分发包而不包含源代码。

我的演示项目目录结构如下:

demo
├── greet
│   ├── greet.go
│   └── hi
│       └── hi.go
├── hello
│   └── hello.go
└── main.go

main.go:

package main

import (
    "fmt"
    "demo/greet"
    "demo/hello"
)

func main(){
    fmt.Println("greet:")
    greet.Greet()

    fmt.Println("hello:")
    hello.Hello()
}

greet.go

package greet

import (
    "demo/greet/hi"
    "fmt"
)

func Greet(){
    fmt.Println("Greet Call Hi")
    hi.Hi()
}

hi.go

package hi

import "fmt"

func Hi(){
    fmt.Println("Hi")
}

hello.go

package hello

import (
    "fmt"
    "demo/greet"
)

func Hello(){
    fmt.Println("hello call greet")
    greet.Greet()
}

我这样做:

[user@localhost greet]$ go install -a ./...

它在$ GOPATH / pkg / linux_amd64 / demo中生成了greet.a和greet / hi.a. 然后我编辑hi.go和greet.go。

[user@localhost greet]$ cat greet.go
//go:binary-only-package

package greet
[user@localhost greet]$ cat hi/hi.go
//go:binary-only-package

package hi

然后我运行main.go,我收到错误:

[user@localhost greet]$ cat hi/hi.go
# command-line-arguments
cannot find package demo/greet/hi (using -importcfg)
/home/user/go/pkg/tool/linux_amd64/link: cannot open file : open : no such file or directory

greet 是我要分发的包。如果我删除包 hi ,则main.go可以正常运行。

demo
├── greet
│   └── greet.go
├── hello
│   └── hello.go
└── main.go

安装:

[user@localhost greet]$ go install .
[user@localhost greet]$ vim greet.go
//go:binary-only-package

package greet
[user@localhost greet]$ cd ..
[user@localhost demo]$ go run main.go
greet:
Greet ...
hello:
hello call greet
Greet ...
[user@localhost demo]$ 

所以我的主要问题是:我如何构建二进制库,而其他人则无法查看我的源代码。并且包中有很多子包。(如果包没有子包,我使用//go:binary-only-package方法可以很好地工作)

请帮助或尝试提出一些解决方法。提前谢谢。

2 个答案:

答案 0 :(得分:1)

注意(2019):仅二进制软件包不再受支持。

Go 1.12 (February 2019) release notes之后(CL 152918之后):

  

仅二进制包

     

Go 1.12是最后一个支持纯二进制软件包的版本

这在Go issue 28152中有详细说明:

  

仅二进制软件包越来越难以安全地支持。

     

不能保证仅二进制程序包的编译所使用的依赖版本与最终链接所使用的依赖版本相同(并且坚持这样做可能会很麻烦)。
  结果,可能已经使用转义分析结果或内联函数主体来编译仅二进制包,以解决不再准确的依赖项。
  结果可能是无声的内存损坏。

     

我的记忆是,我们最初添加了仅二进制软件包,以便教授可以分发二进制解集,以便未完成实验2的学生仍可以继续进行实验3。
  我不知道为什么还有其他人会使用它们,但是随着编译器变得越来越复杂,它们可能会越来越被破坏。

This was also discussed here

答案 1 :(得分:0)

“go run”将编译并运行给定的主包。因此它会检查源文件的时间戳,如果它们看起来比以前编译的库(.a文件)更新,则重新编译它们。

对于仅二进制包,它将跳过此步骤。因此,在这种情况下,它将检查任何给定的包,只有一个源文件,文本为// go:binary-only-package。这就是指定功能的方式。当它看到它时,它将只使用.a文件。

如果你有一个包含源文件的子包,那么它们中的文件似乎最终会作为封闭根包的一部分计算,并且只有一个源文件的要求被破坏。那么“go run”就会失败。我怀疑这就是为什么它不起作用。这就是为什么删除hi子包会导致它工作。

二进制文件的预期用例是您编译包,然后当您将其提供给其他人时,您不包含任何源文件,只包含.a文件。但要实现这一点,您需要能够告诉其他人的编译器您的包只是.a文件。为此,您需要只包含一个源文件和文本// go:binary-only-package。你基本上已经在这里看到,对于一个有子包的包,整个东西必须只有一个这样的源文件,只能有一个,你不能在子包文件夹中有更多。所以只提供一个。这就是该功能的工作原理。您将.a文件和一个源文件提供给其他人。