J'ai le makefile suivant:
CC=g++
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
all: Lock.o DBC.o Trace.o
%.o: %.cpp $(DEPS)
$(CC) -o $@ $< $(CFLAGS)
clean:
rm -rf *o all
Ce makefile et les trois fichiers source Lock.cpp
, DBC.cpp
, Trace.cpp
se trouvent dans le répertoire courant appelé Core
. L'un des fichiers source Trace.cpp
contient une ligne qui inclut un fichier d'en-tête en dehors du répertoire courant:
//in Trace.cpp
#include "StdCUtil/split.h"
Le fichier d'en-tête split.h
est situé à un niveau au-dessus du répertoire courant, puis dans le sous-répertoire appelé StdCUtil
. Voilà pourquoi j'ai ajouté INC_DIR = ../StdCUtil
dans le makefile. La structure globale du répertoire ressemble à ceci:
root
|___Core
| |
| |____Makefile
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
Mais quand je le fais, ça me donne l'erreur:
Trace.cpp:8:28: fatal error: StdCUtil/split.h: No such file or directory
#include "StdCUtil/split.h"
^
compilation terminated.
<builtin>: recipe for target 'Trace.o' failed
Pourquoi cela ne trouve pas le fichier d'en-tête split.h
même si je spécifie le INC_DIR
dans le makefile? Comment corriger ça?
Ces lignes dans votre makefile,
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
et cette ligne dans votre fichier .cpp,
#include "StdCUtil/split.h"
sont en conflit.
Avec votre makefile dans votre répertoire source et avec ce -I
option que vous devriez utiliser #include "split.h" in your source file, and your dependency should be
../StdCUtil/split.h`.
Une autre option:
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)/.. # Ugly!
DEPS = $(INC_DIR)/split.h
Avec cela, votre #include
la directive resterait comme #include "StdCUtil/split.h"
.
Encore une autre option consiste à placer votre makefile dans le répertoire parent:
root
|____Makefile
|
|___Core
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
Avec cette disposition, il est courant de placer les fichiers objets (et éventuellement l'exécutable) dans un sous-répertoire parallèle à vos répertoires Core
et StdCUtil
. Object
, par exemple. Avec cela, votre makefile devient:
INC_DIR = StdCUtil
SRC_DIR = Core
OBJ_DIR = Object
CFLAGS = -c -Wall -I.
SRCS = $(SRC_DIR)/Lock.cpp $(SRC_DIR)/DBC.cpp $(SRC_DIR)/Trace.cpp
OBJS = $(OBJ_DIR)/Lock.o $(OBJ_DIR)/DBC.o $(OBJ_DIR)/Trace.o
# Note: The above will soon get unwieldy.
# The wildcard and patsubt commands will come to your rescue.
DEPS = $(INC_DIR)/split.h
# Note: The above will soon get unwieldy.
# You will soon want to use an automatic dependency generator.
all: $(OBJS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $@
$(OBJ_DIR)/Trace.o: $(DEPS)
Le préprocesseur recherche StdCUtil/split.h
dans
./
(c'est à dire. /root/Core/
, le répertoire qui contient l'instruction #include ). Alors ./
+ StdCUtil/split.h
= ./StdCUtil/split.h
et le fichier est manquantet en
$INC_DIR
(c'est à dire. ../StdCUtil/
= /root/Core/../StdCUtil/
= /root/StdCUtil/
). Alors ../StdCUtil/
+ StdCUtil/split.h
= ../StdCUtil/StdCUtil/split.h
et le fichier est manquantVous pouvez corriger l'erreur en modifiant le $INC_DIR
variable (meilleure solution):
$INC_DIR = ../
ou la directive include:
#include "split.h"
mais de cette façon, vous avez perdu la "syntaxe du chemin" qui rend très clair à quel espace de noms ou module appartient le fichier d'en-tête.
Référence:
MODIFIER/METTRE À JOUR
Il faut également
CXX = g++
CXXFLAGS = -c -Wall -I$(INC_DIR)
...
%.o: %.cpp $(DEPS)
$(CXX) -o $@ $< $(CXXFLAGS)
Ce n'est pas une question de make, c'est une question de sémantique du #include
directive.
Le problème est qu'il n'y a pas de fichier sur le chemin "../StdCUtil/StdCUtil/split.h". Il s'agit du chemin qui résulte lorsque le compilateur combine le chemin d'inclusion "../StdCUtil" avec le chemin relatif de #include
directive "StdCUtil/split.h".
Pour résoudre ce problème, utilisez simplement -I..
au lieu de -I../StdCUtil
.
Essayez INC_DIR=../ ../StdCUtil
.
Ensuite, définissez CCFLAGS=-c -Wall $(addprefix -I,$(INC_DIR))
EDIT: modifiez également votre #include
Pour qu'il soit #include <StdCUtil/split.h>
Afin que le compilateur sache utiliser -I plutôt que le chemin local du .cpp en utilisant le #include
.