每次构建(make)lib,只有当lib更新时才重新编译项目

时间:2017-07-05 13:36:24

标签: c++ makefile

我有以下项目结构:

lib/
    Makefile
    src/...
    inc/...
    build/
        inc/...
        lib/libmylib.a
subproj1/
    src/main.cpp
    Makefile 

Makefile文件夹中的lib用于创建文件libmylib.a,并将相关的头文件复制到build/inc文件夹。

我希望Makefile中的subproj1始终调用make -C ../lib,但只有在标题发生更改时才重新编译文件,并且仅在必要时重新链接(一个目标文件或{ {1}}较新)。

我有以下内容(libmylib.a等未定义的变量在另一个文件中定义):

CC

即使lib文件夹中没有任何更改,上面的内容也会重新编译LIBDIR = ../lib SRCDIR = src OBJDIR = obj SRCS = $(SRCDIR)/main.cpp MAIN=myexe OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) DEPS = $(OBJS:.o=.d) all: $(MAIN) debug: CFLAGS += -g -DDEBUG debug: LFLAGS += -g debug: $(MAIN) $(MAIN): $(OBJS) $(LIBDIR)/build/lib/libmylib.a $(CC) $^ -o $@ $(LIBS) $(LFLAGS) $(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(LIBDIR)/build/lib/libmylib.a mkdir -p $(OBJDIR) $(CC) -c -o $@ $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $@) $< $(LIBDIR)/build/lib/libmylib.a: make -C $(LIBDIR) -include $(DEPS) .PHONY: clean $(LIBDIR)/build/lib/libmylib.a clean: $(RM) obj/* $(MAIN) 。如果我从main.cpp规则中删除$(LIBDIR)/build/lib/libmylib.a,则如果标题已更改,则不会重新编译$(OBJDIR)/%.o文件(我需要运行.cpp两次)。

只有在make中的标头文件发生更改(或者.cpp文件本身已更改时)才能编译subproj1中的lib个文件),只有在.cpp之一被重新编译(较新的myexe)或.cpp较新的情况下才能构建.o

2 个答案:

答案 0 :(得分:1)

使用递归makefile,您需要以正确的顺序执行子项目makefile,因为依赖关系树不完整(例如,此makefile不知道更新$(LIBDIR)/build/lib/libmylib.a也会更新这些标头)。使用shell脚本或顶级makefile很容易做到这一点。

或者,您的makefile必须以正确的顺序无条件地执行子makefile,这可以使用shell函数来完成,例如:

LIBDIR := ../lib
pid := $(shell ps -o ppid= $$$$)
$(shell ${MAKE} -C ${LIBDIR} >/proc/$(pid)/fd/1 2>/proc/$(pid)/fd/2)

应删除$(LIBDIR)/build/lib/libmylib.a规则,目标文件不应取决于.a,也不应将其标记为.PHONY

这可以确保在${LIBDIR}中构建此makefile之前在${LIBDIR}中分析文件时间戳。

现在,您自动生成的标头依赖项应该可以正常工作。

答案 1 :(得分:0)

这可能会更清洁。

LIBDIR = ../lib
SRCDIR = src
OBJDIR = obj
SRCS = $(SRCDIR)/main.cpp

MAIN=myexe

OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS = $(OBJS:.o=.d)

all: makelib
    $(MAKE) $(MAIN)

debug: CFLAGS += -g -DDEBUG
debug: LFLAGS += -g
debug: $(MAIN)

$(MAIN): $(OBJS)
    $(CC) $^ -o $@ $(LIBS) $(LFLAGS)

$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    mkdir -p $(OBJDIR)
    $(CC) -c -o $@ $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $@) $<

makelib:
    make -C $(LIBDIR)

-include $(DEPS)

.PHONY: clean makelib

clean:
    $(RM) obj/* $(MAIN)

主要目标all需要构建makelib,然后以递归方式为目标$(MAIN)调用自身(因此将重新计算所有$(MAIN)的依赖项makelib完成建设后。)