web-dev-qa-db-fra.com

Obtenir make pour créer des fichiers objets dans un répertoire spécifique

GNU Make 3.82
gcc 4.7.2
c89

J'ai le fichier make suivant:

INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

EXECUTABLE=bin/to

all:    build $(EXECUTABLE)

$(EXECUTABLE):  $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

build:
    @mkdir -p bin

clean:
    rm -rf $(EXECUTABLE) $(OBJECTS) bin
    find . -name "*~" -exec rm {} \;
    find . -name "*.o" -exec rm {} \;

La structure de mon répertoire est la suivante project/src project/bin. Mon Makefile est dans le dossier project (root), et tous mes * .h et * .c sont dans le répertoire src. Actuellement, je n'ai qu'un seul fichier source appelé timeout.c

Je reçois cette erreur:

gcc: error: src/timeout.o: No such file or directory

Je l'ai utilisé pour obtenir tous les fichiers source:

SOURCES=$(wildcard src/*.c)

Et les fichiers objets:

OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

Cependant, la marque semble créer le fichier objet dans le dossier racine du projet où se trouve le Makefile. Ne devrait-il pas le mettre dans le répertoire src?

22
ant2009

Vous avez deux problèmes dans cette règle (enfin, trois):

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

Vous ne l'avez pas encore remarqué, mais la règle fait que chaque objet dépend de tout sources, et essaie de construire de cette façon. Pas un problème tant que vous n'avez qu'une seule source. Facile à corriger avec un règle de modèle statique et ne variable automatique :

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)

De plus, la commande ("$ (CC) ...") ne spécifie pas de nom de fichier de sortie, donc gcc le déduira du nom du fichier source; si vous lui donnez src/timeout.c, il produira timeout.o (dans le répertoire de travail, project/). Vous devez donc spécifier le chemin d'accès souhaité au fichier de sortie. Facile à faire avec une autre variable automatique:

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $@
18
Beta

Utilisez l'option - o de gcc pour écrire le fichier de sortie à un emplacement particulier. Par exemple, vous pourriez dire:

$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)

Malheureusement, il y a un problème avec cette ligne: s'il y a plus d'un fichier source dans $(SOURCES), cela ne fonctionnera pas, car $(OBJECTS) contiendra également plusieurs noms de fichier, et le - - o option ne se lie qu'au premier argument.

Un moyen de compiler chaque fichier dans une liste de fichiers de code source consiste à utiliser des règles implicites. Dans gmake, vous écririez:

$(EXECUTABLE):  $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

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

$ < est remplacé par le nom du fichier d'entrée et $ @ est remplacé par le nom du fichier de sortie.

5
radical7