How to simplify your development with Makefile

7V9R...YaGh
23 Jan 2024
34

Makefiles date way back to early 1970s the main purpose for it in software development is to automate the build process of a project. The necessity of it grows with project complexity to automate, simplify different commands starting with running, dockerizing, populating data for your app and so much more.


In my example will showcase Go and Svelte as an example. Although tech stack makes no difference.


Commands


Makefile has it’s own syntax with rules, dependencies, commands and targets. As mentioned it’s good to use if your project has complex structure for running or executing certain sections.
Same as any other language it’s sometimes essential to create variables for future use cases.

GOCMD=go
GOBUILD=go build
GO_FILE=main.go
BINARY_FILE=main

A target on the other hand is the desired output of a Makefile rule.

build-client:    
    cd ./client && yarn && yarn build

build-server:    
    echo "Building binary"    
    ${GOBUILD} -o ${BINARY_FILE} ${GO_FILE}


Uses indentation and special keywords like make, all, clean, etc.
In above example we created default variables and next like build-client, build-server to run it just in root directory just add make prefix.

Makefile is defaulted available on Linux systems like Ubuntu or MacOS if using windows best to install and use WSL.


Integration


Makefile comes most in handy when introducing third party tools like Docker, Kubernetics, Shell scripting etc.

docker-build:
 echo "Building docker image"
 docker build . -t akshay5995/go-svelte

docker-push:
 echo "Pushing image to docker registry"
 docker login
 docker push akshay5995/go-svelte:latest

run-in-minikube:
 echo "Deploying to minikube"
 kubectl apply -f deployments/redis-master.yml
 kubectl apply -f deployments/go-deployment.yml
 echo "URL for the service"
 minikube service go-svelte --url

deploy-to-gcp:
   echo "Deploying to Google Cloud Platform"
   gcloud config set project YOUR_PROJECT_ID
   gcloud container clusters get-credentials YOUR_CLUSTER_NAME --zone YOUR_CLUSTER_ZONE
   kubectl apply -f deployments/redis-master.yml
   kubectl apply -f deployments/go-deployment.yml
   echo "URL for the service"
   kubectl get servicesm


As you can see the above commands are more lengthy and it would be a pain to type the docker build commands manually, not to mention deploying to PaaS and running kubernetes CLI commands.
Let’s say you have a separate Redis populate data in shell script.

#!/bin/bash

# Database connection parameters
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="your_database"
DB_USER="your_username"
DB_PASSWORD="your_password"

# SQL commands to clean up the database in Redis
REDIS_COMMANDS="FLUSHDB"

# SQL commands to populate the database
SQL_COMMANDS="INSERT INTO your_table (column1, column2) VALUES ('value1', 'value2');"

# Connect to Redis and execute commands
redis-cli -h $DB_HOST -p $DB_PORT -c "$REDIS_COMMANDS"

# Connect to Redis and execute commands
psql -h $DB_HOST -p $DB_PORT -d $DB_NAME -U $DB_USER -W $DB_PASSWORD -c "$SQL_COMMANDS"

# Make a POST request using curl
curl -X POST http://localhost:4000/actions/syncSourceCredAccounts?force=true


Then Makefile can be something like this.

.PHONY: clean-db clean docker-build docker-push run-in-minikube deploy-to-gcp populate-database run-all

all: clean-db clean docker-build run-in-minikube deploy-to-gcp

# Shell script to connect to Redis, clean the database, and execute commands
populate-database:
    ./populate_script.sh

...

clean-db:
    echo "Cleaning up the database in Redis"
    redis-cli FLUSHDB

# Define the 'run-all' target which depends on 'clean-db', 'clean', 'docker-build', 'populate-database', 'run-in-minikube', and 'deploy-to-gcp'
run-all: clean-db clean docker-build populate-database run-in-minikube deploy-to-gcp



I have added .PHONY in Makefile it is a special target that is used to declare a target that doesn't represent a file. 
The purpose of declaring a target as .PHONY is to ensure that the target is always considered out-of-date and its commands are executed, regardless of whether a file with the same name exists or not.
In our example clean-db doesn't generate a file, but using .PHONY helps convey to Make that it's a target intended for executing commands and not for creating a file.
When it comes to rest of the commands populate-database speaks for itself and all or run-all executes multiple make commands instead of executing them one by one.

In a nutshell Makefile is an oldie but goldie for automating your development process and minimizing manually typing different commands to be executed. 
In my article I just scratched the surface of Makefile as it’s quite flexible as it eases and saves development time.

Get fast shipping, movies & more with Amazon Prime

Start free trial

Enjoy this blog? Subscribe to Mozes711

0 Comments