找不到make为的标头

Unable to find headers with make

本文关键字:make 找不到      更新时间:2023-10-16

我有一个(相当简单)的makefile,我正试图用它在Ubuntu上构建一个项目。项目树相当简单:Makefile在根项目目录中,有src/include/build/bin/,分别存储源代码、头文件、对象文件和可执行文件。

当我从项目的根目录运行make时,我得到以下错误消息:

Linking...
g++                  src/Main.cpp src/Foo.cpp -o bin/runner     
src/Main.cpp:1:19: fatal error: Foo.hpp: No such file or directory 
#include "Foo.hpp"
               ^
compilation terminated.
src/Foo.cpp:1:19: fatal error: Foo.hpp: No such file or directory
 #include "Foo.hpp"
               ^
compilation terminated.
make: *** [bin/runner] Error 1

目前项目中的所有内容都是Main.cpp。其从引用头文件Foo.hppFoo.cpp调用两个测试函数Foo()Bar()。这是生成文件:

CC := g++               # This is the main compiler
SRCDIR := src           # Directory for source code
BUILDDIR := build       # Directory containing all object files, which are removed on "make clean"
TARGET := bin/runner    # bin/runner contains the main executable for project
                        # bin/ contains all other executables in the project (such as tests)
SRCEXT := cpp           # File extension of source code
# Look for all the source files in SRCDIR with the file extension specified above
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
# Name all object files the same root name as the source files from which they came, but add a .o extension to the end
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
# The -g flag specifies that debugging information should be produced in the native format of the OS
CFLAGS := -g -Wall
# Various flags for libraries that might need to be linked
INC := -I include       # Ensures that all header files (in the include/ folder) are accessible for build
# Show the components that are currently being compiled/linked
# Also, this is the main procedure for make: The TARGET is built from the objects, and
# object files are built from source
$(TARGET): $(OBJECTS)
    @echo " Linking..."
    @echo " $(CC) $^ -o $(TARGET)"; $(CC) $^ -o $(TARGET)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
    @mkdir -p $(BUILDDIR)
    @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"; $(CC) $(CFLAGS) $(INC) -c -o $@ $<
# Directives for "make clean" which cleans all object files out of the build/ folder
clean:
    @echo " Cleaning..."; 
    @echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Destroys everything in the build/ and bin/runner/ folders. Does not clean test executables.
.PHONY: clean

为了使头文件正确链接,我在这里缺少了什么?

编辑:这是新的生成文件和当前输出:

# This is the main compiler
CC := g++
# Directory for source code
SRCDIR := src
# Directory containing all object files, which are removed on "make clean"
BUILDDIR := build
# bin/runner contains the main executable for project
# bin/ contains all other executables in the project (such as tests)
TARGET := bin/runner
# File extension of source code
SRCEXT := cpp
# Ensures that all header files (in the include/ folder) are accessible for build
INC := -I/include
# Look for all the source files in SRCDIR with the file extension specified above
# SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
SOURCES := $(wildcard $(SRCDIR)/*.$(SRCEXT))
# Name all object files the same root name as the source files from which they came, but add a .o extension to the end
# OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
OBJECTS := $(addprefix $(TARGET)/, $(notdir $(SOURCES:.cpp=.o)))
# The -g flag specifies that debugging information should be produced in the native format of the OS
CFLAGS := -g -Wall
# Various flags for libraries that might need to be linked
LIB := #-pthread -lmongoclient -L lib -lboost_thread-mt -lboost_filesystem-mt -lboost_system-mt
# Show the components that are currently being compiled/linked
# Also, this is the main procedure for make: The TARGET is built from the objects, and
# object files are built from source
$(TARGET): $(OBJECTS)
    @echo " Linking..."
    $(CC) $^ -o $(TARGET)
    # @echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
    @mkdir -p $(BUILDDIR)
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<
# Directives for "make clean" which cleans all object files out of the build/ folder
clean:
    @echo " Cleaning..."; 
    @echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Tests
# tester:
    # $(CC) $(CFLAGS) test/tester.cpp $(INC) $(LIB) -o bin/tester
# Spikes
# ticket:
    # $(CC) $(CFLAGS) spikes/ticket.cpp $(INC) $(LIB) -o bin/ticket
# Destroys everything in the build/ and bin/runner/ folders. Does not clean test executables.
.PHONY: clean

输出:

[scott]> make
make: *** No rule to make target `bin/runner/Foo.o', needed by `bin/runner'.  Stop.

tl;dr

不要在make中对变量赋值进行行尾注释。它并不像你所期望的那样工作。


解释

你的makefile没有运行你期望的步骤。

编译步骤不应该看到Linking...

make不应该试图从源.cpp文件创建目标。

应该在编译行上看到INCCFLAGS值(但您得到的是链接输出,所以显然看不到它们)。

这就是为什么你的标题找不到的原因,顺便说一句,你的链接线上没有-I

发生这种情况的原因是make应用了错误的规则。

make应用了错误的规则,因为您的变量设置不正确。

您的变量设置不正确,因为您的变量具有您意想不到的值。

您启动的makefile存在作者不知道的错误。

make并不总是很聪明。

当你写

FOO := some value     # comment

您希望CCD_ 16具有值CCD_。

make给它值some value,因为它不能区分somevalue之间的空间与value之后和注释之前的空间之间的差异。

因此,当您运行shell命令(不带*.$(SRCEXT))时,shell只会忽略后面的空格。(试着引用*.'$(SRCEXT)',看看你得到了什么。)

然而,当您尝试$(SOURCES:=.$(SRCEXT)=.o)时,make不会丢弃空格,并且您实际上已经编写了$(src/Main.cpp src/Foo.cpp:=cpp =.o),您可能会注意到,这是一个实际上不匹配的模式。

因此,$(OBJECTS)获得了$(SOURCES)的未修改值,并"混淆"了$(TARGET): $(OBJECTS)行,导致make跳过编译目标。

(哦,这也是为什么你的链接行在g++和第一个源文件之间有一百万个空格的原因。)

哦,而且,除非你的src/目录有自己的子目录,否则你不需要在那里寻找,因为$(wildcard $(SRCDIR)/*.$(SRCEXT))会很好地工作(考虑到这个问题,我相信早些时候也会失败)。

定义一个具有的环境变量。(当前工作目录),然后/include(不仅包括子目录,还包括as、/include和由于编译器或其他软件要求而可能已经拥有的include目录的其余部分)

set INCLUDE :=.:./include:$INCLUDE

或者,使用:

INC := -I. -I./include

gcc-I选项为:-I dir将目录dir添加到要搜索头文件的目录列表中。在标准系统包含目录之前,将搜索以"-I"命名的目录。如果目录dir是标准的系统包含目录,则会忽略该选项,以确保系统目录的默认搜索顺序和系统头的特殊处理不会被击败