golang构建工具Makefile使用详解

目录
  • 正文

正文

可能是因为编译太简单了,golang 并没有一个官方的构建工具(类似于 java 的 maven 和 gradle之类的),但是除了编译,我们可能还需要下载依赖,运行测试,甚至像 easyjson,protobuf,thrift 这样的工具下载和代码生成,如果没有构建工具,这些工作就会非常麻烦

为了解决这个问题,之前写过一个 everything.sh 的脚本,把所有的操作都封装在这个脚本里面,只需要执行类似于 sh everything.sh dependency 的命令就可以完成对应的工作,大大简化了构建过程,但是也有一个问题,shell 脚本本身的可读性并不是很好,而且对于各个操作之间的依赖不好描述

一次偶然的机会,在 github 上看到有人用 Makefile,就尝试了一下,发现真的非常合适,Makefile 本身就是用来描述依赖的,可读性非常好,而且与强大的 shell 结合在一起,基本可以实现任何想要的功能

下面是我在实际项目中使用的一个 Makefile,支持的功能包括

make build: 编译

make vendor: 下载依赖

make api: 生成协议代码

make json: easyjson 代码生成

make test: 运行单元测试

make benchmark: 运行性能测试

make stat: 代码复杂度统计,代码行数统计

make clean: 清理 build 目录

make deep_clean: 清理所有代码以外的其他文件

make third: 下载所有依赖的第三方工具

make protoc: 下载 protobuf 工具

make glide: 下载 glide 依赖管理工具

make golang: 下载 golang 环境

make cloc: 下载 cloc 统计工具

make gocyclo: 下载 gocyclo 圈复杂度计算工具

make easyjson: 下载 easyjson 工具

export PATH:=${PATH}:${GOPATH}/bin:$(shell pwd)/third/go/bin:$(shell pwd)/third/protobuf/bin:$(shell pwd)/third/cloc-1.76
.PHONY: all
all: third vendor api json build test stat
build: cmd/rta_server/*.go internal/*/*.go scripts/version.sh Makefile vendor api json
    @echo "编译"
    @rm -rf build/ && mkdir -p build/bin/ && \
    go build -ldflags "-X 'main.AppVersion=`sh scripts/version.sh`'" cmd/rta_server/main.go && \
    mv main build/bin/rta_server && \
    cp -r configs build/configs/
vendor: glide.lock glide.yaml
    @echo "下载 golang 依赖"
    glide install
api: vendor
    @echo "生成协议文件"
    @rm -rf api && mkdir api && \
    cd vendor/gitlab.mobvista.com/vta/rta_proto.git/ && \
    protoc --go_out=plugins=grpc:. *.proto && \
    cd - && \
    cp vendor/gitlab.mobvista.com/vta/rta_proto.git/* api/
json: internal/rcommon/rta_common_easyjson.go
internal/rcommon/rta_common_easyjson.go: internal/rcommon/rta_common.go Makefile
    easyjson internal/rcommon/rta_common.go
.PHONY: test
test: vendor api json
    @echo "运行单元测试"
    go test -cover internal/rranker/*.go
    go test -cover internal/rserver/*.go
    go test -cover internal/rworker/*.go
    go test -cover internal/rloader/*.go
    go test -cover internal/rrecall/*.go
    go test -cover internal/rmaster/*.go
    go test -cover internal/rsender/*.go
benchmark: benchmarkloader benchmarkall
.PHONY: benchmarkloader
benchmarkloader: vendor api json
    @echo "运行 loader 性能测试"
    go test -timeout 2h -bench BenchmarkS3Loader_Load -benchmem -cpuprofile cpu.out -memprofile mem.out -run=^? internal/rloader/*
    go tool pprof -svg ./rloader.test cpu.out > cpu.benchmarkloader.svg
    go tool pprof -svg ./rloader.test mem.out > mem.benchmarkloader.svg
.PHONY: benchmarkserver
benchmarkserver: vendor api json
    @echo "运行 server 性能测试"
    go test -timeout 2h -bench BenchmarkServer -benchmem -cpuprofile cpu.out -memprofile mem.out -run=^? internal/rserver/*
    go tool pprof -svg ./rserver.test cpu.out > cpu.benchmarkserver.svg
    go tool pprof -svg ./rserver.test mem.out > mem.benchmarkserver.svg
.PHONY: benchmarkall
benchmarkall: vendor api json
    @echo "运行 server 性能测试"
    go test -timeout 2h -bench BenchmarkAll -benchmem -cpuprofile cpu.out -memprofile mem.out -run=^? internal/rserver/*
    go tool pprof -svg ./rserver.test cpu.out > cpu.benchmarkall.svg
    go tool pprof -svg ./rserver.test mem.out > mem.benchmarkall.svg
.PHONY: benchmarkcache
benchmarkcache: vendor api json
    @echo "测试 redis 集群性能"
    go test -timeout 5m -bench BenchmarkRtaCacheBatch -benchmem -cpuprofile cpu.out -memprofile mem.out -run=^? internal/rserver/*
.PHONY: stat
stat: cloc gocyclo
    @echo "代码行数统计"
    @ls internal/*/* scripts/* configs/* Makefile | xargs cloc --by-file
    @echo "圈复杂度统计"
    @ls internal/*/* | grep -v _test | xargs gocyclo
    @ls internal/*/* | grep -v _test | xargs gocyclo | awk '{sum+=?1}END{printf("总圈复杂度: %s", sum)}'
.PHONY: clean
clean:
    rm -rf build
.PHONY: deep_clean
deep_clean:
    rm -rf vendor api build third
third: protoc glide golang cloc gocyclo easyjson
.PHONY: protoc
protoc: golang
    @hash protoc 2>/dev/null || { \
        echo "安装 protobuf 代码生成工具 protoc" && \
        mkdir -p third && cd third && \
        wget https://github.com/google/protobuf/releases/download/v3.2.0/protobuf-cpp-3.2.0.tar.gz && \
        tar -xzvf protobuf-cpp-3.2.0.tar.gz && \
        cd protobuf-3.2.0 && \
        ./configure --prefix=`pwd`/../protobuf && \
        make -j8 && \
        make install && \
        cd ../.. && \
        protoc --version; \
    }
    @hash protoc-gen-go 2>/dev/null || { \
        echo "安装 protobuf golang 插件 protoc-gen-go" && \
        go get -u github.com/golang/protobuf/{proto,protoc-gen-go}; \
    }
.PHONY: glide
glide: golang
    @mkdir -p ?GOPATH/bin
    @hash glide 2>/dev/null || { \
        echo "安装依赖管理工具 glide" && \
        curl https://glide.sh/get | sh; \
    }
.PHONY: golang
golang:
    @hash go 2>/dev/null || { \
        echo "安装 golang 环境 go1.10" && \
        mkdir -p third && cd third && \
        wget https://dl.google.com/go/go1.10.linux-amd64.tar.gz && \
        tar -xzvf go1.10.linux-amd64.tar.gz && \
        cd .. && \
        go version; \
    }
.PHONY: cloc
cloc:
    @hash cloc 2>/dev/null || { \
        echo "安装代码统计工具 cloc" && \
        mkdir -p third && cd third && \
        wget https://github.com/AlDanial/cloc/archive/v1.76.zip && \
        unzip v1.76.zip; \
    }
.PHONY: gocyclo
gocyclo: golang
    @hash gocyclo 2>/dev/null || { \
        echo "安装代码圈复杂度统计工具 gocyclo" && \
        go get -u github.com/fzipp/gocyclo; \
    }
.PHONY: easyjson
easyjson: golang
    @hash easyjson 2>/dev/null || { \
        echo "安装 json 编译工具 easyjson" && \
        go get -u github.com/mailru/easyjson/...; \
    }

以上就是golang构建工具Makefile使用详解的详细内容,更多关于golang构建工具Makefile的资料请关注我们其它相关文章!

(0)

相关推荐

  • golang构建HTTP服务的实现步骤

    目录 HTTP Handler ServeMux Server 创建HTTP服务 http注册路由 开启监听 处理请求 参考:    一个go最简单的Http服务器程序 package main import ( "fmt" "net/http" ) func IndexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hello world") } func m

  • GoLand编译带有构建标签的程序思路详解

    简单构建一个项目,如下是mian.go文件 package main // 条件编译-构建标签-如何使用IDE编译和识别 func main() { RequestByRpc() } 模拟带有一个http tags的文件 // +build http package main import "fmt" func RequestByHttp() { fmt.Println("using http method") } 模拟带有一个rpc tags的文件 // +bui

  • 以alpine作为基础镜像构建Golang可执行程序操作

    Alpine介绍 Alpine 操作系统是一个面向安全的轻型 Linux 发行版.它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐.在保持瘦身的同时,Alpine 还提供了自己的包管理工具 apk,可以通过 https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种

  • Makefile构建Golang项目示例详解

    目录 背景 创建项目并运行 添加 Makefile 文件 Makefile 概念 变量 使用 Makefile 自动化任务 背景 构建和测试大型项目时都会很耗时,且容易出错.开发者在开发过程中需要不断执行go build.go run .go test等相关命令.还可能需要多个命令来构建不同平台的二进制文件.在正式部署时候,我们可能还需要安装一些依赖项,或者在发布之前进行代码覆盖率测试等相关前置工作. 整个过程需要很多步骤,但我们有一种简单的方法可以解决这些复杂琐碎的步骤.使用 Make 进行自

  • 如何使用Goland IDE go mod 方式构建项目

    不管学习什么编程语言一开始都会经历的四步 开发工具安装 IDE安装 设置 依赖/包 国内镜像 项目构建工具,管理依赖/包 一.Golang 开发工具安装 https://golang.org/ 官网(需要各自手段) https://github.com/golang/go github地址 http://docscn.studygolang.com/ golang中文网 二.Goland IDE安装 https://www.jetbrains.com/zh-cn/go/ 三.设置 依赖/包 国内

  • golang构建工具Makefile使用详解

    目录 正文 正文 可能是因为编译太简单了,golang 并没有一个官方的构建工具(类似于 java 的 maven 和 gradle之类的),但是除了编译,我们可能还需要下载依赖,运行测试,甚至像 easyjson,protobuf,thrift 这样的工具下载和代码生成,如果没有构建工具,这些工作就会非常麻烦 为了解决这个问题,之前写过一个 everything.sh 的脚本,把所有的操作都封装在这个脚本里面,只需要执行类似于 sh everything.sh dependency 的命令就可

  • Golang 官方依赖注入工具wire示例详解

    目录 依赖注入是什么 开源选型 wire providers injectors 类型区分 总结 依赖注入是什么 Dependency Injection is the idea that your components (usually structs in go) should receive their dependencies when being created. 在 Golang 中,构造一个结构体常见的有两种方式: 在结构体初始化过程中,构建它的依赖: 将依赖作为构造器入参,传入进

  • Go依赖注入DI工具wire使用详解(golang常用库包)

    目录 什么是依赖注入 第一次编写mysql操作类: 第二次编写mysql操作类: 第三次编写mysql操作类: 何时使用依赖注入 wire 概念说明 provider 和 injector provider injector wire 使用 快速开始 小结 绑定接口 Provider Set 参考 google 出品的依赖注入库 wire:https://github.com/google/wire 什么是依赖注入 依赖注入 ,英文全名是 dependency injection,简写为 DI.

  • 基于make命令与makefile文件详解

    一.多个源文件带来的问题 在编写c/c++测试程序时,我们习惯每次修改一处代码,然后就马上编译运行来查看运行的结果.这种编译方式对于小程序来说是没有多大问题的,可对于大型程序来说,由于包含了大量的源文件,如果每次改动一个地方都需要编译所有的源文件,这个简单的直接编译所有源文件方式对程序员来说简直是噩耗. 我们看一个例子: // main.c #include "a.h" // 2.c #include "a.h" #include "b.h" /

  • Go源码字符串规范检查lint工具strchecker使用详解

    目录 1.背景 2.strchecker介绍 3.结论 1.背景 在大型项目开发过程中,经常会遇到打印大量日志,输出信息和在源码中写注释的情况.对于软件开发来说,我们一般都是打印输出英文的日志(主要考虑软件在各种环境下的兼容性,如果打印中文日志可能会出现乱码,另外英文日志更容易搜索,更容易后续做国际化),但是对于我们中国人来说,很容易就把中文全角的中文标点符号一不注意就写到日志中了.不过源码中的注释因为是完全面向开发者的,不会面向客户,所以如果研发团队全是中国人,那么代码注释用中文就更有效率.

  • Golang 单元测试和基准测试实例详解

    目录 前言 Go 单元测试 单元测试覆盖率 基准测试 前言 多人协作的项目里,要保证代码的质量,自然离不开单元测试.开发完一个功能后肯定要对所写的代码进行测试,测试没有问题之后再合并到代码库供他人使用.如果强行合并到代码库可能会影响其他人开发,被上线的话肯定也会导致线上 Bug ,影响用户使用. 所以,单元测试也是一个很重要的事情.单元测试是指在开发中,对一个函数或模块的测试.其强调的是对单元进行测试. Go 单元测试 Go 语言提供了单元测试的框架,只要遵循其规则即可: 测试文件命名: 单元测

  • 深入Golang中的sync.Pool详解

    我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用的机制,也就是sync.Pool对象池. sync.Pool是可伸缩的,并发安全的.其大小仅受限于内存的大小,可以被看作是一个存放可重用对象的值的容器. 设计的目的是存放已经分配的但是暂时不用的对象,在需要用到的时候直接从pool中取. 任何存放区其中的值可以在任何时候被删除而不通知,在高负载下可以动态的扩容,在不活跃时对象池会收缩. sync.Pool首先

  • Golang之sync.Pool使用详解

    前言 我们通常用 Golang 来开发并构建高并发场景下的服务,但是由于 Golang 内建的GC机制多少会影响服务的性能,因此,为了减少频繁GC,Golang提供了对象重用的机制,也就是使用sync.Pool构建对象池. sync.Pool介绍 首先sync.Pool是可伸缩的临时对象池,也是并发安全的.其可伸缩的大小会受限于内存的大小,可以理解为是一个存放可重用对象的容器.sync.Pool设计的目的就是用于存放已经分配的但是暂时又不用的对象,而且在需要用到的时候,可以直接从该pool中取.

  • 利用JavaScript构建树形图的方法详解

    目录 什么是树形图 浏览JS树形图 创建一个基本的JS树形图 1. 创建一个HTML页面 2. 参考JavaScript文件 3.设置数据 4. 编写一些JS树形图代码 自定义JS树形图 A. 改变颜色 B. 应用线性色标 C. 格式化标签和工具提示 D. 按升序排列图块 树形图可视化广泛用于分层数据分析.如果你没有经验还想创建一个,那将会有些复杂.下面是一个详细教程,教你如何使用JavaScript创建交互式树形图. 宇宙中只有我们吗?我们每个人都曾在某个时候问过自己这个问题.当我们在考虑地球

  • golang字符串本质与原理详解

    目录 一.字符串的本质 1.字符串的定义 2.字符串的长度 3.字符与符文 二.字符串的原理 1.字符串的解析 2.字符串的拼接 3.字符串的转换 总结 一.字符串的本质 1.字符串的定义 golang中的字符(character)串指的是所有8比特位字节字符串的集合,通常(非必须)是UTF-8 编码的文本. 字符串可以为空,但不能是nil. 字符串在编译时即确定了长度,值是不可变的. // go/src/builtin/builtin.go // string is the set of al

随机推荐