SlideShare uma empresa Scribd logo
1 de 34
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

Oslo Vancouver Project Update
Oslo Vancouver Project UpdateOslo Vancouver Project Update
Oslo Vancouver Project UpdateBen Nemec
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquareApigee | Google Cloud
 
AWS Lambda and serverless Java | DevNation Live
AWS Lambda and serverless Java | DevNation LiveAWS Lambda and serverless Java | DevNation Live
AWS Lambda and serverless Java | DevNation LiveRed Hat Developers
 
Containerize ovs ovn components
Containerize ovs ovn componentsContainerize ovs ovn components
Containerize ovs ovn componentsAliasgar Ginwala
 
Streams API (Web Engines Hackfest 2015)
Streams API (Web Engines Hackfest 2015)Streams API (Web Engines Hackfest 2015)
Streams API (Web Engines Hackfest 2015)Igalia
 
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまでLINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまでLINE Corporation
 
Freifunk Munich - How to scale Jitsi
Freifunk Munich - How to scale JitsiFreifunk Munich - How to scale Jitsi
Freifunk Munich - How to scale JitsiAnnika Wickert
 
Angular v2 et plus : le futur du développement d'applications en entreprise
Angular v2 et plus : le futur du développement d'applications en entrepriseAngular v2 et plus : le futur du développement d'applications en entreprise
Angular v2 et plus : le futur du développement d'applications en entrepriseLINAGORA
 
OpenZFS Developer Summit Introduction
OpenZFS Developer Summit IntroductionOpenZFS Developer Summit Introduction
OpenZFS Developer Summit IntroductionMatthew Ahrens
 
Using ssh as portal - The CMS CRAB over glideinWMS experience
Using ssh as portal - The CMS CRAB over glideinWMS experienceUsing ssh as portal - The CMS CRAB over glideinWMS experience
Using ssh as portal - The CMS CRAB over glideinWMS experienceIgor Sfiligoi
 
REST vs gRPC: Battle of API's
REST vs gRPC: Battle of API'sREST vs gRPC: Battle of API's
REST vs gRPC: Battle of API'sLuram Archanjo
 
Logging presentation
Logging presentationLogging presentation
Logging presentationJatan Malde
 
Persistent Storage in Openshift using GlusterFS
Persistent Storage in Openshift using GlusterFSPersistent Storage in Openshift using GlusterFS
Persistent Storage in Openshift using GlusterFSHumble Chirammal
 
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)LINAGORA
 

Mais procurados (20)

Oslo Vancouver Project Update
Oslo Vancouver Project UpdateOslo Vancouver Project Update
Oslo Vancouver Project Update
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at Square
 
AWS Lambda and serverless Java | DevNation Live
AWS Lambda and serverless Java | DevNation LiveAWS Lambda and serverless Java | DevNation Live
AWS Lambda and serverless Java | DevNation Live
 
Containerize ovs ovn components
Containerize ovs ovn componentsContainerize ovs ovn components
Containerize ovs ovn components
 
Streams API (Web Engines Hackfest 2015)
Streams API (Web Engines Hackfest 2015)Streams API (Web Engines Hackfest 2015)
Streams API (Web Engines Hackfest 2015)
 
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまでLINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが
30,000+/min のコメント投稿を捌くようになるまで
 
Freifunk Munich - How to scale Jitsi
Freifunk Munich - How to scale JitsiFreifunk Munich - How to scale Jitsi
Freifunk Munich - How to scale Jitsi
 
Angular v2 et plus : le futur du développement d'applications en entreprise
Angular v2 et plus : le futur du développement d'applications en entrepriseAngular v2 et plus : le futur du développement d'applications en entreprise
Angular v2 et plus : le futur du développement d'applications en entreprise
 
OpenZFS Developer Summit Introduction
OpenZFS Developer Summit IntroductionOpenZFS Developer Summit Introduction
OpenZFS Developer Summit Introduction
 
Using ssh as portal - The CMS CRAB over glideinWMS experience
Using ssh as portal - The CMS CRAB over glideinWMS experienceUsing ssh as portal - The CMS CRAB over glideinWMS experience
Using ssh as portal - The CMS CRAB over glideinWMS experience
 
REST vs gRPC: Battle of API's
REST vs gRPC: Battle of API'sREST vs gRPC: Battle of API's
REST vs gRPC: Battle of API's
 
Logging presentation
Logging presentationLogging presentation
Logging presentation
 
Persistent Storage in Openshift using GlusterFS
Persistent Storage in Openshift using GlusterFSPersistent Storage in Openshift using GlusterFS
Persistent Storage in Openshift using GlusterFS
 
Power-up services with gRPC
Power-up services with gRPCPower-up services with gRPC
Power-up services with gRPC
 
Rust programming-language
Rust programming-languageRust programming-language
Rust programming-language
 
OpenZFS - BSDcan 2014
OpenZFS - BSDcan 2014OpenZFS - BSDcan 2014
OpenZFS - BSDcan 2014
 
Netty training
Netty trainingNetty training
Netty training
 
oVirt – open your virtual datacenter
oVirt – open your virtual datacenteroVirt – open your virtual datacenter
oVirt – open your virtual datacenter
 
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)
[UDS] Cloud Computing "pour les nuls" (Exemple avec LinShare)
 
gRPC Overview
gRPC OverviewgRPC Overview
gRPC Overview
 

Semelhante a Build Golang projects properly with Makefiles

GTALUG Short Talk On Mercurial
GTALUG Short Talk On MercurialGTALUG Short Talk On Mercurial
GTALUG Short Talk On MercurialMyles 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 Announcmentsjasnow
 
Becoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola PaolucciBecoming a Git Master - Nicola Paolucci
Becoming a Git Master - Nicola PaolucciAtlassian
 
Fuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesFuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesOWASPSeasides
 
Sacándole jugo a git
Sacándole jugo a gitSacándole jugo a git
Sacándole jugo a gitBerny Cantos
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto 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 crazyHonza 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
 
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...Automation TIPS and Tricks using Wireshark and tshark in Windows environments...
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...Megumi Takeshita
 
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 2016jasnow
 
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 SpeedSalesforce Marketing Cloud
 

Semelhante a 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
 
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...Automation TIPS and Tricks using Wireshark and tshark in Windows environments...
Automation TIPS and Tricks using Wireshark and tshark in Windows environments...
 
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
 

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