如何编写执行makefile使一个目录升级

时间:2015-09-01 06:50:41

标签: recursion makefile gnu-make

我是否可以编写一个包装器makefile,它将cd升级并使用我给出包装器的所有命令选项执行make

更详细:

  1. 目录project包含一个包含不同目标的真实Makefile。

  2. 目录project/resources包含应该在project中调用Makefile的包装器Makefile。

  3. 当我在目录project/resources的shell中时,执行

    make TARGET
    

    和那里的Makefile只是cds一个目录并调用

    make TARGET
    
    目录project中的

  4. 这可能吗?怎么样?

4 个答案:

答案 0 :(得分:2)

您可以对所有子目录使用非常简单的Makefile

%:
    $(MAKE) -C .. $@

%是最后的匹配任何模式规则,它将匹配任何目标...没有隐式规则(GNU make具有非常多的隐式规则)。因此,如果您的目标都没有被隐式规则覆盖,那么这应该有效。否则你必须告诉make不要使用它知道的隐含规则。这可以通过使用-r选项调用make来完成(使用GNU make):

cd project/resources
make -r <anything>

将在project中为目标<anything>调用make。主要缺点是-r标志被传递给子make,因此隐式规则既不适用于project,也可能是一个问题。如果是,您可以通过向.SUFFIXES中的Makefile添加空的project/resources目标来获得相同的效果:

.SUFFIXES:

%:
    $(MAKE) -C .. $@

使用我的GNU make版本(3.82),它就像一个魅力,而sub-make具有所有默认的隐式规则。

答案 1 :(得分:1)

是的,你可以有一个适用于“任何”目标的makefile。

GNU make手册在Overriding Part of Another Makefile部分讨论了这个问题:

  

有时使用一个makefile就像另一个makefile一样有用。您通常可以使用‘include’指令将一个包含在另一个中,并添加更多目标或变量定义。但是,对于两个makefile,为同一目标提供不同的配方是无效的。但还有另一种方式。

     

在包含makefile(想要包含另一个的makefile)中,您可以使用match-anything模式规则来重新创建无法根据包含的makefile中的信息创建的任何目标{{1}应该查看另一个makefile。有关模式规则的详细信息,请参阅Pattern Rules

     

例如,如果你有一个名为make的makefile,它说明了如何制作目标Makefile(以及其他目标),你可以编写一个名为‘foo’的makefile,其中包含: / p>

GNUmakefile
     

如果你说foo: frobnicate > foo %: force @$(MAKE) -f Makefile $@ force: ; ,make会找到‘make foo’,阅读它,并看到要生成GNUmakefile,它需要运行配方foo。如果您说‘frobnicate > foo’,则‘make bar’将无法在make中设置栏,因此它将使用模式规则中的配方:GNUmakefile。如果‘make -f Makefile bar’提供更新Makefile的规则,bar将应用该规则。同样对于make没有说明如何制作的任何其他目标。

     

这样做的方式是模式规则只有GNUmakefile的模式,所以它匹配任何目标。该规则指定先决条件‘%’,以确保即使目标文件已存在也将运行配方。我们为force目标提供一个空配方,以防止force搜索隐式规则来构建它 - 否则它会将相同的匹配任何规则应用于make本身并创建先决条件循环!

答案 2 :(得分:0)

一个选项:使用包装器文件执行命令来执行此操作。确保您的目标make文件不包含具有包装器的子目录,否则您可以创建无限循环。例如,

clean: 
  pushd .. && make clean && popd

答案 3 :(得分:0)

使用用户Renaud Pacaletanswer to a different question的评论,以下单行内容尽可能接近。整个Makefile读取:

IGNORE := $(shell $(MAKE) -C .. $(MAKECMDGOALS))

这个解决方案有几点需要注意:

  • 命令行选项-B不会传递给后续的make调用。
  • 随后调用的make进程的输出(在project目录中)不会打印到stdout。
  • 包装器制作过程最后报告任何给定目标:

      

    make:***没有规则来制作目标TARGET。停止。