对我的 Makefile 如何重新制作目标文件感到困惑
Confused how my Makefile is remaking object files
我的 make 文件在尝试重新制作目标文件时找不到我的 include 目录。例如,当我调用 make tests
时,我得到输出:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
我的 Makefile 是这样的:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
我的理解是,当我调用 make tests
时,它应该尝试重新制作 sdl_class.o 文件。然后这应该调用 %.o
规则,它应该尝试通过调用类似的东西来制作目标文件:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
然而,事实并非如此,因为它看起来像是在调用 $(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
,正如您从上面看到的那样。
我对 make 如何构建其规则有根本性的误解吗?很可能,这是我的第一个 Makefile。也许我对编译的一般工作方式感到困惑,因为我对此也有些陌生。
CC/CCFLAGS 用于 C 编译。对于 C++,您应该使用 CXX 和 CXXFLAGS。它们用在内置规则和 LINK.cc 宏中,使 Makefile 更简单,因此更不容易出错。
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $@ $^
见Default linker setting in Makefile for linking C++ object files
我会说问题是一个或多个文件 ../include/sdl_class.h
或 ../include/SDL_image.h
不存在。因此,make 决定你的模式规则不匹配(因为不是所有的先决条件都可以找到或制作)并且它默认使用内置规则从 .cpp
文件创建目标文件。
内置规则对 C++ 编译器使用 make 变量 CXX
,对 C++ 标志使用 CXXFLAGS
:CC
和 CFLAGS
变量用于C编译器。这就是为什么您对 CFLAGS
的设置被忽略的原因。
如果你 运行 make -d sdl_class.o
你会看到 make 正在寻找哪个文件以及为什么它决定不使用你的模式规则。
如果你像这样重写你的规则,它会更好地工作:
%.o: %.cpp
$(CC) -c -o $@ $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
因为 make 现在会抱怨找不到或创建相关文件。
当然还有其他问题。您不应该将 $(LIBS)
传递给您的编译命令;仅属于您的 link 行。而且,对于 C++ 编译器,您可能应该坚持使用标准变量 CXX
,对于 -I
和 -D
等预处理器标志使用 CPPFLAGS
,对于 C++ 编译器使用 CXXFLAGS
旗帜。此外,linker 库标志如 -L../lib
进入 LDFLAGS
和 linker 库标志如 -lSDL2
进入 LDLIBS
.
我的 make 文件在尝试重新制作目标文件时找不到我的 include 目录。例如,当我调用 make tests
时,我得到输出:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
我的 Makefile 是这样的:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
我的理解是,当我调用 make tests
时,它应该尝试重新制作 sdl_class.o 文件。然后这应该调用 %.o
规则,它应该尝试通过调用类似的东西来制作目标文件:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
然而,事实并非如此,因为它看起来像是在调用 $(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
,正如您从上面看到的那样。
我对 make 如何构建其规则有根本性的误解吗?很可能,这是我的第一个 Makefile。也许我对编译的一般工作方式感到困惑,因为我对此也有些陌生。
CC/CCFLAGS 用于 C 编译。对于 C++,您应该使用 CXX 和 CXXFLAGS。它们用在内置规则和 LINK.cc 宏中,使 Makefile 更简单,因此更不容易出错。
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $@ $^
见Default linker setting in Makefile for linking C++ object files
我会说问题是一个或多个文件 ../include/sdl_class.h
或 ../include/SDL_image.h
不存在。因此,make 决定你的模式规则不匹配(因为不是所有的先决条件都可以找到或制作)并且它默认使用内置规则从 .cpp
文件创建目标文件。
内置规则对 C++ 编译器使用 make 变量 CXX
,对 C++ 标志使用 CXXFLAGS
:CC
和 CFLAGS
变量用于C编译器。这就是为什么您对 CFLAGS
的设置被忽略的原因。
如果你 运行 make -d sdl_class.o
你会看到 make 正在寻找哪个文件以及为什么它决定不使用你的模式规则。
如果你像这样重写你的规则,它会更好地工作:
%.o: %.cpp
$(CC) -c -o $@ $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
因为 make 现在会抱怨找不到或创建相关文件。
当然还有其他问题。您不应该将 $(LIBS)
传递给您的编译命令;仅属于您的 link 行。而且,对于 C++ 编译器,您可能应该坚持使用标准变量 CXX
,对于 -I
和 -D
等预处理器标志使用 CPPFLAGS
,对于 C++ 编译器使用 CXXFLAGS
旗帜。此外,linker 库标志如 -L../lib
进入 LDFLAGS
和 linker 库标志如 -lSDL2
进入 LDLIBS
.