build - create - makefile example
Hacer ignora las dependencias generadas (1)
Intento escribir un Makefile para mi proyecto que genera automáticamente las dependencias entre mis archivos fuente. El archivo Makefile es el siguiente:
CC = g++
CFLAGS = -std=c++11 -Wfatal-errors -fdiagnostics-color=always
LDFLAGS = -lm -lfftw3
SRCDIR = src
OBJDIR = obj
DEPDIR = dep
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRCS))
DEPS = $(patsubst $(SRCDIR)/%.cpp,$(DEPDIR)/%.d,$(SRCS))
PROG = whistle_recognition
$(PROG): $(OBJS)
$(CC) $(CFLAGS) -o$(PROG) $(OBJS) $(LDFLAGS)
.PHONY: clean run
$(DEPS): $(DEPDIR)/%.d : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -MM $< -MF $@
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -r $(OBJS) $(DEPS) $(PROG)
run: $(PROG)
./$(PROG)
-include $(DEPS)
Generar las dependencias funciona bien. Sin embargo, Make los ignora. Supongamos que tengo un archivo foo.cpp que incluye el archivo de encabezado quux.h. Si foo.cpp cambia Realiza reconstrucciones foo.o. Sin embargo, si quux.h cambia, Make piensa que foo.o está actualizado. ¿Cómo puedo arreglar esto?
Editar: Heres más información: salida de make -d whistle_recognition | grep signalscanner.d
make -d whistle_recognition | grep signalscanner.d
:
Reading makefile ''dep/signalscanner.d'' (search path) (don''t care) (no ~ expansion)...
Considering target file ''dep/signalscanner.d''.
File ''dep/signalscanner.d'' does not exist.
Finished prerequisites of target file ''dep/signalscanner.d''.
Must remake target ''dep/signalscanner.d''.
g++ -std=c++11 -Wfatal-errors -fdiagnostics-color=always -MM src/signalscanner.cpp -MF dep/signalscanner.d
Putting child 0xcda970 (dep/signalscanner.d) PID 2404 on the chain.
Live child 0xcda970 (dep/signalscanner.d) PID 2404
Successfully remade target file ''dep/signalscanner.d''.
Reading makefile ''dep/signalscanner.d'' (search path) (don''t care) (no ~ expansion)...
Considering target file ''dep/signalscanner.d''.
Finished prerequisites of target file ''dep/signalscanner.d''.
Prerequisite ''src/signalscanner.cpp'' is older than target ''dep/signalscanner.d''.
No need to remake target ''dep/signalscanner.d''.
salida de make -p whistle_recognition | signalscanner.o
make -p whistle_recognition | signalscanner.o
(abreviado):
[...]
obj/signalscanner.o: src/signalscanner.cpp
[...]
signalscanner.o: src/signalscanner.cpp src/signalscanner.h src/frequencyanalyzer.h src/freqanalyzer_test.h src/wav_file.h src/signalscanner_test.h
Y existe el problema: g++
no incluye el obj/
-prefix a los objetivos ... ¿Hay alguna manera de arreglar esto mediante la sustitución de patrones?
La gente a menudo tiene tales reglas para la generación de dependencias, pero en realidad son innecesarias.
La primera vez que se construye un proyecto, no se necesitan dependencias, ya que construye todas las fuentes de todos modos. Solo las compilaciones posteriores requieren las dependencias de la compilación anterior para detectar lo que debe reconstruirse.
Las dependencias son solo un subproducto de la compilación.
Las dependencias generadas contienen rutas a los archivos .o
correspondientes. Como las rutas de salida .o
no se especificaron al generar dependencias, esas rutas son incorrectas.
La siguiente solución coloca los archivos .d
junto con los archivos .o
correspondientes y los archivos .d
contienen las rutas correctas a .o
. También hace compilación y dependencias en una sola pasada.
Correcciones:
Eliminar estas líneas:
$(DEPS): $(DEPDIR)/%.d : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -MM $< -MF $@
-include $(DEPS)
Actualiza estas líneas:
DEPS = $(OBJS:%.o=%.d)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -c $(CFLAGS) -MD -MP -o $@ $<
Agregue estas líneas en la parte inferior:
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif