Makefile:如何正确包含头文件及其目录?

ton*_*nga 20 c c++ makefile

我有以下makefile:

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
Run Code Online (Sandbox Code Playgroud)

此生成的文件和所有三个源文件Lock.cpp,DBC.cpp,Trace.cpp位于被称为当前目录Core.其中一个源文件Trace.cpp包含一行,其中包含当前目录之外的头文件:

//in Trace.cpp
#include "StdCUtil/split.h"
Run Code Online (Sandbox Code Playgroud)

头文件split.h位于当前目录上方的一个级别,然后位于名为的子目录中StdCUtil.这就是我INC_DIR = ../StdCUtil在makefile中添加的原因.整个目录结构如下所示:

root
  |___Core
  |     |
  |     |____Makefile
  |     |____DBC.cpp
  |     |____Lock.cpp
  |     |____Trace.cpp
  |
  |___StdCUtil
        |___split.h
Run Code Online (Sandbox Code Playgroud)

但是当我做它时,它给了我错误:

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
Run Code Online (Sandbox Code Playgroud)

为什么split.h即使我INC_DIR在makefile中指定了这个也找不到头文件?怎么纠正这个?

Dav*_*men 26

makefile中的这些行,

INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
Run Code Online (Sandbox Code Playgroud)

和.cpp文件中的这一行,

#include "StdCUtil/split.h"
Run Code Online (Sandbox Code Playgroud)

有冲突.

将makefile放在源目录中并使用该-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
Run Code Online (Sandbox Code Playgroud)

有了这个,你的#include指令将保持不变#include "StdCUtil/split.h".

另一种选择是将makefile放在父目录中:

root
  |____Makefile
  |
  |___Core
  |     |____DBC.cpp
  |     |____Lock.cpp
  |     |____Trace.cpp
  |
  |___StdCUtil
        |___split.h
Run Code Online (Sandbox Code Playgroud)

通过这种布局,通常将目标文件(可能还有可执行文件)放在与您CoreStdCUtil目录并行的子目录中.Object, 例如.有了这个,你的makefile变成:

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)
Run Code Online (Sandbox Code Playgroud)

  • @AlexJohnson——这正是它的意思。gcc 文档说`-I` 选项被指定为`-Idir`,其中`dir` 是要添加到包含路径的目录的名称。`-I=dir` 会将目录 `=dir` 添加到包含路径中。(但是在 `-I` 和目录路径之间有一个空格的 `-I dir` 似乎确实有效。) (2认同)

man*_*lio 5

预处理器正在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 = ../
Run Code Online (Sandbox Code Playgroud)

或包含指令:

#include "split.h"
Run Code Online (Sandbox Code Playgroud)

但这样你就失去了“路径语法”,它使得头文件所属的命名空间或模块非常清楚。

参考:

编辑/更新

也应该是

CXX = g++
CXXFLAGS = -c -Wall -I$(INC_DIR)

...

%.o: %.cpp $(DEPS)
    $(CXX) -o $@ $< $(CXXFLAGS)
Run Code Online (Sandbox Code Playgroud)