SlideShare a Scribd company logo
Build Golang projects
properly with Makefiles
Raül Pérez - @repejota - 25/11/2015
Who am I?
Hi! My name is Raül Pérez
● Lead Software Engineer at Carrenza Ltd. http://www.carrenza.com
● Living between Barcelona & London.
● Working on devops stuff, but I’m still more a Dev than an Op.
● Proud to be a Gopher, but I’m not a fanboy. I write code on multiple
languages.
Twitter: https://twitter.com/repejota
Github: https://github.com/repejota
LinkedIn: https://linkedin.com/in/repejota
Raül Pérez - @repejota GolangBCN - 25/11/2015
Why Makefiles?
Why using Makefiles?
● Build != Compile
○ Building a project means more than just compile your code.
○ Static analysis, Linters, Installation, configuration, packaging, etc ...
● Same tool on each phase of the project.
○ Makefiles act as the glue to go tools (build, install, clean)
○ But can use also third party tools ( go lint, go vet, gb, etc ... )
● Language agnostic.
○ Probably your project does not rely on just one language.
○ Generate configuration files, man pages, fixture data, etc ...
● Available on multiple platforms.
○ Because users use whatever they want.
○ Cross compilation.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Why using Makefiles? (II)
Three goals are necessary to accomplish when you properly want to build your
project:
1. Easy & portable compilation, installation and cleanup.
2. Make trivial to use compile time variables.
3. Reproducible builds.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Example code to build.
package main
import “fmt”
func main() {
// Probably the most awesome piece of code you’ve ever seen.
fmt.Println(“foo bar”)
}
Raül Pérez - @repejota GolangBCN - 25/11/2015
Example Makefile
default:
go build
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ ls -al
total 4560
drwxr-xr-x 5 raul staff 170 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ ./gomake
foo bar
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Easy & portable compilation,
installation and cleanup
Easy compilation, installation and cleanup (I).
Compilation: Just type “make”
○ Laziness! Less keystrokes than “go build <package>”
○ You can also build multiple projects with a single Makefile.
■ A Makefile could call to another Makefile.
○ Want to use more sophisticated build tool with your code?
■ All scripts and data to build a project belongs to the project itself.
■ Just change the Makefile not your continuous integration process.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Easy compilation, installation and cleanup (II).
Installation: Just type “make install”
○ Most of the times “go install <package>” is not enough, there is probably extra steps to do
after creating the binary.
○ Generate configuration files, man pages, fixture data, etc ...
○ Just change the Makefile not your deployment process.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Easy compilation, installation and cleanup (III).
Cleanup: Just type “make clean”
○ Cleaning your project means more than just deleting your old binary.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Improved Makefile
# Default target: builds the project
build:
go build
# Installs our project: copies binaries
install:
go install
# Cleans our project: deletes binaries
clean:
go clean
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ ls -al
total 4560
drwxr-xr-x 5 raul staff 170 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ ./gomake
foo bar
$ make clean
go clean
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Make trivial to use compile
time variables
Make trivial to use compile time variables
● Adding a VERSION number.
● Adding the Build Time.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Improved source code.
package main
import (
“fmt”
)
// Variables to identify the build
var (
Version = “1.0.0”
Build = “2015-11-25T00:23:32+0100”
)
func main() {
fmt.Println(“Version: “, Version)
fmt.Println(“Build Time: “, Build)
}
Raül Pérez - @repejota GolangBCN - 25/11/2015
Improved Makefile
# This how we want to name the binary output
BINARY=gomake
# Builds the project
build:
go build -o ${BINARY}
# Installs our project: copies binaries
install:
go install
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ ls -al
total 4560
drwxr-xr-x 5 raul staff 170 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ ./gomake
Version: 1.0.0
Build Time: 2015-11-25T00:23:32+0100
$ make clean
if [ -f gomake ] ; then rm gomake ; fi
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Make trivial to use compile time variables (II)
● Adding a VERSION number.
○ Editing the code to bump the version is painful.
○ Your are going to forget it, commit, and your git history is going to be broken.
● Adding a Build Time.
○ It happens the same than with the VERSION.
○ Which format of timestamp to use? It is a weird string!
○ And obviously you need a clock to check the exact time before! :P
Raül Pérez - @repejota GolangBCN - 25/11/2015
Improved source code.
package main
import (
“fmt”
)
// Variables to identify the build
var (
Version string
Build string
)
func main() {
fmt.Println(“Version: “, Version)
fmt.Println(“Build Time: “, Build)
}
Raül Pérez - @repejota GolangBCN - 25/11/2015
Improved Makefile
# This how we want to name the binary output
BINARY=gomake
# These are the values we want to pass for VERSION and BUILD
VERSION=1.0.0
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD}"
# Builds the project
build:
go build ${LDFLAGS} -o ${BINARY}
# Installs our project: copies binaries
install:
go install ${LDFLAGS}
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ ls -al
total 4560
drwxr-xr-x 5 raul staff 170 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ ./gomake
Version: 1.0.0
Build Time: 2015-11-25T05:23:32+0100
$ make clean
if [ -f gomake ] ; then rm gomake ; fi
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Make trivial to use compile time variables (III)
● Using LDFLAGS
○ The go link command allows you to set string variables at compile time with the -X option.
○ Use the format: importpath.name=value
○ http://golang.org/cmd/link/
● Differences between Golang 1.5+ and previous version.
○ Golang 1.5+ -X option takes one argument split on the first = sign.
○ Example:
■ go build -ldflags “-X main.Version=1.0.0 -X main.Build=2015-11-25T00:23:32+0100”
○ Golang < 1.5 -X options takes two separate arguments.
○ Example:
■ go build -ldflags “-X main.Version 1.0.0 -X main.Build 2015-11-25T00:23:32+0100”
Raül Pérez - @repejota GolangBCN - 25/11/2015
Reproducible builds
Reproducible builds.
● Delivering binaries is hard.
○ You just can’t serve the binary over Internet.
○ Packages, installators there is plenty of tools to help you.
● You must be sure your binary is not modified or compromised.
○ Once the binary leaves your server you are not controlling it.
○ Also, a security attack can replace your binary on your server for a malicious one.
● shasum all your binaries!
○ Checking the finger-print of your binary allows you to ensure the binary has not been modified
without permission.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Reproducible builds (II).
● Our previous example introduces a new problem.
○ Using a timestamp variable changes the shashum of your file!
○ Just avoiding the build time fixes the problem.
○ But then, you’re forced to bump the version on each build.
● Why not use the Git commit hash instead of the timestamp?
○ Can work together with the VERSION.
○ You are not anymore forced to bump a version on each build. Nightly builds!!
○ It doesn’t change if the source code is not modified.
○ Identifies your binary, so you can know its “origin”.
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ shasum gomake
c6dd654ffe6f0e5af518d281da702187cc577cd4 gomake
$ make
go build
$ shasum gomake
dbf0cbe34067c42ecf6d221fcd789073370fa297 gomake
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ shasum gomake
c6dd654ffe6f0e5af518d281da702187cc577cd4 gomake
$ make
go build
$ shasum gomake
dbf0cbe34067c42ecf6d221fcd789073370fa297 gomake
$
Different shasum values!
Raül Pérez - @repejota GolangBCN - 25/11/2015
Final source code.
package main
import (
“fmt”
)
// Variables to identify the build
var (
Version string
Build string
)
func main() {
fmt.Println(“Version: “, Version)
fmt.Println(“Git commit hash: “, Build)
}
Raül Pérez - @repejota GolangBCN - 25/11/2015
Final Makefile
# This how we want to name the binary output
BINARY=gomake
# These are the values we want to pass for VERSION and BUILD
VERSION=1.0.0
BUILD=`git rev-parse HEAD`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD}"
# Default target
.DEFAULT_GOAL: $(BINARY)
# Builds the project
$(BINARY):
go build ${LDFLAGS} -o {$BINARY} ./..
# Installs our project: copies binaries
install:
go install ${LDFLAGS} -o {$BINARY} ./..
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ shasum gomake
b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake
$ make
go build
$ shasum gomake
b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake
$
Raül Pérez - @repejota GolangBCN - 25/11/2015
Demo
$ ls -al
total 16
drwxr-xr-x 4 raul staff 136 25 Nov 05:08 .
drwxr-xr-x 9 raul staff 306 25 Nov 03:36 ..
-rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile
-rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go
$ make
go build
$ shasum gomake
b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake
$ make
go build
$ shasum gomake
b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake
$
Same shasum values!
Reproducible builds!!
Raül Pérez - @repejota GolangBCN - 25/11/2015
Thanks!
Questions?
Slides & Code Examples : https://github.com/repejota/gomake

More Related Content

What's hot

Proximal Policy Optimization
Proximal Policy OptimizationProximal Policy Optimization
Proximal Policy Optimization
ShubhaManikarnike
 
Planning and Learning with Tabular Methods
Planning and Learning with Tabular MethodsPlanning and Learning with Tabular Methods
Planning and Learning with Tabular Methods
Dongmin Lee
 
GitHub Appsの作り方
GitHub Appsの作り方GitHub Appsの作り方
GitHub Appsの作り方
zaru sakuraba
 
トピックブランチとは
トピックブランチとはトピックブランチとは
トピックブランチとは
nakajima_yuji
 
새해 일어난 일
새해 일어난 일새해 일어난 일
새해 일어난 일
Eunhyang Kim
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
Jeongmin Cha
 
2018 종합선물세트 for 취준생
2018 종합선물세트 for 취준생2018 종합선물세트 for 취준생
2018 종합선물세트 for 취준생
Yu Yongwoo
 
Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)
Bongseok Cho
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
Kohsuke Yuasa
 
회사 밖 개발자로 살아가기
회사 밖 개발자로 살아가기회사 밖 개발자로 살아가기
회사 밖 개발자로 살아가기
Siyoung Oh
 
들로네 삼각분할과 보로노이 다이어그램
들로네 삼각분할과 보로노이 다이어그램들로네 삼각분할과 보로노이 다이어그램
들로네 삼각분할과 보로노이 다이어그램
ssuserbe87d6
 
Introduction to Makefile
Introduction to MakefileIntroduction to Makefile
Introduction to Makefile
Zakaria El ktaoui
 
デザイナのためのGit入門
デザイナのためのGit入門デザイナのためのGit入門
デザイナのためのGit入門
dsuke Takaoka
 
SPH 기법을 이용한 2D 물 물리 엔진 개발
SPH 기법을 이용한 2D 물 물리 엔진 개발SPH 기법을 이용한 2D 물 물리 엔진 개발
SPH 기법을 이용한 2D 물 물리 엔진 개발
SeongWan Kim
 
文書比較 (diff)
文書比較 (diff)文書比較 (diff)
文書比較 (diff)
Satoshi MATSUURA
 
공간정보아카데미 - Day1 오픈소스개발 일반
공간정보아카데미 - Day1 오픈소스개발 일반공간정보아카데미 - Day1 오픈소스개발 일반
공간정보아카데미 - Day1 오픈소스개발 일반
BJ Jang
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料
Nobuhiro Iwamatsu
 
svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드
Insub Lee
 
웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화
NAVER D2
 

What's hot (20)

Proximal Policy Optimization
Proximal Policy OptimizationProximal Policy Optimization
Proximal Policy Optimization
 
Planning and Learning with Tabular Methods
Planning and Learning with Tabular MethodsPlanning and Learning with Tabular Methods
Planning and Learning with Tabular Methods
 
GitHub Appsの作り方
GitHub Appsの作り方GitHub Appsの作り方
GitHub Appsの作り方
 
トピックブランチとは
トピックブランチとはトピックブランチとは
トピックブランチとは
 
Git Tutorial 教學
Git Tutorial 教學Git Tutorial 教學
Git Tutorial 教學
 
새해 일어난 일
새해 일어난 일새해 일어난 일
새해 일어난 일
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
 
2018 종합선물세트 for 취준생
2018 종합선물세트 for 취준생2018 종합선물세트 for 취준생
2018 종합선물세트 for 취준생
 
Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
 
회사 밖 개발자로 살아가기
회사 밖 개발자로 살아가기회사 밖 개발자로 살아가기
회사 밖 개발자로 살아가기
 
들로네 삼각분할과 보로노이 다이어그램
들로네 삼각분할과 보로노이 다이어그램들로네 삼각분할과 보로노이 다이어그램
들로네 삼각분할과 보로노이 다이어그램
 
Introduction to Makefile
Introduction to MakefileIntroduction to Makefile
Introduction to Makefile
 
デザイナのためのGit入門
デザイナのためのGit入門デザイナのためのGit入門
デザイナのためのGit入門
 
SPH 기법을 이용한 2D 물 물리 엔진 개발
SPH 기법을 이용한 2D 물 물리 엔진 개발SPH 기법을 이용한 2D 물 물리 엔진 개발
SPH 기법을 이용한 2D 물 물리 엔진 개발
 
文書比較 (diff)
文書比較 (diff)文書比較 (diff)
文書比較 (diff)
 
공간정보아카데미 - Day1 오픈소스개발 일반
공간정보아카데미 - Day1 오픈소스개발 일반공간정보아카데미 - Day1 오픈소스개발 일반
공간정보아카데미 - Day1 오픈소스개발 일반
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料
 
svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드
 
웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화
 

Similar to Build Golang projects properly with Makefiles

GTALUG Short Talk On Mercurial
GTALUG Short Talk On MercurialGTALUG Short Talk On Mercurial
GTALUG Short Talk On Mercurial
Myles Braithwaite
 
Let's contribute, HTML5Rocks/ko!
Let's contribute, HTML5Rocks/ko!Let's contribute, HTML5Rocks/ko!
Let's contribute, HTML5Rocks/ko!
Chang W. Doh
 
ATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback AnnouncmentsATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback Announcments
jasnow
 
Becoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola PaolucciBecoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola Paolucci
Atlassian
 
Fuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesFuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP Seasides
OWASPSeasides
 
Becoming a Git Master
Becoming a Git MasterBecoming a Git Master
Becoming a Git Master
Nicola Paolucci
 
Sacándole jugo a git
Sacándole jugo a gitSacándole jugo a git
Sacándole jugo a git
Berny Cantos
 
Linuxcommands 091018105536-phpapp01
Linuxcommands 091018105536-phpapp01Linuxcommands 091018105536-phpapp01
Linuxcommands 091018105536-phpapp01
Nagarajan Kamalakannan
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
Arto Artnik
 
Pipfile, pipenv, pip… what?!
Pipfile, pipenv, pip… what?!Pipfile, pipenv, pip… what?!
Pipfile, pipenv, pip… what?!
Ivan Chernoff
 
Take care of hundred containers and not go crazy
Take care of hundred containers and not go crazyTake care of hundred containers and not go crazy
Take care of hundred containers and not go crazy
Honza Horák
 
Austin agile conf 2012 infrastructure automation-gmiranda
Austin agile conf 2012 infrastructure automation-gmirandaAustin agile conf 2012 infrastructure automation-gmiranda
Austin agile conf 2012 infrastructure automation-gmirandaGeorge Miranda
 
nginxをソースからインストールしてみたよ
nginxをソースからインストールしてみたよnginxをソースからインストールしてみたよ
nginxをソースからインストールしてみたよmamoru tateoka
 
ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016
jasnow
 
Installing GravCMS
Installing GravCMSInstalling GravCMS
Installing GravCMS
George Sumpster
 
Biicode OpenExpoDay
Biicode OpenExpoDayBiicode OpenExpoDay
Biicode OpenExpoDayfcofdezc
 
#CNX14 - Using Ruby for Reliability, Consistency, and Speed
#CNX14 - Using Ruby for Reliability, Consistency, and Speed#CNX14 - Using Ruby for Reliability, Consistency, and Speed
#CNX14 - Using Ruby for Reliability, Consistency, and Speed
Salesforce Marketing Cloud
 
ZFS Talk Part 1
ZFS Talk Part 1ZFS Talk Part 1
ZFS Talk Part 1
Steven Burgess
 

Similar to Build Golang projects properly with Makefiles (20)

GTALUG Short Talk On Mercurial
GTALUG Short Talk On MercurialGTALUG Short Talk On Mercurial
GTALUG Short Talk On Mercurial
 
Let's contribute, HTML5Rocks/ko!
Let's contribute, HTML5Rocks/ko!Let's contribute, HTML5Rocks/ko!
Let's contribute, HTML5Rocks/ko!
 
ATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback AnnouncmentsATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback Announcments
 
Becoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola PaolucciBecoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola Paolucci
 
Fuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesFuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP Seasides
 
Becoming a Git Master
Becoming a Git MasterBecoming a Git Master
Becoming a Git Master
 
Sacándole jugo a git
Sacándole jugo a gitSacándole jugo a git
Sacándole jugo a git
 
Linuxcommands 091018105536-phpapp01
Linuxcommands 091018105536-phpapp01Linuxcommands 091018105536-phpapp01
Linuxcommands 091018105536-phpapp01
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Pipfile, pipenv, pip… what?!
Pipfile, pipenv, pip… what?!Pipfile, pipenv, pip… what?!
Pipfile, pipenv, pip… what?!
 
Take care of hundred containers and not go crazy
Take care of hundred containers and not go crazyTake care of hundred containers and not go crazy
Take care of hundred containers and not go crazy
 
Austin agile conf 2012 infrastructure automation-gmiranda
Austin agile conf 2012 infrastructure automation-gmirandaAustin agile conf 2012 infrastructure automation-gmiranda
Austin agile conf 2012 infrastructure automation-gmiranda
 
nginxをソースからインストールしてみたよ
nginxをソースからインストールしてみたよnginxをソースからインストールしてみたよ
nginxをソースからインストールしてみたよ
 
ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016
 
Installing GravCMS
Installing GravCMSInstalling GravCMS
Installing GravCMS
 
Biicode OpenExpoDay
Biicode OpenExpoDayBiicode OpenExpoDay
Biicode OpenExpoDay
 
Infrastructure as Code with Chef / Puppet
Infrastructure as Code with Chef / PuppetInfrastructure as Code with Chef / Puppet
Infrastructure as Code with Chef / Puppet
 
Loading...git
Loading...gitLoading...git
Loading...git
 
#CNX14 - Using Ruby for Reliability, Consistency, and Speed
#CNX14 - Using Ruby for Reliability, Consistency, and Speed#CNX14 - Using Ruby for Reliability, Consistency, and Speed
#CNX14 - Using Ruby for Reliability, Consistency, and Speed
 
ZFS Talk Part 1
ZFS Talk Part 1ZFS Talk Part 1
ZFS Talk Part 1
 

Build Golang projects properly with Makefiles

  • 1. Build Golang projects properly with Makefiles Raül Pérez - @repejota - 25/11/2015
  • 2. Who am I? Hi! My name is Raül Pérez ● Lead Software Engineer at Carrenza Ltd. http://www.carrenza.com ● Living between Barcelona & London. ● Working on devops stuff, but I’m still more a Dev than an Op. ● Proud to be a Gopher, but I’m not a fanboy. I write code on multiple languages. Twitter: https://twitter.com/repejota Github: https://github.com/repejota LinkedIn: https://linkedin.com/in/repejota Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 4. Why using Makefiles? ● Build != Compile ○ Building a project means more than just compile your code. ○ Static analysis, Linters, Installation, configuration, packaging, etc ... ● Same tool on each phase of the project. ○ Makefiles act as the glue to go tools (build, install, clean) ○ But can use also third party tools ( go lint, go vet, gb, etc ... ) ● Language agnostic. ○ Probably your project does not rely on just one language. ○ Generate configuration files, man pages, fixture data, etc ... ● Available on multiple platforms. ○ Because users use whatever they want. ○ Cross compilation. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 5. Why using Makefiles? (II) Three goals are necessary to accomplish when you properly want to build your project: 1. Easy & portable compilation, installation and cleanup. 2. Make trivial to use compile time variables. 3. Reproducible builds. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 6. Example code to build. package main import “fmt” func main() { // Probably the most awesome piece of code you’ve ever seen. fmt.Println(“foo bar”) } Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 7. Example Makefile default: go build Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 8. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ ls -al total 4560 drwxr-xr-x 5 raul staff 170 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ ./gomake foo bar $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 9. Easy & portable compilation, installation and cleanup
  • 10. Easy compilation, installation and cleanup (I). Compilation: Just type “make” ○ Laziness! Less keystrokes than “go build <package>” ○ You can also build multiple projects with a single Makefile. ■ A Makefile could call to another Makefile. ○ Want to use more sophisticated build tool with your code? ■ All scripts and data to build a project belongs to the project itself. ■ Just change the Makefile not your continuous integration process. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 11. Easy compilation, installation and cleanup (II). Installation: Just type “make install” ○ Most of the times “go install <package>” is not enough, there is probably extra steps to do after creating the binary. ○ Generate configuration files, man pages, fixture data, etc ... ○ Just change the Makefile not your deployment process. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 12. Easy compilation, installation and cleanup (III). Cleanup: Just type “make clean” ○ Cleaning your project means more than just deleting your old binary. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 13. Improved Makefile # Default target: builds the project build: go build # Installs our project: copies binaries install: go install # Cleans our project: deletes binaries clean: go clean Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 14. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ ls -al total 4560 drwxr-xr-x 5 raul staff 170 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ ./gomake foo bar $ make clean go clean $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 15. Make trivial to use compile time variables
  • 16. Make trivial to use compile time variables ● Adding a VERSION number. ● Adding the Build Time. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 17. Improved source code. package main import ( “fmt” ) // Variables to identify the build var ( Version = “1.0.0” Build = “2015-11-25T00:23:32+0100” ) func main() { fmt.Println(“Version: “, Version) fmt.Println(“Build Time: “, Build) } Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 18. Improved Makefile # This how we want to name the binary output BINARY=gomake # Builds the project build: go build -o ${BINARY} # Installs our project: copies binaries install: go install # Cleans our project: deletes binaries clean: if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi .PHONY: clean install Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 19. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ ls -al total 4560 drwxr-xr-x 5 raul staff 170 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ ./gomake Version: 1.0.0 Build Time: 2015-11-25T00:23:32+0100 $ make clean if [ -f gomake ] ; then rm gomake ; fi $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 20. Make trivial to use compile time variables (II) ● Adding a VERSION number. ○ Editing the code to bump the version is painful. ○ Your are going to forget it, commit, and your git history is going to be broken. ● Adding a Build Time. ○ It happens the same than with the VERSION. ○ Which format of timestamp to use? It is a weird string! ○ And obviously you need a clock to check the exact time before! :P Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 21. Improved source code. package main import ( “fmt” ) // Variables to identify the build var ( Version string Build string ) func main() { fmt.Println(“Version: “, Version) fmt.Println(“Build Time: “, Build) } Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 22. Improved Makefile # This how we want to name the binary output BINARY=gomake # These are the values we want to pass for VERSION and BUILD VERSION=1.0.0 BUILD=`date +%FT%T%z` # Setup the -ldflags option for go build here, interpolate the variable values LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD}" # Builds the project build: go build ${LDFLAGS} -o ${BINARY} # Installs our project: copies binaries install: go install ${LDFLAGS} # Cleans our project: deletes binaries clean: if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi .PHONY: clean install Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 23. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ ls -al total 4560 drwxr-xr-x 5 raul staff 170 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rwxr-xr-x 1 raul staff 2324096 25 Nov 05:08 gomake -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ ./gomake Version: 1.0.0 Build Time: 2015-11-25T05:23:32+0100 $ make clean if [ -f gomake ] ; then rm gomake ; fi $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 24. Make trivial to use compile time variables (III) ● Using LDFLAGS ○ The go link command allows you to set string variables at compile time with the -X option. ○ Use the format: importpath.name=value ○ http://golang.org/cmd/link/ ● Differences between Golang 1.5+ and previous version. ○ Golang 1.5+ -X option takes one argument split on the first = sign. ○ Example: ■ go build -ldflags “-X main.Version=1.0.0 -X main.Build=2015-11-25T00:23:32+0100” ○ Golang < 1.5 -X options takes two separate arguments. ○ Example: ■ go build -ldflags “-X main.Version 1.0.0 -X main.Build 2015-11-25T00:23:32+0100” Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 26. Reproducible builds. ● Delivering binaries is hard. ○ You just can’t serve the binary over Internet. ○ Packages, installators there is plenty of tools to help you. ● You must be sure your binary is not modified or compromised. ○ Once the binary leaves your server you are not controlling it. ○ Also, a security attack can replace your binary on your server for a malicious one. ● shasum all your binaries! ○ Checking the finger-print of your binary allows you to ensure the binary has not been modified without permission. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 27. Reproducible builds (II). ● Our previous example introduces a new problem. ○ Using a timestamp variable changes the shashum of your file! ○ Just avoiding the build time fixes the problem. ○ But then, you’re forced to bump the version on each build. ● Why not use the Git commit hash instead of the timestamp? ○ Can work together with the VERSION. ○ You are not anymore forced to bump a version on each build. Nightly builds!! ○ It doesn’t change if the source code is not modified. ○ Identifies your binary, so you can know its “origin”. Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 28. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ shasum gomake c6dd654ffe6f0e5af518d281da702187cc577cd4 gomake $ make go build $ shasum gomake dbf0cbe34067c42ecf6d221fcd789073370fa297 gomake $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 29. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ shasum gomake c6dd654ffe6f0e5af518d281da702187cc577cd4 gomake $ make go build $ shasum gomake dbf0cbe34067c42ecf6d221fcd789073370fa297 gomake $ Different shasum values! Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 30. Final source code. package main import ( “fmt” ) // Variables to identify the build var ( Version string Build string ) func main() { fmt.Println(“Version: “, Version) fmt.Println(“Git commit hash: “, Build) } Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 31. Final Makefile # This how we want to name the binary output BINARY=gomake # These are the values we want to pass for VERSION and BUILD VERSION=1.0.0 BUILD=`git rev-parse HEAD` # Setup the -ldflags option for go build here, interpolate the variable values LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD}" # Default target .DEFAULT_GOAL: $(BINARY) # Builds the project $(BINARY): go build ${LDFLAGS} -o {$BINARY} ./.. # Installs our project: copies binaries install: go install ${LDFLAGS} -o {$BINARY} ./.. # Cleans our project: deletes binaries clean: if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi .PHONY: clean install Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 32. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ shasum gomake b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake $ make go build $ shasum gomake b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake $ Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 33. Demo $ ls -al total 16 drwxr-xr-x 4 raul staff 136 25 Nov 05:08 . drwxr-xr-x 9 raul staff 306 25 Nov 03:36 .. -rw-r--r-- 1 raul staff 19 25 Nov 03:11 Makefile -rw-r--r-- 1 raul staff 132 25 Nov 05:07 main.go $ make go build $ shasum gomake b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake $ make go build $ shasum gomake b2c879490419f5a6473fa9d290f49a7e6a5b3353 gomake $ Same shasum values! Reproducible builds!! Raül Pérez - @repejota GolangBCN - 25/11/2015
  • 34. Thanks! Questions? Slides & Code Examples : https://github.com/repejota/gomake