我目前正在尝试在 Windows 中为简单的 C++ 项目设置我的第一个 Makefile,以便能够将它用于我创建的每个项目,只需要做一些更改。 在这里,我从所有文件夹中获取源文件:
sources := $(wildcard src/*.cpp) $(wildcard src/*/*.cpp) $(wildcard include/*.cpp) $(wildcard include/*/*.cpp)
这给了我以下输出:
src/main.cpp src/core/console.cpp src/core/filehandler.cpp src/core/framework.cpp src/core/globals.cpp src/core/textureeditor.cpp src/ui/buttonfuncs.cpp src/ui/interface.cpp src/ui/userinterfaces.cpp
现在我想将我的文件编译成目标文件,如下所示:
$(OBJDIR)%.o: $(sources)
@echo compiling $< to $@
@$(CC) -c $< -o $@ $(FLAGS)
它输出:
compiling src/main.cpp to obj/main.o
compiling src/main.cpp to obj/console.o
compiling src/main.cpp to obj/filehandler.o
compiling src/main.cpp to obj/framework.o
compiling src/main.cpp to obj/globals.o
compiling src/main.cpp to obj/textureeditor.o
compiling src/main.cpp to obj/buttonfuncs.o
compiling src/main.cpp to obj/interface.o
compiling src/main.cpp to obj/userinterfaces.o
这清楚地表明它获取了正确的目标文件,但没有从源中获取正确的文件。
是否有解决方案可以迭代源或每次运行时删除源的第一个元素?或者也许有更好的解决方案?
旁注:.o 文件始终与列表中的 .cpp 文件匹配,因为 .o 名称是从源列表生成的。
我尝试将文件夹名称放入 srcs_dir:
srcs_dir = $(foreach wrd,$(sources),$(dir $(wrd)))
并像这样运行它:
$(OBJDIR)%.o: $(srcs_dir)%.cpp
@echo compiling $< to $@
@$(CC) -c $< -o $@ $(FLAGS)
输出如下:
make: *** No rule to make target
obj/main.o',debug'. Stop.
需要
整个 Makefile:
#defining project settings
project_name := Nimble
version := 0.0.1
#defining compiler settings
INCLUDE_PATHS := $(foreach wrd,$(wildcard src/*/),-I $(dir $(wrd))) \
$(foreach wrd,$(wildcard include/*/),-I $(dir $(wrd)))
LIBS := -lraylib -lopengl32 -lgdi32 -lwinmm -llua54
CC := g++
CPP := c++20
DEBUGFLAGS_O := -std=$(CPP) -Wno-missing-braces -w -g -Wall -m64 $(INCLUDE_PATHS)
RELEASEFLAGS_O := -std=$(CPP) -Wno-missing-braces -w -O3 -Wall -m64 $(INCLUDE_PATHS)
#defining paths
OUTPATH_DEBUG := bin/debug/$(project_name)
OUTPATH_RELEASE := bin/release/$(project_name)
OBJDIR := obj/
SRCDIR := src/
#getting headers
headers := $(wildcard src/*.h) $(wildcard src/*/*.h) $(wildcard include/*.h) $(wildcard include/*/*.h)
#getting sourcefiles
sources := $(wildcard src/*.cpp) $(wildcard src/*/*.cpp) $(wildcard include/*.cpp) $(wildcard include/*/*.cpp)
srcs_dir = $(foreach wrd,$(sources),$(dir $(wrd)))
#object_files := $(sources:.cpp=.o)
srcs = $(foreach wrd,$(sources),$(notdir $(wrd)))
object_files := $(foreach wrd,$(srcs:.cpp=.o),$(OBJDIR)$(wrd))
print:
@echo Object Files:
@echo $(object_files)
@echo Sources:
@echo $(sources)
@echo srcs:
@echo $(srcs)
@echo include paths:
@echo $(INCLUDE_PATHS)
@echo headers:
@echo $(headers)
@echo srcs_dir:
@echo $(srcs_dir)
debug: FLAGS := $(DEBUGFLAGS_O)
release: FLAGS := $(RELEASEFLAGS_O)
release: $(object_files)
@$(CC) obj/*.o -o $(OUTPATH_RELEASE) -s -L lib/ $(LIBS)
@xcopy graphics\\ bin\\release\\graphics\\ /s /Y
debug: $(object_files)
@$(CC) obj/*.o -o $(OUTPATH_DEBUG) -L lib/ $(LIBS)
@xcopy graphics\\ bin\\debug\\graphics\\ /s /Y
$(OBJDIR)%.o: $(sources)
@$(CC) -c $< -o $@ $(FLAGS)
clean:
@echo > Cleaning Object files
@cd obj/ && del *.o
@echo > Cleaning
作为总经理建议您想要 使用
VPATH
或 vpath
。在模式规则中,词干(与 %
匹配的部分)必须与目标和先决条件中的相同字符串匹配。没有办法说“这个,加上随机的其他子目录”。
要使用 VPATH,您需要执行以下操作:
sources := $(wildcard src/*.cpp) $(wildcard src/*/*.cpp) $(wildcard include/*.cpp) $(wildcard include/*/*.cpp)
object_files := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(sources)))
VPATH := $(sort $(dir $(sources)))
...
$(OBJDIR)%.o: %.c
$(CC) -c $< -o $@ $(FLAGS)
大多数 make 函数,如
$(dir ...)
和 $(notdir ...)
,接受要操作的单词列表,因此您不需要使用循环并一次传递一个单词。
此外,请不要在您的配方中添加
@
前缀,直到它们完全起作用,否则您只是丢弃重要的调试信息。