Makefile

# `:=` (Simple Assignment): This is known as immediate or simple assignment. The right-hand side is evaluated once, at the time of the variable assignment. Subsequent references to the variable use the already computed value. It is useful when you want to avoid recomputing the value each time the variable is referenced.
VAR := $(shell echo "Hello")
 
# = (Simple Recursive Assignment): This is known as recursive assignment. The right-hand side is re-evaluated every time the variable is referenced. It means that if the variable is used multiple times, the right-hand side is executed each time.
VAR = $(shell echo "Hello")
 
# ?= (Conditional Assignment): This operator only sets the variable if it doesn't already have a value. It's useful for providing default values.
VAR ?= default_value
 
# command to execute if no argument
default: help
 
# set default variable
# can be override by setting in argument: make app_name=popo
app_name=foobar
# set a variable from command
project_name=$(shell basename "$(PWD)")
# only set variable if env variable is not already defined
JAVA_HOME?=/opt/java
# stops commandline arguments from changing this variable
override username=admin
 
# variables can be used using $() or ${}
echo-variables:
	@echo ${app_name}
	@echo $(project_name)
 
# avoid phony rules breaking when a real file has the same name as the command
.PHONY: help
# command example that read the Makefile and print all lines with prefix ##
help: Makefile
	@echo
	@echo " Choose a command run in "$(project_name)":"
	@echo
	@sed -n 's/^##//p' $< | column -t -s ':' |  sed -e 's/^/ /'
	@echo
 
foobar:
	cat foo > foo.txt
	# @ stops the command from being echoed to stdout
	@cat foo > foo.txt
	# - means that make will keep going even if there is an error
	-@cat foo > foo.txt
 
 
file0.txt:
	echo "foo" > file0.txt
 
# this rule will only run if the file0.txt is newer than file1.txt
file1.txt: file0.txt
	cat file0.txt > file1.txt
 
# a rule can have multiple targets and multiple prerequisites
all: file0.txt file1.txt
 
process: file*.txt  #using a wildcard to match filenames
	@echo $^    # $^ is a variable containing the list of prerequisites
	@echo $@    # prints the target name
	@echo $<    # the first prerequisite listed
	@echo $?    # only the dependencies that are out of date
	@echo $+    # all dependencies including duplicates (unlike normal)
 
# multi lines are possible, but the shell receives the whole command concatenated into a single
# line, so we also need to terminate with a semi-colon
#
# escape with a $ for using bash scripts and variables
multi-lines:
	@for f in $$(ls); do \
		echo $$f; \
	done