Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 调用父目录的Makefile_Recursion_Build_Makefile_Latex - Fatal编程技术网

Recursion 调用父目录的Makefile

Recursion 调用父目录的Makefile,recursion,build,makefile,latex,Recursion,Build,Makefile,Latex,我有一个具有以下目录结构的项目: foo/ foo/Makefile foo/bar/ 我的目标是添加一个文件foo/bar/Makefile,这样,如果在foo/bar中调用make,将使用父目录的Makefile。它是一种反向递归的Makefile结构(我希望每个Makefile调用父目录,直到它到达项目根目录) 符号链接失败,因为从错误目录调用它会中断所有相关路径: $ ln -s ../Makefile foo/bar/Makefile $ make -C foo/bar [error

我有一个具有以下目录结构的项目:

foo/
foo/Makefile
foo/bar/
我的目标是添加一个文件
foo/bar/Makefile
,这样,如果在
foo/bar
中调用
make
,将使用父目录的Makefile。它是一种反向递归的Makefile结构(我希望每个Makefile调用父目录,直到它到达项目根目录)

符号链接失败,因为从错误目录调用它会中断所有相关路径:

$ ln -s ../Makefile foo/bar/Makefile
$ make -C foo/bar
[error]
我找到的唯一解决方案是编写一个Makefile,它捕获我感兴趣的所有目标,并使用该目标调用父目录:

$ cat foo/bar/Makefile
all clean:
    $(MAKE) -C .. $@
这是一项艰巨的任务,很容易被打破。有更优雅的解决方案吗

理由


该项目是一个大型LaTeX文档,其中包含章节、图表等的
.tex
文件的多个子目录。我希望能够从这些目录中的任何一个调用
make
,以构建文档。

您可以创建一个自定义函数,在右侧文件夹中运行
make

make-foo() {
    make -C /absolute/path/to/foo "$@"
}

感谢Etan Reisner指出问题所在。此生成文件将捕获所有目标并将其传递给父生成文件:

all:
    @make -C .. $@
%:
    @make -C .. $@

注意,除了match anything规则之外,还需要提供默认的all规则,否则
make
如果在没有参数的情况下调用,
make:**no targets,就会发出抱怨。停止。

您不需要在此处使用多个
Makefile
s和递归调用
Make
。递归
Make
本身就不好,除非您确切了解其局限性,否则不应使用它

GNU Make的功能取决于其环境。因此,应该始终(在一个严肃的系统中,而不是玩具中)控制环境,并将
Make
包装在一个包装器shell脚本中,该脚本设置环境,然后调用
Make
(一次,从顶部开始)。你对“只做”的渴望被误导了

在本例中,包装器脚本进入循环,在循环中查找名为
Makefile
的文件,如果找不到,则将
cd
发送到父目录并重复。找到后,使用给定的参数执行
Make

在我的实践中,我还使用了上面更详细的版本,其中包装器脚本研究给定的参数,对于那些目标,在它们前面加上它开始的子目录的路径。所以

subdir>make foobar
相当于

>make subdir/foobar

基于@chris cummins之前的回答,最好使用
$(MAKE)
而不是
@MAKE

除其他事项外,这将保留并行构建(-j XX),否则会留下大量性能

最终版本将是(在GNU Make 4.2.1上测试):

全部:
美元(MAKE)-C$@
%:
美元(MAKE)-C$@

有关说明,请参见

此操作有效,谢谢。不过,我在理想情况下需要一个makeonly解决方案,因为我不想只为一个项目修改shell环境。这也可以通过一个别名来实现:
alias make foo='make-C/abs/path/to/foo'
如果您觉得您的解决方案“费力且容易崩溃”,为什么不让它
$(make)-C/path/to/project/root$@
?这样一来,您只需要进行一次递归调用,而不是多次调用,一个已断开的makefile不会断开树中它下面的所有makefile。讨论如何做(以及其他许多事情)。谢谢@EtanReisner<代码>全部%:@make-C$@@EtanReisner您不能混合隐式规则和常规规则,因此会出现重复。这很公平。它在GNU Make 3.81中工作,但在较新版本中会出错。嗨,马克,我很感激你的回答,但我不同意递归Make。递归make本身并不坏,通常对它的批评都不适用于这种简单的情况。除顶层外的所有makefile都是简单的包装器,不会向环境中注入任何内容。@ChrisCummins无需反对,听起来好像,您确实了解递归Make限制,然后,如我所说,如果您喜欢它而不是包装器脚本,那么使用它是可以的。