Vai al contenuto

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 .PHONY per evitare conflitti con i file effettivi e migliorare le prestazioni Traduzione:

  • Le dipendenze geniali automaticamente: Utilizzare bandiere di compilatore come -MMD -MP per 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 -j per 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 @echo per 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