我正在通过编写一个简单的基于新建字段基于makefile的项目来学习/加强对makefile的理解。
我的项目树的结构如下:
.
│ makefile
│
├───dep
├───exe
├───include
│ b.h
│ c.h
│
├───lib
├───obj
└───src
a.cpp
b.cpp
c.cpp
所以我的意图/目标是:
在项目根目录下有一个makefile
具有源,头文件,目标文件,库,依赖文件和 每个可执行文件都位于项目根目录的自己的子目录中。
src/
中恰好一个源文件将实现int main(...)
。
makefile应该编译所有源文件,除了那些
对int main(...)
中的目标文件实现obj/
。
makefile应该将所有目标文件归档到lib/
makefile应该通过链接链接将实现int
main(...)
的源文件直接编译为exe/
中的可执行文件。
创建的库。
我想我已经用这个makefile实现了我想要的:
SRCDIR = ./src
INCDIR = ./include
OBJDIR = ./obj
LIBDIR = ./lib
EXEDIR = ./exe
DEPDIR = ./dep
EXE = foo
EXESRC = $(SRCDIR)/a.cpp
DEP = $(DEPDIR)/$(EXE).dep
CXX = g++
CXXFLAGS = -g
AR = ar
# List of *.cpp in $(SRCDIR) that are not $(EXE)
LIBSRC = $(filter-out $(EXESRC),$(wildcard $(SRCDIR)/*.cpp))
# Replace {$(SRCDIR)/a.cpp $(SRCDIR)/b.cpp} w/ {$(OBJDIR)/a.o $(OBJDIR)/b.o} etc
OBJS = $(patsubst %.cpp,%.o,$(patsubst $(SRCDIR)%,$(OBJDIR)%,$(LIBSRC)))
LIB = $(LIBDIR)/lib$(EXE).a
bin: $(EXEDIR)/$(EXE)
$(EXEDIR)/$(EXE): $(EXEDIR) $(EXESRC) $(LIB)
$(CXX) -o $(EXEDIR)/$(EXE) $(CXXFLAGS) -I$(INCDIR) $(EXESRC) -L$(LIBDIR) -l$(EXE)
$(LIB): $(OBJDIR) $(OBJS) $(LIBDIR)
$(AR) ur $(LIB) $(OBJS)
$(EXEDIR):
mkdir $(EXEDIR)
$(LIBDIR):
mkdir $(LIBDIR)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEP)
$(CXX) $(CXXFLAGS) -I$(INCDIR) -o $@ -c $<
$(OBJDIR):
mkdir $(OBJDIR)
$(DEP): $(DEPDIR)
makedepend -- $(CXXFLAGS) -I$(INCDIR) -- $(LIBSRC) $(EXESRC) -f- 2>/dev/null > $(DEP)
sed -i 's,$(SRCDIR),$(OBJDIR),' $(DEP)
$(DEPDIR):
mkdir $(DEPDIR)
-include $(DEP)
但是观察到“ make bin
”的输出连续运行两次:
> make bin
mkdir ./dep
makedepend -- -g -I./include -- ./src/c.cpp ./src/b.cpp ./src/a.cpp -f- 2>/dev/null > ./dep/foo.dep
sed -i 's,./src,./obj,' ./dep/foo.dep
mkdir ./exe
mkdir ./obj
g++ -g -I./include -o obj/c.o -c src/c.cpp
g++ -g -I./include -o obj/b.o -c src/b.cpp
mkdir ./lib
ar ur ./lib/libfoo.a ./obj/c.o ./obj/b.o
ar: creating ./lib/libfoo.a
g++ -o ./exe/foo -g -I./include ./src/a.cpp -L./lib -lfoo
>
> make bin
ar ur ./lib/libfoo.a ./obj/c.o ./obj/b.o
问题:
为什么当我连续多次运行“ make bin
”时,makefile总是执行$(LIB)
配方吗?
根据我对makefile的不稳定理解,当目标的依赖关系比目标的依赖关系新时,会发生这种情况。在这种情况下,我认为这意味着$(LIBDIR)
比$(LIB)
更新。但是为什么会这样呢?根据预期,根据第一个“ make bin
”的输出,在{em> $(LIBDIR)
之前创建$(LIB)
。
我想我不了解makefile中是否有需要纠正的内容,或者我不了解文件系统计时的内容。最终,我正在尝试消除粗糙的边缘,所以在这个问题上,我想了解需要纠正的内容,以便使makefile可以更正确地了解何时没有需要更新的内容,尤其是为什么$(LIBDIR)
当make配方的输出暗示(对我而言)并非如此时,它比$(LIB)
更新。
>ls --full-time -ld lib/libfoo.a
-rw-r--r-- 1 User None 81448 2018-12-22 00:42:07.188906200 -0800 lib/libfoo.a
>
>ls --full-time -ld lib/
drwxr-xr-x+ 1 User None 0 2018-12-22 00:42:07.204531200 -0800 lib/
构建环境为cygwin。