GNU/Make manual§5.7声明如下:
5.7 make 的递归使用递归使用make意味着在make文件中使用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
)目录名。考虑下面的例子。在/tmp/b
目录中有以下Makefile
,这是到/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
选项总是让它去引用目录路径,没有什么好理由。我试图在文档中找到这种行为的任何解释,但不能。在运行make
之前,如果不使用cd
更改目录(或者通过LD_PRELOAD
没有非常糟糕的钩子),我也不能想出一个解决这个问题的方法。
问题是——其他人以前遇到过这个问题吗,有解释或解决方法吗?谢谢!
更新:
试图得到它的底部,我已经下载了make
的源代码,并没有发现任何特殊的处理目录,只有调用chdir
。所以我写了一个小程序来做一个实验,下面是我的发现。
当你在一个符号链接目录(/tmp/b
)中,并试图将目录更改为相同的目录时,操作无效,当前工作目录继续指向符号链接。
当您调用chdir ()
并指定完整路径或相对路径时,它会在更改目录之前取消引用它。下面是一个证明:
$ cat cd.cpp
#include <stdio.h>
#include <unistd.h>
int main ()
{
chdir ("/tmp/b/");
printf ("Current dir: %sn",
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 ()
手册页没有提到任何关于它的内容,但是在Borland Builder文档中有一个注释,在这里。所以我想知道bash
在这方面做了什么。
在ephemient的帮助下,我能够弄清楚这个问题。所以有一些事情正在发生:
- Linux不支持将当前工作目录设置为符号链接。
chdir ()
总是将其设置为实际目录。 - 有一个叫做
PWD
的变量,它代表当前的工作目录。 - 有些函数/系统调用支持
PWD
变量,有些不支持。 Bash维护一个使用符号名构建的"假"路径,并相应地设置
PWD
变量。它解释了gmake
的行为。当gmake
被sh
调用时,PWD
在gmake
进程执行之前被更新。因此,PWD
被设置为"符号"路径,并且尊重它的函数继续正常工作。否则,gmake
调用chdir ()
,后者将更改工作目录并设置PWD
,而不需要sh的技巧。因此,所有函数,包括那些遵循PWD
的函数,都开始返回"真实"路径。
总而言之,我想说依赖符号路径名是一个坏主意,事情很容易崩溃。例如,因为getcwd ()
系统调用不关心PWD
。在运行make
之前调用cd
可以作为短期解决方案。