Makefile: как правильно включить заголовочный файл и его каталог?
У меня есть следующий make файл:
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 [email protected] $< $(CFLAGS)
clean:
rm -rf *o all
Этот файл makefile и все три исходных файла Lock.cpp
, DBC.cpp
, Trace.cpp
расположены в текущем каталоге с именем Core
. Один из исходных файлов Trace.cpp
содержит строку, которая содержит файл заголовка за пределами текущего каталога:
//in Trace.cpp
#include "StdCUtil/split.h"
Заголовочный файл split.h
расположен на одном уровне выше текущего каталога, а затем в подкаталоге StdCUtil
. Поэтому я добавил INC_DIR = ../StdCUtil
в make файл. Общая структура каталогов выглядит следующим образом:
root
|___Core
| |
| |____Makefile
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
Но когда я это сделаю, это дает мне ошибку:
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
Почему это не находит заголовочный файл split.h
, даже если я укажу INC_DIR
в файле makefile? Как исправить это?
Ответы
Ответ 1
Эти строки в вашем файле makefile,
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
и эта строка в вашем .cpp файле,
#include "StdCUtil/split.h"
находятся в конфликте.
С вашим make файлом в исходном каталоге и с этим параметром -I
вы должны использовать #include "split.h" in your source file, and your dependency should be
../StdCUtil/split.h`.
Другая опция:
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)/.. # Ugly!
DEPS = $(INC_DIR)/split.h
При этом ваша директива #include
останется как #include "StdCUtil/split.h"
.
Еще один вариант - поместить ваш make файл в родительский каталог:
root
|____Makefile
|
|___Core
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
В этом макете обычно размещается объектный файл (и, возможно, исполняемый файл) в подкаталоге, параллельном вашим каталогам Core
и StdCUtil
. Object
, например. При этом ваш make файл будет выглядеть следующим образом:
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 [email protected]
$(OBJ_DIR)/Trace.o: $(DEPS)
Ответ 2
Препроцессор ищет StdCUtil/split.h
в
и в
-
$INC_DIR
(т.е. ../StdCUtil/
= /root/Core/../StdCUtil/
= /root/StdCUtil/
). Итак ../StdCUtil/
+ StdCUtil/split.h
= ../StdCUtil/StdCUtil/split.h
и файл отсутствует
Вы можете исправить ошибку, изменяя переменную $INC_DIR
(лучшее решение):
$INC_DIR = ../
или директива include:
#include "split.h"
но таким образом вы потеряли "синтаксис пути", который очень четко указывает, к какому пространству имен или модулю принадлежит файл заголовка.
Ссылка:
ИЗМЕНИТЬ/UPDATE
Он также должен быть
CXX = g++
CXXFLAGS = -c -Wall -I$(INC_DIR)
...
%.o: %.cpp $(DEPS)
$(CXX) -o [email protected] $< $(CXXFLAGS)
Ответ 3
Это не вопрос о make, это вопрос о семантике директивы #include
.
Проблема в том, что на пути нет файла "../StdCUtil/StdCUtil/split.h". Это путь, который возникает, когда компилятор объединяет путь включения "../StdCUtil" с относительным путем из директивы #include
"StdCUtil/split.h".
Чтобы исправить это, используйте -I..
вместо -I../StdCUtil
.
Ответ 4
Попробуйте INC_DIR=../ ../StdCUtil
.
Затем установите CCFLAGS=-c -Wall $(addprefix -I,$(INC_DIR))
EDIT: измените свой #include
на #include <StdCUtil/split.h>
, чтобы компилятор знал использовать -I, а не локальный путь .cpp, используя #include
.