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/...; \
    }

转载请注明出处

本文链接:http://www.hatlonely.com/2018/04/11/golang-构建工具之-Makefile/

原文地址:https://www.cnblogs.com/hatlonely/p/8800661.html

时间: 2024-10-30 15:23:24

golang 构建工具之 Makefile的相关文章

Gradle与Makefile构建工具的对比

随着Android Studio的普及,越来越多的Android开发者也要开始了解和学习Gradle这款强大的代码构建工具了.我们在学习和了解一项新事物的时候,最快速的方法往往是与已知的事物进行比较,对于熟悉Makefile编译机制的Linux程序员而言,认识和掌握Gradle最好的方法莫过于比较它们之间的区别了,本文不准备详细介绍Gradle的方方面面,而是希望通过与Makefile的对比帮助Gradle初学者更快速地理解Gradle的基础和原理. Makefile是一种管理和编译 Linux

构建工具的发展及Android Gradle快速上手

前话: 最近谷歌宣布官方不再维护Eclipse ADT了,之后将更加专注于Android Studio的功能和性能上的改进,早在2013年的Google IO大会上首次推出了Android Studio,当时刚出来的时候我就好奇的去下载体验了一下,想看一下新开发工具的优势在哪里,据官方介绍,最吸引我的一点就是使用Studio使用了Gradle编译系统,可以支持很灵活的定制需求,而我当时正在研究当成库使用的APK(就是现在的aar文件,不过当时还没有出身),刚好遇到了ADT编译系统的限制,所以当时

Blade和其他构建工具有什么不同

大部分人都至少接触过不止一种构建工具,比如make,autotools.而我们开发了Blade,为什么那么多现成的工具不用,而又再造了一个轮子,相对于传统的make等工具,Blade的好处在又哪里呢?你的项目是否适合用Blade来构建, 以前的文档都是冷冰的介绍,今天本文将从作者和开发人员以及项目代码维护者的角度回答这些问题. Blade总的来说要解决这些问题: 真正环境下的C++软件的开发,往往有数十人甚至数百个开发人员,源代码有成千上万个文件,百万甚至千万行.如何高效而安全地构建这些代码?

Qt构建工具QBS之零 —— QBS 概览

本系列文章起因 自己非常喜欢 QT 这个框架, 使用 QT 这几年, IDE 一直是使用的 QT 自带的 Qt Creator, 这个 IDE 本身比较轻巧, 同事相关的语法提示之类的也算够用, 但是 qmake 有的时候就显得不那么只能了, 有时非得手动qmake一下才行, 有时需要清除再构建, 有时这两者合一起也不一定解决问题. 需要删除构建目录才行. 很多新手学习的时候, 经常会再论坛或群里问, 为什么我的代码和书上的一模一样, 怎么构建时就出错呢? 这种情况, 大多是 qmake “抽风

Google软件构建工具Bazel

转载Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用方法介绍系列 Bazel是什么? Bazel是一个构建工具,即一个可以运行编译和测试来组装软件的工具,跟Make.Ant.Gradle.Buck.Pants和Maven一样. Bazel有什么特殊之处 Bazel是设计用来配合Google的软件开发模式.有以下几个特点: 多语言支持:Bazel支持J

SCons构建工具使用

scons是一个Python写的自动化构建工具,和GNU make相比优点明显:    1. 移植性:python能运行的地方,就能运行scons    2. 扩展性:理论上scons只是提供了python的类,scons使用者可以在这个类的基础上做所有python能做的事情.比如想把一个已经使用了Makefile大型工程切换到scons,就可以保留原来的Makefile,并用python解析Makefile中的编译选项.源/目标文件等,作为参数传递给scons,完成编译.    3. 智能:S

VS构建工具介绍

VS构建工具介绍 我们都知道C/C++源代码要生成可执行的.exe程序,需要经过编译.链接的过程.你在VS工具中只需要选择菜单Build或按一下F5可以编译.链接.运行了,其实IDE帮我隐藏了好多的具体细节. 我先假设VS2010安装在以下目录中: C:\Program Files (x86)\Microsoft Visual Studio 10.0 打开安装目录下的VSDIR\VC\bin可以看到一系列的可执行程序.exe和批处理文件,这些就是VS2010构建.编译.链接时要用到的工具.看一下

Ninja - chromium核心构建工具

转自:http://guiquanz.me/2014/07/28/a_intro_to_Ninja/ Ninja - chromium核心构建工具Jul 28, 2014 [在线编辑] 缘由 经过上次对chromium核心代码的初步了解之后,我转头去研究了一番ninja,并对其进行了一些改造(爱折腾的,都是小NB).今天就来简单介绍一下ninja及其使用.(BTW: 细节的内容,大家阅读ninja 的手册就好了,我这里不会关注.) ninja是一个专注于速度的小型构建系统(Ninja is a

Build Tool-自动化构建工具

输入:工程文件+编译说明文件: 处理:自动化构建工具+编译器: 输出:可执行文件. 相对于手动编译. Historically, build automation was accomplished through makefiles. Today, there are two general categories of tools:[1] Build automation utility (like Make, Rake, Cake, MS build, Ant, Gradle etc.) Wh