Makfile order-only prerequisites 应用场景,解决并行编译遇到的object存放的自定子目录未被提前创建导致编译失败的问题,No target rule

1 normal prerequisites和order-only prerequisites的区别

https://blog.csdn.net/wwwlyj123321/article/details/107634687

2 场景参考

在工程中使用makefile将所有的object文件,存放一个集中的目录中,而不是放置在与source同目录的情况下。这样带来的好处是,源码目录中不存在中间object文件,方便代码管理。

由于不同的子目录可能存在同名的源文件,因此不建议将所有的object放在同级的目录下面,会导致原来不同的文件会被覆盖。

可以考虑这样的方式:

源码目录

└── a
├── b
│ └── c
└── d

顶层目录存在makefile,执行makefile时,顶层目录创建objs。整个文件目录结构将会变成下面这样,这样对应a/b目录下的某xx.cpp,将会链接到objs/a/b/xx.o。创造一种镜像文件目录结构的方式。

├── a
│ ├── b
│ │ └── c
│ └── d
└── objs
| └── a
| ├── b
| │ └── c
| └── d

因此,在makefile中,编译所有的object时,前提是创建好objs目录结构。可以采用foreach函数逐次mkdir -p的方式。所有的目录采用wildcard 和 patsubst的方式,遍历镜像目录

BASE_SRCDIR = a a/b a/b/c a/b/d
OBJ_PATH = objs

#C_SOURCES = $(wildcard *.c)
C_SRCDIR  = $(BASE_SRCDIR)
C_SOURCES = $(foreach d,$(C_SRCDIR),$(wildcard $(d)/*.c) )
C_OBJS    = $(patsubst %.c, $(OBJ_PATH)/%.o, $(C_SOURCES))

#CPP_SOURCES = $(wildcard *.cpp)
CPP_SRCDIR  = $(BASE_SRCDIR) 
CPP_SOURCES = $(foreach d,$(CPP_SRCDIR),$(wildcard $(d)/*.cpp) )
CPP_OBJS    = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(CPP_SOURCES))

2.1 非并行编译

很简单,一般放置在objs被编译之前的目标位置就ok。

2.2 并行编译

并行编译时,目录创建的目标的操作,可能会被放在gcc -o object之后,导致目标目录不存在,进而导致makefile执行失败。报错

make: *** No rule to make target 

此时,必须将mkdir的操作放置在obj的依赖项中,即prerequisite。

2.2.1 normal prerequiresite

normal prerequiresite的方式带来的问题时,每次重新编译,makefile误认为所有目标依赖的文件已经更新,需要重建目标。
也就是说,每次make带来两个操作,(不管源文件source file是否真的有更新)
1.重新mkdir 所有的目录
2.重新编译所有的object

init_env: 
	mkdir -p $(OBJ_PATH)
	$(foreach d,$(C_SRCDIR), `mkdir -p  $(OBJ_PATH)/$(d)`)
	$(foreach d,$(CPP_SRCDIR), `mkdir -p $(OBJ_PATH)/$(d)`)

$(C_OBJS):$(OBJ_PATH)/%.o:%.c  init_env
	$(CC) -c $(CFLAGS) $< -o $@

$(CPP_OBJS):$(OBJ_PATH)/%.o:%.cpp  init_env
	$(CXX) -c $(CPPFLAGS) $< -o $@

2.2.2 order-only prerequiresite

order-only 的方式,就会避免此问题。

init_env: 
	mkdir -p $(OBJ_PATH)
	$(foreach d,$(C_SRCDIR), `mkdir -p  $(OBJ_PATH)/$(d)`)
	$(foreach d,$(CPP_SRCDIR), `mkdir -p $(OBJ_PATH)/$(d)`)

$(C_OBJS):$(OBJ_PATH)/%.o:%.c | init_env
	$(CC) -c $(CFLAGS) $< -o $@

$(CPP_OBJS):$(OBJ_PATH)/%.o:%.cpp | init_env
	$(CXX) -c $(CPPFLAGS) $< -o $@
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值