25/9/25 Makefile
Programación de Sistemas Avanzados
GERARDO ANDRES, ALBERTO
218798964
Actividad: Diseño y optimización de un Makefile
Parte 1: El Escenario
Parte 2: Makefile
1. Diseño del Makefile:
CC := gcc
CFLAGS := -Wall -Wextra -O2 -Isrc -Ilib
LDFLAGS :=
BUILD_DIR:= build
BIN_DIR := bin
SRC_DIR := src
LIB_DIR := lib
TARGET := $(BIN_DIR)/mi_app
SRC_FILES := $(wildcard $(SRC_DIR)/*.c)
LIB_FILES := $(wildcard $(LIB_DIR)/*.c)
OBJ := $(patsubst
$(SRC_DIR)/%.c,$(BUILD_DIR)/$(SRC_DIR)/%.o,$(SRC_FILES)) $(patsubs
t $(LIB_DIR)/%.c,$(BUILD_DIR)/$(LIB_DIR)/%.o,$(LIB_FILES))
DEPS := $(OBJ:.o=.d)
.PHONY: all clean run
all: $(TARGET)
$(TARGET): $(OBJ) | $(BIN_DIR)
$(CC) $(OBJ) -o $@ $(LDFLAGS)
@echo ">>> Generado $@"
$(BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
@echo "cc $< -> $@"
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
-include $(DEPS)
run: $(TARGET)
./$(TARGET)
clean:
@rm -rf $(BUILD_DIR) $(BIN_DIR)
@echo ">>> Limpiado: $(BUILD_DIR) y $(BIN_DIR)"
2.
Ejecución y resultados:
Ejecución de Make
Resultados de las carpetas creadas
Resultado del ejecutable mi_app:
2. Modificación y Optimización:
Make con el cambio en utility.c
Ejecución de mi_app con el cambio:
3. Make Clean:
Resultado de la limpieza
4. ¿Por qué es importante que calculator.h sea prerrequisito de
main.c?
Porque main.c depende de las declaraciones de funciones expuestas en calculator.h.
Si el header cambia (por ejemplo, firmas de funciones, macros, constantes), main.c
debe recompilarse para validar y reflejar esos cambios. Si no se declara la
dependencia, podrías enlazar con objetos inconsistentes o pasar por alto errores de
compilación, produciendo comportamientos indefinidos o fallas de enlace.
3. Investigación y Documentación (Tarea de Investigación), esto va
en la introducción.
1. Proceso de compilación de C/C++
• Preprocesamiento: el preprocesador expande #include, resuelve macros
#define, y evalúa directivas condicionales (#if, #ifdef). La salida sigue
siendo código fuente, pero “plano”, sin macros ni includes pendientes.
• Compilación: cada .c se traduce a código ensamblador específico de la
arquitectura, aplicando análisis léxico/sintáctico, comprobaciones y
optimizaciones.
• Ensamblado: el ensamblador convierte el ensamblador en código objeto
(.o) con símbolos y secciones.
• Enlazado (linking): el enlazador combina múltiples .o (y librerías) en un
ejecutable (o librería), resolviendo referencias entre símbolos (por ejemplo,
que main encuentre add).
2. Cómo un Makefile automatiza y simplifica
Un Makefile define reglas (qué construir), prerrequisitos (de qué depende) y
comandos (cómo construir). Make calcula qué está desactualizado comparando
marcas de tiempo: si un archivo fuente o cabecera cambia, recompila solo los
objetos afectados y vuelve a enlazar el binario. Con reglas genéricas (patrones
%.o: %.c) y variables, evitamos reglas repetitivas y mantenemos el build
consistente, rápido y reproducible.
3. Diferencia entre las variables $<, $@ y $^
• $@ → el target → lo que voy a construir.
Representa el archivo que se está generando en esa regla.
Ejemplo: si la regla produce programa.o, entonces $@ = programa.o.
• $< → el primer prerequisito → el primer archivo fuente que necesito.
Usualmente es el archivo fuente principal de la regla.
Ejemplo: si la regla es programa.o: programa.c, entonces $< = programa.c.
• $^ → todos los prerequisitos (sin duplicados) → todos los archivos necesarios
para construirlo
Lista completa de dependencias de esa regla.
Ejemplo: si la regla es app: main.o utils.o math.o, entonces $^ = main.o
utils.o math.o.
Ejemplos prácticos
1. Uso de $@
main.o: main.c
gcc -c main.c -o $@
Aquí $@ se expande a main.o. Es decir, el compilador genera un archivo objeto con
ese nombre.
2. Uso de $<
main.o: main.c
gcc -c $< -o main.o
Aquí $< se expande a main.c. Es útil en reglas genéricas como %.o: %.c.
3. Uso de $^
app: main.o utils.o math.o
gcc $^ -o $@
Aquí $^ se expande a main.o utils.o math.o, y $@ a app.
El resultado es que gcc enlaza todos los objetos y produce el ejecutable.
4. Evaluación final
Diseño del Makefile: ¿Está bien estructurado? ¿Usa variables y reglas genéricas de
forma correcta?
Cumple
Funcionalidad: ¿Compila el proyecto correctamente? ¿La regla clean funciona como
se espera?
Cumple
Demostración de Comprensión: ¿Los alumnos demuestran que el Makefile solo
recompila los archivos modificados?
Cumple
Respuesta a Preguntas: ¿Son correctas y claras las respuestas a las preguntas de
razonamiento e investigación?
Cumple