当前位置: 首页 > 科技观察

使用Golang的交叉编译

时间:2023-03-13 12:36:18 科技观察

走出我的舒适区,我了解了Go的交叉编译能力。在Linux上测试软件时,我使用的是各种架构的服务器,如Intel、AMD、Arm等。当我分配到满足我测试需求的Linux机器后,我仍然需要执行一些步骤:下载并安装先决条件验证构建服务器上是否有新的测试包获取并设置依赖包所需的yum仓库下载并安装新的测试包(根据步骤2)获取并设置所需的SSL证书设置测试环境,获取所需的Git存储库,更改配置,重新启动守护程序等。做任何其他需要做的事情用脚本自动化这些步骤如此例行公事,使其自动化并将脚本保存到中央位置(例如文件服务器)是有意义的需要的时候可以在哪里下载。为此,我编写了一个100-120行的Bashshell脚本,它为我完成了所有配置(包括错误检查)。这个脚本通过以下方式简化了我的工作流程:配置一个新的Linux系统(支持测试的架构)登录系统并从中央位置下载一个自动化的shell脚本运行它来配置系统开始测试学习Go我想学习Go是时候了,将我钟爱的shell脚本转换成Go程序似乎是一个让我入门的好项目。它的语法看起来很简单,在尝试了一些测试程序之后,我开始着手提高自己的知识并熟悉Go标准库。我花了一周时间在笔记本电脑上编写Go程序。我经常在我的x86服务器上测试程序,清除错误并使程序健壮,一切正常。在我完全转换为Go程序之前,我继续依赖自己的shell脚本。然后我将二进制文件推送到中央文件服务器,这样每次我配置新服务器时,我所要做的就是获取二进制文件,打开可执行标志,然后运行二进制文件。我对早期的结果很满意:$wgethttp://file.example.com//bins/prepnode$chmod+x./prepnode$./prepnode然后,第二周出现了问题,我从资源池中分配了一个新服务器,像往常一样,我下载了二进制文件,设置了可执行标志,然后运行了二进制文件。但是这次出错了,奇怪的错误:$./prepnodebash:./prepnode:cannotexecutebinaryfile:Execformaterror$一开始我以为可能是可执行标志没有设置成功。但是,它按预期设置:$ls-lprepnode-rwxr-xr-x.1rootroot2640529Dec1605:43prepnode发生了什么?我没有对源代码做任何改动,编译也没有出现任何错误或警告,而且上次运行时效果很好,所以我仔细查看了错误信息格式错误。我检查了二进制文件的格式,一切看起来都正常:$fileprepnodeprepnode:ELF64-bitLSBexecutable,x86-64,version1(SYSV),staticallylinked,notstripped我快速运行以下命令来识别配置的测试服务器的架构和平台二进制文件正在尝试继续运行。它是Arm64架构,但我编译的二进制文件(在我的x86笔记本电脑上)生成x86-64格式的二进制文件:$uname-maarch64脚本编写第一课在此之前,我从未考虑过这种情况(尽管我知道)。我主要使用脚本语言(通常是Python)和shell脚本。Bashshell和Python解释器在任何架构的大多数Linux服务器上都可用。总而言之,之前一切都很顺利。但是,现在我正在处理Go,一种生成可执行二进制文件的编译语言。编译后的二进制文件由特定于体系结构的脚本或汇编指令组成,这就是我收到格式错误的原因。由于Arm64CPU(运行二进制文件的地方)无法解释二进制文件的x86-64指令,因此它会抛出错误。以前,shell和Python解释器为我处理低级脚本或特定于体系结构的指令。Go的交叉编译我查看了Golang的文档,发现要生成Arm64二进制文件,我只需要在运行gobuild命令编译Go程序之前设置两个环境变量。GOOS指的是操作系统,比如Linux、Windows、BSD等,而GOARCH指的是程序建立在哪个架构上。$envGOOS=linuxGOARCH=arm64gobuild-oprepnode_arm64构建程序后,我重新运行文件命令,这次它显示的是ARMAArch64而不是之前显示的x86。所以我可以在我的笔记本电脑上为不同的架构构建二进制文件。$fileprepnode_arm64prepnode_arm64:ELF64-bitLSBexecutable,ARMaarch64,version1(SYSV),staticallylinked,notstripped我将二进制文件从笔记本电脑复制到ARM服务器。现在运行二进制文件(打开可执行标志)不会产生任何错误:$./prepnode_arm64-hUsageof./prepnode_arm64:-cCleanexistinginstallation-nDonotstarttestrun(defaulttrue)-sUsestageenvironment,defaultisqa-vEnableverboseoutput其他架构呢?x86和Arm是我测试的软件支持的5种架构中的两种,我担心Go可能不支持其他,但事实并非如此。你可以查看Go支持的架构:$gotooldistlistGo支持多种平台和操作系统,包括:AIXAnd??roidDarwinDragonflyFreeBSDIllumosJavaScriptLinuxNetBSDOpenBSDPlan9SolarisWindows要查找其支持的特定Linux架构,请运行:$gotooldistlist|greplinux如下如上输出所示,Go支持我使用的所有架构。虽然x86_64不在列表中,但AMD64与x86-64兼容,因此您可以生成AMD64二进制文件,它将在x86架构上运行良好:$gotooldistlist|greplinuxlinux/386linux/amd64linux/armlinux/arm64linux/mipslinux/mips64linux/mips64lelinux/mipslelinux/ppc64linux/ppc64lelinux/riscv64linux/s390x处理所有架构为我测试的所有架构生成二进制文件,就像从我的x86笔记本电脑上编写一个小的shell脚本一样简单:#!/usr/bin/basharchs=(amd64arm64ppc64leppc64s390x)forarchin${archs[@]}doenvGOOS=linuxGOARCH=${arch}gobuild-oprepnode_${arch}done$fileprepnode_*prepnode_amd64:ELF64-bitLSB可执行,x86-64,版本1(SYSV),静态链接,GoBuildID=y03MzCXoZERH-0EwAAYI/p909FDnk7xEUo2LdHIYo/V2LABa6H5p_q8MZiR2WYkA5CzJiF,notstrippedprepnode_arm64:ELF64-bitLSBexecutable,ARMaarch64,version1(SYSV),staticallylinked,GoBuildID=q-H-CCtLv__jVOcdcOpA/CywRwDz9LN2Wk_fWeJHt/K4-3P5tU2mzlWJa0noGN/SEev9TJFyvHdKZnPaZgb,notstrippedprepnode_ppc64:ELF64-bitMSBexecutable,64位PowerPCorcisco7500,version1(SYSV),静态链接,GoBuildID=DMWfc1QwOGIq2hxEzL_u/UE-9CIvkIMeNC_ocW4ry/r-7NcMATXatoXJQz3yUO/xzfiDIBuUxbuiyaw5Goq,notstrippedprepnode_ppc64le:ELF64-bitLSBexecutable,64-bitPowerPCorcisco7500,version1(SYSV),staticallylinked,GoBuildID=C6qCjxwO9s63FJKDrv3f/xCJa4E6LPVpEZqmbF6B4/Mu6T_OR-dx-vLavn1Gyq/AWR1pK1cLz9YzLSFt5eU,notstrippedprepnode_s390x:ELF64-bitMSBexecutable,IBMS/390,version1(SYSV),staticallylinked,GoBuildID=faC_HDe1_iVq2XhpPD3d/7TIv0rulE4RZybgJVmPz/o_SZW_0iS0EkJJZHANxx/zuZgo79Je7zAs3v6Lxuz,notstripped现在,每当我配置一台新机器时,我都会运行以下wget命令来下载特定于体系结构的二进制文件,并打开可执行标志http/file,然后运行:$wget.domain.com//bins/prepnode_$chmod+x./prepnode_$./prepnode_为什么?您可能想知道为什么我不坚持使用shell脚本或将程序移植到Python而不是编译语言来避免这些麻烦是值得的。那样的话,我就不会理解Go的交叉编译功能,也不会理解程序在CPU上执行时的底层工作原理。在计算中,总是需要权衡取舍,但永远不要让它们阻碍你的学习。