Saltar a contenido

GNU Hacer Cheatsheet

Instalación

Platform Command
Ubuntu/Debian INLINE_CODE_23 or INLINE_CODE_24
RHEL/CentOS/Fedora INLINE_CODE_25 or INLINE_CODE_26
Arch Linux INLINE_CODE_27 or INLINE_CODE_28
Alpine Linux INLINE_CODE_29
macOS (Xcode) INLINE_CODE_30
macOS (Homebrew) INLINE_CODE_31 (installs as INLINE_CODE_32)
Windows (Chocolatey) INLINE_CODE_33
Windows (WSL) INLINE_CODE_34
Verification INLINE_CODE_35

Comandos básicos

Command Description
INLINE_CODE_36 Build the first target in Makefile (usually 'all')
INLINE_CODE_37 Build a specific target (e.g., INLINE_CODE_38, INLINE_CODE_39)
INLINE_CODE_40 Remove generated files (must be defined in Makefile)
INLINE_CODE_41 Dry run - show commands without executing them
INLINE_CODE_42 Use a specific makefile instead of default
INLINE_CODE_43 Change to directory before executing
INLINE_CODE_44 Set/override a variable from command line
INLINE_CODE_45 Override compilation flags
INLINE_CODE_46 Run 4 jobs in parallel for faster builds
INLINE_CODE_47 Use all available CPU cores for parallel builds
INLINE_CODE_48 Silent mode - don't print commands being executed
INLINE_CODE_49 Ignore errors and continue building
INLINE_CODE_50 Keep going after errors, skip failed targets
INLINE_CODE_51 Unconditionally rebuild all targets
INLINE_CODE_52 Touch files to update timestamps without rebuilding
INLINE_CODE_53 Check if target needs rebuilding (exit code 0=no, 1=yes)

Comandos Avanzados

Command Description
INLINE_CODE_54 Show detailed debug information during execution
INLINE_CODE_55 Show basic debug information (less verbose)
INLINE_CODE_56 Print all rules and variable values
INLINE_CODE_57 Show all built-in rules and variables
INLINE_CODE_58 Warn when undefined variables are referenced
INLINE_CODE_59 Parallel builds with system load limiting
INLINE_CODE_60 Synchronize output for parallel builds
INLINE_CODE_61 Group output by target in parallel builds
INLINE_CODE_62 Show why each target is being remade
INLINE_CODE_63 Environment variables override Makefile variables
INLINE_CODE_64 Disable built-in implicit rules
INLINE_CODE_65 Disable built-in variables
INLINE_CODE_66 Check symlink times instead of target times
INLINE_CODE_67 Set multiple variables from command line
INLINE_CODE_68 Print working directory before and after execution

Makefile Syntax

Basic Structure

# 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

Variables automáticas

Variable Description
INLINE_CODE_69 Target name
INLINE_CODE_70 First prerequisite
INLINE_CODE_71 All prerequisites (space-separated)
INLINE_CODE_72 Prerequisites newer than target
INLINE_CODE_73 Stem of pattern match
INLINE_CODE_74 Directory part of target
INLINE_CODE_75 File part of target
INLINE_CODE_76 Directory part of first prerequisite
INLINE_CODE_77 File part of first prerequisite

Funciones incorporadas

# 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))

Directivas condicionales

# 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

Pattern Rules

# 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 $@

Configuración

Standard Makefile Variables

# 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

Configuración de proyectos multi-file

# 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)

Incluido la configuración externa

# 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 Ejemplo

# 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++ Project Build System

# 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: Documentation Generation

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

Buenas prácticas

Use .PHONY__ targets*: Declarar objetivos que no crean archivos como .PHONY para evitar conflictos con archivos reales y mejorar el rendimiento makefile .PHONY: all clean install test

  • Las dependencias generadas automáticamente: Usar banderas de compilador como __INLINE_CODE_80_ para rastrear automáticamente las dependencias de archivos de cabecera, evitando las reconstrucciones incompletas makefile DEPS = $(OBJECTS:.o=.d) -include $(DEPS) $(CC) $(CFLAGS) -MMD -MP -c $< -o $@

Crear directorios automáticamente Use @mkdir -p $(dir $@)_ antes de crear archivos de salida para asegurar que existan directorios de destino makefile $(BUILDDIR)/%.o: $(SRCDIR)/%.c @mkdir -p $(dir $@) $(CC) -c $< -o $@

  • Use variables para flexibilidad: Definir compilador, banderas y caminos como variables en la parte superior de su Makefile para fácil personalización y mantenimiento makefile CC = gcc CFLAGS = -Wall -O2 PREFIX = /usr/local

  • La distancia se construye paralelamente: Use make -j para construir más rápido sistemas multi-core, especialmente para grandes proyectos con unidades de compilación independientes

  • Fuente separada y directorios de construcción*: Mantenga los archivos generados en un directorio independiente build/ para mantener los árboles de fuente limpia y simplificar .gitignore_

  • Use reglas de patrón sobre reglas explícitas: Las reglas del patrón como %.o: %.c son más sostenibles y escalables que escribir reglas individuales para cada archivo

  • Proporción de salida informativa: Use @echo_ para proporcionar mensajes de progreso de construcción al suprimir el comando haciendo eco con @ para una salida más limpia makefile $(TARGET): $(OBJECTS) @echo "Linking $@..." @$(CC) $^ -o $@

Troubleshooting

Issue Solution
"missing separator" error Ensure recipe lines are indented with TAB characters, not spaces. Configure your editor to insert tabs in Makefiles
Target always rebuilds Check file timestamps with INLINE_CODE_88. Use INLINE_CODE_89 to debug why Make thinks rebuild is needed. Verify prerequisites exist and have correct timestamps
Variables are empty Use INLINE_CODE_90 to print all variables and their values. Check for typos in variable names. Verify variable assignment syntax (INLINE_CODE_91 vs INLINE_CODE_92 vs INLINE_CODE_93)
Parallel build failures Some targets may have missing dependencies. Run INLINE_CODE_94 to identify the issue, then add proper prerequisites. Use order-only prerequisites (INLINE_CODE_95) for directory creation
"No rule to make target" error Verify the target name is spelled correctly. Check that prerequisite files exist. Use INLINE_CODE_96 to see all available targets
Commands not found Ensure required tools are installed and in PATH. Use full paths for commands or check with INLINE_CODE_97. Prefix with INLINE_CODE_98 to suppress output and see actual errors
Recursive make issues Use INLINE_CODE_99 instead of INLINE_CODE_100 in recipes. Export necessary variables with INLINE_CODE_101. Consider using INLINE_CODE_102 to change directories instead of recursive makes
Pattern rules not matching Verify pattern syntax (INLINE_CODE_103 placement). Check that source files exist in expected locations. Use INLINE_CODE_104 to see rule matching process
Changes not detected Ensure file modification times are correct. Use INLINE_CODE_105 to force rebuild. Check if using INLINE_CODE_106 touched files incorrectly. Verify dependencies are listed correctly
** Problemas de la ruta de Windows** ← Usar barras delanteras / en lugar de barras traseras. Considere usar MSYS2 o WSL para una mejor compatibilidad. Usar $(subst \,/,$(PATH))_ para convertir caminos si es necesario