GNU # Fare il Cheatsheet¶
Installazione¶
Tabella_116_
Comandi di base¶
Tabella_117_
Comandi avanzati¶
Tabella_118
Makefile Syntax¶
Struttura di base¶
# Variable definitions
CC = gcc
CFLAGS = -Wall -O2
SOURCES = main.c utils.c
OBJECTS = $(SOURCES:.c=.o)
# Target: prerequisites
target: prerequisite1 prerequisite2
command1 # Must use TAB, not spaces
command2
# Phony targets (not actual files)
.PHONY: all clean install
all: program
program: $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJECTS) program
Variabili automatici¶
Tabella_119_
Funzioni integrate¶
# Wildcard expansion
SOURCES = $(wildcard src/*.c)
# Pattern substitution
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
OBJECTS = $(SOURCES:.c=.o) # Shorthand
# Directory/file operations
DIRS = $(dir $(SOURCES))
FILES = $(notdir $(SOURCES))
BASENAME = $(basename $(SOURCES))
# Shell execution
GIT_VERSION = $(shell git describe --tags)
FILE_COUNT = $(shell ls -1 *.c | wc -l)
# Conditional
BUILD_TYPE = $(if $(DEBUG),debug,release)
# Foreach loop
DIRS = src lib bin
ALL_SOURCES = $(foreach dir,$(DIRS),$(wildcard $(dir)/*.c))
# Filter operations
C_FILES = $(filter %.c,$(SOURCES))
NOT_TEST = $(filter-out %_test.c,$(SOURCES))
# String operations
UPPERCASE = $(shell echo $(PROJECT) | tr a-z A-Z)
JOINED = $(subst $(space),$(comma),$(LIST))
Direttive condizionali¶
# ifdef/ifndef
ifdef DEBUG
CFLAGS += -g -DDEBUG
else
CFLAGS += -O2
endif
# ifeq/ifneq
ifeq ($(CC),gcc)
CFLAGS += -fno-strict-aliasing
endif
ifneq ($(PLATFORM),windows)
LDFLAGS += -lpthread
endif
# Comparing strings
ifeq ($(strip $(VERBOSE)),1)
Q =
else
Q = @
endif
Regole del modello¶
# Basic pattern rule
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Multiple patterns
%: %.c
$(CC) $(CFLAGS) $< -o $@
# Static pattern rules
OBJECTS = foo.o bar.o baz.o
$(OBJECTS): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
# With different directories
$(BUILDDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
Configurazione¶
Variabili standard del Makefile¶
# Compilers
CC = gcc # C compiler
CXX = g++ # C++ compiler
AS = as # Assembler
AR = ar # Archive tool
LD = ld # Linker
# Compiler flags
CFLAGS = -Wall -O2 # C compilation flags
CXXFLAGS = -Wall -O2 # C++ compilation flags
CPPFLAGS = -I./include # Preprocessor flags
LDFLAGS = -L./lib # Linker flags
LDLIBS = -lm -lpthread # Libraries to link
# Installation directories
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
LIBDIR = $(PREFIX)/lib
INCLUDEDIR = $(PREFIX)/include
# Project structure
SRCDIR = src
BUILDDIR = build
OBJDIR = $(BUILDDIR)/obj
BINDIR_LOCAL = bin
Multifile Project Configuration¶
# Project metadata
PROJECT = myapp
VERSION = 1.0.0
DESCRIPTION = My Application
# Source discovery
SOURCES = $(wildcard $(SRCDIR)/*.c)
HEADERS = $(wildcard $(SRCDIR)/*.h)
OBJECTS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES))
# Dependencies
DEPS = $(OBJECTS:.o=.d)
# Include dependency files
-include $(DEPS)
# Automatic dependency generation
$(OBJDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(CPPFLAGS) -MMD -MP -c $< -o $@
# Target-specific variables
debug: CFLAGS += -g -DDEBUG -O0
debug: $(PROJECT)
release: CFLAGS += -O3 -DNDEBUG
release: $(PROJECT)
Compresa configurazione esterna¶
# Main Makefile
-include config.mk # Optional local config
-include $(HOME)/.makerc # User-specific settings
include rules.mk # Required shared rules
# Export variables to sub-makes
export CC CXX CFLAGS LDFLAGS
config. mk Esempio¶
# Local machine-specific configuration
# This file is not committed to version control
# Override compiler
CC = clang
CXX = clang++
# Add sanitizers for development
CFLAGS += -fsanitize=address -fsanitize=undefined
LDFLAGS += -fsanitize=address -fsanitize=undefined
# Custom installation prefix
PREFIX = /opt/myapp
# Enable verbose output
VERBOSE = 1
Common Use Cases¶
Use Case 1: C/C++ Sistema di creazione di progetti¶
# Makefile for C project with separate source/build directories
PROJECT = myprogram
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -O2
LDFLAGS = -lm
SRCDIR = src
BUILDDIR = build
BINDIR = bin
SOURCES = $(wildcard $(SRCDIR)/*.c)
OBJECTS = $(patsubst $(SRCDIR)/%.c,$(BUILDDIR)/%.o,$(SOURCES))
DEPS = $(OBJECTS:.o=.d)
.PHONY: all clean install
all: $(BINDIR)/$(PROJECT)
$(BINDIR)/$(PROJECT): $(OBJECTS)
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
@echo "Build complete: $@"
$(BUILDDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
clean:
rm -rf $(BUILDDIR) $(BINDIR)
install: $(BINDIR)/$(PROJECT)
install -m 0755 $< /usr/local/bin/
-include $(DEPS)
# Build commands
make # Build project
make clean # Remove build artifacts
make install # Install to system
make -j4 # Parallel build with 4 jobs
Use Case 2: Multi-Target Build with Debug/Release¶
PROJECT = myapp
SRCDIR = src
BUILDDIR_DEBUG = build/debug
BUILDDIR_RELEASE = build/release
SOURCES = $(wildcard $(SRCDIR)/*.c)
OBJECTS_DEBUG = $(patsubst $(SRCDIR)/%.c,$(BUILDDIR_DEBUG)/%.o,$(SOURCES))
OBJECTS_RELEASE = $(patsubst $(SRCDIR)/%.c,$(BUILDDIR_RELEASE)/%.o,$(SOURCES))
CC = gcc
CFLAGS_COMMON = -Wall -Wextra -std=c11
CFLAGS_DEBUG = $(CFLAGS_COMMON) -g -O0 -DDEBUG
CFLAGS_RELEASE = $(CFLAGS_COMMON) -O3 -DNDEBUG
.PHONY: all debug release clean
all: debug release
debug: $(BUILDDIR_DEBUG)/$(PROJECT)
release: $(BUILDDIR_RELEASE)/$(PROJECT)
$(BUILDDIR_DEBUG)/$(PROJECT): $(OBJECTS_DEBUG)
@mkdir -p $(dir $@)
$(CC) $^ -o $@
$(BUILDDIR_RELEASE)/$(PROJECT): $(OBJECTS_RELEASE)
@mkdir -p $(dir $@)
$(CC) $^ -o $@
$(BUILDDIR_DEBUG)/%.o: $(SRCDIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS_DEBUG) -c $< -o $@
$(BUILDDIR_RELEASE)/%.o: $(SRCDIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS_RELEASE) -c $< -o $@
clean:
rm -rf build
# Usage
make debug # Build debug version
make release # Build release version
make all # Build both versions
Use Case 3: Testing and Code Quality¶
PROJECT = myapp
TEST_DIR = tests
TEST_SOURCES = $(wildcard $(TEST_DIR)/*_test.c)
TEST_BINS = $(patsubst $(TEST_DIR)/%.c,$(TEST_DIR)/bin/%,$(TEST_SOURCES))
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -I./src
LDFLAGS = -lcheck -lm
.PHONY: all test coverage lint clean
all: $(PROJECT)
test: $(TEST_BINS)
@echo "Running tests..."
@for test in $(TEST_BINS); do \
echo "Running $$test..."; \
$$test || exit 1; \
done
@echo "All tests passed!"
$(TEST_DIR)/bin/%: $(TEST_DIR)/%.c src/*.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
coverage: CFLAGS += --coverage
coverage: LDFLAGS += --coverage
coverage: clean test
gcov src/*.c
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory coverage_html
lint:
cppcheck --enable=all --suppress=missingIncludeSystem src/
clang-tidy src/*.c -- $(CFLAGS)
clean:
rm -rf $(TEST_DIR)/bin *.gcda *.gcno *.gcov coverage.info coverage_html
# Usage
make test # Run all tests
make coverage # Generate coverage report
make lint # Run static analysis
Use Case 4: Generazione di documentazione¶
PROJECT = myapp
DOC_DIR = docs
BUILD_DOC_DIR = $(DOC_DIR)/build
SOURCES = $(wildcard src/*.c src/*.h)
MD_FILES = $(wildcard $(DOC_DIR)/*.md)
.PHONY: docs docs-html docs-pdf clean-docs
docs: docs-html docs-pdf
docs-html: $(BUILD_DOC_DIR)/html/index.html
docs-pdf: $(BUILD_DOC_DIR)/$(PROJECT).pdf
# Generate HTML documentation with Doxygen
$(BUILD_DOC_DIR)/html/index.html: $(SOURCES) Doxyfile
@mkdir -p $(BUILD_DOC_DIR)
doxygen Doxyfile
# Generate PDF from Markdown
$(BUILD_DOC_DIR)/$(PROJECT).pdf: $(MD_FILES)
@mkdir -p $(BUILD_DOC_DIR)
pandoc $(MD_FILES) -o $@ \
--toc \
--number-sections \
-V geometry:margin=1in
# Generate man pages
$(BUILD_DOC_DIR)/man/$(PROJECT).1: $(DOC_DIR)/$(PROJECT).1.md
@mkdir -p $(dir $@)
pandoc $< -s -t man -o $@
clean-docs:
rm -rf $(BUILD_DOC_DIR)
# Usage
make docs # Generate all documentation
make docs-html # Generate HTML docs only
make docs-pdf # Generate PDF docs only
Use Case 5: Asset Processing Pipeline¶
SRC_IMG_DIR = assets/images
DIST_IMG_DIR = dist/images
SRC_CSS_DIR = assets/css
DIST_CSS_DIR = dist/css
SRC_JS_DIR = assets/js
DIST_JS_DIR = dist/js
PNG_SOURCES = $(wildcard $(SRC_IMG_DIR)/*.png)
PNG_OPTIMIZED = $(patsubst $(SRC_IMG_DIR)/%.png,$(DIST_IMG_DIR)/%.png,$(PNG_SOURCES))
SCSS_SOURCES = $(wildcard $(SRC_CSS_DIR)/*.scss)
CSS_FILES = $(patsubst $(SRC_CSS_DIR)/%.scss,$(DIST_CSS_DIR)/%.css,$(SCSS_SOURCES))
JS_SOURCES = $(wildcard $(SRC_JS_DIR)/*.js)
JS_MINIFIED = $(patsubst $(SRC_JS_DIR)/%.js,$(DIST_JS_DIR)/%.min.js,$(JS_SOURCES))
.PHONY: all assets images css js clean
all: assets
assets: images css js
images: $(PNG_OPTIMIZED)
css: $(CSS_FILES)
js: $(JS_MINIFIED)
# Optimize PNG images
$(DIST_IMG_DIR)/%.png: $(SRC_IMG_DIR)/%.png
@mkdir -p $(dir $@)
optipng -o7 $< -out $@
# Compile SCSS to CSS
$(DIST_CSS_DIR)/%.css: $(SRC_CSS_DIR)/%.scss
@mkdir -p $(dir $@)
sass --style=compressed $< $@
# Minify JavaScript
$(DIST_JS_DIR)/%.min.js: $(SRC_JS_DIR)/%.js
@mkdir -p $(dir $@)
uglifyjs $< -c -m -o $@
clean:
rm -rf dist
# Usage
make assets # Process all assets
make images # Optimize images only
make css # Compile SCSS only
make js # Minify JavaScript only
make -j4 assets # Process in parallel
Migliori Pratiche¶
-
Utilizzare gli obiettivi
.PHONY_: Denuncia obiettivi che non creano file come.PHONYper evitare conflitti con i file effettivi e migliorare le prestazioni Traduzione: -
Le dipendenze geniali automaticamente: Utilizzare bandiere di compilatore come
-MMD -MPper monitorare automaticamente le dipendenze dei file di intestazione, evitando ricostruzioni incomplete Traduzione: -
**Crea le directory automaticamente * Utilizzare
@mkdir -p $(dir $@)prima di creare file di output per garantire l'esistenza di directory target Traduzione: -
** Utilizzare variabili per flessibilità**: Definire compilatore, bandiere e percorsi come variabili in cima al Makefile per una facile personalizzazione e manutenzione Traduzione:
-
Leverage parallel Builds: Utilizzare
make -jper costruire più velocemente su sistemi multi-core, soprattutto per grandi progetti con unità di compilazione indipendenti -
Separare fonte e costruire directory: Mantenere i file generati in una directory separata
build/_ per mantenere alberi di origine pulita e semplificare la gestione.gitignore -
** Utilizzare le regole del modello su regole esplicite**: Regole del modello come
%.o: %.c_ sono più manutenbili e scalabili di scrivere regole individuali per ogni file -
Provi l'output informativo: Utilizzare
@echoper fornire messaggi di progresso durante la soppressione del comando eco con@_ per l'output più pulito Traduzione:
Risoluzione dei problemi¶
Traduzione: ** Problemi di percorso di Windows** | Utilizzare slash in avanti / invece di backslashes. Considerare l'utilizzo di MSYS2 o WSL per una migliore compatibilità. Utilizzare $(subst \,/,$(PATH))_ per convertire i percorsi se necessario