当前位置:网站首页>Go新项目-编译项目的细节(4)

Go新项目-编译项目的细节(4)

2022-08-03 02:09:00 编程圈小学生

在这里插入图片描述

Go 语言是一门需要编译才能运行的编程语言,也就是说代码在运行之前需要通过编译器生成二进制机器码,包含二进制机器码的文件才能在目标机器上运行,下边就展开讲解下Go语言的编译的细节。

go build 编译时的附加参数

附加参数备 注
-v编译时显示包名
-p n开启并发编译,默认情况下该值为 CPU 逻辑核数
-a强制重新构建
-n打印编译时会用到的所有命令,但不真正执行
-x打印编译时会用到的所有命令
-race开启竞态检测

编译器:gc 和 gccgo

gc,全称Golang Compiler

go有两种不同的编译器,但是默认采用gc,这也会后边提到项目中运用了gccgo的编译错误的问题;

  • Go 语言始终由 spec 说明书而不是实现定义。 Go 团队编写了两种实现该规范的不同编译器:gc 和 gccgo。具有两种不同的实现方式有助于确保规范的完整性和正确性:当编译器不同意时,我们会修复规范,并相应地更改一个或两个编译器。 Gc 是原始编译器,默认情况下 go 工具使用它。 Gccgo 是一种不同的实现方式,具有不同的侧重点,在这篇文章中,我们将对其进行更深入的研究。
  • Gccgo 作为 GCC(GNU 编译器集合)的一部分进行分发。 GCC 支持不同语言的几种前端。 gccgo 是连接到 GCC 后端的 Go 前端。 Go 前端与 GCC 项目是分开的,旨在能够连接到其他编译器后端,但目前仅支持 GCC。
  • 与 gc 相比,gccgo 编译代码的速度较慢,但支持更强大的优化,因此 gccgo 构建的受 CPU 约束的程序通常运行速度更快。多年来,在 GCC 中实现的所有优化都是可用的,包括内联,循环优化,向量化,指令调度等。尽管它并不总是能产生更好的代码,但在某些情况下,使用 gccgo 编译的程序可以运行 30%更快。
  • gc 编译器仅支持最受欢迎的处理器:x86(32 位和 64 位)和 ARM。但是,Gccgo 支持 GCC 支持的所有处理器。并非所有这些处理器都经过了 gccgo 的全面测试,但是许多处理器都进行了测试,包括 x86(32 位和 64 位),SPARC,MIPS,PowerPC 甚至 Alpha。 Gccgo 还已经在 gc 编译器不支持的操作系统(尤其是 Solaris)上进行了测试。
  • Gccgo 提供了标准的,完整的 Go 库。 Go 运行时的许多核心功能在 gccgo 和 gc 中都相同,包括 goroutine 调度程序,通道,内存分配器和垃圾收集器。 Gccgo 和 gc 编译器一样,支持拆分 goroutine 堆栈,但目前仅在 x86(32 位或 64 位)上,并且仅在使用 gold 链接器时(在其他处理器上,每个 goroutine 将具有较大的堆栈,以及一系列深层次的函数调用可能会运行到堆栈末尾并使程序崩溃)。

对比

  • gc是Go语言原生的编译器,不需要安装,使用方便;而gccgo需要自已安装。
  • gc编译速度比gccgo快。
  • gc只支持一些主流的处理器,如x86、amd、ARM等。 而gccgo支持基本上所有的处理器。
  • gccgo编译出的程序运行效率更高,因为gccgo比GC代码优化能力更强大。
  • gccgo编译的代码可以更好的用于GDB。
  • gccgo并不能支持编译所有的Golang版本,这个在使用时要注意。

编译的过程

Go 语言编译器的源代码在 src/cmd/compile 目录中,目录下的文件共同组成了 Go 语言的编译器,学过编译原理的人可能听说过编译器的前端和后端,
编译器的前端一般承担着词法分析、语法分析、类型检查和中间代码生成几部分工作,而编译器后端主要负责目标代码的生成和优化,也就是将中间代码翻译成目标机器能够运行的二进制机器码。

跨平台编译

Go 语言源代码的 src/cmd/compile/internal 目录中包含了很多机器码生成相关的包,不同类型的 CPU 分别使用了不同的包生成机器码,其中包括 amd64、arm、arm64、mips、mips64、ppc64、s390x、x86 和 wasm

下边列举一些常用的机器码生成的场景

windows编译linux

SET CGO_ENABLED=0  // 禁用CGO
SET GOOS=linux     // 目标平台是linux
SET GOARCH=amd64   // 目标处理器架构是amd64

SET CGO_ENABLED=0  GOOS=linux  GOARCH=amd64

go build custom.go                //编译原名称
go build -o customLinux custom.go //编译自定义名称

GOOS=linux GOARCH=amd64 go build 

同理linux下也可以用windows的exe

GOOS=windows GOARCH=amd64 go build

Mac 下编译 Linux 和 Windows平台 64位 可执行程序:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Linux 下编译 Mac 和 Windows 平台64位可执行程序:

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Windows下编译Mac平台64位可执行程序:

SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build

错误记录

上边提到go的两种编译方式:gc和gccgo,在项目过程有用到了go-sqlite3组件,并且还必须依赖cgo去编译生成;

当禁止cgo编译器时,出现这种错误:

Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work.

开启了gcc,直接go build ,还是报错:

/usr/local/go1.18/pkg/tool/linux_amd64/link: running gcc failed: exit status 1

推荐的解决方案
讨论细节:https://github.com/golang/go/issues/44703
源头:https://github.com/golang/go/issues/43996

rm -rf ~/.cache/go-build : this contained a few build artifacts
rm -rf ${MyProject}/{bin,pkg} : for the same reason

export CXXFLAGS="-stdlib=libstdc++" CC=/usr/bin/gcc CXX=/usr/bin/g++

当代码开启了cgo,以上解决不了的,再使用如下代码执行,适用于:Linux

1.Liunx需要安装gcc

yum install gcc
yum install gcc-c++ libstdc++-devel

yum install glibc-static.x86_64 -y

2.再进行编译操作(临时方案)

大概率是Linux版本过低

gcflags的参数

  • -N: 禁止编译器优化
  • -l: 关闭内联 (inline)
  • -c int: 编译过程中的并发数,默认是1
# 为当前模块下的所有包关闭编译优化和内联
go build -v -gcflags="all=-N -l"
or
go build -v -gcflags="all=-N -l" -o customeLinux custom.go

go build -gcflags all="-N -l" *.go

单独介绍windows中gccgo编译问题

Windows下安装gcc

MinGW 的全称是:Minimalist GNU on Windows 。是将经典的开源 C语言 编译器 GCC 移植到了 Windows 平台下,并且包含了 Win32API ,因此可以将源代码编译为可在 Windows 中运行的可执行程序。

没有gcc的报错:

cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in %PATH%
  • 官网下载地址:https://www.mingw-w64.org/downloads/,直接安装免安装版,本机配置环境变量
    • i686纯32位版供32位win系统使用
      • x86_64是64位系统用的版本
      • seh结尾是纯64位编译
      • sjlj结尾是32 64两种编译,需加-m32或-m64参数
      • posix通常用于跨平台,比win32兼容性好一些
  • 在桌面选择“计算机” --》右击选择“属性” --》进入“控制面板\所有控制面板项\系统”选项 --》选择左边的“高级系统设置” --》弹出的系统属性,选择“环境变量” --》在系统环境变量里,找到变量名为“Path” --》双击“Path”变量 --》在结尾追加“;D:\mingw64\bin”
  • Windows版:https://github.com/niXman/mingw-builds-binaries/releases
  • 验证调出cmd窗口:gcc -v
原网站

版权声明
本文为[编程圈小学生]所创,转载请带上原文链接,感谢
https://blog.csdn.net/hmx224_2014/article/details/126080129