linux - 有没有办法在一个二进制文件中包含多个 c-archive 包

标签 linux go cgo

我试图在单个 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

最佳答案

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

关键是定义一个单一的主包来导入你需要的包,并用一个“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 将提示未使用的包。

关于linux - 有没有办法在一个二进制文件中包含多个 c-archive 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34333107/

相关文章:

python - Docker 容器 Linux 在使用 * 读取 Python 参数时的奇怪行为

javascript - 使用 Javascript 读取 Linux 系统文件?

go - 在golang中将结构转换为结构

docker - 如何列出网络; docker 容器附加到使用格式模板?

go - CGO : Undefined symbols for architecture x86_64

java - 在 Java 中与命令行工具通信

c - 并非所有写入 FIFO 的消息都在读取时收到

reflection - 在 golang 中将 interface{} 转换为 *[]int

c - 为什么 dlsym 在 cgo 中产生的结果与在 c 中产生的结果不同?

go - 将结构和结构数组从 Go 传递给 C 函数