percorso di includere e di src makefile

Seguendo questo tutorial:

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

Ha 3 file di cui 2 .c file e 1 .h file. Il tutorial è di circa impostazione makefile, e i primi passi sono di lavoro. L’ultima fase prevede la creazione di percorsi di directory per il .h e .c file. Ho messo il .c file in un file di origine e il .h file in un file di inclusione.

Sembra che questo /home/bob/testcode/src <- contenente la .c file.

E /home/bob/testcode/include <- contenente la .h file.

Codice:

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)/*~ 

Voglio capire come funziona e poi di usare una libreria che sto lavorando con. Qualcuno potrebbe per favore indicarmi come impostare questo codice? Ho provato un sacco di opzioni come "/home/bob/testcode/include/" w/e w/o " e / e non riesco ancora a farlo funzionare.

L’obiettivo è quello di ottenere un lavoro con una libreria che contiene oltre il 60 file di intestazione e 30 file di origine, da questi file devo eseguire 1 principale, quindi ho davvero bisogno di ottenere questo di base makefile cosa che lavorano così ho potuto espandere.

Il problema generale sono queste le linee che vengono lasciati aperti:

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

e

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

Per il quale ho provato una moltitudine di differenti percorso sostituti, ma l’errore che mi genera dice:

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

Si prega di aiutare, grazie in anticipo.

  • Benvenuti a StackOverflow ! Si prega di utilizzare parole con significato reale di circa il vero problema, invece di cose come “farlo funzionare”. Inoltre si prega di inviare quello che hai provato qui.
  • spero che sia chiaro ora, è solo un problema di sintassi penso, il “pathsubst” bisogno il corretto percorso che ho fornito, ma ho ancora un errore fatale.
  • Il tuo errore è abbastanza chiaro. Si diede alcun file da gcc per collegarli in hellomake
  • Inserisci il tuo codice vero e proprio, e il formato in modo che sia leggibile
  • non credo che dovrebbe fornire gcc con un file, il tutto è contenuto nel makefile e tutti mi chiamano è fare in directory, perché tutti e 3 i file sono già inclusi nel makefile
  • Un trucco che io trovo utile quando il debug di un file è quello di impostare una “mostra” target (o qualsiasi altro nome), senza dipendenze, che consente di stampare solo le variabili, ovvero: @echo "OBJ=$(OBJ)" (una riga per ogni variabile). Poi con make show, è possibile vedere chiaramente se tenere il contenuto corretto.
  • Lo scopo di un Makefile per comandi di chiamata. Uno di questi è gcc per esempio. Se non si fornisce gcc con i file link insieme, non è intenzione di inventare.
  • beh, io non ho nessuna intenzione di imparare a script makefile, ma sembra che sarà l’unico modo per farmi spostare a fare quello che vuole realmente fare. speravo che il tutorial dovrebbe fornire la struttura di base su cui ho potuto ampliare il codice come i primi passi, tutto ha funzionato bene, ho pertanto assumere il collegamento parte è anche corretto, ma grazie comunque.
  • C’è qualcosa circa il makefile o il tuo ambiente non stai dicendo a noi, perché il makefile che funziona bene come scritto sopra. L’unica spiegazione per il comportamento di vedere è se il OBJ variabile è vuota. Non vedo alcun modo che possa accadere dato sopra makefile. Sei sicuro di stare usando GNU make? Quale versione? (eseguire make --version) questo È davvero esattamente il makefile stai usando?
  • Che è lo scopo del $(info ) comando.
  • Sì, so che $info, solo una personale abitudine. Ma oltre al fatto che echo è un comando di shell e $info un make comando, siete a conoscenza di eventuali differenze pratiche ? (curioso)
  • $info può essere collocato quasi ovunque nel makefile, mentre echo possono essere collocati in una dichiarazione di variabile o di una regola per il corpo.
  • Sei su MacOS o un altro sistema BSD? make non di default per Gnu make c’. È possibile installare e utilizzare gmake.

 

3 Replies
  1. 35

    Il tuo tutorial promuove le cattive pratiche, si dovrebbe evitare IMHO.

    In regola qui:

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

    Stai dicendo a fare a guardare nella directory corrente, mentre i file di origine sono in src directory, quindi questo modello non viene mai utilizzato e non adatto.


    Assicurarsi che si organizza un progetto di directory come questo :

    + 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

    Quindi diamo il processo passo per passo, utilizzando le buone pratiche.

    In primo luogo, non definire nulla se non è necessario. Ha un sacco di variabili predefinite e le funzioni che si dovrebbe usare prima di tentare di farlo manualmente. In realtà, egli ha così tanti che si può compilare un semplice progetto senza neanche avere un Makefile nella directory a tutti !

    1. Nome il tuo obiettivo finale, che è, il tuo eseguibile:

      EXE = hellomake
    2. Elenco di origine e di costruire la directory di output:

      SRC_DIR = src
      OBJ_DIR = obj
    3. Lista il tuo file di origine:

      SRC = $(wildcard $(SRC_DIR)/*.c)
    4. Dal file di origine, un elenco di file oggetto:

      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. Avuto qualche preprocessore flag passare? Andare su.

      CPPFLAGS += -Iinclude # -I is a preprocessor flag, not a compiler flag
    6. Avuto qualche flag di compilazione aggiungere? Qui si va.

      CFLAGS += -Wall # some warnings about bad code
    7. Avuto qualche linker bandiere?

      LDFLAGS += -Llib # -L is a linker flag
    8. Ottenuto alcune librerie di terze parti per linkare?

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

    Ok, il tempo per stendere un po ‘ di ricette, ora che il nostro variabili sono correttamente compilati.

    È ampiamente diffuso che il target di default dovrebbe essere chiamato all. Per semplicità, si deve essere il primo obiettivo nel Makefile, e i suoi prerequisiti deve essere l’obiettivo che si vuole costruire, durante la scrittura di make sulla riga di comando:

    all: $(EXE)

    Ora elenco i prerequisiti per la costruzione del vostro eseguibile, e riempire la sua ricetta per raccontare a fare ciò che a che fare con questi:

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

    Alcune note veloci:

    • $(CC) è una variabile che contiene già di che cosa avete bisogno quando la compilazione e collegamento in C,
    • Per evitare errori del linker, si dovrebbe mettere $(LDFLAGS) prima il tuo file oggetto e $(LDLIBS) dopo.
    • $(CPPFLAGS) e $(CFLAGS) sono inutile qui, durante la fase di compilazione è già finita, è la fase di collegamento qui.

    Passo successivo, dal momento che la sorgente e i file oggetto non condividono lo stesso prefisso, è necessario indicare esattamente cosa fare, dato che la sua built-in e le regole non riguardano il tuo caso specifico:

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

    Ok, adesso l’eseguibile dovrebbe costruire bene, siamo in grado di pulire la directory di compilazione, se vogliamo:

    clean:
        $(RM) $(OBJ)

    Ultima cosa. Si dovrebbe indicare ogni volta che una regola non produce alcun output di destinazione con il .PHONY sepcial regola:

    .PHONY: all clean

    Risultato finale:

    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)
    • Grazie! Ben scritto, introduzione su come scrivere un makefile 🙂
    • Impressionante la copertura. Sono stato con la stessa tutorial di questo ragazzi è riportato di seguito per ANNI! Questo è così chiaro e conciso.
    • Questo è grande. Questo finalmente mi permette di organizzare il modo in cui voglio senza muck intorno nell’iperspazio (autoconf)
  2. 0

    Semplice Makefile definizioni sembrano OK a me come appaiono nella tua domanda. Provare a specificare le opzioni del compilatore prima i nomi dei file:

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

    È necessario eseguire make dalla directory di origine.

    • Cambio l’ordine delle bandiere, non aiuta… il problema è che il file oggetto sono effettivamente mancanti dalla riga di comando.
    • la commutazione tra le opzioni non è la soluzione, ma è consigliabile. Perché questo $(OBJ) è vuota, l’OP non è l’utilizzo di Gnu fare o c’è qualcosa che manca dalla domanda.
  3. 0

    l’utilità, con specifici “target” farà la prima destinazione nel file.

    Il primo target è di solito chiamato ‘all’

    Per il file inviato, farà il file oggetto e non continuare a fare l’eseguibile quando il bersaglio non è indicata nella riga di comando

    Suggeriscono i seguenti:

    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
    • Il tuo commento non è corretto. Schema di regole e le regole di suffisso (regole implicite) non possono contare come predefinito obiettivi. La prima regola esplicita nel makefile sopra è helloworld e che è la destinazione che verrà creato se non altro obiettivo è dato dalla riga di comando. Sebbene l’aggiunta di un all di destinazione non è una cattiva idea, non è necessario. Inoltre, il tuo commento sull’utilizzo di -D è sbagliato: fare non utilizzare -D per definire le variabili. E non è possibile scrivere il preprocessore dichiarazioni come #ifdef in un makefile (che è solo un commento da fare). Ci sono altre problematiche cose anche qui.

Lascia un commento