我为项目创建了一个makefile,但是make不会遍历我的源文件。我不知道该怎么办。
我的atm目录中有2个源文件
Makefile:
LIBNAME=hazelicious
FLIBNAME=lib$(LIBNAME).so
VERSION=
CC=g++
CXXFLAGS=-W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
LDFLAGS=-shared -Wl,-soname,$(FLIBNAME)
DSRC=src/
DTGT=
DOBJ=$(DTGT)obj/
DOUT=$(DTGT)bin/
EXEC=$(DOUT)$(APPNAME)
SRC= $(wildcard $(DSRC)**/*.cpp)
OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))
all: $(FLIBNAME)
install:
@sudo cp $(DOUT)$(FLIBNAME) /usr/local/lib/
@sudo cp $(DSRC)Hazelicious.h /usr/local/include/
@echo "Library and header files copied!"
$(FLIBNAME): $(OBJ)
@mkdir -p $(DOUT)
@$(CC) -o $(DOUT)$@ $^ $(LDFLAGS)
$(OBJ): $(SRC)
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
checkvar:
@echo $(SRC)
@echo $(OBJ)
clean:
@rm -rf $(DOBJ)
@rm -rf $(EXEC)
run:
@./$(EXEC)
输出:
g++ -o obj/Hazelicious/Log.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
g++ -o obj/Hazelicious/Application.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
您会看到第二行使用相同的Log.cpp
文件
我的目录结构:
/src
/Hazelicious
Application.cpp
Log.cpp
...
/obj
/Hazelicicous
/bin
答案 0 :(得分:0)
如果您期望这样:
SRC= $(wildcard $(DSRC)**/*.cpp)
要在.cpp
的所有子目录中找到所有$(DSRC)
文件,您会很失望的。 **
特殊的globbing序列是非标准的,并且仅受某些shell支持(如zsh或bash(如果启用了特殊选项))。它不是POSIX标准通配符的一部分,并且不受GNU make的wildcard
函数支持。您必须使用标准的实现,例如:
SRC := $(shell find $(DSRC) -name \*.cpp)
(此处使用简单的变量分配(:=
,而不是递归变量分配(=
),以大大提高效率)。
也是这样:
OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))
可能会惹上麻烦,因为subst
会替换 all 个实例,即使在单词中间,即使一个单词中有多个实例也是如此。更好(更简单)的只是:
OBJ := $(patsubst $(DSRC)/%.cpp,$(DOBJ)/%.o,$(SRC))
看到相同源文件的原因是您的配方错误:
$(OBJ): $(SRC)
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
假设SRC
解析为src/foo.cpp src/bar.cpp src/biz.cpp
。然后OBJ
解析为obj/foo.o obj/bar.o obj/biz.o
。因此,在扩展了以上规则的目标和前提条件之后,make将获得以下信息:
obj/foo.o obj/bar.o obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
当make在一个显式规则中看到多个目标时,它将视为多个显式规则,每个目标一个,如下所示:
obj/foo.o : src/foo.cpp src/bar.cpp src/biz.cpp
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
obj/bar.o : src/foo.cpp src/bar.cpp src/biz.cpp
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
mkdir -p $(DOBJ)
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
您可以看到,在所有规则中,第一个必备条件(即$<
扩展到的前提)将是src/foo.cpp
,这正是您所观察到的行为。
Make不会以某种方式神奇地遍历所有目标和先决条件并为您匹配它们。
在in中,您始终会从该目标的先决条件列表中编写一个构建单个目标的规则。在您的情况下,您可能想要编写如下的 pattern规则:
$(DOBJ)/%.o : $(DSRC)/%.cpp
mkdir -p $(@D)
$(CC) -o $@ -c $< $(CXXFLAGS)
代替上面的明确规则。这为make提供了一种模式,可用于构建与其匹配的任何目标,并列出了关联的.cpp
文件的先决条件。