Cheatsheet erstellen
Überblick
GNU Make ist ein Build Automation Tool, das automatisch ausführbare Programme und Bibliotheken aus Quellcode baut, indem Dateien namens Makefiles gelesen werden, die festlegen, wie das Zielprogramm abgeleitet werden soll.
Grundkonzepte
Makefile Struktur
target: dependencies
command
command
```_
### Schlüsselbegriffe
Target # File to be created or action to be performed Dependency # Files that target depends on Recipe # Commands to create target Rule # Target + dependencies + recipe Variable # Named value that can be reused
## Basic Makefile
### Einfaches Beispiel
```makefile
# Simple C program build
program: main.o utils.o
gcc -o program main.o utils.o
main.o: main.c
gcc -c main.c
utils.o: utils.c
gcc -c utils.c
clean:
rm -f *.o program
```_
### Mit Variablen
```makefile
CC = gcc
CFLAGS = -Wall -g
OBJECTS = main.o utils.o
TARGET = program
$(TARGET): $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
main.o: main.c
$(CC) $(CFLAGS) -c main.c
utils.o: utils.c
$(CC) $(CFLAGS) -c utils.c
clean:
rm -f $(OBJECTS) $(TARGET)
.PHONY: clean
```_
## Variablen
### Variable Definition
```makefile
# Simple assignment
CC = gcc
CFLAGS = -Wall -g
# Recursive assignment (evaluated when used)
SOURCES = $(wildcard *.c)
# Simple assignment (evaluated immediately)
OBJECTS := $(SOURCES:.c=.o)
# Conditional assignment (only if not already defined)
CC ?= gcc
# Append to variable
CFLAGS += -O2
```_
### Einbauvariablen
```makefile
# Automatic variables
$@ # Target name
# Make Cheatsheet
## Overview
GNU Make is a build automation tool that automatically builds executable programs and libraries from source code by reading files called Makefiles which specify how to derive the target program.
## Basic Concepts
### Makefile Structure
```makefile
Ziel: Abhängigkeiten
Befehl
Befehl
Key Terms
Ziel # Datei zu erstellen oder Aktion auszuführen
Abhängigkeit # Dateien, die Ziel ist abhängig von
Rezept # Befehle, um Ziel zu erstellen
Regel # Ziel + Abhängigkeiten + Rezept
Variabler # Named-Wert, der wieder verwendet werden kann
Basic Makefile
Simple Example
# Einfache C-Programm bauen
Programm: main.o utils.o
gcc -o Programm main.o utils. o
Haupt.o: Haupt.c
gcc -c main. c)
utils.o: utils.c
gcc -c utils. c)
sauber:
rm -f *.o Programm
With Variables
CC = gcc
CFLAGS = -Wall -g
OBJECTS = main.o utils.o
TARGET = Programm
$(TARGET): $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
Haupt.o: Haupt.c
$(CC) $(CFLAGS) -c main. c)
utils.o: utils.c
$(CC) $(CFLAGS) -c utils. c)
sauber:
rm -f $(OBJECTS) $(TARGET)
. PHONY: sauber
Variables
Variable Definition
# Einfache Zuordnung
CC = gcc
CFLAGS = -Wall -g
# Wiederkehrende Zuordnung (bewertet bei Verwendung)
GERICHTE = $(wildcard *.c)
# Einfache Zuordnung (ausgewertet sofort)
OBJECTS:= $(SOURCEN:.c=.o)
# Zustandszuweisung (nur wenn nicht bereits definiert)
CC ?= gcc
# Anpassung an Variable
CFLAGS += -O2
Built-in Variables
`< # First dependency $^ # All dependencies $? # Dependencies newer than target $* # Stem of pattern rule match
Example usage
%.o: %.c $(CC) $(CFLAGS) -c $< -o $@ ```_
Umweltvariablen
```makefile
Use environment variables
HOME_DIR = $(HOME) PATH_VAR = $(PATH)
Override environment variables
export CC = gcc export CFLAGS = -Wall ```_
Musterregeln
Grundmuster
```makefile
Pattern rule for C files
%.o: %.c $(CC) $(CFLAGS) -c $< -o $@
Pattern rule for C++ files
%.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@
Multiple patterns
%.o: %.c %.h $(CC) $(CFLAGS) -c $< -o $@ ```_
Erweiterte Muster
```makefile
Static pattern rule
$(OBJECTS): %.o: %.c $(CC) $(CFLAGS) -c $< -o $@
Pattern with subdirectories
build/%.o: src/%.c @mkdir -p build $(CC) $(CFLAGS) -c $< -o $@ ```_
Funktionen
String Funktionen
```makefile
Substitution
SOURCES = main.c utils.c OBJECTS = $(SOURCES:.c=.o)
or
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
Word functions
FIRST_WORD = $(firstword $(SOURCES)) WORD_COUNT = $(words $(SOURCES)) NTH_WORD = $(word 2,$(SOURCES))
Filter functions
C_FILES = $(filter %.c,$(SOURCES)) NOT_MAIN = $(filter-out main.c,$(SOURCES)) ```_
Dateifunktionen
```makefile
Wildcard
SOURCES = $(wildcard src/.c) HEADERS = $(wildcard include/.h)
Directory functions
SRC_DIRS = $(dir $(SOURCES)) BASE_NAMES = $(notdir $(SOURCES)) BASENAMES = $(basename $(SOURCES)) SUFFIXES = $(suffix $(SOURCES))
Path manipulation
ABS_PATH = $(abspath relative/path) REAL_PATH = $(realpath symlink/path) ```_
Bedingte Funktionen
```makefile
If function
RESULT = $(if $(DEBUG),debug,release)
Or function
COMPILER = $(or $(CC),gcc)
And function
VALID = $(and $(CC),$(SOURCES)) ```_
Bedingte Aussagen
ifeq/ifneq
```makefile ifeq ($(DEBUG),1) CFLAGS += -g -DDEBUG else CFLAGS += -O2 -DNDEBUG endif
ifneq ($(OS),Windows_NT) CFLAGS += -fPIC endif ```_
ifdef/ifndef
```makefile ifdef DEBUG CFLAGS += -g endif
ifndef CC CC = gcc endif ```_
Zustandszuweisung
```makefile
Set if not already defined
CC ?= gcc
Set based on condition
CFLAGS = $(if $(DEBUG),-g -O0,-O2) ```_
Erweiterte Funktionen
Dateien einschließen
```makefile
Include other makefiles
include config.mk include $(wildcard *.d)
Silent include (no error if file doesn't exist)
-include optional.mk ```_
Dependance Generation
```makefile
Automatic dependency generation
DEPDIR := .deps DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
%.o: %.c $(DEPDIR)/%.d|$(DEPDIR) $(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
$(DEPDIR): @mkdir -p $@
DEPFILES := $(SOURCES:%.c=$(DEPDIR)/%.d) $(DEPFILES):
include $(wildcard $(DEPFILES)) ```_
Nur Voraussetzungen
```makefile
Create directory before building objects
$(OBJECTS):|$(OBJDIR)
$(OBJDIR): mkdir -p $(OBJDIR) ```_
Phony Ziele
Gemeinsame Phony Ziele
```makefile .PHONY: all clean install test help
all: $(TARGET)
clean: rm -f $(OBJECTS) $(TARGET)
install: $(TARGET) cp $(TARGET) /usr/local/bin/
test: $(TARGET) ./$(TARGET) --test
help: @echo "Available targets:" @echo " all - Build the program" @echo " clean - Remove build files" @echo " install - Install the program" @echo " test - Run tests" ```_
Multi-Target baut
Mehrere Programme
```makefile PROGRAMS = client server COMMON_OBJS = utils.o network.o
all: $(PROGRAMS)
client: client.o $(COMMON_OBJS) $(CC) -o $@ $^
server: server.o $(COMMON_OBJS) $(CC) -o $@ $^
clean: rm -f *.o $(PROGRAMS)
.PHONY: all clean ```_
Bibliotheksgebäude
```makefile LIBNAME = libutils STATIC_LIB = $(LIBNAME).a SHARED_LIB = $(LIBNAME).so LIB_OBJS = utils.o network.o
all: $(STATIC_LIB) $(SHARED_LIB)
$(STATIC_LIB): $(LIB_OBJS) ar rcs $@ $^
$(SHARED_LIB): $(LIB_OBJS) $(CC) -shared -o $@ $^
%.o: %.c $(CC) $(CFLAGS) -fPIC -c $< -o $@ ```_
Verwendung der Befehlszeile
Grundlegende Befehle
```bash
Build default target
make
Build specific target
make clean make install
Build with variables
make DEBUG=1 make CC=clang
Parallel builds
make -j4 make -j$(nproc)
Dry run (show commands without executing)
make -n
Silent mode
make -s
Keep going on errors
make -k ```_
Debugging
```bash
Print variables
make -p
Debug mode
make -d
Print database
make --print-data-base
Trace execution
make --trace ```_
Komplexe Beispiele
C++ Projekt
```makefile CXX = g++ CXXFLAGS = -std=c++17 -Wall -Wextra -g LDFLAGS = -lpthread
SRCDIR = src OBJDIR = obj SOURCES = $(wildcard $(SRCDIR)/*.cpp) OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) TARGET = myprogram
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJECTS) $(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp|$(OBJDIR) $(CXX) $(CXXFLAGS) -c $< -o $@
$(OBJDIR): mkdir -p $(OBJDIR)
clean: rm -rf $(OBJDIR) $(TARGET)
Dependency generation
-include $(OBJECTS:.o=.d)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp|$(OBJDIR) $(CXX) -MM -MT $(@:.d=.o) $< >`` $@ ```_
Multidirektorprojekt
```makefile
Project structure
PROJECT_ROOT = . SRC_DIRS = src src/utils src/network INC_DIRS = include OBJ_DIR = build BIN_DIR = bin
Find all source files
SOURCES = $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c)) OBJECTS = $(SOURCES:%.c=$(OBJ_DIR)/%.o) TARGET = $(BIN_DIR)/myapp
Compiler settings
CC = gcc CFLAGS = -Wall -g $(addprefix -I,$(INC_DIRS)) LDFLAGS = -lm
.PHONY: all clean dirs
all: dirs $(TARGET)
dirs: @mkdir -p $(OBJ_DIR) $(BIN_DIR) @mkdir -p $(foreach dir,$(SRC_DIRS),$(OBJ_DIR)/$(dir))
$(TARGET): $(OBJECTS) $(CC) $^ -o $@ $(LDFLAGS)
$(OBJ_DIR)/%.o: %.c $(CC) $(CFLAGS) -c $< -o $@
clean: rm -rf $(OBJ_DIR) $(BIN_DIR) ```_
Best Practices
Makefile Organisation
```makefile
Variables at the top
CC = gcc CFLAGS = -Wall -g TARGET = myprogram
Default target first
all: $(TARGET)
Pattern rules
%.o: %.c $(CC) $(CFLAGS) -c $< -o $@
Specific rules
$(TARGET): $(OBJECTS) $(CC) $^ -o $@
Phony targets at the end
.PHONY: all clean install
clean: rm -f *.o $(TARGET) ```_
Fehlerbehebung
```makefile
Check for required tools
ifeq ($(shell which $(CC)),) $(error Compiler $(CC) not found) endif
Validate variables
ifndef SOURCES $(error SOURCES variable is not defined) endif
Conditional compilation
ifeq ($(shell pkg-config --exists gtk+-3.0; echo $?),0) CFLAGS += $(shell pkg-config --cflags gtk+-3.0) LDFLAGS += $(shell pkg-config --libs gtk+-3.0) else $(warning GTK+ 3.0 not found, building without GUI) endif ```_
Leistungsspitzen
```makefile
Use order-only prerequisites for directories
$(OBJECTS):|$(OBJDIR)
Minimize shell calls
SOURCES := $(shell find src -name '*.c')
Use built-in rules when possible
Instead of:
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
Just use the built-in rule
Parallel-safe directory creation
$(OBJDIR): @mkdir -p $@ ```_
Integration
Mit Versionskontrolle
```makefile
Get version from git
VERSION = $(shell git describe --tags --always --dirty) CFLAGS += -DVERSION=\"$(VERSION)\"
Include git info
GIT_COMMIT = $(shell git rev-parse HEAD) BUILD_DATE = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") CFLAGS += -DGIT_COMMIT=\"$(GIT_COMMIT)\" -DBUILD_DATE=\"$(BUILD_DATE)\" ```_
Mit Paketmanagern
```makefile
pkg-config integration
CFLAGS += $(shell pkg-config --cflags libssl) LDFLAGS += $(shell pkg-config --libs libssl)
Check dependencies
check-deps: | @pkg-config --exists libssl | | (echo "libssl not found" && exit 1) | ```_
Fehlerbehebung
Gemeinsame Themen
```bash
Missing separator error
Make sure recipes use tabs, not spaces
Target not found
make: *** No rule to make target 'foo'. Stop.
Check target name and dependencies
Circular dependency
make: Circular dependency dropped.
Review dependency chain
Debug makefile
make -p|grep target_name make -d ```_
Debugging Tipps
```makefile
Print variable values
debug: @echo "CC = $(CC)" @echo "CFLAGS = $(CFLAGS)" @echo "SOURCES = $(SOURCES)" @echo "OBJECTS = $(OBJECTS)"
Check if file exists
check-file: | @test -f myfile.c && echo "File exists" | | echo "File missing" | ```_
Ressourcen
- Amtshandbuch: [gnu.org/software/make/manual](https://__LINK_4___
- GNU Make: [gnu.org/software/make](__LINK_4___
- Tutorial: [makefiletutorial.com](__LINK_4___
- *Best Practices: clarkgrubb.com/makefile-style-guide