GNU / Make手册§5.7声明如下:
5.7递归使用make
递归使用make意味着在makefile中使用make作为命令。 当您需要各种不同的makefile时,此技术非常有用 组成更大系统的子系统。例如,假设你有 一个子目录subdir,它有自己的makefile,你想要 包含目录的makefile在子目录上运行make。 你可以写下这个:
subsystem: cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): subsystem: $(MAKE) -C subdir
因此,基本上它意味着cd subdir && $(MAKE)
与$(MAKE) -C subdir
相同。
然而,事实证明它并不是真正的等价物。使用-C
选项时,目录路径(如果是符号链接)始终是取消引用的,因此无法获得“逻辑”(如pwd -L
)目录名称。请考虑以下示例。在Makefile
目录中有以下/tmp/b
,这是/tmp/a/
目录的符号链接:
foo:
@echo PWDL=$(shell pwd -L)
@echo PWDP=$(shell pwd -P)
@echo CURDIR=$(CURDIR)
现在,让我们以不同的方式调用make
:
$ pwd
/tmp
$ (cd b && make foo)
PWDL=/tmp/b
PWDP=/tmp/a
CURDIR=/tmp/a
$ make -C b foo
make: Entering directory `/tmp/a'
PWDL=/tmp/a
PWDP=/tmp/a
CURDIR=/tmp/a
make: Leaving directory `/tmp/a'
$ make --directory=b foo
make: Entering directory `/tmp/a'
PWDL=/tmp/a
PWDP=/tmp/a
CURDIR=/tmp/a
make: Leaving directory `/tmp/a'
$
如您所见,pwd -P
和$(CURDIR)
始终显示已取消引用的符号链接。但是pwd -L
只有在运行make
之前更改目录时才有效,这证明GNU / Make的-C
选项总是使它取消引用目录路径,这是没有充分理由的。我试图在文档中找到对此行为的任何解释但不能。在运行cd
之前,我没有使用make
更改目录,也没有为此问题提出解决方法(或者通过LD_PRELOAD
非常糟糕的挂钩)。
问题是 - 之前是否有其他人遇到此问题,有解释或解决方法?谢谢!
更新
试图找到它的底部,我已经下载了make
的源代码,但没有找到任何特殊的目录处理,只调用了chdir
。所以我写了一个小程序来进行实验,这就是我找到的。
当您处于符号链接目录(/tmp/b
)并尝试将目录更改为相同目录时,该操作无效,当前工作目录继续指向符号链接。
当您调用chdir ()
并指定完整路径或相对路径时,它会在更改目录之前取消引用它。这是一个证明:
$ cat cd.cpp
#include <stdio.h>
#include <unistd.h>
int main ()
{
chdir ("/tmp/b/");
printf ("Current dir: %s\n",
get_current_dir_name ()); /* Forgive my memory leak. */
}
$ gcc -o test ./cd.cpp
$ pwd
/tmp/b
$ ./test
Current dir: /tmp/b
$ cd ../
$ ./b/test
Current dir: /tmp/a
$ cd /
$ /tmp/b/test
Current dir: /tmp/a
$
所以似乎libc
或Linux正在玩弄我以前并不真正关心的技巧。最重要的是,bash s
cd`的工作方式有所不同。
奇怪的是,Linux chdir ()
man page没有提及任何相关内容,但在Borland Builder(!sic)文档中有一个注释,here。所以我想知道bash
在这方面做了什么。
答案 0 :(得分:8)
在ephemient的帮助下,我能够解决这个问题。所以很少有事情发生:
chdir ()
始终将其设置为真实目录。PWD
的变量代表当前的工作目录。PWD
变量,有些则不承担。PWD
变量。它解释了gmake
行为。当gmake
调用sh
时,PWD
会在gmake
进程执行之前更新。因此,PWD
被设置为“符号”路径,并且履行它的功能继续正常工作。否则,gmake
会调用chdir ()
,这会更改工作目录并设置PWD
而无需耍花招。因此,包括尊重PWD
的所有功能都开始返回“真实”路径。
总而言之,我会说取决于符号路径名称是一个坏主意,事情很容易崩溃。例如,因为getcwd ()
系统调用不关心PWD
。在运行cd
之前调用make
可以作为短期解决方案。