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

PDF
Read-only rootfs: theory and practice
PDF
Linux Binary Exploitation - Return-oritend Programing
PDF
Introduction to yocto
PDF
Network Drivers
PDF
Using eBPF for High-Performance Networking in Cilium
PDF
LISA17 Container Performance Analysis
PDF
[OpenInfra Days Korea 2018] Day 2 - CEPH 운영자를 위한 Object Storage Performance T...
PDF
ユーザー情報格納基盤におけるApache Pulsarの利用事例
Read-only rootfs: theory and practice
Linux Binary Exploitation - Return-oritend Programing
Introduction to yocto
Network Drivers
Using eBPF for High-Performance Networking in Cilium
LISA17 Container Performance Analysis
[OpenInfra Days Korea 2018] Day 2 - CEPH 운영자를 위한 Object Storage Performance T...
ユーザー情報格納基盤におけるApache Pulsarの利用事例

What's hot (20)

PPTX
Git - Basic Crash Course
PDF
Distributed Databases Deconstructed: CockroachDB, TiDB and YugaByte DB
PDF
Embedded Linux BSP Training (Intro)
PDF
ROS-TSC-ros-k8s.20230309.pdf
PDF
OS X Drivers Reverse Engineering
PDF
FCスイッチISL 追加削除時の考慮点
PPTX
YoctoをつかったDistroの作り方とハマり方
PPTX
PDF
Project ACRN hypervisor introduction
PPT
Unix Shell Scripting Basics
PDF
EBPF and Linux Networking
PPTX
LinkIt 7697 IoT tutorial
PPTX
コンテナネットワーキング(CNI)最前線
PPTX
工程師必備第一工具 - Git
PDF
15分でわかるGit入門
PDF
Raspberry PiのUSB OTGを試す
PDF
BPF: Tracing and more
ODP
Q4.11: Porting Android to new Platforms
PDF
今だからこそ知りたい Docker Compose/Swarm 入門
PDF
データセンター向け高機能スイッチ Cisco Nexus スイッチ ガイド
Git - Basic Crash Course
Distributed Databases Deconstructed: CockroachDB, TiDB and YugaByte DB
Embedded Linux BSP Training (Intro)
ROS-TSC-ros-k8s.20230309.pdf
OS X Drivers Reverse Engineering
FCスイッチISL 追加削除時の考慮点
YoctoをつかったDistroの作り方とハマり方
Project ACRN hypervisor introduction
Unix Shell Scripting Basics
EBPF and Linux Networking
LinkIt 7697 IoT tutorial
コンテナネットワーキング(CNI)最前線
工程師必備第一工具 - Git
15分でわかるGit入門
Raspberry PiのUSB OTGを試す
BPF: Tracing and more
Q4.11: Porting Android to new Platforms
今だからこそ知りたい Docker Compose/Swarm 入門
データセンター向け高機能スイッチ Cisco Nexus スイッチ ガイド
Ad

Similar to Build Golang projects properly with Makefiles (20)

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

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