简体   繁体   English

必须使用 CGO_ENABLED 时会发生什么

[英]When using CGO_ENABLED is must and what happens

Question问题

Please help understand when CGO_ENABLED is must and unavoidable, and what happens with the go compilation process.请帮助了解CGO_ENABLED 何时是必须且不可避免的,以及 go 编译过程会发生什么。

When CGO_ENABLED is must当 CGO_ENABLED 是必须的

After having read the articles in references , it looks as far as go has cross-compile native support for the target platform, CGO_ENABLED will never be a must.在阅读了参考资料中的文章后,似乎 go 对目标平台具有交叉编译原生支持, CGO_ENABLED绝不是必须的。 Is this correct?这个对吗?

The situation when cgo and CGO_ENABLED is absolute-must is when go compiler cannot produce the binary code for the target platform. cgoCGO_ENABLED绝对必须的情况是 go 编译器无法为目标平台生成二进制代码。 For instance, imagine I am writing a Space X control board embedded program in Go and I have to use C library and the compiler for the board.例如,假设我正在 Go 中编写 Space X 控制板嵌入式程序,我必须使用 C 库和板的编译器。 There is no other library or compiler available for the board.该板没有其他可用的库或编译器。

In such case, I have to do CGO_ENABLED=1 and tell cgo the compiler and the linker to use and where the C library binaries are copied in my laptop, and setup the compilers CFLAGS etc etc. Perhaps I would have to use C for all the coding instead of using Go in this case, but somehow I was in the situation that I had to use Go. In such case, I have to do CGO_ENABLED=1 and tell cgo the compiler and the linker to use and where the C library binaries are copied in my laptop, and setup the compilers CFLAGS etc etc. Perhaps I would have to use C for all在这种情况下,编码而不是使用 Go,但不知何故,我不得不使用 Go。 This is when CGO_ENABLED=1 would be must.这是必须的CGO_ENABLED=1的时候。 Is this correct?这个对吗?

Otherwise, if especially go has the support for the target platform cross-compilation, using CGO_ENABLED=1 could be a short-cut to just re-use the existing C library for the target platform.否则,如果特别是 go 支持目标平台交叉编译,则使用CGO_ENABLED=1可能是为目标平台重新使用现有 C 库的捷径。 Is this correct or is there any other reason why CGO_ENABLED is required?这是正确的还是需要CGO_ENABLED的任何其他原因?

What happens怎么了

I suppose when CGO_ENABLED=1 is used, basically there will be a composition of the binary from Go part, and the binary from the C library in the executable created by go build command.我想当使用CGO_ENABLED=1时,基本上会有来自 Go 部分的二进制文件和来自 C 库的二进制文件在由Z34D1F91FB2E514B8576FAB1A6B7DA创建的可执行文件中组成。 And at runtime, the execution goes back and forth between the two binary world of go and C.在运行时,执行在 go 和 C 这两个二进制世界之间来回执行。 Go binary side would not know C side, so the go tools like debugger would not be available. Go 二进制端不知道 C 端,因此调试器等 go 工具将不可用。

I suppose whether the executable hard-links all the libraries or uses dynamic linking depends on the target platform compiler.我想可执行文件是硬链接所有库还是使用动态链接取决于目标平台编译器。

Are these correct understandings?这些是正确的理解吗?

The reason CGO_ENABLED=0 by default for cross-compilation is because we should use the go built-in support of the target platform cross-compilation and there should be no reason not to do so.交叉编译默认CGO_ENABLED=0的原因是我们应该使用 go 内置的目标平台交叉编译支持,没有理由不这样做。

The reason CGO_ENABLED=1 by default for the native local platform is because the cgo compiler knows (or the author of the compiler knows) the local machine architecture and the OS libraries (or well known 3rd party's) available, hence best-optimization can be expected?本机本地平台默认CGO_ENABLED=1的原因是因为 cgo 编译器知道(或编译器的作者知道)本地机器架构和可用的操作系统库(或众所周知的第 3 方),因此可以进行最佳优化预期的? But I am not sure this is true because the go compiler itself can be best-optimized for the local OS and architecture, then why need to use cgo?但我不确定这是不是真的,因为 go 编译器本身可以针对本地操作系统和架构进行最佳优化,那为什么需要使用 cgo?

Kindly explain why CGO_ENABLED=1 by default for the native local platform.请解释为什么原生本地平台默认CGO_ENABLED=1

References参考

  • cgo is not Go cgo 不是 Go

    Some people, when confronted with a problem, think “I know, I'll use cgo.”有些人在遇到问题时会想“我知道,我会使用 cgo”。 Now they have two problems.现在他们有两个问题。

    cgo is an amazing technology which allows Go programs to interoperate with C libraries. cgo 是一项了不起的技术,它允许 Go 程序与 C 库进行互操作。 It's a tremendously useful feature without which Go would not be in the position it is today.这是一个非常有用的功能,没有它 Go 就不会出现在今天的 position 中。 cgo is key to ability to run Go programs on Android and iOS. cgo 是在 Android 和 iOS 上运行 Go 程序的关键。

    However, and to be clear these are my opinions, I am not speaking for anyone else, I think cgo is overused in Go projects.但是,要明确这些是我的意见,我不代表任何人,我认为 cgo 在 Go 项目中被过度使用。 I believe that when faced with reimplementing a large piece of C code in Go, programmers choose instead to use cgo to wrap the library, believing that it is a more tractable problem.相信程序员面对在Go中重新实现一大段C代码时,会选择使用cgo来封装库,认为这是一个比较容易解决的问题。 I believe this is a false economy.我认为这是一种虚假的经济。

    Obviously, there are some cases where cgo is unavoidable, most notably where you have to interoperate with a graphics driver or windowing system that is only available as a binary blob.显然,在某些情况下 cgo 是不可避免的,最明显的是您必须与只能作为二进制 blob 使用的图形驱动程序或窗口系统进行互操作。 But those cases where cgo's use justifies its trade-offs are fewer and further between than many are prepared to admit.但是,那些使用 cgo 证明其权衡的情况比许多人准备承认的要少得多。

    Go's support for cross compilation is best in class. Go 对交叉编译的支持最好在 class 中。 As of Go 1.5 you can cross compile from any supported platform to any other platform with the official installer available on the Go project website.从 Go 1.5 开始,您可以使用 Go 项目网站上提供的官方安装程序从任何受支持的平台交叉编译到任何其他平台。

    By default cgo is disabled when cross compiling.默认情况下,交叉编译时禁用 cgo。 Normally this isn't a problem if your project is pure Go.如果您的项目是纯 Go,通常这不是问题。 When you mix in dependencies on C libraries, you either have to give up the option to cross compile your product, or you have to invest time in finding and maintaining cross compilation C toolchains for all your targets.当您混合对 C 库的依赖项时,您要么必须放弃交叉编译产品的选项,要么必须花时间为所有目标查找和维护交叉编译 C 工具链。

    The number of platforms that Go supports continues to grow. Go 支持的平台数量持续增长。 Go 1.5 added support for 64 bit ARM and PowerPC. Go 1.5 添加了对 64 位 ARM 和 PowerPC 的支持。 Go 1.6 adds support for 64 bit MIPS, and IBM's s390 architecture is touted for Go 1.7. Go 1.6 增加了对 64 位 MIPS 的支持,IBM 的 s390 架构被吹捧为 Go 1.7。 RISC-V is in the pipeline. RISC-V 正在筹备中。 If your product relies on a C library, not only do you have the all problems of cross compilation described above, you also have to make sure the C code you depend on works reliably on the new platforms Go is supporting — and you have to do that with the limited debuggability a C/Go hybrid affords you.如果您的产品依赖于 C 库,那么您不仅有上述交叉编译的所有问题,您还必须确保您所依赖的 C 代码在新平台上可靠运行 Z5F075AE3E1F9D0382BB8ZC4F 支持 - 和2F C/Go 混合为您提供有限的可调试性。 Which brings me to my next point.这让我想到了下一点。

  • Why does CGO_ENABLE make a such impact on virtual memory? 为什么 CGO_ENABLE 会对虚拟 memory 产生如此大的影响?

    the compiler of the "reference" Go implementation (historically dubbed "gc"; that one, available for download from the main site) by default produces statically-linked binaries.默认情况下,“参考”Go 实现(历史上称为“gc”;可从主站点下载)的编译器生成静态链接的二进制文件。 This means, such binaries rely only on the so-called "system calls" provided by the OS kernel and do not depend on any shared libraries provided by the OS (or 3rd parties).这意味着,此类二进制文件仅依赖于操作系统 kernel 提供的所谓“系统调用”,而不依赖于操作系统(或第 3 方)提供的任何共享库。

    On Linux-based platforms, this is not completely true: in the default setting (building on Linux for Linux, ie, not cross-compiling) the generated binary is actually linked with libc and with libpthread (indirectly, via libc).在基于 Linux 的平台上,这并不完全正确:在默认设置中(基于 Linux 构建 Linux,即不交叉编译)生成的二进制文件实际上与 libc 和 libpthread 链接(通过 libc 间接)。

  • cmd/cgo: document how CGO_ENABLED works today cmd/cgo:记录今天 CGO_ENABLED 是如何工作的

    The cgo tool is enabled by default for native builds on systems where it is expected to work.默认情况下,cgo 工具在预期可以工作的系统上为本地构建启用。 It is disabled by default when cross-compiling.交叉编译时默认禁用。 You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it.您可以通过在运行 go 工具时设置 CGO_ENABLED 环境变量来控制这一点:将其设置为 1 以启用 cgo 的使用,设置为 0 以禁用它。 The go tool will set the build constraint "cgo" if cgo is enabled.如果启用了 cgo,go 工具将设置构建约束“cgo”。

    When cross-compiling, you must specify a C cross-compiler for cgo to use.交叉编译时,必须指定一个C交叉编译器供cgo使用。 You can do this by setting the CC_FOR_TARGET environment variable when building the toolchain using make.bash, or by setting the CC environment variable any time you run the go tool.您可以通过在使用 make.bash 构建工具链时设置 CC_FOR_TARGET 环境变量来执行此操作,或者在运行 go 工具的任何时候设置 CC 环境变量。 The CXX_FOR_TARGET and CXX environment variables work in a similar way for C++ code. CXX_FOR_TARGET 和 CXX 环境变量的工作方式与 C++ 代码类似。

  • C? C? Go? Go? Cgo!加油!

  • cgo cgo

Many things are only available as C libraries, and re-implementing that all in Go would be costly.许多东西只能作为 C 库提供,并且在 Go 中重新实现所有这些将是昂贵的。 cgo has its downsides, but it can be a good trade-off. cgo 有其缺点,但它可以是一个很好的权衡。 Even the standard library uses it ( net for DNS lookups, os/user for user lookups) because it doesn't re-implement 100% of the behaviour in Go.甚至标准库也使用它( net用于 DNS 查找, os/user用于用户查找),因为它不会 100% 地重新实现 Go 中的行为。

Cross-compiling C code is still rather hard;交叉编译 C 代码还是比较难的; you'll need the target architecture's C compiler and toolchain (eg CC=aarch64-linux-musl-gccgo build to build an arm64 binary).您需要目标架构的 C 编译器和工具链(例如CC=aarch64-linux-musl-gccgo build来构建 arm64 二进制文件)。 None of that is installed by default so for most people cgo simply won't work when cross-compiling;默认情况下都没有安装,因此对于大多数人来说,cgo 在交叉编译时根本无法工作; they need to take manual steps to set it up first.他们需要先手动进行设置。

cgo often isn't strictly required (like in the net and os/user packages), so disabling it by default seems the most user-friendly option. cgo 通常不是严格要求的(例如在 net 和 os/user 包中),因此默认禁用它似乎是最用户友好的选项。

But there are no such constraints on the native platform, and it's expected to work by default without any user setup;但是在原生平台上没有这样的限制,并且预计在没有任何用户设置的情况下默认工作; so why not enable it by default?那么为什么不默认启用它呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么CGO_ENABLED = 0的编译速度较慢? - Why is compiling with CGO_ENABLED=0 slower? 使用 go build CGO_ENABLED 交叉编译 - 警告:未找到 libudev.so.1 - Cross-compile using go build CGO_ENABLED - warning: libudev.so.1 not found CGO_Enabled=1 需要在 Alpine Docker 容器中使用 SQLite 构建 Go 二进制文件 - CGO_Enabled=1 required building Go binary using SQLite in Alpine Docker container CGO_ENABLED 如何影响动态与 static 链接? - How does CGO_ENABLED affect dynamic vs static linking? 从 windows 10 交叉编译到树莓派 CGO_ENABLED = 1 - Cross compilation from windows 10 to raspberry pi CGO_ENABLED = 1 CGO:使用 cgo_enabled = 1 从 mac/windows 交叉编译到 linux amd64 - CGO: Cross compile from mac/windows to linux amd64 with cgo_enabled = 1 二进制是用 'CGO_ENABLED=0' 编译的,go-sqlite3 需要 cgo 才能工作。 这是一个存根 - Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub 使用 cgo 时的多重定义 - multiple definition when using cgo Golang distroless Docker exec 失败:启用 CGO 时没有这样的文件或目录 - Golang distroless Docker exec failed: No such file or directory when CGO is enabled 麻烦在Mac OS X上使用go 1.3启用cgo交叉编译 - Troubles cross compiling with cgo enabled using go 1.3 on Mac OS X
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM