[makefile] automatisch Subfolder suchen und nach h- und c-Dateien durchsuchen



  • Hallo c-community,

    ich möchte meine Arbeit bei der Aktualisierung meiner Makefiles automatisieren. Ich arbeite derzeit mit einem Unterordner in welchem alle Sourcefiles liegen und muss bei neuen h- und c-Dateien händisch diese in meine Makefile einpflegen. Dies würde ich gern automatisieren. Leider bleibe ich derzeit immer an (glaube ich) einfachen Problemen hängen.

    Hier mal eine aktuelle Makefile von mir:

    VERSION	=	0.0.0.1
    CC		=	gcc
    CFLAGS		=	-ggdb -Wall -Werror -O0 -DVERSION=\"$(VERSION)\"
    LDFLAGS		=	-lpthread
    
    ODIR		=	obj
    
    CLASSES_SDIR	=	classes/src
    CLASSES_IDIR	=	classes/header
    CLASSES__DEPS	=	listelement.h list.h object.h process.h event.h
    CLASSES_DEPS	=	$(patsubst %,$(CLASSES_IDIR)/%,$(CLASSES__DEPS))
    CLASSES__OBJ	=	listelement.o list.o object.o process.o event.o
    CLASSES_OBJ	=	$(patsubst %,$(ODIR)/%,$(CLASSES__OBJ))
    
    $(ODIR)/%.o: $(CLASSES_SDIR)/%.c $(CLASSES_DEPS)
    	$(CC) -c -o $@ $< $(CFLAGS)
    
    COM_SDIR	= src
    COM_IDIR	= header
    COM__DEPS	= main.h 
    COM_DEPS	= $(patsubst %,$(COM_IDIR)/%,$(COM__DEPS))
    COM__OBJ	= main.o
    COM_OBJ		= $(patsubst %,$(ODIR)/%,$(COM__OBJ))
    
    $(ODIR)/%.o: $(COM_SDIR)/%.c $(COM_DEPS)
    	$(CC) -c -o $@ $< $(CFLAGS)
    
    programm: $(COM_OBJ) $(CLASSES_OBJ)
    	$(CC) -o $@ $+ $(CFLAGS) $(LDFLAGS)
    
    .PHONY: clean
    
    clean:
    	rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
    

    Hier gut zu sehen: 1.) für jeden Unterordner müssen mehrere Zeilen ergänzt und 2.) jede h- und c-Datei muss händisch ergänzt werden.
    Dies möchte ich ändern. Ich habe im ersten Schritt versucht die h-Dateien automatisch im Ordner suchen zu lassen aber dies scheint nicht wie gewünscht zu funktionieren:

    CLASSES__DEPS   =  $(shell find $(CLASSES__DEPS) -type f -name "\*.h")
    

    Hoffe jemand kann hier den ein oder anderen Ansatz zeigen, wie man diese Probleme lösen kann.

    Vielen Dank

    mirrowwinger



  • probier die make wildcard funktion

    MY_FILES = $(wildcard *.h)
    

    http://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html#Wildcard-Function


  • Mod



  • Hallo nochmal c-community,

    sorry dass ich mich erst jetzt auf die Beiträge antworten kann. Also erstmal an ScottZhang und SeppJ vielen Dank für die Beiträge. Leider war der Verweis von SeppJ nicht sehr hilfreich, da das Thema ja eigentlich makefile mit Subfoldern heißt. Aber trotzdem haben mir einige Zeilen in der Makefile für die Recherche geholfen. Die Wildcard ist auch nicht schlecht aber schlussendlich habe ich ersteinmal folgende Makefile aus mehreren Internetbeiträgen geschrieben:

    VERSION             =  0.0.1
    CC                  =  gcc
    WARNINGS            =  -Wall -Wextra -Werror -pedantic -Wshadow -Wpointer-arith -Wcast-align \
                           -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations \
                           -Wredundant-decls -Wnested-externs -Winline -Wno-long-long \
                           -Wuninitialized -Wconversion -Wstrict-prototypes
    DEBUG               =  -ggdb
    CFLAGS              =  -std=c99 $(WARNINGS) $(DEBUG) -DVERSION=\"$(VERSION)\"
    LDFLAGS             =  -lpthread
    
    BUILD               =  build
    SOURCE              =  sources
    BINARY              =  name
    
    VPATH               =  $(shell find $(SOURCE) -name '*.h' -exec dirname {} \; | uniq)
    
    SOURCES_FILENAME    =  $(shell find $(SOURCE) -name '*.c' -exec basename {} \; | uniq)
    SOURCES_OBJECTNAME  =  $(patsubst %.c, %.o, $(SOURCES_FILENAME))
    SOURCES_OBJECTS     =  $(patsubst %, $(BUILD)/%, $(SOURCES_OBJECTNAME))
    
    $(BUILD)/%.o: %.c %.h
    	@mkdir -p $(BUILD)
    	$(CC) -c -o $@ $< $(CFLAGS)
    
    $(BINARY): $(SOURCES_OBJECTS)
    	$(CC) -o $@ $+ $(CFLAGS) $(LDFLAGS)
    
    .PHONY: setup clean
    
    setup:
    	mkdir -p $(BUILD)
    
    clean:
    	@$(RM) -rf $(BINARY) $(SOURCES_OBJ) $(BUILD)
    

    Mit VPATH spare ich mir das zusammenschnipseln der Pfade und Quelldateien. Mit find werden alle c-Dateien (basename = nur Dateiname) gesucht (auch in Unterverzeichnissen) und in o-Dateien im BUILD-Ordner erstellt. Einziges Manko ist noch, dass bei Ausführung von:

    make test.o

    Die o-Datei nicht automatisch im BUILD-Ordner gelegt wird sondern ins Verzeichnis der Makefile. Bei normalem make:

    make

    wird wie gewünscht alles ins BUILD-Verzeichnis gelegt und die BINARY erzeugt.
    Vieleicht kann mir ja jemand noch helfen diesen kleinen Fehler zu beseitigen, sonst kann ich aber auch damit jetzt leben.

    Vielen Dank
    mirrowwinger



  • mirrowwinger schrieb:

    Einziges Manko ist noch, dass bei Ausführung von:

    make test.o

    Die o-Datei nicht automatisch im BUILD-Ordner gelegt wird sondern ins Verzeichnis der Makefile.

    Ja, make sucht ein Target für "test.o", findet keines und nimmt das Default-Target. Lass mich raten, die test.c liegt auch im selben Verzeichnis?
    Die Default-Regeln kannst du durch ein leeres Suffixes entfernen:

    .SUFFIXES:
    

    durch ein "make build/test.o" hättest du dein gewünschtes Verhalten. Wäre ja ein Unding, wenn "make foo"inWirklichkeit"makebar/foo" in Wirklichkeit "make bar/foo" ausführen würde. Dann müsste ich ja wieder umständlich nach $foo suchen.



  • @oenone:
    Nein meine Struktur sieht ungefähr so aus:

    Projektordner
        |
        |- makefile
        |- build/               // <-- enthält all .o-Dateien
        |    |- test.o
        |    |- test2.o
        |    |- main.o
        |
        |- sources/             // <-- enhält alle .c- und .h-Dateien auch in weiteren Unterverzeichnissen
        |    |- Unterordner1
        |    |       |- test.c
        |    |       |- test.h
        |    |- Unterordner2
        |    |       |- test2.c
        |    |       |- test2.h
        |    |- main.c
        |    |- main.h
    

    .
    Die .o-Dateien werden also mit:

    make
    

    richtig ins build/-Verzeichnis abgelegt. Bei

    make test.o
    

    soll dies eigentlich auch so sein aber es wird im Projektordner abgelegt. Ich hoffe die Darstellung macht das Problem deutlicher. Aber natürlich macht dein Einwand auch Sinn, dass

    make test.o
    

    und

    make build/test.o
    

    sich unterscheiden sollten.


Anmelden zum Antworten