Montag, Januar 27, 2020

Pfad include und src-Verzeichnis makefile

Nach diesem tutorial:

http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

Es hat 3 Dateien 2 .c Dateien und 1 .h – Datei. Das tutorial über die Einrichtung von makefiles, und die ersten paar Schritte zu arbeiten. Der Letzte Schritt beinhaltet die Einrichtung Verzeichnispfade für die .h und .c – Dateien. Ich habe die .c – Dateien im src-Datei und die .h Dateien in einer include-Datei.

Sieht es so aus /home/bob/testcode/src <- mit der .c – Dateien.

Sowie /home/bob/testcode/include <- mit der .h – Dateien.

Code:

IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)

ODIR=obj
LDIR =../lib

_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = hellomake.o hellofunc.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -c -o [email protected] $< $(CFLAGS)

hellomake: $(OBJ)
    gcc -o [email protected] $^ $(CFLAGS)

.PHONY: clean

clean:
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

Ich möchte verstehen, wie es funktioniert und dann verwenden Sie es auf eine Bibliothek, die ich arbeite mit. Könnte jemand bitte zeigen Sie mir, wie man diesen code? Ich habe versucht, eine Menge von Optionen, wie "/home/bob/testcode/include/" w/und w/o – " und / und ich immer noch nicht bekommen es funktioniert.

Das Ziel ist es, die Arbeit mit einer Bibliothek enthält über 60-header-Dateien und 30 source-Dateien aus diese Dateien, die ich haben 1 Hauptfach, so dass ich wirklich brauchen, um diese grundlegende makefile Sache arbeiten, so konnte ich es erweitern.

Das Allgemeine problem sind diese Zeilen, welche sich nach Links öffnen:

IDIR =../include
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

und

OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))

Für die ich habe versucht eine Vielzahl von verschiedenen Pfad ersetzt, aber der Fehler, das ich Erzeuge, sagt:

gcc -o hellomake  -I../include
gcc: fatal error: no input files
compilation terminated.
make: *** [hellomake] Error 4

Bitte um Hilfe, vielen Dank im Voraus.

  • Herzlich willkommen auf StackOverflow ! Bitte verwenden echte Wörter, die mit realen Bedeutung über Ihre eigentliche problem, anstatt die Dinge, wie „es funktioniert“. Auch bitte posten, was Sie versucht haben, hier.
  • ich hoffe es ist jetzt klar, es ist nur ein problem der syntax, die ich denke, die „pathsubst“ müssen Sie den richtigen Pfad, die ich zur Verfügung gestellt haben, aber ich bekomme immer noch ein schwerwiegender Fehler.
  • Ihr Fehler ist ziemlich klar. Sie gab keine Datei zum gcc link in hellomake
  • Poste deinen aktuellen code, und es formatieren, damit es lesbar ist
  • ich glaube nicht, ich sollte mit gcc eine Datei, die alle enthalten ist, in das makefile und alles, was ich Anruf ist in das Verzeichnis, da alle 3 Dateien sind bereits enthalten, die im makefile
  • Ein trick, den ich finden nützlich, beim Debuggen eine make-Datei ist die Einrichtung einer „Karte“ Ziel (oder welche Namen auch immer), ohne Abhängigkeiten, druckt nur die Variablen, d.h.: @echo "OBJ=$(OBJ)" (eine Zeile für jede variable). Dann mit make show Sie deutlich sehen, wenn Sie die richtigen Inhalte.
  • Der Zweck eines Makefile-Aufruf-Befehle. Einer von denen ist gcc zum Beispiel. Wenn Sie nicht liefern gcc mit den Dateien miteinander verknüpfen, es ist nicht gonna erfinden.
  • nun, ich habe nicht die Absicht zu lernen, wie ein Skript makefiles aber es scheint, es wird der einzige Weg sein, um mich bewegen zu tun was ich eigentlich tun will. ich hatte gehofft, das tutorial würde die Grundstruktur, auf der ich könnte erweitern Sie den code mit den ersten paar Schritten alles geklappt hat, ich also davon ausgehen, das die Verknüpfung Teil ist auch richtig, aber trotzdem danke.
  • Es gibt etwas über Ihrem makefile oder Ihrer Umgebung sind Sie nicht, uns zu erklären, denn das makefile funktioniert wie oben geschrieben. Die einzige Erklärung für das Verhalten, das Sie sehen, ist, wenn die OBJ variable leer waren. Ich sehe keine Möglichkeit, die passieren können, angesichts der oben genannten makefile. Sind Sie sicher, dass Sie mit GNU make? Welche version? (führen Sie make --version) Ist das wirklich genau das makefile verwendest du?
  • Das ist der Zweck der $(info ) Befehl.
  • Ja, ich weiß $info nur persönliche Gewohnheit. Aber neben der Tatsache, dass echo ist ein shell-Befehl und $info eine make Befehl, kennen Sie keine praktischen Unterschiede ? (neugierig)
  • $info platziert werden kann fast überall in Ihrem makefile, in der Erwägung, dass echo können nur gelegt werden, in der Deklaration von Variablen oder Regel-Körper.
  • Sind Sie auf MacOS oder ein anderes BSD system? make standardmäßig nicht Gnu make gibt. Sie können installieren und verwenden von gmake.

InformationsquelleAutor iBeyondPower | 2015-06-01

3 Kommentare

  1. 29

    Dein tutorial fördert schlechte Praktiken, die Sie vermeiden sollten es IMHO.

    In der Regel hier:

    $(ODIR)/%.o: %.c $(DEPS)

    Sagst du zu schauen, in das aktuelle Verzeichnis, während Ihre source-Dateien sind in der src – Verzeichnis, damit dieses Muster wird nie verwendet werden, und Sie haben keine passende ein.


    Stellen Sie sicher, organisieren Sie Ihre Projekt-Verzeichnis wie diese :

    + include/
    |-- all .h files here
    + lib/
    |-- all thirdparty library files (.a files) here
    + obj/
    |-- all .o files will be placed here
    + src/
    |-- all .c files here
    + Makefile

    Dann nehmen wir den Prozess Schritt für Schritt, mit guten Praktiken.

    Erstens nicht definieren, alles, wenn Sie nicht brauchen, um. Machen hat eine Menge von vordefinierten Variablen und Funktionen, die Sie nutzen sollten, bevor Sie versuchen, es manuell zu tun. In der Tat, er hat so viele, dass man kompilieren kann ein einfaches Projekt, ohne auch nur ein Makefile in dem Verzeichnis überhaupt !

    1. Namen Ihrem letzten Ziel, das heißt, Ihre ausführbaren Datei:

      EXE = hellomake
    2. Liste der Quell-und build-output-Verzeichnisse:

      SRC_DIR = src
      OBJ_DIR = obj
    3. Liste der Quelldateien:

      SRC = $(wildcard $(SRC_DIR)/*.c)
    4. Den Quellcode-Dateien, Liste der object-Dateien:

      OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) # patsubst is far less readable
      # You can also do it like that
      OBJ = $(addprefix $(OBJ_DIR)/, $(notdir $(SRC)))
    5. Habe einige Präprozessor-flags übergeben werden? Gehen auf.

      CPPFLAGS += -Iinclude # -I is a preprocessor flag, not a compiler flag
    6. Habe einige compiler flags hinzufügen? Hier gehen Sie.

      CFLAGS += -Wall # some warnings about bad code
    7. Habe einige linker flags?

      LDFLAGS += -Llib # -L is a linker flag
    8. Habe einige thirdparty Bibliotheken link gegen?

      LDLIBS += -lm # Left empty if no libs are needed

    Ok, jetzt Rollen einige Rezepte nun, da sich die Variablen sind richtig gefüllt.

    Ist es weit verbreitet, dass die Standard-Ziel genannt werden sollte all. Für Einfachheit, es ist das erste Ziel im Makefile, und deren Voraussetzungen wird das Ziel, das Sie bauen möchten, die beim schreiben make auf der Kommandozeile:

    all: $(EXE)

    Nun die Voraussetzungen für die Erstellung Ihrer Datei, und füllen Sie Ihr Rezept, das zu sagen, was zu tun mit diesen:

    $(EXE): $(OBJ)
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o [email protected]

    Einige kurze Hinweise:

    • $(CC) ist eine built-in variable schon enthalten, was Sie benötigen, wenn Sie kompilieren und linken in C,
    • Zu vermeiden linker-Fehler, den Sie sollte setzen $(LDFLAGS) vor Ihre Objekt-Dateien und $(LDLIBS) nach.
    • $(CPPFLAGS) und $(CFLAGS) sind nutzlos hier die Zusammenstellung phase ist schon vorbei, es ist die Verknüpfung der phase hier.

    Nächste Schritt, da der Quell-und Objekt-Dateien, die nicht teilen, die das gleiche prefix, müssen Sie sagen genau, was zu tun ist, da seine eingebauten Regeln nicht abdecken, Ihrem konkreten Fall:

    $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected]

    Ok, nun die ausführbare Datei aufbauen sollte, schön, wir können reinigen Sie die build-Verzeichnis, wenn wir wollen:

    clean:
        $(RM) $(OBJ)

    Letzte Sache. Sie sollten angeben, wenn in der Regel erzeugt keine Ziel-Ausgabe mit den .PHONY sepcial Regel:

    .PHONY: all clean

    Endergebnis:

    EXE = hellomake
    
    SRC_DIR = src
    OBJ_DIR = obj
    
    SRC = $(wildcard $(SRC_DIR)/*.c)
    OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
    
    CPPFLAGS += -Iinclude
    CFLAGS += -Wall
    LDFLAGS += -Llib
    LDLIBS += -lm
    
    .PHONY: all clean
    
    all: $(EXE)
    
    $(EXE): $(OBJ)
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o [email protected]
    
    $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected]
    
    clean:
        $(RM) $(OBJ)
    • Danke!!! Gut geschriebene Einführung darüber, wie zu schreiben makefiles 🙂
    • Danke Mann, Ihr rockt!
    • Genial Abdeckung. Ich habe mit dem gleichen tutorial dieser Jungs ist folgenden für JAHRE! Dies ist so klar und prägnant.
    • Das ist großartig. Dies erlaubt mir zu organisieren, wie ich will ohne zu mucken um in den Hyperraum (autoconf)
  2. 0

    Den einfachen Makefile Definitionen scheinen OK zu mir sind, wie Sie erscheinen, die in Ihrer Frage. Versuchen Sie, die compiler-Optionen, bevor Sie die Datei-Namen:

    $(ODIR)/%.o: %.c $(DEPS)
        $(CC) $(CFLAGS) -c -o [email protected] $<
    
    hellomake: $(OBJ)
        gcc $(CFLAGS) -o [email protected] $^

    Müssen Sie führen make aus dem source-Verzeichnis.

    • Die Umschaltung der Reihenfolge der flags wird nicht helfen… das problem ist, dass die Objekt-Dateien sind tatsächlich fehlt von der Befehlszeile aus.
    • die Umschaltung der Optionen ist nicht die Lösung, aber es ist ratsam. Wie, warum $(OBJ) leer ist, entweder die OP ist nicht Gnu make oder es fehlt etwas von der Frage.
  3. 0

    make-utility, mit keine spezifischen ‚target‘ wird das erste Ziel in der Datei.

    Das erste Ziel ist in der Regel mit dem Namen ‚alle‘

    Für die Datei geschrieben werden, wird die Objekt-Dateien und wird nicht fortgesetzt, um die ausführbare Datei, wenn das Ziel nicht in der Befehlszeile angegebene

    Folgendes vorschlagen:

    SHELL := /bin/sh
    
    # following so could define executable name on command line
    # using the '-D' parameter
    #ifndef $(NAME)
        NAME := hellomake
    #endif
    
    # use ':=' so macros only evaluated once
    
    
    MAKE    :=  /usr/bin/make
    CC      :=  /usr/bin/gcc
    
    CFLAGS  := -g -Wall -Wextra -pedantic
    LFLAGS  :=
    
    ODIR    := obj
    IDIR    := ../include
    LIBS    :=
    LIBPATH := ../lib
    
    DEPS    := $(wildcard $(IDIR)/*.h)
    SRCS    := $(wildcard *.c)
    OBJS    := $(SRCS:.c=.o)
    
    .PHONY: all
    all: $(NAME) $(OBJS)
    
    $(ODIR)/%.o: %.c $(DEPS)
        $(CC) $(CFLAGS) -c -o [email protected] $< -I$(DEPS)
    
    $(NAME): $(OBJS)
        $(CC) $(LFLAGS) -o [email protected] $^ -L$(LIBPATH) -l$(LIBS)
    
    .PHONY: clean
    clean:
        rm -f $(ODIR)/*.o
        rm -f $(NAME)
    
    
    however, in your proposed project,
    not every source file needs every header file
    so should use either gcc or sed to generate the dependency files
    then use makefile rules similar to the following,
    which may need a little 'tweaking' for your project
    because the include files are not in the same directory
    as the source files:
    
    DEP := $(SRCS:.c=.d)
    
    #
    #create dependency files
    #
    %.d: %.c 
        # 
        # ========= START $< TO [email protected] =========
        $(CC) -M $(CPPFLAGS) $< > [email protected]$$$$;                      \
        sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected];     \
        rm -f [email protected]$$$$
        # ========= END $< TO [email protected] =========
    
    # 
    # compile the .c files into .o files using the compiler flags
    #
    %.o: %.c %.d 
         # 
         # ========= START $< TO [email protected] =========
         $(CC) $(CCFLAGS) -c $< -o [email protected] -I$(IDIR) 
         # ========= END $< TO [email protected] =========
         # 
    
    # include the contents of all the .d files
    # note: the .d files contain:
    # <filename>.o:<filename>.c plus all the dependencies for that .c file 
    # I.E. the #include'd header files
    # wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
    #
    ifneq "$(MAKECMDGOALS)" "clean"
    -include $(DEP)
    endif
    • Ihr Kommentar ist nicht korrekt. Muster, Regeln und suffix-Regeln (implizite Regeln) nicht rechnen kann als Standard-Ziele. Die erste explizite Regel im makefile oben ist helloworld – und das ist das Ziel, die erstellt wird, wenn kein anderes Ziel in der Befehlszeile angegeben wird. Obwohl das hinzufügen einer all Ziel ist nicht eine schlechte Idee, es wird nicht benötigt. Auch Ihr Kommentar über die Verwendung -D ist falsch: machen Sie nicht verwenden -D zur Definition von Variablen. Und Sie können nicht schreiben, Präprozessor-Anweisungen, wie #ifdef in ein makefile (das ist nur ein Kommentar, zu machen). Es gibt auch andere problematische Dinge auch hier.

Kostenlose Online-Tests