前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在 Golang 开发中使用 Makefile

在 Golang 开发中使用 Makefile

作者头像
用户1558438
发布2018-08-23 17:41:00
1.5K0
发布2018-08-23 17:41:00
举报
文章被收录于专栏:liuchengxuliuchengxu

使用 Golang 已经有一阵了,在 Golang 的开发过程中,我已经习惯于不断重复地手动执行 go buildgo test 这两个命令. 不过,现在我已经摆脱了这个习惯。如果只用到了不带参数的简单命令,直接这么操作可能并不可怕。但是在一些复杂的任务中,如果依旧是手动执行 go buildgo test ,就可能会成为一个让人头疼的事情。

我们可以通过其他方式解决这个问题。比如,可以用一个 bash 脚本来完成这些工作,或者一个更好的选择(至少对于我来说)是,写一个 makefile. make 这个工具生来就是为了做这些事情,在 makefile 中我们可以将所有常见的任务都放在一起。我并不是一个 makefile 专家,所以可能不太能够教大家如何写一个好的 makefile. 但是在本文,我将向大家展示我所使用的 Makefile,我的大部分项目都使用了这些 makefile 。让我们开始吧:

代码语言:javascript
复制
# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get
BINARY_NAME=mybinary
BINARY_UNIX=$(BINARY_NAME)_unix

all: test build
build:
        $(GOBUILD) -o $(BINARY_NAME) -v
test:
        $(GOTEST) -v ./...
clean:
        $(GOCLEAN)
        rm -f $(BINARY_NAME)
        rm -f $(BINARY_UNIX)
run:
        $(GOBUILD) -o $(BINARY_NAME) -v ./...
        ./$(BINARY_NAME)
deps:
        $(GOGET) github.com/markbates/goth
        $(GOGET) github.com/markbates/pop


# Cross compilation
build-linux:
        CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v
docker-build:
        docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v

我比较喜欢 DRY(Don't Repeat Yourself) 原则。所以,在 makefile 的开头定义常用的命令和变量,我们可以在后面方便地对定义的命令和变量进行引用。

代码语言:javascript
复制
# Basic go commands
GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get

# Binary names
BINARY_NAME=mybinary
BINARY_UNIX=$(BINARY_NAME)_unix

: 前面的叫做 makefile 的目标,比如 build:, build 就是一个目标。如果在执行 make 命令时指定目标,比如 make run,那么 make 就会构建该目标。如果没有提供任何参数,那么 make 默认会执行第一个目标。在我们的示例中,也就是叫 all 的目标会被构建。

代码语言:javascript
复制
$ make run ## call specific task
$ make     ## make tool calls "all" task

基本命令

makefile 最关键的部分就是构建。当 make 进行执行时,定义的变量会被展开,$(GOBUILD) 会被展开为 go build, make 实际就会执行 go build 命令。生成的二进制文件被命名为 -o $(BINARY_NAME). 另外,我发现使用 -v 参数切换到 verbose mode 非常有用。在 verbose mode 中,你可以看到当前正在构建的包。

代码语言:javascript
复制
build:
  $(GOBUILD) -o $(BINARY_NAME) -v ## expands to: "go build -o mybinary -v"

因为我们大部分人都很懒,所以就有了一个叫做 run 的目标。run 会构建二进制文件,并且在 build 完成后执行这个二进制文件。

代码语言:javascript
复制
run:
        $(GOBUILD) -o $(BINARY_NAME) -v ./...
        ./$(BINARY_NAME)

通常来讲,test 命令应该是 makefile 的一部分。我个人总是喜欢使用 verbose mode 来更好地 debug 和观测 test 的运行。

代码语言:javascript
复制
test:
  $(GOTEST) -v ./...

如果项目使用 CI(Continuous Integration)/CD(Continuous Delivery), 哪怕仅仅是为了一致性,将一系列依赖维护在包里面也是一个非常好的做法。这可以通过 deps 目标来完成,它会通过 go get 命令获取所有相关的依赖。

代码语言:javascript
复制
deps:
        $(GOGET) github.com/markbates/goth
        $(GOGET) github.com/markbates/pop

clean 来结束这一节的内容。rm -f 命令被用来移除名为 $(BINARY_XXX) 的二进制文件。

代码语言:javascript
复制
clean:
        $(GOCLEAN)
        rm -f $(BINARY_NAME)
        rm -f $(BINARY_UNIX)

交叉编译命令

如果项目开发是在一个系统上,而需要在另一个系统上运行,那么在 makefile 中包含一个交叉编译的命令是非常方便的。我通常在容器的 Linux 平台上运行二进制,所以 makefile 包含了 Linux 构建。

代码语言:javascript
复制
build-linux:
        CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v

如果你的代码使用了 C binding,你可能会遇到一些问题。CGO 的问题在于你需要一个与给定平台兼容的 gcc. 如果开发在 OSX/Windows 上完成,那么你需要有一个能够兼容 Linux 的 gcc. 至少对我来说,在 OSX 上使用配置 gcc 交叉编译 C 代码并不容易。如果需要 CGO, docker 镜像是创建 Linux 构建的最好方式。这种方式唯一的要求就是必须安装 Docker。

代码语言:javascript
复制
docker-build:
        docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v

本文的 Makefile 示例可在 这里 找到。


译者:原文使用的 Makefile 其实还可以更好,比如在原文下面的评论中指出,至少应该指明 .PHONY:, 另外 build 应该是 run 的前提条件。不过,我们可以学习其中可取的部分。

本文译自:Golang: Don’t afraid of makefiles

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.09.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本命令
  • 交叉编译命令
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档