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.