makefile - Makefile忽略包含的规则
问题描述
我正在尝试为一个非常基本的 c++ 程序创建一个生成文件。我试图通过使用 -M 标志运行 g++ 来实现依赖项的自动生成,将此输出存储在一个.d
文件中,然后将这些.d
文件包含在我的主 makefile 中。makefile 内容如下
CC=g++
CPPFLAGS=-Wall -Wextra -g -std=c++11
SOURCEDIR=src
SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)
BUILDDIR=build
OBJDIR=$(BUILDDIR)/objs
OBJS=$(SOURCES:$(SOURCEDIR)/%.cpp=$(OBJDIR)/%.o)
DEP_FILES = $(OBJS:.o=.d)
OUTFILE=hello.out
$(OUTFILE) : $(OBJS)
$(CC) -o $@ $^ $(CPPFLAGS)
include $(DEP_FILES)
$(OBJDIR)/%.d : $(SOURCEDIR)/%.cpp
$(CC) $(CPPFLAGS) $< -MM -MT $(@:.d=.o) > $@
$(DEP_FILES) : | $(OBJDIR)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
.PHONY: clean
clean:
rm -f $(BUILDDIR) -r
rm -f *~
rm -f $(OUTFILE)
当我运行make
时,会生成目录build/objs/
并生成一个.d
包含规则的文件。这是main.d
文件:
build/objs/main.o: src/main.cpp src/main.h
这是myfunc.d
文件:
build/objs/myfunc.o: src/myfunc.cpp src/main.h
这是问题
由于我在这些 .d 文件上调用 include ,我希望随后创建它们指定的 .o 文件,然后将主输出文件创建为主要规则。但是,make 创建.d
文件,然后直接跳到主编译步骤而不创建任何 .o 文件:
g++ -o hello.out build/objs/myfunc.o build/objs/main.o -Wall -Wextra -g -std=c++11
这将失败并出现以下错误,因为.o
从未创建文件:
g++: error: build/objs/myfunc.o: No such file or directory
g++: error: build/objs/main.o: No such file or directory
g++: fatal error: no input files
如何使用此 makefile 生成.o
g++ 所需的文件?感谢您提前提供任何帮助!
解决方案
我看到你的 makefile 可以正常工作,但我只是想添加一些你可能想要为未来项目考虑的东西。我建议使用 vpath 变量,而不是$(OBJDIR)/%.o
在您的 makefile 配方中指定。我实际上在某处读到,在单独的目录中构建目标文件不是“大炮”,但是在发布之前进行的粗略搜索中,我找不到该文档。
话虽这么说,我写了一个makefile来做你想做的事;它构建输出文件夹、生成依赖项并编译程序。我特别包含了$(COMPILE.cpp)
定义,所以你可以看到它是由什么组成的。$(CC)
特别是 C 编译器,特别是 C 编译器$(CFLAGS)
的标志。很明显,它们只是变量,因此您可以像以前那样更改它们并且它会正常工作,但要记住的主要想法是,使用您的程序的人都希望能够按照他们认为合适的方式配置编译。这意味着他们将设置$(CXX)
并$(CXXFLAGS)
期望设置 C++ 编译器和标志。$(CPPFLAGS)
代表 C/C++ 预处理器标志。
它不是最干净的 makefile,如果我要更改某些内容,我只需将目标文件编译到位,就可以省去头疼的问题。这减少了不必要的黑客攻击,但为了回答您的问题,这里是。无论如何,我希望这对您有所帮助,如果您有任何问题,请告诉我。
哦,是的,我差点忘了;请注意我更改了您的make clean
脚本。我用$(RM)
的不是简单的rm -f
. 当您在 makefile 中使用实用程序时,您希望将它们用作变量。同样,这是为了让您的用户在编译您的程序时尽可能多地自由和灵活。
vpath %.cpp src
vpath %.hpp include
vpath %.o build/objs
vpath %.d build/objs
.SUFFIXES:
.SUFFIXES: .cpp .hpp .o .d
SRCDIR = src
INCLUDESDIR = include
BUILDDIR = build
OBJDIR = $(BUILDDIR)/objs
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
DEP_FILES = $(patsubst %.o, %.d, $(OBJS))
INCLUDE_DIRS = -I $(INCLUDESDIR)
CXX = g++
CPPFLAGS =
CXXFLAGS = -Wall -Wextra -g -std=c++11
PROGRAM = hello.out
COMPILE.cpp = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) $(TARGET_ARCH)
all: $(PROGRAM)
$(PROGRAM): %: $(OBJS)
$(LINK.cpp) $(INCLUDE_DIRS) $(addprefix $(OBJDIR)/, $^) $(LOADLIBES) $(LDLIBS) -o $@
%.o: %.cpp
$(COMPILE.cpp) -c -o $(OBJDIR)/$@ $<
%.d: %.cpp
mkdir -p $(OBJDIR)
$(COMPILE.cpp) $^ -MM -MT $(addprefix $(OBJDIR)/, $(@:.d=.o)) > $(OBJDIR)/$@
include $(DEP_FILES)
.PHONY: clean
clean:
@echo $(RM)
$(RM) $(BUILDDIR) -r
$(RM) *~
$(RM) $(PROGRAM)
推荐阅读
- odoo - 字段类型的上下文参考
- computer-vision - 从单个图像估计相机高度、方向和视野
- r - 模拟与多个其他向量相关的数据
- java - Java - 向大查询重复插入一行数据问题
- python - 我的标准缩放器输出 ValueError: could not convert string to float
- r - How to customize x axis tick labels for ggplot2 object created by plot() method
- code-coverage - Powermock 在 Maven 中具有 jacoco 代码覆盖率
- c - 有没有办法在我的 64 位 PC 中使用 minGW 编译 x64 程序?
- facebook - 如何获取 Facebook Facebook 公共页面内容访问权限只是为了提取数据?
- amazon-web-services - AWS RDS 多主写入多个区域