Makefile
Installation
Ubuntu/Debian
# Install make and build tools
sudo apt update
sudo apt install build-essential make -y
# Verify installation
make --versionCentOS/RHEL
# Install make and build tools
sudo yum groupinstall "Development Tools" -y
# Verify installation
make --versionBasic Makefile Structure
# Simple Makefile example
.PHONY: help install build test clean
help:
@echo "Available targets:"
@echo " make install - Install dependencies"
@echo " make build - Build project"
@echo " make test - Run tests"
@echo " make clean - Clean build files"
install:
@echo "Installing dependencies..."
npm install
build:
@echo "Building project..."
npm run build
test:
@echo "Running tests..."
npm test
clean:
@echo "Cleaning build files..."
rm -rf dist
rm -rf node_modulesCommon Makefile Variables
# Define variables
SHELL := /bin/bash
PROJECT_NAME := myproject
VERSION := 1.0.0
PORT := 3000
# Environment
.EXPORT_ALL_VARIABLES:
ENVIRONMENT := production
# Targets using variables
build:
@echo "Building $(PROJECT_NAME) v$(VERSION)"
run:
@echo "Running on port $(PORT)"
npm start -- --port $(PORT)
info:
@echo "Project: $(PROJECT_NAME)"
@echo "Version: $(VERSION)"
@echo "Environment: $(ENVIRONMENT)"Prerequisites & Dependencies
# Define prerequisites
.PHONY: check-node check-npm
check-node:
@command -v node >/dev/null 2>&1 || { echo "Node.js not installed"; exit 1; }
check-npm:
@command -v npm >/dev/null 2>&1 || { echo "npm not installed"; exit 1; }
# Use as prerequisite
install: check-node check-npm
npm installCommon Patterns
Docker Targets
.PHONY: docker-build docker-run docker-stop
docker-build:
docker build -t myapp:latest .
docker-run:
docker run -d -p 3000:3000 --name myapp myapp:latest
docker-stop:
docker stop myapp
docker rm myappFile Operations
.PHONY: create-dirs copy-files clean-files
create-dirs:
mkdir -p build dist src
copy-files:
cp -r src/* build/
clean-files:
rm -f *.log
find . -name "*.tmp" -deleteGit Operations
.PHONY: git-status git-commit git-push
git-status:
git status
git-commit:
git add .
git commit -m "Auto-commit"
git-push:
git push origin mainServer Management
.PHONY: start stop restart logs
start:
sudo systemctl start myapp
stop:
sudo systemctl stop myapp
restart:
sudo systemctl restart myapp
logs:
sudo journalctl -u myapp -fAdvanced Features
Conditional Statements
# Simple if-else
deploy: build
ifeq ($(ENV),production)
@echo "Deploying to production"
./deploy-prod.sh
else
@echo "Deploying to staging"
./deploy-staging.sh
endifLoops
# Loop through files
cleanup:
@for file in *.log; do \
echo "Removing $$file"; \
rm $$file; \
doneShell Commands
# Execute shell commands
version:
@echo "Version: $$(cat package.json | grep version | head -1 | awk -F: '{ print $$2 }')"
date-build:
@echo "Build time: $$(date)"Best Practices
Use .PHONY for Non-File Targets
.PHONY: all install build test clean deployAdd Help Target
help:
@echo "Available commands:"
@grep -E "^[a-zA-Z_-]+:" Makefile | sed 's/:.//' | sortUse Variables for DRY Code
SRC_DIR := src
BUILD_DIR := build
TEST_DIR := tests
# Reuse variables
build:
@echo "Building from $(SRC_DIR) to $(BUILD_DIR)"
cp -r $(SRC_DIR)/* $(BUILD_DIR)/Suppress Output
# Suppress command output
silent-build: SHELL := /bin/sh
silent-build:
@npm run build >/dev/null 2>&1
@echo "Build complete"Debugging
# Show expanded variables
make -p
# Trace execution
make -d
# Dry run (show commands without executing)
make -n
# Show specific target
make -n target-name