Вопрос:
У меня есть следующий 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 $@ $< $(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? Как исправить это?
Лучший ответ:
Эти строки в вашем файле 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 $@ $(OBJ_DIR)/Trace.o: $(DEPS) Ответ №1
Препроцессор ищет StdCUtil/split.h в
- ./ (т.е. /root/Core/, каталог, содержащий инструкцию #include). Итак ./ + StdCUtil/split.h= ./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»
но таким образом вы потеряли “синтаксис пути”, который очень четко указывает, к какому пространству имен или модулю принадлежит файл заголовка.
Ссылка:
- С++ #include семантика
ИЗМЕНИТЬ/UPDATE
Он также должен быть
CXX = g++ CXXFLAGS = -c -Wall -I$(INC_DIR) … %.o: %.cpp $(DEPS) $(CXX) -o $@ $< $(CXXFLAGS) Ответ №2
Это не вопрос о make, это вопрос о семантике директивы #include.
Проблема в том, что на пути нет файла “../StdCUtil/StdCUtil/split.h”. Это путь, который возникает, когда компилятор объединяет путь включения “../StdCUtil” с относительным путем из директивы #include “StdCUtil/split.h”.
Чтобы исправить это, используйте -I.. вместо -I../StdCUtil.
Ответ №3
Попробуйте INC_DIR=../ ../StdCUtil.
Затем установите CCFLAGS=-c -Wall $(addprefix -I,$(INC_DIR))
EDIT: измените свой #include на #include <StdCUtil/split.h>, чтобы компилятор знал использовать -I, а не локальный путь .cpp, используя #include.