在腾讯云CVM上使用Go语言编译软件

简介

Go 语言强大之处在于其能够快速编译为机器能识别的可执行文件,Go 语言有完整的开发体系,使其能够简单的获取包及编译。go语言编译的软件全平台通用,没必要再去给专门的平台开发相关的软件。

本文将教你从Git平台下载caddy所需的依赖环境,并让你熟悉Go语言的编译过程,然后,学会如何快速编译Windows和macOS的执行文件。

准备

教程开始前,你需要做一些准备

  • 一个Linux服务器,本文以 腾讯云 CVM Ubuntu 16.04为例,该服务器用户为非root权限
  • 安装好Go语言开发环境

第一步,获取安装包

在编译安装caddy之前,我们需要下载其源码包。这里我们使用go get命令获取caddy在Github的源码。如果执行顺利,你会在系统目录 $GOPATH/src/的子目录下查看到相关的源码。源码构建后将会在$GOPATH/bin 查看到已经构建的软件,同时,GO语言也会自动配置到系统$PATH中,这时你就可以在系统任意位置使用软件的命令了。

go get语法是go get package-import-path,其中package-import-path是go语言包的地址。大部分情况下这里的软件包来自github,还有可能是系统$GOPATH/src/配置的目录。

go get命令常和-u命令连用,它的意思的是使用go get命令获取该软件包所需要的依赖或更新系统已经存在的依赖。

这里我以编译安装Go语言编写的web服务器 Caddy为例,我们将使用go get命令获取在Github上面的Caddy软件包。

go get -u github.com/mholt/caddy/caddy

当然,执行命令需要一定时间,如果你发现输入命令后没反应,那就证明安装成功啦!

命令执行成功后,你应该会在$GOPATH/src/github.com/mholt/caddy目录下看到Caddy的源码,此外,由于Caddy里面有Go语言的执行文件,它在$GOPATH/bin目录下。所以你可以使用which命令查看。

which caddy

您将看到以下输出:

/home/sammy/work/bin/caddy

注意:go get命令主要是从master分支拉取安装包,在使用go get命令之前,请先查看目录下的README文件说明。

你可以使用git checkout命令获取其他分支,获取后在使用go get命令进行安装。

下面,我们更深入了解下如何编译相关环境。

第二步,编译可执行文件

go get命令已经为我们下载并安装好了caddy,但是我还是想构建新的执行文件怎么办呢?使用go build命令编译新的可执行文件。

虽然在这个系统上我已经安装了Caddy,但是我还是想创建编译环境,执行go build命令并指定相关路径。

go build github.com/mholt/caddy/caddy

和上面一样,没有输出则表明执行成功,可执行文件将在当前目录下创建。可执行文件名字为caddy

如果你在当前目录下,可以直接执行go build直接执行。

如果想要你的可执行文件放在其他位置,可以加-o命令,我们构建一个名字为caddy-server的文件吧,放在当前的目录下。

go build -o build/caddy-server github.com/mholt/caddy/caddy

此命令会创建新的可执行文件,如果./build命令不存在,则会自动创建。

接下来我们看看如何让安装可执行文件。

第三步,安装可执行文件

编译好的执行文件可能会在当前目录创建,安装可执行文件会将编译好的可执行文件储存在$GOPATH/bin中, go install 命令和go build接近,但是go install 只负责将文件存储到正确的位置。

要安装可执行文件,我们进到相关的目录,以caddy为例:

go install github.com/mholt/caddy/caddy

和之前一样,你应该看不到输出。同时,可执行文件创建的包与复制到新的包的名称相同,但这次,可执行文件是

复制到$GOPATH/bin中,如果$GOPATH/bin是环境变量的一部分,那么你就可任意在系统目录下使用这个命令。

which caddy

您将看到以下输出:

/home/sammy/work/bin/caddy

那么。你现在应该明白go getgo buildgo install 命令如何使用了吧,那么接下来,我们试试go语言的

新功能,为其他平台编译创建可执行文件。

第四步,为不同系统创建可执行文件

go build 命令允许您在本平台构建其他平台的可执文件,这意味着你可以在本平台测试发布你想要的应用程序,

无需考虑其他平台。

交叉编译需要你提前了解其他系统的类型和cpu架构,可以使用GOOS命令指定操作系统,使用GOARCH 命令指定

CPU架构。命令如下:

env GOOS=target-OS GOARCH=target-architecture go build package-import-path

env命令可以修改系统的环境变量,执行该命令后,将取消或重置当前变量。

下表列出了你可能会用到的GOOSGOARCH组合。

GOOS - 操作系统

GOARCH - CPU架构

android

arm

darwin

386

darwin

amd64

darwin

arm

darwin

arm64

dragonfly

amd64

freebsd

386

freebsd

amd64

freebsd

arm

linux

386

linux

amd64

linux

arm

linux

arm64

linux

ppc64

linux

ppc64le

linux

mips

linux

mipsle

linux

mips64

linux

mips64le

netbsd

386

netbsd

amd64

netbsd

arm

openbsd

386

openbsd

amd64

openbsd

arm

plan9

386

plan9

amd64

solaris

amd64

windows

386

windows

amd64

注意:安卓编译环境需要Android NDK编译环境以及超出本文教程范围的部分设置。

假如我们需要编译Windows64位的caddy,则可以使用下面的命令:

env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy

没有任何输出,则表明编译成功,由于我们设置了以Windows构建此文件,所以你将看到exe可执行文件,该文件

以.exe结尾。

您可以使用ls命令验证并查看该文件。

ls caddy.exe

您将看到caddy.exe输出中列出的文件:

caddy.exe

注意:你可以使用-o命令重命名可执行文件,但是为Windows构建可执行文件的时候,需要增加.exe结尾。

接下来,我们看看如何快速创建自动化脚本,方便操作。

第五步,创建脚本以自动交叉编译

给多平台创建可执行文件过程是在是太麻烦了,我们能不能写一个全自动执行脚本呢?

我是这样想的,这个脚本可以自动编译各个系统的软件包,并自动输出到当前目录。文件名为系统名称和架构,命

名方式package-OS-architecture

首先,切换到主目录并在文本编辑器中创建一个名字为go-executable-build.bash新文件:

cd ~
nano go-executable-build.bash

我们创建一个bash文件,第一行内容如下,主要是解释我们用哪个解释器来解析这个脚本

#!/usr/bin/env bash

为了更方便运行代码,我们将创建几个变量。创建变量$n,要求变量n不能为负数。创建变量$0为脚本的名称,

创建变量$1 为用户创建的参数。下面代码中,将吧$1储存在package中。

...
package=$1

为了获取到这个值,我们需要给用户展现出来。

...

if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi

这里if语句是检查$package变量的值。如果未设置,我们将使用echo打印正确的用法,然后使用终止脚本

exitexit将返回值作为参数,该参数为0的情况下,则执行成功,否则不成功。这里我们输出的为1

行不成功。

接下来,我们要从路径中提取包名称。导入路径由/字符分隔,所以,我们需要使用/作为分隔符分割数组。

package_split=(${package//\// })

软件包的名称应该为新的package_split数组最后一个元素,在bash中,你可以引入负数数组来整理新的变量,

新的变量将存储在package_name

...
package_name=${package_split[-1]}

接下来,我们需要确定其构建可执行文件的平台和CPU架构。我这里将以Windows 64位,Windows 32位和64位

的macOS构建可执行文件。 我将这些目标放在一个格式为OS / Platform的数组中,因此我可以使用我们用从路

径中提取包名称的相同方法将每个对分成GOOSGOARCH变量。 将平台添加到脚本:

...
platforms=("windows/amd64" "windows/386" "darwin/amd64")

接下来,我们将遍历平台数组,将每个平台条目拆分为GOOSGOARCH环境变量的值,并使用它们构建可执行文件。 我们可以通过以下for 循环来做到这一点:

...
for platform in "${platforms[@]}"
do
    ...
done

平台变量将在每次迭代中包含来自platforms 数组的条目。 我们需要将平台分成两个变量GOOSGOARCH。 将以下行添加到for循环:

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}

done

接下来,我们将通过将包名称与OS和体系结构相结合来生成可执行文件的名称。 当为Windows构建时,我们还需

要在文件名中添加.exe后缀。 将此代码添加到for循环:

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}

    output_name=$package_name'-'$GOOS'-'$GOARCH

    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi
done

设置变量后,我们使用go build来创建可执行文件。

...
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

done

最后,我们应该检查构建可执行文件是否存在错误。 我们可以检查go build命令的非零值的返回码。 变量$?

含上一个命令执行的返回码。 如果go build返回0以外的任何内容,则会出现问题,我们将要退出脚本。 将此

代码添加到for循环中。

...

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi

好了,这下我们就可以简单快速的编译go语言软件包了!

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}

platforms=("windows/amd64" "windows/386" "darwin/amd64")

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}
    output_name=$package_name'-'$GOOS'-'$GOARCH
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi  

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi
done

在我们使用该脚本之前,我们必须使用chmod命令给其权限可执行:

chmod +x go-executable-build.bash

最后,通过为Caddy构建可执行文件来测试脚本:

./go-executable-build.bash github.com/mholt/caddy/caddy

如果一切顺利,您应该在当前目录中有可执行文件。没有输出表明脚本执行成功。您可以验证使用ls 命令创建的

可执行文件:

ls caddy*

您应该看到所有三个版本:

caddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe

要更改目标平台,只需更改platforms脚本中的变量即可。

结论

在本文中,您已经学习了如何使用Go语言从Git获取相关安装包,以为不同平台构建和交叉编译可执行文件。 感谢您的阅读!你学会了嘛?购买一台服务器试试吧:https://cloud.tencent.com/product/cvm


参考文献:《How To Build Go Executables for Multiple Platforms on Ubuntu 16.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小俊博客

微软 Edge 浏览器爆高危漏洞,受控电脑可执行任意命令

10月12日,有安全研究人员发布了Windows Shell REC( CVE-2018-8495))漏洞概念验证代码,受影响软件为Windows 10内置的M...

1001
来自专栏乐沙弥的世界

基于CentOS 7 安装Percona XtraDB Cluster(PXC) 5.7

Percona XtraDB Cluster(简称PXC)是很多企业基于MySQL实现集群方案的不二选择。PXC它支持服务高可用,数据同步复制(并发复制),几乎...

5265
来自专栏Windows Community

New Windows 10 SDK - Multi-instance UWP apps

概述 前面一篇 About Windows 10 SDK Preview Build 17110 中,我们简单介绍了 Multi-instance UWP Ap...

3379
来自专栏GuZhenYin

ASP.NET Core使用静态文件、目录游览与MIME类型管理

前言 今天我们来了解了解ASP.NET Core中的静态文件的处理方式. 以前我们寄宿在IIS中的时候,很多静态文件的过滤 和相关的安全措施 都已经帮我们处理好...

34910
来自专栏Aloys的开发之路

Windows日志查看工具合集

希望可以和大家多多交流。 平时在Linux下查看日志,使用tail、grep、find等命令还比较方便,后来需要在Windows中处理一些问题,发现缺少类似的功...

6959
来自专栏IMWeb前端团队

meteor 简介

本文作者:IMWeb helondeng 原文出处:IMWeb社区 未经同意,禁止转载 What “Meteor gives you a radica...

2309
来自专栏韩东吉的Unity杂货铺

零基础入门 5: 自定义脚本内容和脚本ICON

Hello,这几天忙碌的不可开交,又有几天没更新了。这么久不见大家,今天来更新一发。

1222
来自专栏张善友的专栏

移植Windows自宿主WCF服务到Linux/Mono2.8

Windows服务是这些后台程序、后台服务的正规名词。Windows服务的运行可以在没有用户干预的情况下,在后台运行,没有任何界面。通过Windows服务管理器...

2138
来自专栏大内老A

ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存

.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中。对于...

28110
来自专栏跟着阿笨一起玩NET

通过SvcUtil.exe生成客户端代码和配置

WCF服务调用通过两种常用的方式:一种是借助代码生成工具SvcUtil.exe或者添加服务引用的方式,一种是通过ChannelFactory直接创建服务代理对象...

942

扫码关注云+社区

领取腾讯云代金券