Tengo el siguiente archivo MAKE que utilizo para construir un programa (un kernel, en realidad) en el que estoy trabajando. Es desde cero y estoy aprendiendo sobre el proceso, por lo que no es perfecto, pero creo que es lo suficientemente poderoso en este punto para mi nivel de experiencia escribiendo archivos MAKE.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $@ $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $@
%.o: %.c
@echo Compiling $<...
$(CC) $(CFLAGS) -c -o $@ $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
Mi principal problema con este archivo MAKE es que cuando modifico un archivo de encabezado que incluyen uno o más archivos C, los archivos C no se reconstruyen. Puedo solucionar esto con bastante facilidad haciendo que todos mis archivos de encabezado sean dependencias para todos mis archivos C, pero eso causaría efectivamente una reconstrucción completa del proyecto cada vez que cambie / agregue un archivo de encabezado, lo que no sería muy elegante.
Lo que quiero es solo para los archivos C que incluyen se reconstruyan el archivo de encabezado que cambio y que todo el proyecto se vuelva a vincular. Puedo hacer el enlace haciendo que todos los archivos de encabezado sean dependencias del objetivo, pero no puedo averiguar cómo hacer que los archivos C se invaliden cuando sus archivos de encabezado incluidos son más nuevos.
Escuché que GCC tiene algunos comandos para hacer esto posible (por lo que el archivo MAKE de alguna manera puede averiguar qué archivos deben reconstruirse) pero no puedo por mi vida encontrar un ejemplo de implementación real para mirar. ¿Alguien puede publicar una solución que habilite este comportamiento en un archivo MAKE?
EDITAR: Debo aclarar, estoy familiarizado con el concepto de poner los objetivos individuales y hacer que cada objetivo. O requiera los archivos de encabezado. Eso requiere que edite el archivo MAKE cada vez que incluyo un archivo de encabezado en alguna parte, lo cual es un poco molesto. Estoy buscando una solución que pueda derivar las dependencias del archivo de encabezado por sí sola, lo cual estoy bastante seguro de haber visto en otros proyectos.
fuente
Puede agregar un comando 'make depend' como otros han dicho, pero ¿por qué no hacer que gcc cree dependencias y compile al mismo tiempo?
El parámetro '-MF' especifica un archivo para almacenar las dependencias.
El guión al comienzo de '-include' le dice a Make que continúe cuando el archivo .d no existe (por ejemplo, en la primera compilación).
Tenga en cuenta que parece haber un error en gcc con respecto a la opción -o. Si configura el nombre de archivo del objeto para que diga
obj/_file__c.o
, el generado_file_.d
aún contendrá_file_.o
, noobj/_file_c.o
.fuente
g++ -c -Wall -Werror -MM -MF main.d -o main.o main.cpp
obtuve el archivo main.d, pero main.o tenía 0 bytes. Sin embargo, la bandera -MMD parece hacer exactamente lo que se requería. Así que mi regla de trabajo MAKE se convirtió en:$(CC) -c $(CFLAGS) -MMD -o $@ $<
Esto es equivalente a la respuesta de Chris Dodd , pero usa una convención de nomenclatura diferente (y casualmente no requiere la
sed
magia. Copiado de un duplicado posterior .Si está utilizando un compilador GNU, el compilador puede ensamblar una lista de dependencias por usted. Fragmento de Makefile:
También está la herramienta
makedepend
, pero nunca me gustó tanto comogcc -MM
fuente
SRCS
yOBJS
. Estoy de acuerdo la mayor parte del tiempo, pero todos deberían saber cuáles son.Tendrá que crear objetivos individuales para cada archivo C y luego enumerar el archivo de encabezado como una dependencia. Todavía puede usar sus objetivos genéricos y simplemente colocar las
.h
dependencias después, así:fuente
Básicamente, necesita crear dinámicamente las reglas del archivo MAKE para reconstruir los archivos de objeto cuando cambian los archivos de encabezado. Si usa gcc y gnumake, esto es bastante fácil; solo pon algo como:
en su archivo MAKE.
fuente
Además de lo que dijo @mipadi, también puede explorar el uso de la
-M
opción ' ' para generar un registro de las dependencias. Incluso podría generarlos en un archivo separado (tal vez 'depend.mk') que luego incluiría en el archivo MAKE. O puede encontrar unamake depend
regla ' ' que edita el archivo MAKE con las dependencias correctas (términos de Google: "no elimine esta línea" y dependa).fuente
Ninguna de las respuestas funcionó para mí. Por ejemplo, la respuesta de Martin Fido sugiere que gcc puede crear un archivo de dependencia, pero cuando intenté que estaba generando archivos de objetos vacíos (cero bytes) para mí sin advertencias ni errores. Podría ser un error de gcc. Estoy en
Así que aquí está mi Makefile completo que funciona para mí; es una combinación de soluciones + algo que nadie más mencionó (por ejemplo, "regla de reemplazo de sufijo" especificada como .cc.o :):
Observe que utilicé .cc .. El Makefile anterior es fácil de ajustar para archivos .c.
También note la importancia de estas dos líneas:
entonces gcc se llama una vez para construir un archivo de dependencia primero, y luego compila realmente un archivo .cc. Y así sucesivamente para cada archivo fuente.
fuente
Solución más simple: simplemente use Makefile para que la regla de compilación .c to .o dependa de los archivos de encabezado y de cualquier otra cosa que sea relevante en su proyecto como dependencia.
Por ejemplo, en el Makefile en algún lugar:
fuente
Creo que el
mkdep
comando es lo que quieres. De hecho, escanea archivos .c en busca de#include
líneas y crea un árbol de dependencia para ellos. Creo que los proyectos de Automake / Autoconf usan esto de forma predeterminada.fuente