Jak Mogę mieć plik Makefile automatycznie odbudowujący pliki źródłowe zawierające zmodyfikowany plik nagłówkowy? (W C / C++)

Mam następujący plik makefile, którego używam do budowania programu (jądra), nad którym pracuję. Jego od podstaw i uczę się o tym procesie, więc nie jest doskonały, ale myślę, że jest wystarczająco silny w tym momencie dla mojego poziomu doświadczenia w pisaniu plików makefiles.

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

Mój główny problem z tym plikiem makefile polega na tym, że gdy modyfikuję plik nagłówka, który zawiera jeden lub więcej plików C, pliki C nie są przebudowywane. Mogę to naprawić dość łatwo, mając wszystkie moje pliki nagłówkowe być zależności dla wszystkich moich plików C, ale to skutecznie spowoduje całkowitą przebudowę projektu za każdym razem zmieniłem / dodałem plik nagłówkowy, co nie byłoby zbyt wdzięczne.

Chcę tylko, aby pliki C, które zawierają plik nagłówkowy, który zmieniam, zostały przebudowane i aby cały projekt został ponownie połączony. Mogę zrobić linkowanie, powodując, że wszystkie pliki nagłówkowe są zależnościami od celu, ale nie mogę wymyślić, jak sprawić, by pliki C zostały unieważnione, gdy ich Dołączone pliki nagłówkowe są nowsze.

Słyszałem, że GCC ma kilka poleceń, aby to było możliwe (więc plik makefile może w jakiś sposób dowiedzieć się, które Pliki należy przebudować), ale nie mogę na całe życie znaleźć rzeczywistego przykładu implementacji do obejrzenia. Czy ktoś może zamieścić rozwiązanie, które umożliwi takie zachowanie w pliku makefile?

EDIT: powinienem wyjaśnić, jestem zaznajomiony z koncepcją umieszczania poszczególnych celów i posiadania każdego celu.o wymagaj plików nagłówkowych. To wymaga ja będę edytował plik makefile za każdym razem, gdy dołączam gdzieś plik nagłówkowy, co jest trochę uciążliwe. Szukam rozwiązania, które może samodzielnie wyprowadzać zależności od pliku nagłówkowego, co jestem dość pewien, że widziałem w innych projektach.

Author: Nicholas Flynt, 2008-11-18

9 answers

Jak już wspomniano w innych miejscach na tej stronie, zobacz tę stronę: http://make.paulandlesley.org/autodep.html

W skrócie, gcc może automatycznie tworzyć .d pliki zależności dla Ciebie, które są fragmentami mini makefile zawierające zależności z .plik C, który skompilowałeś. Za każdym razem, gdy zmieniasz .plik c i skompilować go, the .plik d zostanie zaktualizowany.

Poza dodaniem flagi-M do gcc, musisz załączyć .pliki d w makefile (tak jak Chris napisał powyżej). Istnieje kilka bardziej skomplikowanych problemów na stronie, które są rozwiązywane za pomocą sed, ale można je zignorować i zrobić "make clean", aby usunąć.pliki d za każdym razem, gdy skarżą się na brak możliwości zbudowania pliku nagłówkowego, który już nie istnieje.

 27
Author: Udi Meiri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-09 13:47:57

Możesz dodać polecenie 'make depend', jak stwierdzili inni, ale dlaczego nie dostać gcc do tworzenia zależności i kompilacji w tym samym czasie:

DEPS := $(COBJS:.o=.d)

-include $(DEPS)

%.o: %.c
    $(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$@) -o $@ $<

Parametr '-MF ' Określa plik do przechowywania zależności.

Myślnik na początku '- include ' mówi Make, aby kontynuował, gdy .plik d nie istnieje (np. przy pierwszej kompilacji).

Uwaga w gcc pojawił się błąd dotyczący opcji-o. Jeśli ustawisz nazwę pliku obiektu na obj/_file__c.o, wygenerowany _file_.d nadal będzie zawierać _file_.o, NIE obj/_file_c.o.

 20
Author: Martin Fido,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-25 22:28:44

Jest to odpowiednik odpowiedzi Chrisa Dodda , ale używa innej konwencji nazewnictwa (i przypadkowo nie wymaga magii sed. Skopiowany z późniejszy duplikat.


JeĹ "li uĺźywasz kompilatora GNU, kompilator moĹźe zgromadziÄ ‡ dla Ciebie listÄ ™ zaleĹźnoĹ" ci. Fragment Makefile:

depend: .depend

.depend: $(SOURCES)
        rm -f ./.depend
        $(CC) $(CFLAGS) -MM $^>>./.depend;

include .depend

Jest też narzędzie makedepend, ale nigdy nie podobało mi się tak bardzo, jak gcc -MM

 16
Author: dmckee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:19

Będziesz musiał stworzyć indywidualne cele dla każdego pliku C, a następnie wymienić plik nagłówkowy jako zależność. Możesz nadal używać ogólnych celów i po prostu umieścić .h zależności, w ten sposób:

%.o: %.c
        @echo Compiling $<...
        $(CC) $(CFLAGS) -c -o $@ $<

foo.c: bar.h
# And so on...
 7
Author: mipadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 00:59:40

Poza tym, co powiedział @mipadi, możesz również zbadać użycie opcji '-M ' do wygenerowania rekordu zależności. Możesz nawet wygenerować je do osobnego pliku (być może 'depend.mk"), które następnie umieszczasz w pliku makefile. Możesz też znaleźć regułę ' make depend', która edytuje plik makefile z poprawnymi zależnościami(Google terms: "DO not remove this line" and depend).

 3
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 01:06:17

Zasadniczo, musisz dynamicznie utworzyć reguły makefile, aby odbudować pliki obiektowe, gdy zmienią się pliki nagłówkowe. Jeśli używasz gcc i gnumake, jest to dość proste; wystarczy umieścić coś w stylu:

$(OBJDIR)/%.d: %.c
        $(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@

ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif

W Twoim pliku makefile.

 3
Author: Chris Dodd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 01:08:36

Żadna z odpowiedzi nie zadziałała. Na przykład odpowiedź Martina Fido sugeruje, że gcc może tworzyć plik zależności, ale kiedy próbowałem generować puste (zerowe bajty) pliki obiektowe dla mnie bez żadnych ostrzeżeń i błędów. To może być błąd gcc. Jestem na

$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)

Oto mój kompletny Makefile, który działa dla mnie; jest to kombinacja rozwiązań + coś, o czym nikt inny nie wspomniał (np. " sufiks reguła zastępcza " określona jako. cc. o:):

CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/

# LFLAGS = -L../lib
# LIBS = -lmylib -lm

# List of all source files
SRCS = main.cc cache.cc

# Object files defined from source files
OBJS = $(SRCS:.cc=.o)

# # define the executable file 
MAIN = cache_test

#List of non-file based targets:
.PHONY: depend clean all

##  .DEFAULT_GOAL := all

# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)

all: $(MAIN)

-include $(DEPS)

$(MAIN): $(OBJS)
    $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)

#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
    $(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$@) $<
    $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

clean:
    $(RM) *.o *~ $(MAIN) *.d

Notice I used. cc .. Powyższy plik Makefile można łatwo dostosować .pliki C.

Należy również zwrócić uwagę na znaczenie tych dwóch linii:

$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$@) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

Więc gcc jest wywoływany raz, aby najpierw zbudować plik zależności, a następnie faktycznie skompilować plik. cc. I tak dalej dla każdego pliku źródłowego.

 0
Author: Tagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-01 21:29:08

Prostsze rozwiązanie: wystarczy użyć Makefile, aby mieć .c do .o reguła kompilacji zależy od Pliku (ów) nagłówka i cokolwiek innego jest istotne w projekcie jako zależność.

Np. w Makefile gdzieś:

DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv

::: (your other Makefile statements like rules 
:::  for constructing executables or libraries)

# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
        $(CC) $(CFLAGS) -c -o $@ $<
 0
Author: Richard Elkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-02 15:59:40

Wierzę, że polecenie mkdep jest tym, czego chcesz. To skanuje .pliki c dla linii #include i tworzy dla nich drzewo zależności. Uważam, że projekty Automake / Autoconf używają tego domyślnie.

 -1
Author: jdizzle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-07 00:45:15