Makefile修改子库源码需执行两次make才触发重链接问题求助
问题原因分析
第一个版本需要二次执行才重链接的原因
- 你将
libs设为了$(NAME)的order-only依赖(|后的依赖项),这类依赖仅保证执行顺序,不会因为自身更新触发目标重生成 - 搭配
vpath和模式规则lib%.a使用时,make在启动阶段就缓存了所有静态库的时间戳,即使子make更新了静态库文件,本次运行的make也不会重新读取更新后的时间戳,只有第二次运行make时才会识别到静态库更新,触发重链接。
第二个版本子库修改不触发重编译的原因
你给libft/libft.a、libgc/libgc.a写的生成规则没有配置任何依赖,只要这两个文件存在,make就会默认它们是最新状态,永远不会执行规则内的子make命令,自然无法检测子库的源码修改。
解决方案
添加一个空的FORCE目标作为子库静态库规则的依赖,强制主make每次都执行子库的make命令,由子make自行判断子库是否需要重编译:
... all: $(NAME) # 新增空的FORCE目标,没有依赖和执行命令 FORCE: ; $(NAME): $(OBJS) libft/libft.a libgc/libgc.a $(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LDFLAGS) -include $(DEPENDENCIES) $(OBJS_DIR)/%.o: %.c $(OBJS_DIR)/debug$(DEBUG) | $(OBJS_DIR) $(CC) $(CFLAGS) $(INCLUDES_DIR:%=-I %) -c $< -o $@ $(OBJS_DIR): $(MKDIR) $@ # 给子库静态库规则添加FORCE依赖 libft/libft.a: FORCE $(MAKE) -C libft libgc/libgc.a: FORCE $(MAKE) -C libgc ...
这个方案的优势:
- 每次执行主make都会进入子库目录执行make,子make会自行对比源码和静态库的时间戳,如果没有修改会直接输出
nothing to be done,不会做多余编译操作 - 只有子库确实有修改、静态库被重新生成时,主make才会触发最终的重链接操作,不需要二次执行make
内容的提问来源于stack exchange,提问作者Romain T-BIGOT
相关产品推荐
相关产品推荐

