前言:我的团队正在开发一些硬件的驱动程序,另一个团队正在开发硬件内部微控制器的固件。不同的工作空间,不同的 Git,除了我们依赖他们的 FW。
编译他们的工作区时,输出之一是文件
fw.h
。它是自动生成的,不是我的 Git 的一部分。
假设我有文件
driver.cpp
,其中包含文件fw.h
.
我希望我的 Make 会自动检测我的工作区中是否缺少
fw.h
,从 Git 中引入 FW 工作区,编译它,将 fw.h
复制到正确的位置,然后编译我的驱动程序。
虽然我知道如何完成这些步骤中的大部分,但我不知道如何依赖
fw.h
.
我目前的解决方案是这样的:
get_fw:
rm -rf $(fw_ws)
git clone https://mygit/fw $(fw_ws)
cd $(fw_ws) && $(MAKE) "all kind of flags specific for FW"
cp $(fw_ws)/output/fw.h $(driver_inc)
driver.o: get_fw
问题是现在这个
get_fw
每次编译我的驱动程序时都会运行,即使 fw.h
已经存在。这需要相当多的时间。
我试过像这样天真的方法:
driver.o: fw.h
fw.h: get_fw
但它的效果为零,
get_fw
只是不运行并且 driver.cpp
的编译因缺少包含而失败。
您的
get_fw
规则不会生成名为 get_fw
的文件,因此 get_fw
总是过时的。 driver.o
以 get_fw
作为先决条件,因此不仅它本身总是过时的,而且 get_fw
的配方必须在 driver.o
的配方之前运行。
从
make
的角度来看,最一致的做法可能是将 get_fw
规则转换为创建真正的 driver.o 先决条件的适当规则。像这样的东西,也许:
driver.o: $(driver_inc)/fw.h
$(driver_inc)/fw.h:
rm -rf $(fw_ws)
git clone https://mygit/fw $(fw_ws)
cd $(fw_ws) && $(MAKE) "all kind of flags specific for FW"
cp $(fw_ws)/output/$(@F) $(@D)
$(@D)
和 $(@F)
是自动变量,分别扩展到规则目标的目录和基本名称部分。在这种情况下,$(@F)
扩展为 fw.h
,而 $(@D)
扩展为 $(driver_inc)
扩展到的任何内容。
请注意,因为标题规则本身没有先决条件,所以如果标题存在,它将始终被认为是最新的。要重建标头,您需要将其删除。
如果你想拥有按需重建标头的能力,那么你有多种选择。一种方法是创建标头配方所依赖的外部脚本,您也可以直接运行该脚本。另一种方法是为其创建一个单独的
make
规则,您可以通过递归 make
: 从标头配方访问该规则
driver.o: $(driver_inc)/fw.h
$(driver_inc)/fw.h:
$(MAKE) create_fw_header
.PHONY: create_fw_header
create_fw_header:
rm -rf $(fw_ws)
git clone https://mygit/fw $(fw_ws)
cd $(fw_ws) && $(MAKE) "all kind of flags specific for FW"
cp $(fw_ws)/output/fw.h $(driver_inc)
还有其他替代品,包括但不限于这两者之间的各种中间体。