Notes to Self

Alex Sokolsky's Notes on Computers and Programming

make and Makefile

My definition: make is a data-driven (data is in a Makefile) filter for building ‘targets’.

GNU man page, manual, quick reference.

Tutorial

Summary of automatic variables

Manual on automatic variables

Variable Description
$@ the target name
$% the target member name, when the target is an archive member
$< just the first prerequisite
$? all the prerequisites newer than the target
$^ all the prerequisites
.PHONY Adding .PHONY to a target will prevent make from confusing the phony target with a file name. manual, one of many special built-in targets

Examples

c-simple.mak:

#
# simple C program build
#
CC=gcc
CFLAGS=-g
RM=rm -f

default: all

all: build

build: hello.c
	$(CC) $(CFLAGS) -o hello hello.c

clean:
	$(RM) hello

c.mak:

# The name of the source files
SOURCES = main.c foo.c bar.c

# The name of the executable
EXE = main

# Flags for compilation (adding warnings are always good)
CFLAGS = -g -Wall

# Flags for linking, e.g. -L./lib
LDFLAGS =

# Libraries to link with, e.g.  -lcurl
LIBS = -lcurl

# Use the GCC frontend program when compiling
CC = gcc

# Use the GCC frontend program when linking
LD = gcc

# place to store auto-generated dependencies
DEPDIR = .d

#
# Nothing to change below
#

# This creates a list of object files from the source files
OBJECTS = $(SOURCES:%.c=%.o)

.PHONY: all
# Having an "all" target is customary, so one could write "make all"
# It depends on the executable program
all: $(EXE)

# The first target, this will be the default target if none is specified
# This target tells "make" to make the "all" target
default: all


# This will link the executable from the object files
$(EXE): $(OBJECTS)
	$(LD) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(EXE)

# Target to clean up after us
.PHONY: clean
clean:
	# Remove the executable file
	rm -f $(EXE) $(OBJECTS)
	# Remove the dependencies and symbols
	rm -Rf $(DEPDIR) $(EXE).dSYM

# Advanced auto-dependency, from:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/

$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td

COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d

%.o : %.c
%.o : %.c $(DEPDIR)/%.d
	$(COMPILE.c) $(OUTPUT_OPTION) $<
	$(POSTCOMPILE)

$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d

-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES)))

python.mak

.DEFAULT_GOAL := help
SHELL:=/bin/bash
export PROJECT_ROOT = $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

# define the name of the virtual environment directory
VENV:=.venv

PYTHON=$(VENV)/bin/python3
PIP=$(VENV)/bin/pip

# targets which are NOT files
.PHONY: help venv run test clean build

help:										## Shows the help
	@echo 'Usage: make <TARGETS>'
	@echo ''
	@echo 'Available targets are:'
	@echo ''
	@grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(shell echo "$(MAKEFILE_LIST)" | tr " " "\n" | sort -r | tr "\n" " ") \
		| sed 's/Makefile[a-zA-Z\.]*://' | sed 's/\.\.\///' | sed 's/.*\///' | \
		awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}'
	@echo ''

# venv is a shortcut target
venv: $(VENV)/bin/activate                  ## Activate the venv

$(VENV)/bin/activate: requirements.txt
	python3 -m venv $(VENV)
	$(PIP) install -r requirements.txt

run: venv									## Execute python program
	$(PYTHON) main.py $(SITE)

test: venv									## Execute python tests
	$(PYTHON) -m unittest -v *_test.py

clean:										## Cleanup the artifacts
	rm -rf $(VENV) .mypy_cache
	find . -name __pycache__ | xargs rm -rf

DOCKER_USERNAME ?= john.doe
APPLICATION_NAME ?= da-app
GIT_HASH ?= $(shell git log --format="%h" -n 1)

build:								## Build docker image
	docker build --tag ${DOCKER_USERNAME}/${APPLICATION_NAME}:${GIT_HASH} .

release:							## Release docker image
	cat ./.docker-password | docker login --username ${DOCKER_USERNAME} --password-stdin
	docker push ${DOCKER_USERNAME}/${APPLICATION_NAME}:${GIT_HASH}
	docker pull ${DOCKER_USERNAME}/${APPLICATION_NAME}:${GIT_HASH}
	docker tag  ${DOCKER_USERNAME}/${APPLICATION_NAME}:${GIT_HASH} ${DOCKER_USERNAME}/${APPLICATION_NAME}:latest
	docker push ${DOCKER_USERNAME}/${APPLICATION_NAME}:latest

World class:

Support in VSCode

Makefile Support in VS Code