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 -jpara 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: %.cson 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 limpiamakefile $(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 |