Makefile con compilación condicional

 Un código avanzado para un Makefile que utiliza compilación condicional para soportar arquitecturas x86, x64 y ARM automáticamente. Este diseño es modular y utiliza variables, reglas y condiciones basadas en la arquitectura.

# Variables para el compilador y las opciones de compilación
CC = gcc
AS = nasm
ARCH ?= $(shell uname -m)  # Detectar automáticamente la arquitectura
CFLAGS = -ffreestanding -O2 -Wall -Wextra
LDFLAGS = 
OUTPUT = bootloader.bin

# Definir opciones condicionales según la arquitectura
ifeq ($(ARCH), x86_64)
    CFLAGS += -m64
    ARCH_DIR = arch/x64
    ARCH_NAME = x64
else ifeq ($(ARCH), i386)
    CFLAGS += -m32
    ARCH_DIR = arch/x86
    ARCH_NAME = x86
else ifneq (,$(filter arm aarch64,$(ARCH)))
    CC = arm-none-eabi-gcc
    CFLAGS += -march=armv8-a
    ARCH_DIR = arch/arm
    ARCH_NAME = arm
else
    $(error Arquitectura no soportada: $(ARCH))
endif

# Directorios del proyecto
SRC_DIR = src
ARCH_SRC = $(SRC_DIR)/$(ARCH_DIR)
OBJ_DIR = obj
INCLUDE_DIR = include

# Crear lista de archivos fuente y objetos
SRC = $(wildcard $(SRC_DIR)/**/*.c)
OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRC))

# Regla principal
all: $(OUTPUT)

# Crear el binario final
$(OUTPUT): stage1.bin $(OBJS)
    @echo "Generando $(OUTPUT)..."
    cat stage1.bin $(OBJS) > $(OUTPUT)

# Compilar ensamblador para la etapa 1
stage1.bin: stage1.asm
    @echo "Compilando código ensamblador para stage1.bin..."
    $(AS) -f bin stage1.asm -o stage1.bin

# Compilar los archivos fuente en objetos
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
    @echo "Compilando $< para la arquitectura $(ARCH_NAME)..."
    mkdir -p $(OBJ_DIR)
    $(CC) $(CFLAGS) -I$(INCLUDE_DIR) -c $< -o $@

# Limpiar archivos generados
clean:
    @echo "Limpiando archivos generados..."
    rm -rf $(OBJ_DIR) $(OUTPUT) stage1.bin

# Información de depuración
info:
    @echo "Arquitectura detectada: $(ARCH)"
    @echo "Archivos fuente: $(SRC)"
    @echo "Objetos generados: $(OBJS)"

 

Explicación del Makefile

  1. Detección Automática de Arquitectura:
    • La variable ARCH utiliza uname -m para detectar automáticamente la arquitectura.
    • Arquitecturas soportadas:

      • x86_64 (x64)
      • i386 (x86)
      • arm, aarch64 (ARM).
    • Si no se detecta una arquitectura soportada, el Makefile lanza un error.
  2. Opciones Condicionales:
    • Basado en la arquitectura, se configuran las banderas de compilación (CFLAGS) y la ruta de los archivos específicos (ARCH_DIR).
    • Para ARM, se utiliza un compilador cruzado (arm-none-eabi-gcc).
  3. Estructura del Proyecto:

    • src/: Contiene todos los archivos fuente organizados por subdirectorios (arch/x64, arch/x86, arch/arm).
    • obj/: Carpeta para los archivos objeto generados.
    • include/: Archivos de encabezado compartidos.
  4. Reglas Principales:

    • all: Genera el binario final combinando stage1.bin y los objetos compilados.
    • stage1.bin: Compila el archivo ensamblador inicial (stage1.asm) usando NASM.
    • $(OBJ_DIR)/%.o: Compila los archivos fuente (.c) en objetos (.o), organizándolos en el directorio obj/.
  5. Regla de Limpieza:
    • Elimina archivos intermedios y de salida, incluyendo los objetos y el binario final.
  6. Regla de Depuración (info):
    • Imprime información útil sobre la configuración actual, como la arquitectura detectada y los archivos a compilar.

Organización del Proyecto

Estructura del proyecto esperada:

BootloaderManager/
├── Makefile
├── stage1.asm
├── include/
│   ├── common.h
│   └── interface.h
├── src/
│   ├── arch/
│   │   ├── x86/
│   │   │   ├── gdt.c
│   │   │   ├── idt.c
│   │   │   ├── memory.c
│   │   │   └── peripherals.c
│   │   ├── x64/
│   │   │   ├── gdt.c
│   │   │   ├── idt.c
│   │   │   ├── memory.c
│   │   │   └── peripherals.c
│   │   ├── arm/
│   │   │   ├── gdt.c
│   │   │   ├── idt.c
│   │   │   ├── memory.c
│   │   │   └── peripherals.c
│   └── interface/
│       ├── interface.c
│       └── menu.c
└── obj/

 

Compilación y Prueba

  1. Compilar para Arquitectura x86:   
  2. Compilar para Arquitectura x64:
  3. Compilar para Arquitectura ARM:
  4. Limpiar Archivos Generados:
  5. Depuración del Makefile:

 

Conclusión

Este Makefile avanzado detecta automáticamente la arquitectura y adapta las opciones de compilación y enlaces en consecuencia. Es altamente modular y permite agregar nuevas arquitecturas fácilmente.

 

 

 

 

Destacado

Bootloader Avanzado en Ensamblador

Bootloader Avanzado en Ensamblador Características del Bootloader Se carga en la dirección 0x7C00 (BIOS). ...