bash

Makefiles

Make was created for compiled languages like C and C++, but people still use them for this day for doing stuff, often random bash commands.


Makefiles usually define variables and run Targets, which look like this:

# This is a file named makefile

target: [dependencies]
        <command>
        <command 2>
        ...


They're supposed to use tabs, not spaces. Some have made it work with spaces, but it's usually tabs.


They have parameters sometimes:

# makefile example 2

CC = gcc
FILES = in_one.c in_two.c
# This line is an example of an optional param:
OUT_EXE ?= out_executable

build: $(FILES)
        $(CC) -o $(OUT_EXE) $(FILES) $(environment) $(tags)

If I run `make build OUT_EXE="test.exe"` it will output to test.exe

If I run `make build` it will output to out_executable


Be careful with changing variables, because `=` and `?=` can use the end result, rather than the value at the time.

e.g.

testvar = abcd
setme = $(testvar)
testvar = efgh

# setme is now equal to efgh
# you can use := to prevent this:

testvar2 = abcd
setme2 := $(testvar)   # <-- Key difference
testvar2 = efgh

# setme2 is now equal to abcd

I think the above is mainly used when appending text to a variable.


You can append, but it will just create a variable if it doesn't already exist:

# makefile example 3

VARIABLE += value

# another example:

grep_command = "ggrep" #GNU grep example, being run on a Mac
arguments := "-I --exclude-dir=node_modules"

arguments += "--exclude=yarn.lock"


You can use conditionals:

# makefile example 4

args := "--exclude-dir=node_modules"

# Using a wildcard function to verify file exists
ifneq ("",$(wildcard ./yarn.lock))
     args += "--exclude=yarn.lock"
endif

ifeq ("test","test")
     testvar = happened
endif

some_target:
        echo $(args)
        echo $(testvar)


This checks OS version and processor:

UNAME_S := $(shell uname -s)

ifeq ($(UNAME_S),Linux)
    CCFLAGS += -D LINUX
endif
ifeq ($(UNAME_S),Darwin)
    CCFLAGS += -D OSX
endif

UNAME_P := $(shell uname -p)
ifeq ($(UNAME_P),x86_64)
    CCFLAGS += -D AMD64
endif
ifneq ($(filter %86,$(UNAME_P)),)
    CCFLAGS += -D IA32
endif
ifneq ($(filter arm%,$(UNAME_P)),)
    CCFLAGS += -D ARM
endif

ifeq ("test","test")
        testvar = happened
endif

some_target:
        @echo $(UNAME_S)
        @echo $(UNAME_P)