
cgo 允许 go 程序调用 c 代码,反之亦然。虽然 go build 命令通常会自动化这个过程,但在某些特定场景下,例如使用自定义构建系统时,理解其底层编译步骤变得至关重要。cgo 的编译过程并非单一工具完成,而是 go 工具链与系统 c/c++ 编译器(如 gcc)协同工作的多阶段流程。
以下是 CGO 项目从 Go 源代码到最终可执行文件(或库)的关键步骤:
接下来,我们将详细解析每个步骤及其涉及的文件。
以下步骤基于 make 在 32 位 Linux 环境下编译 misc/cgo/life 项目的输出,并映射到现代 Go 工具链的概念。
这是 CGO 编译的第一步,由 cgo 工具完成。它负责解析 Go 源文件中的 CGO 指令,并生成 Go 和 C 语言之间的桥接代码。
命令示例:
cgo -- life.go
说明:cgo 命令会读取 life.go 文件,识别其中的 import "C" 块和 C 函数调用/Go 函数导出,然后生成一系列中间文件。
生成文件及其作用:
此阶段使用 Go 编译器编译 CGO 生成的 Go 源文件,以及部分由 CGO 生成但需要 Go 工具链处理的 C 源文件。
命令示例:
# 编译 cgo 生成的 Go 文件 go tool compile -o _go_.o _obj/life.cgo1.go _obj/_cgo_gotypes.go # 编译 cgo 生成的、由 Go 工具链处理的 C 文件 # 注意:在较旧的 Go 版本中是 8c,现代 Go tool compile 也能处理 C 文件 go tool compile -o _cgo_defun.o _obj/_cgo_defun.c
说明:
此阶段使用系统 C 编译器(如 GCC)编译所有纯 C/C++ 源文件,包括用户提供的 C 源文件和 CGO 生成的 C 源文件。
命令示例:
# 编译 cgo 生成的 C 文件 gcc -m32 -I . -g -fPIC -O2 -o _cgo_main.o -c _obj/_cgo_main.c gcc -m32 -I . -g -fPIC -O2 -o life.cgo2.o -c _obj/life.cgo2.c gcc -m32 -I . -g -fPIC -O2 -o _cgo_export.o -c _obj/_cgo_export.c # 编译用户提供的 C 文件 (例如本例中的 c-life.c) gcc -m32 -g -fPIC -O2 -o c-life.o -c c-life.c
说明:
将所有由 GCC 编译生成的 C 对象文件链接成一个中间目标文件或静态库。
命令示例:
gcc -m32 -g -fPIC -O2 -o _cgo1_.o _cgo_main.o c-life.o life.cgo2.o _cgo_export.o
说明:
cgo 工具再次被调用,这次是为了从 C 侧的中间链接结果中提取动态链接所需的信息,并生成一个 C 源文件。
命令示例:
cgo -dynimport _cgo1_.o >_obj/_cgo_import.c_ && mv -f _obj/_cgo_import.c_ _obj/_cgo_import.c
说明:
将上一步生成的 _cgo_import.c 文件编译成 Go 兼容的对象文件。
命令示例:
# 同样,在较旧的 Go 版本中是 8c,现代 Go tool compile 也能处理 C 文件 go tool compile -o _cgo_import.o _obj/_cgo_import.c
说明:
将所有 Go 对象文件和 C 对象文件(或其 Go 兼容形式)打包成一个 Go 归档文件(.a)。这个归档文件是 Go
以上就是CGO 项目手动编译流程详解的详细内容,更多请关注php中文网其它相关文章!
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号