【问题标题】:Is there a way to include multiple c-archive packages in a single binary有没有办法在一个二进制文件中包含多个 c-archive 包
【发布时间】:2016-06-21 06:35:17
【问题描述】:

我试图在单个 C 二进制文件中包含多个 Go c-archive 包,但由于每个 c-archive 中包含完整的运行时,我遇到了多个定义错误。

我尝试将多个包放在同一个 c-archive 中,但 go build 不允许这样做。

我还尝试从除一个之外的所有档案中删除 go.o,但似乎我自己的 Go 代码也在该目标文件中,所以这不起作用,这甚至是我得到多个定义而不是链接器从后续存档中忽略 go.o

使用c-shared 代替c-archive 可能会起作用,但我不希望这样做,因为我必须将共享库放在我的目标机器上,这比只放置最终程序二进制文件。如果可能,我希望所有内容都静态链接。

有没有办法让它工作?如果这很重要,我可以接受仅限 linux 的解决方案(在这种情况下可能会有一些 GNU ld 诡计)。

将所有内容放在一个 Go 包中并不是一个真正的选择,因为它是一个相当大的代码库,并且会有不同的程序需要不同的部分。在这种情况下,它必须是一个自动生成的包。

重现问题的完整步骤:

cd $GOPATH/src
mkdir a b
cat > a/a.go <<EOT
package main

import "C"

//export a
func a() {
    println("a")
}

func main() {}
EOT
cat > b/b.go <<EOT
package main

import "C"

//export b
func b() {
    println("b")
}

func main() {}
EOT
cat > test.c <<EOT
#include "a.h"
#include "b.h"

int
main(int argc, char *argv[]) {
    a();
    b();
}
EOT
go build -buildmode=c-archive -o a.a a
go build -buildmode=c-archive -o b.a b
gcc test.c a.a b.a

【问题讨论】:

  • 可以使用ar命令构建库(.a)
  • 您可能更有可能在 go 邮件列表中获得有关此类实施细节的答案。

标签: linux go cgo


【解决方案1】:

在遇到你的问题后,我今天摸索着解决了这个问题。

关键是定义一个单独的主包来导入您需要的包,并使用一个“go install”命令将它们全部构建在一起。我无法让它与“go build”一起使用。

package main //import golib

import (
        _ "golib/operations/bar"
        _ "golib/foo"
)
func main() {}

go install  -buildmode=c-archive golib

这会将您的 .a 和 .h 文件放在 pkg/arch/golib 目录下。您可以像往常一样包含 .h 文件,但您只需要链接到 golib.a

aaron@aaron-laptop:~/code/pkg/linux_amd64$ ls
github.com  golang.org  golib  golib.a
aaron@aaron-laptop:~/code/pkg/linux_amd64$ ls golib
foo.a  foo.h operations  
aaron@aaron-laptop:~/code/pkg/linux_amd64$ ls golib/operations
bar.a bar.h

请注意,如果您在导入中省略下划线,go 会抱怨未使用的包。

【讨论】:

    猜你喜欢
    • 2019-06-08
    • 2015-12-21
    • 1970-01-01
    • 2022-01-21
    • 2022-01-05
    • 2017-12-20
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    相关资源
    最近更新 更多