loading...
Cover image for How to become more productive using Makefile

How to become more productive using Makefile

xarala221 profile image Ousseynou Diop ・2 min read

Originally posted on my blog

Introduction

You want to become more productive, automate your workflow, there are many tools to help you achieve your goal.

make gives you the flexibility to run and compile a program from source.
In this guide, we will use it to automate our development workflow.
Note: I will use Django as an example, but the technics are applicable to other technologies.
In this guide, I will use Makefile to automate many things in Django like database migration, superuser, deployment, and more.
At the end of the guide, you'll be more productive in your development.
Before you continue, ensure that make is installed in your system.

Installation

In Order to use make we need two(2) things one(1) we need to install it in our system and finally we need to create a file called Makefile.

To install make in your system you can follow these links :
OSX
Windows

Basic examples

To explore make let's begin with this simple program, go to any directory, and create a Makefile.
Note: Don't give it an extension.

$ mkdir test_make && cd test_make
$ touch Makefile

Open the file with your text editor and put this

say_hello:
        echo "Hello world"

run the file by typing make inside the directory test_make

$ make

What is the output?
Here is what I get.

echo "Hello world"
Hello world

Django integration

If you're a Django developer, you know how tedious is to repeat again and again these commands :

python manage.py runserver
python manage.py makemigrations
python manage.py migrate
...

Let's automate them with make

Clone the example project here and follow the README guide.

git clone https://github.com/xarala221/consume-restfull-api-with-django && cd consume-restfull-api-with-django

Run the application to ensure that everything is working fine.

python manage.py migrate
python manage.py runserver

Open your browser and go to http://localhost:8000.

Inside the project, folder created a file called Makefile and add these lines.

touch Makefile

The final file will look like this

SHELL := /bin/bash

help:
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

install:
    pipenv install

activate:
    pipenv shell

run:
    python manage.py runserver

migration:
    python manage.py makemigrations

migrate:
    python manage.py migrate

superuser:
    python manage.py createsuperuser

heroku:
    git push heroku master

deploy:
    docker-compose build
    docker-compose up -d

down:
    docker-compose down

you'll be more productive with these tips.

Conclusion

Become more productive and make things done is very important, in this guide you've learned how to automate your workflow by using make.

What do you think about this? Let us know in the comment section.

Posted on Jun 27 by:

xarala221 profile

Ousseynou Diop

@xarala221

Freelance ❯ Fullstack Dev ❯ Python Lover ❯ Django ❯Js ❯ Node ❯ React ❯ GraphQL🔥

Discussion

markdown guide
 

But you don’t really save time though since the commands are short already. I question the productivity improvements here and would use bash aliases instead.

Make was invented for compiling (C/C++) codebases which involves a lot of long commands for compiler, linker, finding libraries, dependency tracking, etc. And it’s still a pain in the ass to maintain makefiles for those purposes. Nowadays I see less and less makefiles at work and in the opensource community.

 

Hi, yeah, the example is a little bit too simplistic, however with a bit more involved example, one can start seeing the benefits:

include Makefile.settings

.PHONY: init build clean publish log jenkins slave

# Jenkins settings
export DOCKER_GID ?= 100
export JENKINS_USERNAME ?= admin
export JENKINS_PASSWORD ?= password
export JENKINS_SLAVE_VERSION ?= 2.2
export JENKINS_SLAVE_LABELS ?= DOCKER

# AWS settings
# The role to assume to inject temporary credentials into your Jenkins container
AWS_ROLE ?= `aws configure get role_arn`
# KMS encrypted password - the temporary credentials must possess kms:decrypt permissions for the key used to encrypt the credentials
export KMS_JENKINS_PASSWORD ?=

init:
    ${INFO} "Creating volumes..."
    @ docker volume create --name=jenkins_home

build:
    ${INFO} "Building image..."
    @ docker-compose build --pull
    ${INFO} "Build complete"

jenkins: init
    @ $(if $(and $(AWS_PROFILE),$(KMS_JENKINS_PASSWORD)),$(call assume_role,$(AWS_ROLE)),)
    ${INFO} "Starting Jenkins..."
    ${INFO} "This may take some time..."
    @ docker-compose up -d jenkins
    @ $(call check_service_health,$(RELEASE_ARGS),jenkins)
    ${INFO} "Jenkins is running at http://$(DOCKER_HOST_IP):$(call get_port_mapping,jenkins,8080)..."

publish:
    ${INFO} "Publishing images..."
    @ docker-compose push
    ${INFO} "Publish complete"

slave:
    ${INFO} "Checking Jenkins is healthy..."
    @ $(if $(and $(AWS_PROFILE),$(KMS_JENKINS_PASSWORD)),$(call assume_role,$(AWS_ROLE)),)
    @ $(call check_service_health,$(RELEASE_ARGS),jenkins)
    ${INFO} "Starting $(SLAVE_COUNT) slave(s)..."
    @ docker-compose up -d --scale jenkins-slave=$(SLAVE_COUNT)
    ${INFO} "$(SLAVE_COUNT) slave(s) running"

clean:
    ${INFO} "Stopping services..."
    @ docker-compose down -v || true
    ${INFO} "Services stopped"

destroy: clean
    ${INFO} "Deleting jenkins home volume..."
    @ docker volume rm -f jenkins_home
    ${INFO} "Deletion complete"

log:
    ${INFO} "Streaming Jenkins logs - press CTRL+C to exit..."
    @ docker-compose logs -f jenkins

what I see is that makefiles are less used with some languages, but are still quite heavily used with others.
Though I agree that I also haven't seen complex makefile in a while, but that is probably because more and more languages have their own tooling.

  • JS: npm scripts, gulp, grunt, etc.
  • C#: Powershell (Invoke!), maybe Cake
  • F#: FAKE
  • Rust: cargo custom tasks
  • JVM languages had their own for a long time also: sbt (Scala), gradle (a lot of JVM langs)
  • Python: Fabric, but here I've seen a lot of makefiles :-)
  • Ruby: Rake
  • Elixir: mix with custom tasks
  • Go: maybe Task, but here I've also seen quite a lot of makefiles

Can't tell for the rest, these are the ones I am familiar with.

 

Great content, Thank you.

 

Thank you,
I find this very interesting.

 

I love Makefiles and use them in almost all my projects, but I think the main benefits of them is walking DAGs of dependencies, which the article doesn't really mention.

For example, if your toolchain generates files:

source-file
   |
   tool-a
   |
intermediate-file
   |
   tool-b
   |
final-file

Then you can define some Makefile targets:

# final-file depends upon the state of intermediate-file
final-file: intermediate-file
     tool-b intermediate-file >final-file

# intermediate file depends on source-file
intermediate-file: source-file
    tool-a source-file >intermediate-file

Then the command 'make final-file' will run tool-b to generate the intermediate file, and knows that it first needs to run tool-a to generate the intermediate-file, and (the clever bit) it only runs each step if the output of the step is older than any of its inputs.

This means you eliminate needless typing (from running a tree of pre-requisite steps), and you eliminate needless (and possibly slow) rebuilding of files which don't need it. This is the core value of make, and if you can't take advantage of this, then there isn't much value over a set of script files.

I'd classify my current employer (Canonical) as high on the technically savvy scale, and my team uses a Makefile or two on every project. Even in cases where we can't make use of the above dependency analysis, it's nice for us to standardize on one approach to controlling how to build/test/etc projects.

 

Very interesting, thanks.

 

I added some missing "dependencies" (the parts after the colon) in my Makefile example.

 

Great article, i use to handle some of those task with custom django commands... but it really depends on what the task has to achieve, for example initializing app with default data... but it's a good idea to use makefile also.

But i am not sure if it can do everything, for example can it help you to deploy on remote server via SSH like fabfile ?

 

Thank you, friend.
Yes, you can do that.
I use this file to deploy my app to a docker container or Heroku server.

 

yeah i use it also but for VPS deployment and sometime on EC2....

 

TABS! Make sure you mention you need to use tabs not spaces to indent the start of a command. That is something that still gets me two decades of using Makefile's later.

 
 

It's an interesting approach, but why use make for a bash script's job?

 

Great article! I'm trying it for a workflow for Node apps :)

 
 

I have thought about this a while ago, and Make seems to be both quite standard, and preinstalled (if not using Windows).