如何编写一个makefile执行make一个目录级别



我可以写一个包装器makefile,它将cd一级并执行那里的make与我给包装器的所有命令选项吗?

详细说明:

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

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

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

    make TARGET
    

    和Makefile只是打开一个目录并调用

    make TARGET
    

    目录project

这可能吗?以及如何?

您可以为所有子目录使用一个非常简单的Makefile:

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

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

cd project/resources
make -r <anything>

将在project中为目标<anything>调用make。主要的缺点是-r标志被传递给sub-make,因此隐式规则在project中也不适用,这可能是一个问题。如果是,您可以通过向project/resources:

中的Makefile添加一个空的.SUFFIXES目标来获得相同的效果。
.SUFFIXES:
%:
    $(MAKE) -C .. $@

在我的GNU make(3.82)版本中,它像一个魅力一样工作,子make具有所有默认的隐式规则。

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

GNU make手册在另一个Makefile的重写部分讨论了这一点:

有时候,一个makefile与另一个makefile大致相同是很有用的。您通常可以使用‘include’指令将一个包含在另一个中,并添加更多的目标或变量定义。但是,对于同一个目标,两个makefile给出不同的recipe是无效的。但是还有另一种方法。

在包含的makefile中(想要包含另一个的那个),您可以使用match-anything模式规则来表示,要重新构建任何不能从包含的makefile中的信息中生成的目标,make应该在另一个makefile中查找。有关模式规则的更多信息,请参阅模式规则。

例如,如果您有一个名为Makefile的makefile,说明如何制作目标‘foo’(和其他目标),您可以编写一个名为GNUmakefile的makefile,其中包含:
foo:
        frobnicate > foo
%: force
        @$(MAKE) -f Makefile $@
force: ;

如果您输入‘make foo’, make将找到GNUmakefile,读取它,并看到要制作foo,它需要运行配方‘frobnicate > foo’。如果您说‘make bar’, make将无法在GNUmakefile中制作bar,因此它将使用模式规则中的配方:‘make -f Makefile bar’。如果Makefile提供了更新bar的规则,则make将应用该规则。对于GNUmakefile没有说明如何制作的任何其他目标也是如此。

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

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

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

使用用户Renaud Pacalet的评论和另一个问题的答案,下面的一行代码是我所能得到的最接近的。整个Makefile为:

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

这个解决方案有几个注意事项:

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

    make: ***没有make target target的规则。停止。

最新更新