我有一个(相当简单的)改编自here的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()
调用两个测试函数Bar()
和Foo.cpp
,它们引用头文件Foo.hpp
。这是makefile:
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
为了让头文件正确链接,我在这里缺少什么?
编辑:这是新的makefile,以及当前的输出:
# 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.
答案 0 :(得分:1)
不要在make中对变量赋值放置行尾注释。它没有按照你期望的方式工作。
你的makefile没有运行你期望的步骤。
您不应该在编译步骤中看到Linking...
。
make不应该尝试从源.cpp
文件创建目标。
你 应该在编译行上看到你的INC
和CFLAGS
值(但是你得到了链接输出,所以显然没有看到它们。)< / p>
这就是为什么你的标题无法找到的原因,你的链接线在任何地方都没有-I
。
发生这种情况的原因是因为make正在应用错误的规则。
make正在应用错误的规则,因为您的变量设置不正确。
您的变量设置不正确,因为您的变量具有您不期望的值。
您开始使用的makefile存在作者无法识别的错误。
make并不总是很聪明。
写作时
FOO := some value # comment
您希望FOO
的值为some value
,但make会以不同的方式查看。
make为其赋予值some value
,因为它无法区分some
和value
之间的空格与value
之后和*.$(SRCEXT)
之后的空格评价。
因此,当您运行shell命令(*.'$(SRCEXT)'
未加引号)时,shell只会忽略尾随空格。 (尝试引用$(SOURCES:=.$(SRCEXT)=.o)
,看看你得到了什么。)
然而,当您尝试$(src/Main.cpp src/Foo.cpp:=cpp =.o)
时,请不要删除空格并且您实际上已经写了$(OBJECTS)
,您可能会注意到,这是一种实际上并不匹配的模式
结果$(SOURCES)
获得未修改的$(TARGET): $(OBJECTS)
值和&#34;混淆&#34; g++
行后来导致make跳过编译目标。
(哦,这就是为什么你的链接行在src/
和第一个源文件之间有一百万个空格的原因。)
哦,而且,除非你的$(wildcard $(SRCDIR)/*.$(SRCEXT))
目录有自己的子目录(甚至没有一些make魔法),否则你不需要在那里找到它,因为{{1}将工作得很好(并且也会早先失败,我相信这个问题)。
答案 1 :(得分:1)
定义一个具有的环境变量。 (当前工作目录)首先,然后是./include(不仅包括子目录,而是因为编译器或其他软件要求,你可能已经拥有的INCLUDE目录中的as,/ include和其余部分)
set INCLUDE :=.:./include:$INCLUDE
或者,使用:
INC := -I. -I./include
gcc -I选项如下:-I dir 将目录dir添加到要搜索头文件的目录列表中。以&#39; -I&#39;命名的目录在标准系统包含目录之前搜索。如果目录dir是标准系统包含目录,则忽略该选项以确保系统目录的默认搜索顺序和系统头的特殊处理不会被破坏