Prueba de Makefile con Separación de Objetos en U-Boot

Introducción

Este artículo describe una prueba de Makefile que emula el sistema de compilación de U-Boot, enfocándose en la separación entre archivos objeto y código fuente. La estructura se basa en principios clave de U-Boot Maekfile, como la gestión de directorios de salida y la inclusión modular de reglas de compilación.

Estructura del Código Fuente de Prueba

El código fuente de prueba consta de cuatro directorios: tres carpetas de origen que contienen archivos .c y sus Makefiles, y un directorio raíz con archivos config.mk y rules.mk.

Detalles de los Archivos Makefile

Makefile Principal

ifneq ($(OUTPUT_DIR),)
saved_output := $(OUTPUT_DIR)
# Crear el directorio de salida si no existe
$(shell [ -d $(OUTPUT_DIR) ] || mkdir -p $(OUTPUT_DIR))
OUTPUT_DIR := $(shell cd $(OUTPUT_DIR) && /bin/pwd)
$(if $(OUTPUT_DIR),,$(error El directorio de salida "$(saved_output)" no existe))
endif
OBJ_ROOT := $(if $(OUTPUT_DIR),$(OUTPUT_DIR),$(CURDIR))
SRC_ROOT := $(CURDIR)
TOP_DIR := $(SRC_ROOT)
LN_DIR := $(OBJ_ROOT)
export SRC_ROOT OBJ_ROOT TOP_DIR 

ifneq ($(OBJ_ROOT),$(SRC_ROOT))  
REMOTE_BUILD := 1   
export REMOTE_BUILD # Variable usada en config.mk
endif

include $(TOP_DIR)/config.mk # Incluye definiciones de compilador y reglas

CROSS_COMPILE =  
export CROSS_COMPILE

OBJS = add/add.o sub/sub.o test/test.o # Objetivos a generar
OBJS := $(addprefix $(obj),$(OBJS)) # Rutas completas de objetos
.PHONY : $(OBJS) # Forzar reconstrucción al modificar fuentes

ALL = $(obj)programa
all: $(ALL)

$(obj)programa: $(OBJS)
    $(CC) $^ -o $@

$(OBJS):        
    make -C $(dir $(subst $(obj),,$@)) # Ejecuta Makefiles en subdirectorios

SUBDIRS = add/ sub/ test/
.PHONY: clean distclean
clean:
    for dir in $(SUBDIRS); do make -C $$dir clean; done
    rm -f $(ALL) 
    
distclean:
    for dir in $(SUBDIRS); do make -C $$dir distclean; done
    rm -f $(ALL) 

Archivo config.mk

ifneq ($(OBJ_ROOT),$(SRC_ROOT)) # Verifica si la separación de directorios está activa
ifeq ($(CURDIR),$(SRC_ROOT)) # Caso: directorios separados, en raíz de fuentes
dir :=
else
dir := $(subst $(SRC_ROOT)/,,$(CURDIR))
endif

obj := $(if $(dir),$(OBJ_ROOT)/$(dir)/,$(OBJ_ROOT)/) # Ruta completa para objetos
src := $(if $(dir),$(SRC_ROOT)/$(dir)/,$(SRC_ROOT)/) # Ruta actual de fuentes

$(shell mkdir -p $(obj)) # Crear directorio de objetos si no existe
else     # Caso: directorios de objetos y fuentes iguales
obj :=    
src :=
endif

# Definición de herramientas de compilación
AS    = $(CROSS_COMPILE)as
LD    = $(CROSS_COMPILE)ld
CC    = $(CROSS_COMPILE)gcc
CPP    = $(CC) -E
AR    = $(CROSS_COMPILE)ar
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump

#########################################################################

ifndef REMOTE_BUILD

%.s:    %.S
    $(CPP) $(AFLAGS) -o $@ $<
%.o:    %.S
    $(CC) $(AFLAGS) -c -o $@ $<
%.o:    %.c
    $(CC) $(CFLAGS) -c -o $@ $<

else

$(obj)%.s:    %.S
    $(CPP) $(AFLAGS) -o $@ $<
$(obj)%.o:    %.S
    $(CC) $(AFLAGS) -c -o $@ $<
$(obj)%.o:    %.c
    $(CC) $(CFLAGS) -c -o $@ $<
endif

#########################################################################

Archivo rules.mk

#########################################################################

$(obj).depend: $(src)Makefile $(TOP_DIR)/config.mk $(SRCS) # SRCS definido en Makefiles de subdirectorios
 @rm -f $@  
 @for f in $(SRCS); do \\  
 g=`basename $$f | sed -e 's/\\(.*\\)\\.\\w/\\1.o/'`; \\  
 $(CC) -M $(HOST\_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; \\  
 done

#########################################################################

Makefile de Subdirectorio

include $(TOP_DIR)/config.mk # Incluye configuración de compilación

COBJS    := add.o # Objetivos de archivos .c
SOBJS    :=       # Objetivos de archivos .S

SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c) # Fuentes para compilación
OBJS    := $(addprefix $(obj),$(COBJS)) # Rutas completas de objetos
SOBJS    := $(addprefix $(obj),$(SOBJS))

all: $(obj).depend $(OBJS) # Generar dependencias antes de compilar

clean:
    rm -f $(SOBJS) $(OBJS)

distclean:    clean
    rm -f $(LIB) $(obj).depend

#########################################################################

# Incluye reglas para dependencias
include $(SRC_ROOT)/rules.mk

sinclude $(obj).depend # Incluye archivo de dependencias generado

#########################################################################    

Métodos de Compilación

Para compilar con objetos en el mismo directorio que las fuentes, ejecutar en el directorio raíz: make.

Para compilar con objetos en un directorio separado, se puede usar un variable de entorno: export OUTPUT_DIR=/tmp/salida y luego make, o directamente make OUTPUT_DIR=/tmp/salida.

Etiquetas: u-boot Makefile compilación separación-de-código sistemas-de-compilación

Publicado el 7-27 11:12